Installing Nagios on Ubuntu or Debian without Postfix
If you install the default ‘nagios3’ package from the repositories on a Debian-based distribution, you wind up with a full copy of postfix installed. This is fine if you’re simply trying to get the thing to work, but as part of a wider infrastructure you most likely do not want a full-fledged MTA arbitrarily popping up on your Nagios host - an MTA that you have to administer, monitor (!), patch and most importantly secure.
The dependency chain that causes postfix to be installed is:
nagios3 → nagios3-core → nagios3-common → bsd-mailx → default-mta | mail-transport-agent.
Why the package maintainers made bsd-mailx dependent on a fully-fledged MTA I will never know. Perhaps they wanted to ensure things “just worked”? It still seems a bit heavy handed to me, especially when one can configure .mailrc to point to a mailhost and be done with it.
In order to install nagios3 from the repositories and satisfy those dependencies without pulling in postfix you should install the ‘lsb-invalid-mta’ package, which provides ‘mail-transport-agent’ and satisfies the dependency chain above, in place of postfix. The package provides a sendmail binary that does nothing but return a non-zero return code, so you’ll never accidentally send mail from a local system, but you will have to configure your system to take advantage of a suitable MTA host.
Here is some puppet to install nagios3 without postfix:
# /etc/puppet/modules/nagios-server/manifests/init.pp
#
# Class: nagios-server
#
# This class maintains a Nagios server.
#
# Parameters:
# None
#
# Requires:
# nagios-server::install
#
class nagios-server {
include nagios-server::install
service { 'apache2':
ensure => running,
enable => true,
require => Class['nagios-server::install'],
}
service { 'nagios3':
ensure => running,
enable => true,
require => Class['nagios-server::install'],
}
}
# /etc/puppet/modules/nagios-server/manifests/install.pp
#
# Class: nagios-server::install
#
# This class will install a Nagios server from the repo packages
#
# Parameters:
# None
#
# Requires:
# Nothing
#
class nagios-server::install {
# Prevent nagios3-common->mailx dependency from pulling in an MTA.
package { 'lsb-invalid-mta':
ensure => present,
}
$packages = ['nagios3', 'nagios-images', 'nagios-plugins', 'nagios3-doc',]
package { $packages:
ensure => present,
require => Package['lsb-invalid-mta'],
}
}
mailq output is a bastard to parse
I’ve recently had cause to try to parse the output of the `mailq’ command, by dint of it being the common queue output format between sendmail and postfix, and a desire to interoperate with them both. It is a complete bastard!
Here is some to save you running the command:
-Queue ID- --Size-- ----Arrival Time---- -Sender/Recipient-------
637F5CFF9C* 1497 Sat Dec 18 21:40:34 sender@domain.com
recepient@domain.com
4C4D5A32E6* 1481 Sat Dec 18 21:39:45 sender@domain.com
recepient@domain.com
EBBE4D5C93* 1481 Sat Dec 18 21:51:52 sender@domain.com
recepient@domain.com
...
36BAAA3C9E 1471 Sat Dec 18 18:19:16 sender@domain.com
(delivery temporarily suspended: host mailxx-xx.xxxx.aol.com[xxxxxx] refused to talk to me: 421 4.7.1 : (DYN:T1) http://postmaster.info.aol.com/errors/421dynt1.html)
recepient@domain.com
350FE10A66C 1438 Wed Dec 15 01:33:38 sender@domain.com
(lost connection with mx-c1.xxxx.net[61.20.xx.xx] while receiving the initial server greeting)
recepient@domain.com
...
-- 359752 Kbytes in 174586 Requests.
This is awkward to parse because:
-
The queue to which a mail identified by a given queue-id belongs to is denoted by a single character appended to the queue-id. Except if you’re in the deferred queue, in which case there is no special character - an atribute by absence, if you like.
The ‘arrival time’ doesn’t include a year. We either have to assume that the year is the current year and open ourselves up to year-end bugs, or we have to compensate for edge cases with time and boundary checks.
Records span multiple lines, and how many depends on the queue that the mail is in. This leads to nasty “if the last character of the first field of the following line was not an asterix of exclamation mark read two more line, otherwise read three more lines. And that field that was on the second line before is now on the third” logic in parsers.
Whilst parsable with somewhat icky code, it just seems designed not to be parsed or piped: “records” spanning multiple lines is a definite no-no when you’re ‘xargs’-ing or piping through awk or anything else remotely UNIXy. I wonder what was going through the minds of the original authors of the `sendmail -bp` option, that `mailq` ultimately emulates?
I’m currently working on some Ruby code to parse the output of `mailq` and to populate an ActiveRecord model with the appropriate attributes. Wrapped up as a gem, it would be a convenient way to provide Rails applications access to the mail queue.
Running Multiple Sendmail Instances on a Debian-like System (Ubuntu 10.4 LTS Server)
When installing Sendmail from the repository packages it is pretty much assumed that you will only be running one instance on a given server. If, like I had to recently, you want to maintain a number of sendmail configurations and process, but want to fit into the Debian rc script scheme, it takes a bit of work.
I’ve created a patch that can be run against the stock /etc/init.d/sendmail script to produce scripts like /etc/init.d/sendmail.mail1 to manage named instances of sendmail. There are a few things you need to know:
- The patched scripts expects to find the configuration for the named instances in /etc/mail/servers/instancename
- The script expects to be called sendmail.instancename
- Along with changing the INSTANCE= variable at the top of the script, be sure to change the comments so that the update-rc.d style daemon registration works if required. A global search and replace is probably your best bet.
- /etc/default/sendmail can be copied to /etc/default/sendmail.instancename and populated, if present or required.
- PID and lock files end up in /var/run/sendmail.instancename. You will need to edit your named instances sendmail.mc/cf to have the PID files created in the correct location. Spools end up in /var/spool/mqueue.instancename
The final piece of configuration required to make this mechanism work is to copy /etc/mail/sendmail.conf to /etc/mail/servers/instancename/sendmail.conf and to modify the MISC_PARMS variable:
MISC_PARMS="-C/etc/mail/servers/INSTANCENAME/sendmail.cf"
Substituting INSTANCENAME as required. This ensures that the correct configuration file is read from.
If you are binding your sendmail instances to different interfaces you might like to also modify the DAEMON_NETIF variable to have the instance watch the correct interface for state changes, if you have DAEMON_NETMODE set to something other than the default “Static”.
Apart from that the patched script does everything that you would expect and the various logged messages reflect the instance name. Managing individual instances then becomes a matter of:
$ sudo service sendmail.mail3 stop $ sudo service sendmail.mail2 start
Easy as that.
Using virtusertable for Sendmail on Solaris 10 to create a mail sink
If you want your Sendmail instance to accept mails for a nonsense domain and then discard them completely, here is one way of doing it. Another is to use milters. This is documented to death for Linux and the *BSDs, so I thought I’d write down the steps for getting it working under Solaris 10.
This guide assumes that the main *.cf files have always been built through m4, and that the .mc files in /etc/mail/cf/cf are current.
All steps to be performed as root.
Make a backup of your mail configuration, just in case
cd /etc cp -pr mail mail.bak
Edit the sendmail.mc file to add the virtusertable feature definition.
cd /etc/mail/cf/cf vi sendmail.mc ... DOMAIN(`solaris-generic')dnl FEATURE(`virtusertable')dnl define(`confFALLBACK_SMARTHOST', `mailhost$?m.$m$.')dnl ...
Build your new sendmail.cf, setup some configuration files, restart sendmail and ensure the SMF-managed service has been been restarted and is marked “online”.
/usr/ccs/bin/make cd /etc/mail cp sendmail.cf sendmail.cf.bak cp /etc/mail/cf/cf/sendmail.cf . echo "nowhere.com" >> local-host-names echo "@nowhere.com: nobody" >> virtusertable makemap hash /etc/mail/virtusertable < virtusertable svcadm restart sendmail svcs -a | grep -i sendmail
Test that it really works as we think it should. You should also try mailing a “real” deliverable domain if you intend this Sendmail instance to do that for normal mail. (You can paste this whole box straight onto the command line and it’ll work)
mail bob@nowhere.com TEST . mail mary@nowhere.com TEST .
Finally, we check the logs to ensure everything is working. The important parts to look for are ‘to=/dev/null’ and ‘mailer=file’. Check your spools, too.
grep -i nowhere.com /var/log/syslog Jun 11 14:05:59 dev sendmail[4472]: [ID 801593 mail.info] o5BD5xto004472: to=bob@nowhere.com, ctladdr=sam (60005/10), delay=00:00:00, xdelay=00:00:00, mailer=relay, pri=30103, relay=[127.0.0.1] [127.0.0.1], dsn=2.0.0, stat=Sent (o5BD5xsQ004474 Message accepted for delivery) Jun 11 14:05:59 dev sendmail[4476]: [ID 801593 mail.info] o5BD5xsQ004474: to=/dev/null, ctladdr=(1/0), delay=00:00:00, xdelay=00:00:00, mailer=*file*, pri=30551, dsn=2.0.0, stat=Sent Jun 11 14:06:18 dev sendmail[4489]: [ID 801593 mail.info] o5BD6Iem004489: to=mary@nowhere.com, ctladdr=sam (60005/10), delay=00:00:00, xdelay=00:00:00, mailer=relay, pri=30103, relay=[127.0.0.1] [127.0.0.1], dsn=2.0.0, stat=Sent (o5BD6Iru004490 Message accepted for delivery) Jun 11 14:06:18 dev sendmail[4491]: [ID 801593 mail.info] o5BD6Iru004490: to=/dev/null, ctladdr= (1/0), delay=00:00:00, xdelay=00:00:00, mailer=*file*, pri=30553, dsn=2.0.0, stat=Sent

