=head1 Welcome to S<INN 2.7>!

Please read this document thoroughly before trying to install INN.  You'll
be glad you did.

If you are upgrading from a major release of INN prior to 2.3, it is
recommended that you make copies of your old configuration files and use
them as guides for doing a clean installation and configuration of 2.7.
Many config files have changed, some have been added, and some have been
removed.  You'll find it much easier to start with a fresh install than to
try to update your old installation.  This is particularly true if you're
upgrading from a version of INN prior to 2.0.

If you are upgrading from S<INN 2.3> or later, you may be able to just update
the binaries, scripts, and manual pages by running:

    make update

after building INN and then comparing the new sample configuration files
with your current ones to see if anything has changed.  If you take this
route, the old binaries and scripts will be saved with an extension of
C<.OLD> so that you can easily back out.  Note that if you do not want
to have such backup copies, you can deactivate this behaviour with
C<make BACKUP_OPTION='' update> instead of a mere C<make update>.  Be sure to
configure INN with the same options that you used previously if you take
this approach (in particular, INN compiled with B<--enable-largefiles>
can't read the data structures written by INN compiled without that flag,
and vice versa).  If you don't remember what options you used but you have
your old build tree, look at the beginning of F<config.log>.

If you are building INN from a Git clone of the development tree rather than
a snapshot or standard release, you first need to (re)generate the autoconf
files so as to pick up possible changes since the last pull of the Git tree.
This can be done by running the following commands:

    make maintclean
    ./autogen

before building INN with C<./configure> (followed by the wanted configure
options) and C<make>.  You may then also want to run the test suite with
C<make tests>.

If you made B<ckpasswd> setuid root so that you could use system passwords,
you'll have to do that again after C<make update>.  (It's much better to use
PAM instead if you can.)

If you use C<make update> to upgrade from a previous major release of INN,
also look at the new sample configuration files in F<samples> to see if
there are new options of interest to you.

For more information about recent changes, see F<NEWS>.

=head1 Packages and Docker Images

Instead of building INN from sources, you may want to check that a readily
available package does not already exist for your operating system.

If you want to create a Docker image, you can find examples of standard
local Docker containers or GitHub Actions services in projects like
L<apt-get-inn2-docker|https://github.com/cclauss/apt-get-inn2-docker> or
L<inn-docker|https://github.com/greenbender/inn-docker>.

=head1 Supported Systems

As much as possible, INN is written in portable C and should work on any
Unix platform.  It does, however, make extensive use of mmap(2) and
certain other constructs that may be poorly or incompletely implemented,
particularly on very old operating systems.

INN has been confirmed to build on recent versions of the following operating
systems:

    AIX (including 7.2 and 7.3)
    FreeBSD (including 12.1, 13.0, 14.0, 15.0 and 16.0)
    Linux (including 3.16, 4.19, 5.10, 5.15, 6.1, 6.12 and 7.0 kernels,
           glibc 2.19, 2.28, 2.31, 2.36, 2.41 and 2.42,
           and musl 1.1.24, 1.2.2, 1.2.3, 1.2.4, 1.2.5 and 1.2.6)
    macOS (including 11, 12, 13, 14, 15 and 26)
    NetBSD (including 9.2 and 10.1)
    OpenBSD (including 6.8, 7.8 and 7.9)
    Oracle Solaris (including 10 1/13, 11.3 and 11.4)

Current versions of INN may also work on other operating systems like
HP-UX, OpenServer, SCO, UnixWare or UX/4800, as well as old versions of
the above list of operating systems, but have not been confirmed to.
Old versions of INN used to, but current ones have not been tested on
such systems or ancient specific versions.

If you have gotten INN working on an operating system other than the ones
listed above, please let us know at <inn-workers@lists.isc.org>.

=head1 Before You Begin

INN requires several other packages be installed in order to be fully
functional (or in some cases, to work at all):

=over 2

=item *

In order to build INN, you will need a C compiler that understands S<ANSI C>.
If you are trying to install INN on an operating system that doesn't have
an S<ANSI C> compiler (such as SunOS), installing B<gcc> is recommended.  You
can get it from L<https://ftp.gnu.org/gnu/gcc/> or its mirrors.  INN is
tested with B<gcc> more thoroughly than with any other compiler, so even if
you have another compiler available, you may wish to use B<gcc> instead.

=item *

Currently, in order to build INN, you will need an implementation of B<yacc>.
GNU B<bison> (from L<https://ftp.gnu.org/gnu/bison/> or its mirrors) will work
fine.  We hope to remove this requirement in the future.

=item *

INN requires at least S<B<Perl 5.8.0>> to build and to run several
subsystems.  In order to process control messages, B<controlchan>
needs the C<MIME::Parser> module available from the C<MIME-tools>
distribution in CPAN (L<https://metacpan.org/dist/MIME-tools>).  This
Perl module has probably already been packaged for your distribution.
INN is tested primarily with newer versions of Perl, so it's generally
recommended that you install the latest stable distribution of Perl before
compiling INN.  For instructions on obtaining and installing Perl, see
L<https://www.perl.org/get.html>.  Note that you may need to use the same
compiler and options (particularly large file support and shared libraries)
for Perl and INN.

Generating all the documentation from POD requires S<B<Perl 5.12.0>> due
to the use of C<LE<lt>E<gt>> with URL and text in some files but most of the
documentation can be generated with S<B<Perl 5.8.0>>.  If need be, it can be
fetched from the release tarball.

=item *

The INN Makefiles use the syntax C<include FILE>, rather than the syntax
expected by some BSDish systems of C<.include E<lt>FILEE<gt>>.  If your
system expects the latter syntax, the recommended solution is to install
GNU B<make> from L<https://ftp.gnu.org/gnu/make/>.  You may have GNU B<make>
already installed as B<gmake>, in which case using B<gmake> rather than
B<make> to build INN should be sufficient.

=item *

If you want to enable support for authenticated control messages (this is
not required, but is highly recommended for systems carrying public Usenet
hierarchies) then you will need to install some version of PGP.  The
recommended version is B<GnuPG>, since it's actively developed, supports
OpenPGP, is freely available from L<https://www.gnupg.org/> and free to use
for any purpose (in the US and elsewhere), and (as of version 1.0.4 at
least) supports the RSA signatures used by most current control message
senders.

In order to verify some of the control messages currently used on Usenet,
you will need to use a version of GnuPG prior to 2.1.0, which dropped
support for the old keys used by some Usenet control message senders.  On
current systems, this may require the 1.x series of GnuPG.  Sometimes this
is the C<gnupg> package (and GnuPG v2 is C<gnupg2>), and sometimes it is
the C<gnupg1> package.

=item *

If you want to use either the Python embedded hooks, you'll need to have a
suitable version of B<Python> installed.  See F<doc/hook-python> for more
information.

=item *

If you want to use systemd notifications and socket activation,
you'll need to have B<pkg-config> and B<libsystemd> (along with its
F<libsystemd.pc> configuration) installed so that these features are
enabled at configure time.

=item *

Many of INN's optional features require other packages (primarily
libraries) be installed.  If you wish to use any of these optional
features, you will need to install those packages first.  Here is a table
of configure options enabling optional features and the software and
versions you'll need:

    --with-bdb          Berkeley DB 4.4 or higher, 4.7+ recommended
    --with-blocklist    blocklistd from FreeBSD 11, NetBSD 7 or higher versions
    --with-canlock      libcanlock 3.3.0 or higher
    --with-krb5         MIT Kerberos v5 1.6.1 or higher
    --with-openssl      OpenSSL 0.9.6 or higher, 3.0.0+ recommended
                        LibreSSL 2.1.0 or higher, 3.2.0+ recommended
    --with-perl         Perl 5.004_03 or higher, 5.8.0+ recommended
    --with-python       Python 2.3.0 or higher, 2.5.0+ recommended
                        Python 3.3.0 or higher
    --with-sasl         Cyrus SASL 2.1.0 or higher
    --with-sqlite3      SQLite 3.8.2 or higher, 3.20.0+ recommended
    --with-zlib         zlib 1.x or higher

If any of these libraries (other than Perl or Python) are built shared and
installed in locations where your system doesn't search for shared
libraries by default, you may need to encode the paths to those shared
libraries in the INN binaries.  For more information on shared library
paths, see L<https://www.eyrie.org/~eagle/notes/rpath.html>.

For most systems, setting the environment variable LD_RUN_PATH to a
colon-separated list of additional directories in which to look for shared
libraries before building INN will be sufficient.

If you build your own libraries, make sure to generate them as either
shared libraries or static libraries built with B<-fPIC> amongst
the options given to the compiler (to obtain position-independent
code).  Otherwise, building INN will fail, unless you pass
B<--disable-hardening-flags> to C<configure>.

=back

=head1 Unpacking the Distribution

Released versions of INN are available from
L<https://downloads.isc.org/isc/inn/>.  New major releases will be announced
on <inn-announce@lists.isc.org> (see F<README>) when they're made.

If you want a more cutting-edge version, you can obtain current snapshots
from L<https://downloads.isc.org/isc/inn/snapshots/>.  These are snapshots
of the INN Git tree taken daily; there are two snapshots made each
night in the F<daily> subdirectory (one of the current development
branch, and one of the stable branch consisting of bug fixes to the
previous major release), and also daily snapshots at the top level of
the directory, updated only when the code changes in one of the two
branches.  They are stored in date format in the F<daily> subdirectory;
in other words the snapshots from April 6th, 2020, would be named
F<inn-CURRENT-20200406.tar.gz> and F<inn-STABLE-20200406.tar.gz>.
At the top level of the directory, the INN version number is used
followed with either the C<git describe> version number for the stable
branch or the date for the main branch.  Choose the newest file of
whichever branch you prefer.  (Note that the downloading, configuring,
and compiling steps can be done while logged in as any user.)

The distribution is in gzip compressed tar archive format.  To extract it,
execute:

    gunzip -c <inn-src-file> | tar -xf -

Extracting the source distribution will create a directory named F<<
inn-<version> >>, F<< inn-<BRANCH>-<date> >>, F<< inn-<stable branch
version>-<git version> >> or F<< inn-<main branch version>-<date> >>
where the source resides.

=head1 Installing INN

Before beginning installation, you should make sure that there is a user
on your system named C<news>, and that this user's primary group is set to
a group called C<news>.  You can change these with the B<--with-news-user>
and B<--with-news-group> options to C<configure> (see below).  The home
directory of this user should be set to the directory under which you wish
to install INN (F</usr/local/news> is the default and is a good choice).
This location will be set as I<pathnews> in F<inn.conf>.
INN will install itself as this user and group.  You can change these if
you want, but these are the defaults and it's easier to stick with them on
a new installation.

By default, INN sends reports to the user C<usenet>.  This account is
used for instance by B<controlchan> (notifying any changes as for newsgroups)
or B<news.daily> (sending Usenet daily reports).  You can change it with the
B<--with-news-master> option to C<configure> (see below).  There is also
the I<mailto> keyword which can be given to B<news.daily> in order to
modify the mail address to which these reports are sent.

WARNING: By default, INN installs various configuration files as
group-writeable, and in general INN is not hardened from a security
standpoint against an attack by someone who is already in the C<news> group.
In general, you should consider membership in the news group as equivalent
to access to the news account.  You should not rely on being able to keep
anyone with access to the news GID from converting that into access to the
news UID.  The recommended configuration is to have the only member of the
group C<news> be the user C<news>.

Installing INN so that all of its files are under a single directory tree,
rather than scattering binaries, libraries, and man pages throughout the
file system, is strongly recommended.  It helps keep everything involved
in the operation of INN together as a unit and will make the installation
instructions easier to follow.

As a side note, whenever doing anything with a running news server, first
log in as this user.  That way, you can ensure that all files created by
any commands you run are created with the right ownership to be readable
by the server.  Particularly avoid doing anything in the news spool itself
as root, and make sure you fix the ownership of any created files if you
have to.  INN doesn't like files in the news spool owned by a user other
than the news user.  However, since certain binaries need to be setuid
root, indiscriminate use of C<chown news> is not the solution.  (If you
don't like to log in to system accounts, careful use of C<chmod g+s> on
directories and a umask of C<002> or C<007> may suffice.)

INN uses GNU B<autoconf> and a generated C<configure> script to make
configuration rather painless.  Unless you have a rather abnormal setup,
C<configure> should be able to completely configure INN for your system.  If
you want to change the defaults, you can invoke the C<configure> script with
one or more command line options.  Type:

    ./configure --help

for a full list of supported options.  Some of the most commonly used
options are:

=over 4

=item B<--prefix>=PATH

Sets the installation prefix for INN.  The default is F</usr/local/news>.
All of INN's programs and support files will be installed under this
directory.  This should match the home directory of your news user (it
will make installation and maintenance easier).  It is not recommended to
set this to F</usr>; if you decide to do that anyway, make sure to point
INN's temporary directory at a directory that isn't world-writeable (see
B<--with-tmp-dir> below).

=item B<--with-db-dir>=PATH

Sets the prefix for INN database files.  The default is F<PREFIX/db>,
where PREFIX is F</usr/local/news> unless overridden with the option above.
The F<history> and F<active> files will be stored in this directory, and
writes to those files are an appreciable percentage of INN's disk activity.
The F<history> file can also be quite large (requiring up to S<2 GB> or more
during nightly B<expire>), so this is a common portion of INN to move to a
different file system.

=item B<--with-spool-dir>=PATH

Sets the prefix for the news spool (when using any storage method other
than CNFS) and the overview spool.  The default is F<PREFIX/spool>.  This
is another common portion of INN to move to a different file system (often
F</news>).

=item B<--with-tmp-dir>=PATH

Sets the directory in which INN will create temporary files.  This should
under no circumstances be the same as the system temporary directory or
otherwise be set to a world-writeable directory, since INN doesn't take
care to avoid symlink attacks and other security problems possible with a
world-writeable directory.  This directory should be reserved for the
exclusive use of INN and only writeable by the news user.  Usage is
generally light, so this is unlikely to need a separate partition.

It's also possible to set the paths for most other sections of the INN
installation independently; see C<./configure --help> and look for the
B<--with-*-dir>=PATH options.

=item B<--enable-reduced-depends>

Requests that library probes assume shared libraries are in use and
dependencies of libraries should not be probed.  It therefore tries to
minimize the shared library dependencies of the resulting binaries on
platforms with proper shared library dependencies.  This is not enabled
by default, and is of interest primarily to people building packages
for distributions.

=item B<--enable-largefiles>

Enables large file support, arranging for 64-bit file offsets.  This flag
is only useful for 32-bit platforms and some very rare 64-bit platforms that
define a 32-bit I<off_t> type.

This is not enabled by default (unless of course I<off_t> is already 64-bit
long), even on platforms that support it, because it changes the format
of INN's on-disk databases (making it difficult to upgrade an earlier INN
installation) and can significantly increase the size of some of the history
database files.  Large file support is not necessary unless your F<history>
database is so large that it exceeds S<2 GB> or you want to use CNFS buffers
larger than S<2 GB> on 32-bit platforms.

The history, tradindexed and buffindexed overview, and timecaf databases
written by an INN built with this option are incompatible with those
written by an INN without this option.  (CNFS buffers are compatible.)

=item B<--enable-tagged-hash>

Use tagged hash table for the F<history> database.  The tagged hash format
uses much less memory but is somewhat slower.  This option is recommended
if you have less than S<256 MB> of RAM on your news server.  If you install
INN without tagged hash (the default) and B<expire> takes an excessive amount
of time, you should make sure the RAM in your system satisfies the
following formula:

    ram > 10 * tablesize

          ram: Amount of system RAM (in bytes)
    tablesize: 3rd field on the 1st line of history.dir (bytes)

If you don't have at least that much RAM, try rebuilding INN with tagged
hash enabled.

NOTE: B<--enable-largefiles> cannot be used with B<--enable-tagged-hash>.

=item B<--with-perl>

Enables support for embedded Perl, allowing you to install filter scripts
written in Perl.  Highly recommended, because many really good spam
filters are written in Perl.  See F<doc/hook-perl> for all the details.

Even if you do not use this option, INN still requires Perl as mentioned
above.

If the C<$PERL> environment variable is set, it will be used as the path
to Perl.

=item B<--with-python>

Enables support for Python, allowing you to install filter and
authentication scripts written in Python.  You will need S<Python
2.3.0> or later (in the 2.x series), or S<Python 3.3.0> or later
(in the 3.x series) installed on your system to enable this option.
See F<doc/hook-python> for all the details.

If the C<$PYTHON> environment variable is set, it will be used as the path
to Python.

=item B<--with-innd-port>=PORT

By default, innbind(8) refuses to bind to any port under 1024 other than
119, 433 and 563 for security reasons (to prevent attacks on rsh(1)-based
commands and replacing standard system daemons).  If you want to run B<innd>
on a different port under 1024, you'll need to tell C<configure> what port
you intend to use.  (You'll also still need to set the port number in
F<inn.conf> or give it to B<innd> on the command line.)

=item B<--with-syslog-facility>=FACILITY

Specifies the syslog facility that INN programs should log to.  The
default is LOG_NEWS unless C<configure> detects that your system doesn't
understand that facility, in which case it uses LOG_LOCAL1.  This flag
overrides the automatic detection.  Be sure to specify a facility not used
by anything else on your system (one of LOG_LOCAL0 through LOG_LOCAL7, for
example).

=item B<--enable-uucp-rnews>

If this option is given to C<configure>, B<rnews> will be installed setuid
C<news>, owned by group C<uucp>, and mode C<4550>.  This will allow the
UUCP subsystem to run B<rnews> to process UUCP batches of news articles.
Prior to S<INN 2.3>, installing B<rnews> setuid C<news> was standard; since
most sites no longer use UUCP, it is no longer the default as of S<INN 2.3>
and must be requested at configure time.  You probably don't want to use
this option unless your server accepts UUCP news batches.

=item B<--enable-setgid-inews>

If this option is given to C<configure>, B<inews> will be installed setgid
C<news> and world-executable so that non-privileged users on the news
server machine can use B<inews> to post articles locally (somewhat faster
than opening a new network connection).  For standalone news servers, by
far the most common configuration now, there's no need to use this option;
even if you have regular login accounts on your news server, INN's B<inews>
can post fine via a network connection to your running news server and
doesn't need to use the local socket (which is what setgid enables it to do).
Installing B<inews> setgid was the default prior to S<INN 2.3>.

=item B<--with-bdb>=PATH

Enables support for S<Berkeley DB> (4.4 or higher), which means that
it will then be possible to use the ovdb overview method if you wish.
Enabling this configure option doesn't mean you'll be required to use
ovdb, but it does require that S<Berkeley DB> be installed on your
system (including the header files, not just the runtime libraries).
If a path is given, it sets the installed directory of S<Berkeley DB>
(C<configure> will search for it in standard locations, but if you have
it installed elsewhere, you may need this option).  This directory
is expected to have subdirectories F<include> and F<lib> (F<lib32>
and F<lib64> are also checked), containing respectively F<db.h>, and
the library itself.  In case non-standard paths to the S<Berkeley DB>
libraries are used, one or both of the options B<--with-bdb-include>
and B<--with-bdb-lib> can be given to C<configure> with a path.

If the S<Berkeley DB> library is found at configure time, INN will be
built with S<Berkeley DB> support unless the B<--without-bdb> flag is
explicitly passed to C<configure>.

=item B<--with-sqlite3>=PATH

Enables support for SQLite (3.8.2 or higher), which means that it
will then be possible to use the ovsqlite overview method if you wish.
Enabling this configure option doesn't mean you'll be required to use
ovsqlite, but it does require that SQLite be installed on your system
(including the header files, not just the runtime libraries).  If a
path is given, it sets the installed directory of SQLite.  In case
non-standard paths to the SQLite library are used, one or both of the
options B<--with-sqlite3-include> and B<--with-sqlite3-lib> can be given
to C<configure> with a path.

If the SQLite library is found at configure time, INN will be built
with SQLite support unless the B<--without-sqlite3> flag is explicitly
passed to C<configure>.

=item B<--with-zlib>=PATH

Enables support for compression for news reading, which means a
compression layer can be negotiated between your server and newsreaders
supporting that NNTP extension.

Also enables support for compression with the ovdb and ovsqlite overview
storage methods.

This option requires that zlib be installed on your system (including the
header files, not just the runtime libraries).  If a path is given, it
sets the installed directory of zlib.  In case non-standard paths to the
zlib library are used, one or both of the options B<--with-zlib-include>
and B<--with-zlib-lib> can be given to C<configure> with a path.

If the zlib library is found at configure time, INN will be built with
compression support unless the B<--without-zlib> flag is explicitly
passed to C<configure>.

=item B<--with-openssl>=PATH

Enables support for TLS/SSL for news reading, which means it will be
possible to have TLS encrypted NNTP connections between your server and
newsreaders.  This option requires OpenSSL or LibreSSL be installed on
your system (including the header files, not just the runtime libraries).
If a path is given, it sets the installed directory of OpenSSL or LibreSSL.
After compiling and installing INN with this option, you'll still need to
make a certificate and private key to use TLS.  See below for details on
how to do that.

In case non-standard paths to the OpenSSL or LibreSSL libraries are used,
one or both of the options B<--with-openssl-include> and B<--with-openssl-lib>
can be given to C<configure> with a path.

If the OpenSSL or LibreSSL SSL and crypto libraries are found at configure
time, INN will be built with TLS/SSL support unless the B<--without-openssl>
flag is explicitly passed to C<configure>.

=item B<--with-canlock>=PATH

Enables support for Cancel-Lock, using libcanlock (3.3.0 or higher), which
provides a mechanism to authenticate article withdrawals.  This option
requires that libcanlock be installed on your system (including the
header files, not just the runtime libraries).  If a path is given,
it sets the installed directory of libcanlock.  In case non-standard
paths to the libcanlock library are used, one or both of the options
B<--with-canlock-include> and B<--with-canlock-lib> can be given to
C<configure> with a path.

After compiling and installing INN with this option, you'll need setting the
Cancel-Lock secrets in the F<inn-secrets.conf> configuration file.

If the libcanlock library is found at configure time, INN will be built with
Cancel-Lock support unless the B<--without-canlock> flag is explicitly passed
to C<configure>.

=item B<--with-blocklist>=PATH

Enables B<nnrpd> integration with FreeBSD's or NetBSD's blocklistd(8)
for blocking of brute force attacks.  blocklistd and its client library
libblocklist have been available in the FreeBSD base system since S<FreeBSD
11> and should be automatically detected if PATH is not given.  They have also
been in the NetBSD base system since S<NetBSD 7>.  Formerly known as blacklist
back then, blocklist is the new name in S<FreeBSD 15> and S<NetBSD 10>.

For this feature to have any effect, B<nnrpd> needs to be started with the
B<-B> flag, and blocklistd needs to be configured and running.  See the
B<nnrpd> documentation for a short configuration snippet and/or read the
blocklistd(8) documentation.

=back

For the most common installation, a standalone news server, a suggested
set of options is:

    ./configure --with-perl --with-python

provided that you have the necessary versions of Perl and Python installed.
(Compiling with embedded Perl and Python interpreters will allow you
to use one of the available excellent spam filters if you so choose.)

If the B<configure> program runs successfully, then you are ready to build
the distribution.  From the root of the INN source tree, type:

    make

At this point you can step away from the computer for a little while and
have a quick snack while INN compiles.  On a decently fast system it
should only take five or ten minutes at the most to build.

Once the build has completed successfully, you are ready to install INN
into its final home.  Type:

    make install

Under most circumstances, you will need to run the C<make install>
command as root, so that INN can create the directories it needs,
change ownerships (if you did not compile as the news user) and install
a setuid program needed to raise resource limits and allow B<innd> to
bind to ports under 1024.  This step will install INN under the install
directory (F</usr/local/news>, known as I<pathnews> in F<inn.conf>,
unless you specified something else to the configure script).

Exceptionally, if you are installing INN into a directory writable by
the news user, you can run C<make install> as the configured news user.
The resulting INN installation won't be able to use ports below 1024
(including the default NNTP port of 119) unless you then run C<make
install-root> as root, which will install only the setuid helper program.

If you are building INN on a different system than the one on which it
will eventually run, and you therefore want INN to install its files
in a virtual root directory and not into the actual filesystem of the
build machine, you can pass the virtual root directory to the install
step via the DESTDIR variable.  You then just need to type:

    make DESTDIR=/tmp/inn-root install

In the above example, all of INN's directories and files would
be installed under the F</tmp/inn-root> directory instead of
the normal F</> (root) directory.  Just replace C</tmp/inn-root>
with whatever directory you wish to install INN in (the result
will be in F</tmp/inn-root/usr/local/news> if the default value of
F</usr/local/news> for I<pathnews> has not been changed).  This won't
affect any of the paths compiled into INN; it's used primarily in some
situations like building a software distribution, where software has to
be installed into some file system that will later be mounted as F</>
on the final system.  Using DESTDIR permits building INN, installing
it into a virtual root directory, and packaging the resulting files
in a single step, without manual intervention, by a non-root user.
It is possible to build and install INN in this way, but you must set
a DESTDIR value for the install step, and additionally, you must tell
the installation process that it should omit executing C<chown> and
C<chgrp> commands (which will fail if the installation step is being
executed by a non-root user).  To do this, type:

    CHOWNPROG=set CHGRPPROG=set make DESTDIR=/tmp/inn-root install

WARNING: if you install INN in this manner, none of the resulting
directories and files in the virtual root directory will be owned by
the correct users and groups.  It is YOUR responsibility to ensure the
resulting directories and files are packaged with the users, groups,
and modes which INN wanted them to be installed with!

Please note that INN's shared library interface is not stable and
may change drastically in future major releases.  Only INN should use
INN's shared libraries, and you should only use the shared libraries
corresponding to the version of INN that you're installing.

Also, when updating an existing version of INN, INN tries to save
backup copies of all files but man pages and shared libraries so that
you can revert to the previous installed version.  Shared libraries
are not backed up because this confuses B<ldconfig> on some systems
(such as Linux) and the symbolic links for the libraries may point to
the C<.OLD> versions.  Nonetheless, reverting to a previous version of
INN should work fine for official releases (that is to say releases
that are not daily snapshots) because a proper versioning is done during
the release of a new version.

If you are configuring TLS/SSL support for newsreaders, you must make a
certificate and private key at least once.  Type:

    make cert

as root in order to do this.

You can also type C<make DESTDIR=/tmp/inn-root cert> as either root
(preferred) or a non-root user.  All of the warnings and caveats
mentioned above apply.

You are now ready for the really fun part: configuring your copy of INN!

=head1 Choosing an Article Storage Format

The first thing to decide is how INN should store articles on your system.
There are four different methods for you to choose from, each of which has
its own advantages and disadvantages.  INN can support all four at the
same time, so you can store certain newsgroups in one method and other
newsgroups in another method.

The supported storage formats are:

=over 4

=item tradspool

This is the storage method used by all versions of INN previous to 2.0.
Articles are stored as individual text files whose names are the same as
the article number.  The articles are divided up into directories based on
the newsgroup name.  For example, article 12345 in news.software.nntp
would be stored as F<news/software/nntp/12345> relative to the root of the
article spool.

Advantages: Widely used and well-understood storage mechanism, can read
article spools written by older versions of INN, compatible with all
third-party INN add-ons, provides easy and direct access to the articles
stored on your server, makes writing programs that fiddle with the news spool
very easy, gives you fine control over article retention times, and comes with
the B<scanspool> support utility to perform sanity checks.

Disadvantages: Needs a faster file system and I/O system than the cnfs
and timecaf storage methods due to file system overhead.  Groups with heavy
traffic tend to create a bottleneck because of inefficiencies in storing large
numbers of article files in a single directory.  It consumes more inodes and
requires a nightly B<expire> program to delete old articles out of the news
spool.

=item timehash

Articles are stored as individual files as in tradspool, but are divided
into directories based on the arrival time to ensure that no single
directory contains so many files as to cause a bottleneck.

Advantages: Heavy traffic groups do not cause bottlenecks, and a fine
control of article retention time is still possible.

Disadvantages: The ability to easily find all articles in a given newsgroup
and manually fiddle with the article spool is lost, and INN still suffers
from speed degradation due to file system overhead (creating and deleting
individual files is a slow operation) and from a higher inode usage.  It also
requires a nightly B<expire> program to delete old articles out of the news
spool.

=item timecaf

Similar to timehash, articles are stored by arrival time, but instead of
writing a separate file for each article, multiple articles are put in the
same file.

A given CAF file contains all the articles received during a time frame of
4 minutes or so (256 seconds), and is limited to 262,144 articles and about
3,5 GB.  It is enough for normal operations.  The only caveat is when you're
feeding at high speed bunches of articles between two servers; you'll then
want to limit it to that amount of articles during the time frame when a CAF
file stores newly arrived articles.

Advantages: Roughly four times faster than timehash for article writes,
since much of the file system overhead is bypassed, while still retaining
the same fine control over article retention time.

Disadvantages: Even worse than timehash, and similar to CNFS (below), using
this method means giving up all but the most careful manually fiddling with
your article spool.  As one of the newer and least widely used storage types,
timecaf has not been as thoroughly tested as the other methods.  It requires
running a nightly B<expire> program to delete old articles by either
compacting CAF files if they still contain available articles, or removing
them.

=item cnfs

CNFS stores articles sequentially in pre-configured buffer files.  When
the end of the buffer is reached, new articles are stored from the
beginning of the buffer, overwriting older articles.

Advantages: Blazingly fast because no file creations or deletions are
necessary to store an article.  Unlike all other storage methods, does not
require manual article expiration; old articles are deleted to make room
for new ones when the buffers get too full.  Also, with CNFS your server
will never throttle itself due to a full spool disk, and groups are
restricted to just the buffer files you give them so that they can never
use more than the amount of disk space you allocate to them.

Disadvantages: Article retention times are more difficult to control
because old articles are overwritten automatically.  Attacks on Usenet,
such as flooding or massive amounts of spam, can result in wanted articles
expiring much faster than you intended (with no warning).

=back

Some general recommendations: If you are installing a transit news server
(one that just accepts news and sends it out again to other servers and
doesn't support any readers), use CNFS exclusively and don't worry about
any of the other storage methods.  Otherwise, put high-volume groups and
groups whose articles you don't need to keep around very long (binaries
groups, *.jobs*, news.lists.filters, etc.) in CNFS buffers, and use
timehash, timecaf, or tradspool (if you have a fast I/O subsystem or need
to be able to go through the spool manually) for everything else.  You'll
probably find it most convenient to keep special hierarchies like local
hierarchies and hierarchies that should never expire in tradspool.

=head1 Choosing an Overview Storage Mechanism

If your news server will be supporting readers, you'll also need to choose
an overview storage mechanism (by setting I<ovmethod> in F<inn.conf>).
There are four overview mechanisms to choose from:

=over 4

=item buffindexed

It stores overview data and index information into preconfigured large files
like CNFS.  Fast at writing, the C<buffindexed> overview storage method can
keep up with a large feed more easily and never consumes additional disk space
beyond that allocated to these buffers.  The downside is that these buffers
are hard to recover in case of corruption and somewhat slower for readers and
the expiry process.  Also, overview data is limited to S<8 KB> per article,
which may lead to the lack of integration of a few articles with headers of
unusual length into the overview database.  See the buffindexed.conf(5) man
page for more details, and notably how to create the buffers.

=item ovdb

It stores overview information into a S<Berkeley DB> database, whose
development pace has stalled these last years.  This method is fast
and very robust, but may require more disk space, unless compression
is enabled.  Overview data is fetched one article at a time, which makes
this method a bit slower than C<ovsqlite> for readers.  See the ovdb(5)
man page for more details.

=item ovsqlite

It stores overview information into an SQLite database, known for its
long-term stability and compatibility.  Robust and faster than C<ovdb>
at reading ranges of overview data (since overview data is transferred in
128-kilobyte chunks between B<ovsqlite-server> and B<nnrpd>) but somewhat
slower at writing, this method may require more disk space, unless
compression is enabled.  See the ovsqlite(5) man page for more details.

=item tradindexed

It uses two files per newsgroup, one containing the overview data
and one containing the index.  Fast for readers, but slow to write to
because it has to update two files for each incoming article.  Its main
advantage is to be the best tested, the most reliable and the method
with the best recovery tools (B<tdx-util>).

=back

Here are a few elements that can be helpful in choosing the right
overview method for your needs and estimating the associated storage
size.  In 2020, the volume for a full-text Usenet feed is about 18,000
articles per day, with peaks to 1,200 articles per hour.  Article storage
size is about S<65 MB> per day.

As for overview storage size, if you have 5 million articles, you'll
need at least S<3.25 GB> of disk space for buffindexed, S<5.5 GB> for ovdb
(S<4.5 GB> if compressed), S<4.65 GB> for ovsqlite (S<2 GB> if compressed),
and S<3.10 GB> for tradindexed.

If you store more header fields in overview data than the standard
ones, the space needed to store overview data will be superior
than these estimates.  (This is configured in F<inn.conf>, via the
I<extraoverviewadvertised> and I<extraoverviewhidden> parameters.)

=head1 Configuring INN

All documentation from this point on assumes that you have set up the news
user on your system as suggested in L<Installing INN> so that the root of
your INN installation is F<~news> (I<pathnews> in F<inn.conf>).  If you've
moved things around by using options with C<configure>, you'll need to adjust
the instructions to account for that.

All of INN's configuration files are located in I<pathetc> as set in
F<inn.conf>.  Unless noted otherwise, any files referred to below are
in this directory.  When you first install INN, a sample of each file
(containing lots of comments) is installed in I<pathetc>; refer to
these for concrete examples of everything discussed in this section.

All of INN's configuration files, all of the programs that come with it, and
some of its library routines have documentation in the form of man pages.
These man pages were installed in I<pathnews>/share/man as part of the INN
installation process and are the most complete reference to how INN works.
You're strongly encouraged to refer to the man pages frequently while
configuring INN, and for quick reference afterwards.  Any detailed questions
about individual configuration files or the behavior of specific programs
should be answered in them.  You may want to add I<pathnews>/share/man to your
MANPATH environment variable; otherwise, you may have to use a command like:

    man -M <pathnews in inn.conf>/share/man inn.conf

to see the inn.conf(5) man page (for example).

Before we begin, it is worth mentioning the wildmat pattern matching
syntax used in many configuration files.  These are simple wildcard
matches using the asterisk (C<*>) as the wildcard character, much like the
simple wildcard expansion used by Unix shells.

In many cases, wildmat patterns can be specified in a comma-separated list
to indicate a list of newsgroups.  When used in this fashion, each pattern
is checked in turn to see if it matches, and the last pattern in the line
that matches the group name is used.  Patterns beginning with C<!> mean to
exclude groups matching that pattern.  For example:

    *,!comp.*,comp.os.*

In this case, we're saying we match everything (C<*>), except that we
don't match anything under comp (C<!comp.*>), unless it is actually under
the comp.os hierarchy (C<comp.os.*>).  This is because non-comp groups
will match only the first pattern (so we want them), comp.os groups will
match all three patterns (so we want them too, because the third pattern
counts in this case), and all other comp groups will match the first and
second patterns and will be excluded by the second pattern.

Some uses of wildmat patterns also support "poison" patterns (patterns
starting with C<@>).  These patterns behave just like C<!> patterns when
checked against a single newsgroup name.  Where they become special is for
articles crossposted to multiple newsgroups; normally, such an article
will be considered to match a pattern if any of the newsgroups it is
posted to matches the pattern.  If any newsgroup the article is posted to
matches an expression beginning with C<@>, however, that article will not
match the pattern even if other newsgroups to which it was posted match
other expressions.  For instance, if an article is crossposted between
misc.foo and misc.bar, the pattern:

    misc.*,!misc.bar

will match that article whereas the pattern:

    misc.*,@misc.bar

will not match that article.  An article posted only to misc.bar will fail
to match either pattern.

See libinn_uwildmat(3) for full details on wildmat patterns.

In all INN configuration files, blank lines and lines beginning with a
C<#> symbol are considered comments and are ignored.  Be careful, not all
files permit comments to begin in the middle of the line.

=head2 F<inn.conf>

The first, and most important file is F<inn.conf>.  This file is organized
as a series of parameter-value pairs, one per line.  The parameter is
first, followed by a colon and one or more whitespace characters, and then
the value itself.  For some parameters the value is a string or a number;
for others it is true or false.  (True values can be written as C<yes>,
C<true>, or C<on>, whichever you prefer.  Similarly, false values can be
written as C<no>, C<false>, or C<off>.)

F<inn.conf> contains dozens of changeable parameters (see inn.conf(5) for
full details), but only a few really need to be edited during normal
operation:

=over 4

=item allownewnews

If set to true then INN will support the NEWNEWS command for news readers.
While this can be an expensive operation, its speed has been improved
considerably as of S<INN 2.3> and it's probably safe to turn on without
risking excessive server load.  The default is true.  (Note that the
I<access> setting in F<readers.conf> overrides this value; see
readers.conf(5) for more details.)

=item complaints

Used to set the value of the mail-complaints-to attribute of
the Injection-Info header field, which is added to all articles posted
locally.  The usual value would be something like C<abuse@example.com>
or C<postmaster@example.com>.  If not specified, the newsmaster e-mail
address will be used.

=item hiscachesize

The amount of memory (in kilobytes) to allocate for a cache of recently
used F<history> file entries.  Setting this to C<0> disables history caching.
History caching can greatly increase the number of articles per second
that your server is capable of processing.  A value of C<256> is a good
default choice.

=item logipaddr

If set to true (the default), INN will log the IP address (or hostname,
if the host is listed in F<incoming.conf> with a hostname) of the
remote host from which it received an article.  If set to false,
the trailing path identity in Path header fields is logged instead.  If you
are using B<controlchan> (see below) and need to process ihave/sendme
control messages (this is very, very unlikely, so if you don't know
what this means, don't worry about it), make sure you set this to false,
since B<controlchan> needs a site name, not an IP address.

=item organization

Set this to the name of your organization as you want it to appear in the
Organization header field of all articles posted locally and not already
containing that header field.  This will be overridden by the value of the
ORGANIZATION environment variable (if it exists).  If neither this
parameter nor the environment variable is set, no Organization header field
will be added to posts which lack one.

=item pathhost

This is the name of your news server as you wish it to appear in
the Path header field body of all postings which travel through your server
(this includes local posts and incoming posts that you forward out to
other sites).  If this parameter is unspecified, the fully qualified
domain name (FQDN) of the machine, as reported by the operating system,
will be used instead.  Please use the canonical FQDN of your server or
an alias unless you have a very good reason not to; a future version
of the news RFCs may require this.

=item rlimitnofile

If set to a non-negative value (the default is C<-1>), INN (both B<innd> and
B<innfeed>) will try to raise the maximum number of open file descriptors to
this value when it starts.  This may be needed if you have lots of
incoming and outgoing feeds.  Note that the maximum value for this setting
is very operating-system-dependent, and you may have to reconfigure your
system (possibly even recompile your kernel) to increase it.  See L<File
Descriptor Limits> for complete details.

=back

There are tons of other possible settings; you may want to read through
inn.conf(5) to get a feel for your options.  Don't worry if you don't
understand the purpose of most of them right now.  Some of the settings
are only needed for very obscure things, and with more experience running
your news server the rest will make more sense.

=head2 F<newsfeeds>

F<newsfeeds> determines how incoming articles are redistributed to your
peers and to other INN processes.  F<newsfeeds> is very versatile and
contains dozens of options; we will touch on just the basics here.
The man page contains more detailed information.

F<newsfeeds> is organized as a series of feed entries.  Each feed entry is
composed of four fields separated by colons.  Entries may span multiple
lines by using a backslash (C<\>) to indicate that the next line is a
continuation of the current line.  (Note that comments don't interact with
backslashes in the way you might expect.  A commented-out line ending in a
backslash will still be considered continued on the next line, possibly
resulting in more commented out than you intended or bizarre syntax
errors.  In general, it's best to avoid commenting out lines in the middle
of continuation lines.)

The first field in an entry is the name of the feed.  It must be unique,
and for feeds to other news servers it is usually set to the actual
hostname of the remote server (this makes things easier).  The name
can optionally be followed by a slash (C</>) and a comma-separated
exclude list.  If the feed name or any of the names in the exclude list
appear in the Path header field body of an article, then that article
will not be forwarded to the feed as it is assumed that it has passed
through that site once already.  The exclude list is useful when a news
server's hostname is not the same as what it puts in the Path header
field body of its articles, or when you don't want a feed to receive
articles from a certain source.

The second field specifies a set of desired newsgroups and distribution
lists, given as newsgroup-pattern/distribution-list.  The distribution
list is not described here; see newsfeeds(5) for information (it's not
used that frequently in practice).  The newsgroup pattern is a
wildmat-style pattern list as described above (supporting C<@>).

The third field is a comma-separated list of flags that determine both
the type of feed entry and sets certain parameters for the entry.  See
newsfeeds(5) for information on the flag settings; you can do a surprising
amount with them.  The three most common patterns, and the ones mainly
used for outgoing news feeds to other sites, are C<Tf,Wnm> (to write out a
batch file of articles to be sent, suitable for processing by B<nntpsend>
and B<innxmit>), C<Tm> (to send the article to a funnel feed, used with
B<innfeed>), and C<Tc,Wnm*> (to collect a funnel feed and send it via a
channel feed to an external program, used to send articles to B<innfeed>).

The fourth field is a multi-purpose parameter whose meaning depends on the
settings of the flags in the third field.  To get a feel for it using the
examples above, for file feeds (C<Tf>) it's the name of the file to write,
for funnel feeds (C<Tm>) it's the name of the feed entry to funnel into,
and for channel feeds (C<Tc>) it's the name of the program to run and feed
references to articles.

Now that you have a rough idea of the file layout, we'll begin to add the
actual feed entries.  First, we'll set up the special C<ME> entry.  This entry
is required and serves two purposes: the newsgroup pattern specified here
is prepended to the newsgroup list of all other feeds, and the
distribution pattern for this entry determines what distributions (from
the Distribution header field of incoming articles) are accepted from remote
sites by your server.  The example in the sample F<newsfeeds> file is a good
starting point.  If you are going to create a local hierarchy that should
not be distributed off of your system, it may be useful to exclude it from
the default subscription pattern, but default subscription patterns are
somewhat difficult to use right so you may want to just exclude it
specifically from every feed instead.

The C<ME> entry tends to confuse a lot of people, so this point is worth
repeating: the newsgroup patterns set the default subscription for
I<outgoing> feeds, and the distribution patterns set the acceptable
Distribution header field entries for I<incoming> articles.  This is confusing
enough that it may change in later versions of INN.

There are two basic ways to feed articles to remote sites.  The most
common for large sites and particularly for transit news servers is
innfeed(8), which sends articles to remote sites in real time (the article
goes out to all peers that are supposed to receive it immediately after
your server accepts it).  For smaller sites, particularly sites where the
only outgoing messages will be locally posted articles, it's more common
to batch outgoing articles and send them every ten minutes or so from cron
using nntpsend(8) and innxmit(8).  Batching gives you more control and
tends to be extremely stable and reliable, but it's much slower and can't
handle high volume very well.

Batching outgoing posts is easy to set up; for each peer, add an entry to
newsfeeds that looks like:

    remote.example.com/news.example.com\
        :<newsgroups>\
        :Tf,Wnm:

where <newsgroups> is the wildmat pattern for the newsgroups that
site wants.  In this example, the actual name of the remote site is
C<remote.example.com>, but it puts C<news.example.com> in the Path
header field body.  If the remote site puts its actual hostname in the
Path header field body, you won't need the C</news.example.com> part.

This entry will cause B<innd> to write out a file in I<pathspool>/outgoing
named F<remote.example.com> and containing the Message-ID and storage
token of each message to send to that site.  (The storage token is INN's
internal pointer to where an article is stored; to retrieve an article
given its storage token, use sm(8)).  B<innxmit> knows how to read files
of this format and send those articles to the remote site.  For
information on setting it up to run periodically, see L<Setting Up the
Cron Jobs> below.  You will also need to set up a config file for
B<nntpsend>; see the man page for nntpsend.ctl(5) for more information.

If instead you want to use B<innfeed> to send outgoing messages
(recommended for sites with more than a couple of peers), you need some
slightly more complex magic.  You still set up a separate entry for each
of your peers, but rather than writing out batch files, they all "funnel"
into a special B<innfeed> entry.  That special entry collects all of the
separate funnel feeds and sends the data through a special sort of feed to
an external program (B<innfeed> in this case); this is a "channel" feed.

First, the special channel feed entry for B<innfeed> that will collect all
the funnel feeds:

    innfeed!\
        :!*\
        :Tc,Wnm*:<pathbin in inn.conf>/innfeed -y

(adjust the path to innfeed(8) if you installed it elsewhere).  Note that
we don't feed this entry any articles directly (its newsgroup pattern is
C<!*>).  Note also that the name of this entry ends in an exclamation
point.  This is a standard convention for all special feeds; since the
delimiter for the Path header field body is C<!>, no site name containing that
character can ever match the name of a real site.

Next, set up entries for each remote site to which you will be feeding
articles.  All of these entries should be of the form:

    remote.example.com/news.example.com\
        :<newsgroups>\
        :Tm:innfeed!

specifying that they funnel into the C<innfeed!> feed.  As in the
previous example for batching, C<remote.example.com> is the actual name
of the remote peer, C<news.example.com> is what it puts in the Path
header field body (if different than the actual name of the server),
and <newsgroups> is the wildmat pattern of newsgroups to be sent.

As an alternative to NNTP, INN may also feed news out to an IMAP server,
by using imapfeed(8), which is almost identical to B<innfeed>.  The feed
entry for this is as follows:

    imapfeed!\
        :!*\
        :Tc,Wnm*,S16384:<pathbin in inn.conf>/imapfeed

And set up entries for each remote site like:

    remote.example.com/news.example.com\
        :<newsgroups>\
        :Tm:imapfeed!

For more information on B<imapfeed>, look at the
F<innfeed/imap_connection.c> file.  For more information on IMAP in general,
see S<RFC 3501>.

Finally, there is a special entry for controlchan(8), which processes
newsgroup control messages, that should always be in F<newsfeeds> unless
you never want to honor any control messages.  This entry should look
like:

    controlchan!\
        :!*,control,control.*,!control.cancel\
        :AC,Tc,Wnsm:<pathbin in inn.conf>/controlchan

(modified for the actual path to B<controlchan> if you put it somewhere
else).  See L<Processing Newsgroup Control Messages> for more details.

For those of you upgrading from earlier versions of INN, note that the
functionality of overchan(8) and B<crosspost> is now incorporated into INN
and neither of those programs is necessary.  Although B<crosspost> is no
longer shipped with INN (and will not be working if used), you can
still use B<overchan> if you make sure to set I<useoverchan> to true in
F<inn.conf> so that B<innd> doesn't write overview data itself, but be
careful: B<innd> may accept articles faster than B<overchan> can process the
data.

=head2 F<incoming.conf>

F<incoming.conf> file specifies which machines are permitted to connect to
your host and feed it articles.  Remote servers you peer with should be
listed here.  Connections from hosts not listed in this file will (if you
don't allow readers) be rejected or (if you allow readers) be handed off
to B<nnrpd> and checked against the access restrictions in F<readers.conf>.

Start with the sample F<incoming.conf> and, for each remote peer, add an
entry like:

    peer remote.example.com { }

This uses the default parameters for that feed and allows incoming
connections from a machine named C<remote.example.com>.  If that peer could
be connecting from several different machines, instead use an entry like:

     peer remote.example.com {
        hostname: "remote.example.com, news.example.com"
     }

This will allow either C<remote.example.com> or C<news.example.com> to feed
articles to you.  (In general, you should add new peer lines for each
separate remote site you peer with, and list multiple host names using the
I<hostname> key if one particular remote site uses multiple servers.)

You can restrict the newsgroups a remote site is allowed to send you,
using the same sort of pattern that newsfeeds(5) uses.  For example, if
you want to prevent C<example.com> hosts from sending you any articles in
the C<local.*> hierarchy (even if they're crossposted to other groups),
change the above to:

    peer remote.example.com {
        patterns: "*, @local.*"
        hostname: "remote.example.com, news.example.com"
    }

Note, however, that restricting what a remote side can send you will
I<not> reduce your incoming bandwidth usage.  The remote site will still
send you the entire article; INN will just reject it rather than saving it
to disk.  To reduce bandwidth, you have to contact your peers and ask them
not to send you the traffic you don't want.

There are various other things you can set, including the maximum number
of connections the remote host will be allowed.  See incoming.conf(5) for
all the details.

Note for those familiar with older versions of INN: this file replaces
the old F<hosts.nntp> configuration file.

=head2 F<cycbuff.conf>

F<cycbuff.conf> is only required if CNFS is used.  If you aren't using
CNFS, skip this section.

CNFS stores articles in logical objects called I<metacycbuffs>.  Each
metacycbuff is in turn composed of one or more physical buffers called
I<cycbuffs>.  As articles are written to the metacycbuff, each article is
written to the next cycbuff in the list in a round-robin fashion (unless
C<sequential> mode is specified, in which case each cycbuff is filled
before moving on to the next).  This is so that you can distribute the
individual cycbuffs across multiple physical disks and balance the load
between them.

There are two ways to create your cycbuffs:

=over 4

=item 1.

Use a block device directly.  This will probably give you the most speed
since it avoids the file system overhead of large files, but it requires
your OS support mmap(2) on a block device.  Solaris supports this, as do
late S<Linux 2.4> kernels.  FreeBSD does not at last report.  Also on many
PC-based Unixes it is difficult to create more than eight partitions,
which may limit your options.

=item 2.

Use a real file on a filesystem.  This will probably be a bit slower than
using a block device directly, but it should work on any Unix system.

=back

If you're having doubts, use S<option #2>; it's easier to set up and should
work regardless of your operating system.  More information about the
creation of these cycbuffs can be found in cycbuff.conf(5) man page.

Now you need to decide on the sizes of your cycbuffs and metacycbuffs.
You'll probably want to separate the heavy-traffic groups
(C<alt.binaries.*> and maybe a few other things like C<*.jobs*> and
C<news.lists.filters>) into their own metacycbuff so that they don't
overrun the server and push out articles on the more useful groups.  If
you have any local groups that you want to stay around for a while then
you should put them in their own metacycbuff as well, so that they don't
get pushed out by other traffic.  (Or you might store them in one of the
other storage methods, such as tradspool.)

For each metacycbuff, you now need to determine how many cycbuffs will
make up the metacycbuff, the size of those cycbuffs, and where they will
be stored.  Also, when laying out your cycbuffs, you will want to try to
arrange them across as many physical disks as possible (or use a striped
disk array and put them all on that).

In order to use any cycbuff larger than S<2 GB> on 32-bit platforms (and some
very rare 64-bit platforms that define a 32-bit I<off_t> type), you need to
build INN with the B<--enable-largefiles> option.  See L<Installing INN> for
more information and some caveats.

For each cycbuff you will be creating, add a line to F<cycbuff.conf> like
the following:

    cycbuff:NAME:/path/to/buffer:SIZE

NAME must be unique and must be at most seven characters long.  Something
simple like C<BUFF00>, C<BUFF01>, etc. is a decent choice, or you may want
to use something that includes the SCSI target and slice number of the
partition.  SIZE is the buffer size in kilobytes (if you're trying to stay
under S<2 GB>, keep your sizes below C<2097152>).

Now, you need to tell INN how to group your cycbuffs into metacycbuffs.
This is similar to creating cycbuff entries:

    metacycbuff:BUFFNAME:CYCBUF1,CYCBUF2,CYCBUF3

BUFFNAME is the name of the metacycbuff and must be unique and at most
eight characters long.  These should be a bit more meaningful than the
cycbuff names since they will be used in other config files as well.  Try
to name them after what will be stored in them; for example, if this
metacycbuff will hold alt.binaries postings, C<BINARIES> would be a good
choice.  The last part of the entry is a comma-separated list of all of
the cycbuffs that should be used to build this metacycbuff.  Each cycbuff
should only appear in one metacycbuff line, and all metacycbuff lines must
occur after all cycbuff lines in the file.

If you want INN to fill each cycbuff before moving on to the next one
rather than writing to them round-robin, add C<:SEQUENTIAL> to the end of
the metacycbuff line.  This may give noticeably better performance when
using multiple cycbuffs on the same spindle (such as partitions or slices
of a larger disk), but will probably give worse performance if your
cycbuffs are spread out across a lot of spindles.

By default, CNFS data is flushed to disk every 25 articles.  If you're
running a small server with a light article load, this could mean losing
quite a few articles in a crash.  You can change this interval by adding a
cycbuffupdate: line to your F<cycbuff.conf> file; see cycbuff.conf(5) for
more details.

Finally, you have to create the cycbuffs.  See L<Creating the Article
Spool (CNFS only)> for more information on how to do that.

=head2 F<storage.conf>

F<storage.conf> determines where incoming articles will be stored (what
storage method, and in the case of CNFS, what metacycbuff).  Each entry in
the file defines a storage class for articles.  The first matching storage
class is used to store the article; if no storage class matches, INN will
reject that article.  (This is almost never what you want, so make sure
this file ends in a catch-all entry that will match everything.)

A storage class definition looks like this:

    method <methodname> {
        newsgroups: <wildmat>
        class: <storage_class>
        size: <minsize>[,<maxsize>]
        expires: <mintime>[,<maxtime>]
        options: <options>
        exactmatch: <bool>
        filtered: <bool>
        path: <wildmat>
    }

<methodname> is the name of the storage method to use to store articles in
this class (C<cnfs>, C<timehash>, C<timecaf>, C<tradspool>, or the special
method C<trash> that accepts the article and throws it away).

The first parameter is a wildmat pattern in the same format used by the
newsfeeds(5) file, and determines what newsgroups are accepted by this
storage class.

The second parameter is a unique number identifying this storage class and
should be between 0 and 255.  It can be used to control article
expiration, and for timehash and timecaf will set the top-level directory
in which articles accepted by this storage class are stored.  The easiest
way to deal with this parameter is to just number all storage classes in
F<storage.conf> sequentially.  The assignment of a particular number to a
storage class is arbitrary but I<permanent> (since it is used in storage
tokens).

The third parameter can be used to accept only articles in a certain size
range into this storage class.  A <maxsize> of C<0> (or a missing
<maxsize>) means no upper limit (and of course a <minsize> of C<0> would
mean no lower limit, because all articles are more than zero bytes long).
If you don't want to limit the size of articles accepted by this storage
class, leave this parameter out entirely.

The fourth parameter you probably don't want to use lets you assign
storage classes based on the Expires header field of incoming articles.  The
exact details are in storage.conf(5).  It's very easy to use this
parameter incorrectly; leave it out entirely unless you've read the man
page and know what you're doing.

The fifth parameter is the options parameter.  Currently only CNFS uses
this field; it should contain the name of the metacycbuff used to store
articles in this storage class.

The sixth parameter is a boolean which is false by default: any non-zero
number of matching newsgroups is sufficient, provided no newsgroup
matches a poison wildmat.  If it is set to true, all the newsgroups in
the Newsgroups header field body of incoming articles will be examined
to see if they match the newsgroups wildmat pattern.

The seventh and eighth parameters are used to better filter spam articles and
store them in dedicated storage classes.  See the storage.conf(5) manual page
for more information.

If you're using CNFS exclusively, just create one storage class for each
metacycbuff that you have defined in F<cycbuff.conf> and set the
newsgroups pattern according to what newsgroups should be stored in that
buffer.

If you're using timehash or timecaf, the storage class IDs are used to
store articles in separate directory trees, which you can take advantage
of to put particular storage classes on different disks.  Also, currently
storage class is the only way to specify expiration time, so you will need
to divide up your newsgroups based on how long you want to retain articles
in those groups and create a storage class for each such collection of
newsgroups.  Make note of the storage class IDs you assign as they will be
needed when you edit F<expire.ctl> a bit later.

=head2 F<expire.ctl>

F<expire.ctl> sets the expiration policy for articles stored on the
server.  Be careful, since the default configuration will expire most
articles after 90 days; in most circumstances this deletion is
I<permanent>, so read this whole section carefully if you want to keep
local hierarchies forever.  (See archive(8) for a way to automate backups
of important articles.)

Only one entry is required for all storage classes; it looks like:

    /remember/:11

This entry says how long to keep the message-IDs for articles that have
already expired in the history file so that the server doesn't accept them
again.  Occasionally, fairly old articles will get regurgitated somewhere
and offered to you again, so even after you've expired articles from your
spool, you want to keep them around in your history file for a little
while to ensure you don't get duplicates.

INN will reject any articles more than a certain number of days old (the
I<artcutoff> parameter in F<inn.conf>, defaulting to C<10>); the number on
the C</remember/> line should be one more than that number in order to take
into account articles whose posting date is one day into the future.

CNFS makes no further use of F<expire.ctl>, since articles stored in CNFS
buffers expire automatically when the buffer runs out of free space (but
see the C<-N> option in expireover(8) if you really want to expire them
earlier).  For other storage methods, there are two different syntaxes of
this file, depending on I<groupbaseexpiry> in F<inn.conf>.  If it is set
to false, F<expire.ctl> takes entries of the form:

    <storage_class>:<keep>:<default>:<purge>

<storage_class> is the number assigned to a storage class in
F<storage.conf>.  <default> is the number of days to keep normal articles
in that storage class (decimal values are allowed).  For articles that
don't have an Expires header field, those are the only two values that matter.
For articles with an Expires header field, the other two values come into play;
the date given in the Expires header field of an article will be honored,
subject to the constraints set by <keep> and <purge>.  All articles in this
storage class will be kept for at least <keep> days, regardless of their
Expires header fields, and all articles in this storage class will be expired
after <purge> days, even if their Expires header fields specify a longer life.

All three of these fields can also contain the special keyword C<never>.
If <default> is C<never>, only articles with explicit Expires header fields
will ever be expired.  If <keep> is C<never>, articles with explicit
Expires header fields will be kept forever.  Setting <purge> to C<never> says
to honor Expires header fields even if they specify dates far into the future.
(Note that if <keep> is set to C<never>, all articles with Expires
header fields are kept forever and the value of <purge> is not used.)

If the value of I<groupbaseexpiry> is true, F<expire.ctl> takes entries of
the form:

    <wildmat>:<flag>:<keep>:<default>:<purge>

<wildmat> is a wildmat expression (C<!> and C<@> not permitted, and only a
single expression, not a comma-separated set of them).  Each expiration
line applies to groups matching the wildmat expression.  <flag> is C<M>
for moderated groups, C<U> for unmoderated groups, and C<A> for groups
with any moderation status; the line only matches groups with the
indicated expiration status.  All of the other fields have the same
meaning as above.

=head2 F<readers.conf>

Provided that I<noreader> is set to false in F<inn.conf>, any connection
from a host that doesn't match an entry in F<incoming.conf> (as well as
any connection from a host that does match such an entry, but has issued a
MODE READER command) will be handed off to nnrpd(8), the part of INN that
supports newsreading clients.  B<nnrpd> uses F<readers.conf> to determine
whether a given connection is allowed to read news, and if so what
newsgroups the client can read and post to.

There are a variety of fairly complicated things that one can do with
F<readers.conf>, things like run external authentication programs that can
query RADIUS servers.  See readers.conf(5) and the example file for all
the gory details.  Here's an example of probably the simplest reasonable
configuration, one that only allows clients in the C<example.com> domain to
read from the server and allows any host in that domain to read and post
to all groups:

    auth "example.com" {
        hosts: "example.com, *.example.com"
        default: "<user>"
    }

    access "all" {
        users: "*"
        newsgroups: "*"
    }

If you're running a server for one particular domain, want to allow all
hosts within that domain to read and post to any group on the server, and
want to deny access to anyone outside that domain, just use the above and
change C<example.com> in the above to your domain and you're all set.
Lots of examples of more complicated things are in the sample file.

=head1 Creating the Article Spool (CNFS only)

If you are using actual files as your CNFS buffers, you will need to
pre-create those files, ensuring they're the right size.  The easiest way
to do this is with B<dd>.  For each cycbuff in F<cycbuff.conf>, create the
buffer with the following commands (as the news user):

    dd if=/dev/zero of=/path/to/buffer bs=1k count=BUFFERSIZE
    chmod 664 /path/to/buffer

Substitute the correct path to the buffer and the size of the buffer as
specified in F<cycbuff.conf>.  This will create a zero-filled file of the
correct size; it may take a while, so be prepared to wait.

Here's a command that will print out the dd(1) commands that you should
run:

    awk -F: \
    '/^cy/ { printf "dd if=/dev/zero of=%s bs=1k count=%s\n", $3, $4 }' \
    <pathetc in inn.conf>/cycbuff.conf

If you are using block devices, you don't technically have to do anything
at all (since INN is capable of using the devices in F</dev>), but you
probably want to create special device files for those devices somewhere
for INN's private use.  It is more convenient to keep all of INN's stuff
together, but more importantly, the device files used by INN really should
be owned by the news user and group, and you may not want to do that with
the files in F</dev>.

To create the device files for INN, use mknod(1) with a type of C<b>,
getting the major and minor device numbers from the existing devices in
F</dev>.  There's a small shell script in cycbuff.conf(5) that may help
with this.  Make sure to create the device files in the location INN
expects them (specified in F<cycbuff.conf>).

Solaris users please note: on Solaris, do not use block devices that
include the first cylinder of the disk.  Solaris doesn't protect the
superblock from being overwritten by an application writing to block
devices and includes it in the first cylinder of the disk, so unless you
use a slice that starts with cylinder 1 instead of 0, INN will invalidate
the partition table when it tries to initialize the cycbuff and all
further accesses will fail until you repartition.

=head1 Creating the Database Files

At this point, you need to set up the news database directory
(in I<pathdb>).  This directory will hold the active(5) file (the list of
newsgroups you carry), the active.times(5) file (the creator and creation
time of newsgroups created since the server was initialized), the
newsgroups(5) file (descriptions for all the newsgroups you carry), and
the history(5) file (a record of every article the server currently has or
has seen in the past few days, used to decide whether to accept or refuse
new incoming messages).

Before starting to work on this, make sure you're logged on as the news
user, since all of these files need to be owned by that user.  This is a
good policy to always follow; if you are doing any maintenance work on
your news server, log on as the news user.  Don't do maintenance work as
root.  Also make sure that I<pathbin> is in the default path of the news
user (and while you're at it, make sure I<pathnews>/share/man is in the default
MANPATH) so that you can run INN maintenance commands without having to
type the full path.

If you already have a server set up (if you're upgrading, or setting up a
new server based on an existing server), copy F<active> and F<newsgroups>
from that server into I<pathdb>.  Otherwise, you'll need to figure out what
newsgroups you want to carry and create new active and newsgroups files
for them.  If you plan to carry a full feed, or something close to that,
go to L<https://downloads.isc.org/pub/usenet/CONFIG/> and download F<active>
and F<newsgroups> from there; that will start you off with reasonably complete
files.  If you plan to only carry a small set of groups, the default minimal
F<active> file installed by INN is a good place to start; you can create
additional groups after the server is running by using C<ctlinnd newgroup>.
(Another option is to use actsync(8) to synchronize your newsgroup list to
that of another server.)

C<control>, C<control.cancel> and C<junk> must exist as newsgroups in your
F<active> file for INN to start, and creating pseudogroups for the major
types of control messages is strongly encouraged for all servers that aren't
standalone.  If you don't want these groups to be visible to clients,
do I<not> delete them; simply hide them in F<readers.conf>.  C<to> must also
exist as a newsgroup if you have I<mergetogroups> set in F<inn.conf>.

Next, you need to create an empty F<history> database.  To do this, type:

    cd <pathdb in inn.conf>
    touch history
    makedbz -i -o

B<makedbz> will then create a database optimized for handling about 6,000,000
articles (or 500,000 if the slower tagged hash format is used).  If you
expect to inject more articles than that, use the B<-s> flag to specify the
number of entries to size the initial F<history> file for.  To pre-size it for
100,000,000 articles, type:

    makedbz -i -o -s 100000000

This initial size does not limit the number of articles the news server will
accept.  It will just get slower when that size is exceeded, until the next
run of B<news.daily> which will appropriately resize it.

(Note that if you install INN with C<make install>, you do not need to
run these commands: the installation takes care of creating the
F<history> database.)

When it finishes, make sure the file permissions are correct on all
the files you've just created:

    chmod 644 *

Your news database files are now ready to go.

=head1 Configuring syslog

While some logs are handled internally, INN also logs a wide variety of
information via syslog.  INN's nightly report programs know how to roll
and summarize those syslog log files, but when you first install INN you
need to set them up.

If your system understands the C<news> syslog facility, INN will use it;
otherwise, it will log to C<local1>.  Nearly every modern system has a
C<news> syslog facility so you can safely assume that yours does, but if
in doubt take a look at the output from running C<configure>.  You should
see a line that looks like:

    checking log level for news... LOG_NEWS

If that says LOG_LOCAL1 instead, change the below instructions to use
C<local1> instead of C<news>.

If you're using syslogd, edit F</etc/syslog.conf> on your system and add lines
that look like the following:

    news.crit           <pathlog in inn.conf>/news.crit
    news.err            <pathlog in inn.conf>/news.err
    news.notice         -<pathlog in inn.conf>/news.notice

(Change the path names as necessary in order to match I<pathlog>, which
defaults to F</usr/local/news/log>.)

The minus sign as the first character for the path to F<news.notice> instructs
syslogd not to synchronize the log file to disk every time there is a new log
entry (it otherwise degrades performance).  Depending on the syslog daemon you
are using, log synchronization may already be disabled by default (that is for
instance the case for rsyslogd or syslog-ng).

These lines I<must> be tab-delimited, so don't copy and paste from these
instructions.  Type it in by hand and make sure you use a tab, or you'll get
mysterious failures.  You'll also want to make sure that news log messages
don't fill your other log files (INN generates a lot of log traffic); so for
every entry in F</etc/syslog.conf> that starts with C<*>, add C<;news.none>
to the end of the first column.  For example, if you have a line like:

    *.err               /dev/console

change it to:

    *.err;news.none     /dev/console

(You can choose not to do this for the higher priority log messages, if
you want to make sure they go to your normal high-priority log files as
well as INN's.  Don't bother with anything lower priority than C<crit>,
though.  F<news.err> isn't interesting enough to want to see all the
time.)  Now, make sure that the news log files exist; syslog generally
won't create files automatically.  Enter the following commands:

    touch <pathlog in inn.conf>/news.crit
    touch <pathlog in inn.conf>/news.err
    touch <pathlog in inn.conf>/news.notice
    chown news <pathlog in inn.conf>/news.*
    chgrp news <pathlog in inn.conf>/news.*

(again adjusting the paths if necessary for your installation).  Finally,
send a HUP signal to syslogd to make it re-read its configuration file.

=head1 Setting Up the Cron Jobs

INN requires a special cron job to be set up on your system to run
news.daily(8) which performs daily server maintenance tasks such as
article expiration and the processing and rotation of the server logs.
Since it will slow the server down while it is running, it should be run
during periods of low server usage, such as in the middle of the night.
To run it at 3am, for example, add the following entry to the news user's
crontab file:

    0 3 * * * <pathbin in inn.conf>/news.daily expireover lowmark

or, if your system does not have per-user crontabs, put the following line
into your system crontab instead:

    0 3 * * * su news -s /bin/sh -c '<pathbin in inn.conf>/news.daily expireover lowmark'

If you're using any non-CNFS storage methods, add C<delayrm> to the above
option list for B<news.daily>.

The news user obviously must be able to run cron jobs.  On Solaris, this
means that it must have a valid F</etc/shadow> entry and must not be
locked (although it may be a non-login account).  There may be similar
restrictions with other operating systems.

If you use the batching method to send news, also set up a cron job to run
nntpsend(8) every ten minutes.  B<nntpsend> will run B<innxmit> for all
non-empty pending batch files to send pending news to your peers.  That
cron entry should look something like:

    0,10,20,30,40,50 * * * * <pathbin in inn.conf>/nntpsend

The pathnames and user ID used above are the installation defaults; change
them to match your installation if you used something other than the
defaults.

The parameters passed to B<news.daily> in the above example are the most
common (and usually the most efficient) ones to use.  More information on
what these parameters do can be found in the news.daily(8) man page.

You may also want to run B<rnews> each hour to process spooled messages
created while B<innd> is not available:

    12 * * * * <pathbin in inn.conf>/rnews -U

And it is also a good practice to refresh each day INN's cached IP addresses:

    30 2 * * * <pathbin in inn.conf>/ctlinnd -t 120 -s reload incoming.conf 'flush cache'

=head1 File Descriptor Limits

INN likes to use a lot of file descriptors, particularly if you have a lot
of peers.  Depending on what your system defaults are, you may need to
make sure the default limit is increased for INN (particularly for B<innd>
and B<innfeed>).  This is vital on Solaris, which defaults to an absurdly
low limit of 64 file descriptors per process up to Solaris 7, and 256 up to
Solaris 11.4 SRU 26 included.

One way to increase the number of file descriptors is to set I<rlimitnofile>
in F<inn.conf> to a higher value.  This will cause B<innd> and B<innfeed> to
try to increase the file descriptor limits when they start.  Note, however,
that INN won't be able to increase the limits above the hard limits set by
your operating system, usually either 256, 1024, or 65536 (see the value
of C<FD_SETSIZE> in the F<sys/select.h> system header).  Increasing the
limit beyond that value may require serious system configuration work.
(On some operating systems, it requires patching and recompiling the kernel.
On Solaris, it can be changed in F</etc/system>, but for 2.6 or earlier the
limit cannot be increased beyond 1024 without breaking select(2) and thereby
breaking all of INN.  For current versions of Linux, you may be able to change
the maximum with the C<ulimit -n> command.)

256 file descriptors will probably be enough for all but the largest
sites.  There is no harm in setting the limits higher than you actually
need (provided they're set to something lower than or equal to your system
hard limit).  C<256> or C<1024> are therefore reasonable values to try.

If you're installing INN on a Solaris system, particularly if you're
installing it on a dedicated news server machine, it may be easier to just
increase the default file descriptor limit across the board for all
processes.  You can do that by putting the line:

    set rlim_fd_cur = 256

in F</etc/system> and rebooting.  You can increase it all the way to
C<1024> (and may need to if you have a particularly large site), but that
can cause RPC and some stdio applications to break.  It therefore probably
isn't a good idea on a machine that isn't dedicated to INN.

Note for expert users building INN from sources: if you need using more than
C<FD_SETSIZE> file descriptors, you can increase this value for instance to
C<4096> by building INN with the C<-DLARGE_FD_SETSIZE=4096> option given to
the compiler.

=head1 Starting and Stopping the System

INN is started via the shell script B<rc.news>.  This must be run as the
news user and not as root.  To start INN on system boot, you therefore
want to put something like:

    su news -s /bin/sh -c <pathbin in inn.conf>/rc.news

in the system boot scripts.  If B<innd> is stopped or killed, you can restart
it by running B<rc.news> by hand as the news user.

The B<rc.news> script may also be used to shut down INN, with the C<stop>
option:

    su news -s /bin/sh -c '<pathbin in inn.conf>/rc.news stop'

In the F<contrib> directory of this source tree, two sample init scripts
are provided: one for people using System V-style F<init.d> directories,
and another for people using systemd-style init scripts.

If you wish to use TLS/SSL for your readers, you need to start a second
B<nnrpd> to listen to these connections to NNTPS port 563 and put something
like that in your init scripts:

    su news -s /bin/sh -c '<pathbin in inn.conf>/nnrpd -D -c <pathetc in inn.conf>/readers-ssl.conf -p 563 -S'

where F<readers-ssl.conf> is the file which indicates whether a given
connection is allowed to read and post news (you can also use the
previously created F<readers.conf> file to handle TLS/SSL connections).
Note that a news client which supports the STARTTLS command can also
use the conventional NNTP port 119 to dynamically upgrade from unencrypted
to TLS-protected traffic during an NNTP session.  However, this practice
is discouraged in favour of using the separate port 563.  See nnrpd(8)
for more information about TLS support.  You may also want to use the
lowercase B<-s> flag with a long string as its argument to see more
information about incoming connections in ps(1) output.

In the shutdown section of the init script, you can put:

    start-stop-daemon --stop --name nnrpd --quiet --oknodo

or if you do not have a B<start-stop-daemon> utility:

    su news -s /bin/sh -c 'killall nnrpd'

And also, an additional cleaning if a separate TLS B<nnrpd> daemon was
started as explained above:

    # Clean the PID file of the nnrpd daemon we started on port 563.
    #rm -f <pathrun>/nnrpd-563.pid

=head1 Processing Newsgroup Control Messages

Control messages are specially-formatted messages that tell news servers
to take various actions.  Cancels (commands to delete messages) are
handled internally by INN, and all other control messages are processed by
B<controlchan>, a channel feed program which should be run out of
F<newsfeeds> if you want your news server to process any control messages;
see L<Configuring INN> for specific instructions.  Note that I<pgpverify>
must also be set to true in F<inn.conf>.

The actions of B<controlchan> are determined by F<control.ctl>, which lists
who can perform what actions.  The primary control messages to be
concerned with are C<newgroup> (to create a newsgroup), C<rmgroup> (to
remove a newsgroup), and C<checkgroups> (to compare the list of groups
carried in a hierarchy to a canonical list).  INN comes with a
F<control.ctl> file that processes control messages in most major public
hierarchies; if you don't want to act on all those control messages, you
should remove from that file all entries for hierarchies you don't want to
carry.  The last version of that file is available from
L<https://downloads.isc.org/pub/usenet/CONFIG/control.ctl>.

You can tell INN to just authenticate control messages based on the From
header field of the message, but this is obviously perilous and control
messages are widely forged.  Many hierarchies sign all of their control
messages with PGP, allowing news servers to verify their authenticity, and
checking those signatures for hierarchies that use them is highly recommended.
B<controlchan> knows how to do this (using B<pgpverify>) without additional
configuration, but you do have to provide it with a public key ring containing
the public keys of all of the hierarchy administrators whose control messages
you want to check.

INN expects the public key ring to either be in the default location for a
PGP public key ring for the news user (generally I<pathnews>/.gnupg for GnuPG
and I<pathnews>/.pgp for old PGP implementations), or in I<pathetc>/pgp
(F</usr/local/news/etc/pgp> by default).  The latter is the recommended path.
To add a key to that key ring, use:

    gpg --import --homedir=<pathetc in inn.conf>/pgp <file>

where <file> is a file containing the hierarchy key.  Change the homedir
setting to point to I<pathetc>/pgp if you have INN installed in a non-default
location.  You may need to add the flag C<--allow-weak-digest-algos>.

If you're using the old-style PGP program, an equivalent command is:

    env PGPPATH=<pathetc in inn.conf>/pgp pgp <file>

You can safely answer C<no> to questions about whether you want to sign,
trust, or certify keys.  And you may afterwards do:

    cp <pathetc in inn.conf>/pgp/pubring.gpg <pathetc in inn.conf>/pgp/trustedkeys.gpg

The URLs from which you can get hierarchy keys are noted in comments in
F<control.ctl>.  L<https://downloads.isc.org/pub/pgpcontrol/PGPKEYS> tries to
collect the major hierarchy keys and you can just import the whole file.

If you want to make sure that the keys have been correctly imported, use:

    gpg --list-keys

If you are using GnuPG, please note that the first user ID on the key will
be the one that's used by INN for verification and must match the key
listed in F<control.ctl>.  If a hierarchy key has multiple user IDs, you
may have to remove all the user IDs except the one that matches the
F<control.ctl> entry using C<gpg --edit-key> and the C<delkey> command.

=cut
