Systems


27
Jun 12

Recipe: Running qmail-send under systemd

Call me old-fashioned, crazy or whatever, but I do use qmail (only the qmail-send service) as local MTA and for relaying outgoing mail to a smarthost. Over the years I tried several other options like msmtp, nbsmtp, or nullmailer, which would allow to not run a full-fledged MTA, but they either:

  • Do not queue up messages. (Queuing is interesting for sometimes-offline boxes, like a laptop: you still “send” messages normally, and once there is again a working Internet connection , they are delivered all in a row.)
  • Do not provide a sendmail-compatible binary. (Tools like git send-email expect this to be available, so one absolutely wants this.)
  • Are too dumb to provide some sort of reasonable “local” delivery to a remote mail address. (Certain tools like cron may send messages to local accounts, so I want the mailer to be able to forward those local messages to a remote address.)

Then at some point I though “hey, but qmail is no more than a number of small tools glued together which do one task well… why not running just qmail-send for deliveries?” and the idea indeed works like a charm. Traditionally I have been running it with dmon for running it, but lately I have been using systemd in my laptop, and decided to run it directly using it instead of letting it run the SysV init script. It turned out to be reasonably easy.

Those are the contents for the /etc/systemd/system/qmail-send.service unit file:

[Unit]
Description=qmail delivery daemon
After=syslog.target
After=local-fs.target
ConditionFileIsExecutable=/var/qmail/bin/qmail-start

[Install]
WantedBy=multi-user.target

[Service]
Type=simple
Restart=always
StandardOutput=syslog
StandardError=inherit
SyslogFacility=mail
SyslogIdentifier=qmail-send
Environment=PATH=/var/qmail/bin:/usr/bin:/bin:/usr/sbin:/sbin
ExecStart=/var/qmail/bin/qmail-start ~/.maildir/
ExecReload=/var/qmail/bin/qmail-tcpok ; /bin/kill -ALRM ${MAINPID}

Some notes:

  • This assumes that you have a LWQ-style qmail installation, hence the paths pointing to /var/qmail.
  • The Environment= line defines the PATH variable so it contains /var/qmail/bin. This is needed for qmail to work properly.
  • The ExecReload= clears the timeout tables with qmail-tcpok and then sends SIGALRM to the main process. This makes it try to deliver the queued messages. I have a handy script that runs systemctl reload qmail-send.service when NetworkManager connects to Internet.
  • Like all DJB-ware, qmail logs using the stdio streams, so we make them go to both the systemd journal and syslog (I want to be able to tail -f the log file for the mail facility).

Once this unit file is in place, use the following to reload the unit files, and then start and enable the service:

systemctl daemon-reload
systemctl start qmail-send.service
systemctl enable qmail-send.service

Voilà! :-)


27
Feb 11

Recipe: Preventing package installation with APT

This is a quick Debian recipe, mainly as a note to myself, but that can be useful to people out there: what if I wanted instruct APT to never install a particular package? This may lead to wonder whether there is a really sane use case for that, and I can think at least about two:

  • For server setups, to prevent certain packages like the X11 window system to be installed.
  • To avoid dependencies on deprecated packages.

The later is my use-case for today: HAL is nowadays deprecated, being DeviceKit and udev the new shiny stuff that everybody should use in a modern GNU/Linux desktop. My laptop is running Sid, so ideally there shouldn’t be HAL packages in it, should they?

In short, the idea is to pin packages with a lower-than-zero priority. If packages were already installed, they will not be upgraded by APT. For packages that are not installed, this will instruct APT to avoid them as much as possible. This is how my pinning for HAL looks like:

  % cat /etc/apt/preferences.d/nohal
  Package: hal
  Pin: version *
  Pin-Priority: -100

  Package: hal-info
  Pin: version *
  Pin-Priority: -100

  Package: libhal1
  Pin: version *
  Pin-Priority: -100

…and that’s it :-D

Anyway, I still prefer package masking or setting USE="-hal" in Gentoo, it’s cleaner and meaner.


4
Oct 10

DMon status report: evolution to 0.3.7

When I first wrote about DMon, I pointed out that version 0.3 could be already installed from our APT repository, which hosts flavours for i386, amd64 and armel. Five weeks have passed and I feel like I have to write a status update now that 0.3.7 is out. It is not a big version number change because DMon behaves essentially as in 0.3, but a number of new features were added and bugs fixed.

Let’s see which juicy bits are available on top of the features it already had:

  • Additional groups can now be specified using the -u and -U options. As a side effect of their extended syntax, options -g and -G were removed as they are no longer needed.
  • Setting of resource usage limits is now supported with the -r. This uses setrlimit(2) under the hood.
  • DMon can now wait for some time before re-running commands by specifying time intervals with the -i option. Think about it as a poor man’s recurrent job scheduler.
  • Environment variables can now be manipulated (including deletion) by means of the -E option.
  • All commands (dmon, dlog, dslog) can now be built as a single multicall binary. This saves disk space and some kilobytes of memory, which is interestinhg for embedded environments.
  • Tools now honor the DMON_OPTIONS, DLOG_OPTIONS and DSLOG_OPTIONS; environment variables. When defined, they will be interpreted as additional command line arguments. Actual command line arguments take precedence, so values given in environment variablels can still be overriden.
  • A small libnofork.so library is included, which overrides the system-provided fork(2) and daemon(3) functions in such a way that the library can be preloaded (dmon -E LD_PRELOAD=libnofork.so ....) to make programs not to fork. Very useful for applications which create new daemon processes inconditionally so they can be properly monitored. This is tested only under GNU/Linux with glibc at the moment, use with care!

Apart from new features, a couple of bugs related to error handling were fixed, for better reliability.

Last but not least, I would like to thank my friend Andrés J. Díaz who is using DMon and provided feedback and ideas for some of those new features.

Happy monitoring :D


15
Sep 10

SSH + Screen, a shortcut

Most of the time while administering servers, I open an SSH connection and then a Screen session. Lately I have been using with SSH the -t option to force it to create a PTY, which is needed by some programs which do not work when their output and/or input is not a terminal, and just realized that I can just do:

  % ssh user@host -t screen

I even have a small script named shsc which does that for me:

#! /bin/bash

userhost=''
opts=( )

for opt in "$@" ; do
	if [[ ${opt} = *@* ]] ; then
		userhost=${opt}
	else
		opts=( "${opts[@]}" "${opt}" )
	fi
done

if [[ ${#userhost} -eq 0 ]] ; then
	echo "$(basename "$0"): No '[user]@host' specified"
	exit 1
fi >&2

exec ssh "${userhost#@}" -t screen "${opts[@]}"

The idea is that parameters other than the user and hostname to connect to are passed to Screen, so one can do things like checking where there are alive Screen sessions, and reattach to them:

  % shsc @ara-ara.org -ls
  There is a screen on:
	9573.scr	(09/15/2010 06:49:42 PM)	(Detached)
  1 Socket in /var/run/screen/S-aperez.

  Connection to ara-ara.org closed.
  % shsc @ara-ara.org -DRR

Changing topics, I have switched to the Z Shell some weeks ago, so expect a post about why I prefer it over the venerable GNU Bash ;-)


27
Aug 10

DMon: Process monitoring with style

Have you ever wanted to run a lengthy process making sure that it will be restarted on failure? Did you need at some point to daemonize a “normal” program? Well, maybe you already knew about daemontools, runit, freedt, Supervisor, upstart or —recently— systemd. They already do a good job respawning processes, but there are three single things that neither of them are capable of doing:

  • Running a single command and exiting when it exits successfully.
  • Running commands interactively, without daemonizing nor detaching from the terminal.
  • Temporarily suspending execution when the system load goes over a configurable value, and resuming execution automatically as soon as the load drops below another configurable value.

If you ever needed at least one of those features, then DMon is probably what you want. If unsure, read the examples below — you might find some inspiration for use-cases!

The Story

Years ago I discovered Daniel J. Bernstein‘s qmail, and with it came the rest of the “DJB-ware” software stack: djbdns, ucspi, daemontools… and their philosophy!)

Some weeks ago I coded vfand, a small “non-daemon” to control the speed of the fan in my Vaio laptop because it was overheating. I am lazy, so I deliberately left out daemonization and suggested launching it from init(8) — because I knew that DJB’s tools leave daemonization and logging to other tools which just do one thing well.

Days back I had to make a huge data copy in a mission-critical mail server, and used the mighty rsync tool because I wanted the copy to be interruptible so I could stop it when the system load was getting high and then resuming the data copy. I did that manually (Ctrl-Z, wait, fg, repeat), and I do not like performing automatable tasks. Fortunately I seldom do this kind of tasks.

Do you recognize the pattern? DMon is a subproduct of what I have been doing lately, applying the knowledge about daemontools I already had.

How does it work? — Modus operandi

In short it works àla daemontools without control sockets and without using script files for launching processes. All options are specified in the command line, as long as the commands to be run. Like this:

dmon [options] command [command-options]
     [-- log-command [log-command-options]

As an example, consider the following command line:

dmon cron -f -- dlog /var/log/cron.log

This is what DMon wil do:

  1. Daemonize itself.
  2. Create a pipe(2), which will be used to connect the output of the given command to the input of the log-command.
  3. Spawn both the command and the log-command.
  4. Silently wait. If some child is terminated, it will be respawned.

That is pretty close to what the supervise program included in daemontools does, so it have already all the advantages of it, plus without needing stuff in the file system. Passing options to dmon will trigger some of the extra features provided:

  • Passing -n makes it run in the foreground. This is very useful in conjunction with -1: with tha latter the processes will be only respawned if their exit status is non-zero.
  • If you want to log messages from standard error, use -e and both standard output and standard error will be piped to the logging command.
  • For faulty programs which could get somewhat “locked” and sometimes take too much time to run, you may pass a maximum running time with -t. When the timeout is reached the program will be forcibly killed and then started again.
  • Finally, for pausing the program over a given value of system load, use -L. After pausing execution (by means of the SIGSTOP signal), it will be resumed when the system load falls below the value given with -l (by sending SIGCONT). The signals used are the standard ones used for this duty e.g. by the shell, so almost every well-behaved program will work without modifications.

The DMon package already includes a couple tools ready to be used as logging command: dlog will append lines to a log file, optionally adding a timestamp to them, and dsyslog will send lines to the system log. You can use any logging tool which works with daemontools, like multilog (part of it) or my own rotlog ;-)

DMon use-cases & Examples

Running rsync in a terminal (without detaching), pausing the copy when the system load is above 4.0, retrying until the copy succeeds:

dmon -n -1 -L 4.0 rsync -az /path/to/srcdir /path/to/destdir

Launching vfand as a daemon, logging errors to the local syslog, and saving the PID of the process (the second line terminates dmon, vfand and dsyslog in a single shot):

dmon -e -p /var/run/vfand.pid vfand -- dsyslog vfand
kill $(cat /var/run/vfand.pid)

Starting the MediaTomb UPnP server as a user mediatomb (i.e. at bootup), saving auto-rotated logs with rotlog running as user log:

dmon -e -u mediatomb -g mediatomb -U log -G log
     mediatomb --interface eth0 --home /mnt/mediafiles
     -- rotlog -c /var/log/mediatomb/

Final Words

It was fun for me to hack in DMon because C is a language I learnt to love, and using it from time to time is nice to not lose contact with it. Also, I had a clear idea of what I wanted to do for solving a particular problem, which is great for keeping focus.

Albeit DMon is already in its third release (namely version 0.3) and I have been using it since its first inceptions, it may contain bugs as any other piece of software. Do not hesitate to drop me a line with your complaints and suggestions — or even better: get yourself a clone of the Git repository and use its send-email awesomeness!

Have a lot of fun… :-D


26
Jul 10

Escaping manual package installation woes: Enter our APT repository

Lately I have been packaging stuff as ready-to-use .deb packages. But providing just a bunch of links to them and forcing people to use arcane tools like dpkg -i to install software is not very user-friendly… and it is definitely not sysadmin-friendly either. Due to those reasons, we decided to roll our own APT repository. This means that from now on I will stop posting links here, and that you get a convenient way of installing packages em automatically getting updates.

For the moment there is not a lot of packages are in the APT repository, because some of the packages’ control files were not in a very good shape and I need to tweak them a bit before reprepro will happily agree to add them in the repository. The good news is that I am adding some ARM EABI packages ready to use with the GuruPlug.

Instructions for using the repository can be found at apt.igalia.com, as well as the repository PGP key (E438FFC5), which is signed with my own (E4C9123B).

Have a lot of fun… ;-)


31
May 10

Do a bus-trip with OpenAMQ

So you want to do some messaging using AMQP, you have a Debian system (or based on it), and you want to try out OpenAMQ… it’s your lucky day!

I have just built some .deb packages for the OpenAMQ, using some packaging support files I found, plus some patches I throwed in to bring it up to date. Just pick the package of version 1.2c4 for the distribution of your choice:

As always, I am just providing those packages here for your convenience. They work fine for me, but you are on your own using them.

By the way, you may also want to try other options like RabbitMQ (package rabbitmq and/or 0MQ (package zeromq-bin, I did not have luck with this one, though).

And now it is time to start using the just installed message queueing service :-D


2
Nov 09

Running older (pre-etch) Debian releases

This post is quick public information service for everyone using, or having to deal with old Debian releases. This includes all releases prior to Etch: Woody, Sarge, Potato…

You have probably noticed that you cannot longer use APT to install packages in your system.
The package repositories have been moved over to archive.debian.org, so you will need to change your /etc/apt/sources.list accordingly. For Sarge, you would use:

deb http://archive.debian.org/debian sarge main contrib non-free
deb http://archive.debian.org/debian-security sarge/updates main contrib non-free

You may even use archived repository of backports.org of Sarge, adding a line like this:

deb http://archive.debian.org/backports.org sarge-backports main contrib non-free

This way one can inject some fresh air into an existing Debian setup if making a full system upgrading is not an option for you.

Have a lot of fun…


19
Oct 09

Factor out your Apache-fu with mod_macro

For nearly all HTTP-serving related work, our software of choice is the Apache web server. Lately, we have been moving some old setups which were still running Apache 1.3 to the latest version in the 2.x series. This may be a lot of work when the number of virtual hosts you are serving is far from low, or if you have some lengthy, repetitive configuration blocks which must be modified everytime you want introduce some change. One may be tempted to auto-generate configuration snippets from something else using some quick Bash/Perl/Python/Whatever script, but there is a more elegant solution: meet mod_macro.

As the name suggests, it is an Apache 2.x module which allows for defining snippets with customizable optional parameters. Take this real-world example from /etc/apache2/mods-available/macro.conf:

  AuthType basic
  AuthBasicProvider ldap
  AuthLDAPUrl ldap://ldap.local/dc=yoursite,dc=com?uid
  AuthLDAPGroupAttribute uniqueMember
  AuthLDAPGroupAttributeIsDN On
  Require ldap-group cn=$group,ou=Group,dc=yoursite,dc=com

This is a common setup in most of our services, so now everytime one wants to add autentication against the LDAP server, it is only a matter of adding an Use clause in the proper place:

  # Virtual host configuration cruft skipped from example!

    Use AuthLDAPSetup wwwusers

Ta-da! This is 5 lines shorter, and less error-prone. Also, if some day some extra configuration is needed to authenticate using LDAP, it is enough to change the macro definition, and changes will be automatically propagated to all places where it is used.

Wrapping up, you may consider installing mod_macro in your Apache installs for the following reasons:

  • Greatly simplifies repeated code snippets in configuration files.
  • It is integrated with the web server: no external tools are needed.
  • Is especially useful to make changes to big sites in a single shot.
  • Does not add overhead to request processing, only to initial configuration file parsing at server startup.
  • It is simple enough to learn and use in a couple of minutes.

:-)


25
Sep 09

Two months after…

Two months have passed after my last post, and things here have been quieter than usual in this blog, but the world kept moving in the meanwhile so there are some things to tell, and some other that have already been told. Probably the most exciting thing for me and my work mates was the announcement of the shiny Nokia N900. I have resisted the temptation then, because a lot of things have already been said about it. We systems administrators are usually in the shadows, but even so it is a delight working as backing support for people who does big things.

There were a couple of releases this week what are a great example of why Igalia reached its eighth year, and we are still rockin’ in the free world:

  • Hildon 2.2.0, the user interface toolkit used in Maemo. No words are needed to explain how awesome is this!
  • Also, some of my work mates are fine-tuning MAFW after bringing it to life in order to provide multimedia coolness to Maemo, and (who knows!) maybe the desktop as well. Of course all built on top of the lovely GStreamer libraries.
  • GNOME 2.28, which includes the hard work from a lot of work in form all around the world, and a revamped Epiphany web browser which uses WebKitGTK+ as the rendering engine. This means that some of my colleguaes have been killing kitties and their hard work will be deployed in every GNOME install!
  • Frogr 0.1, a tool which carries out out the simple (but important) task of uploading pictures to Flickr, and it is doing a fine task for me right now.
  • In the operating systems ground, Haiku R1 Alpha 1 has been released. This may sound like “some other hobbyist operating system”, but it is a lot more than that: it is a new life for the mighty BeOS R5, which  took eight years to to bring from the dead. I have played a bit with the live CD: the experience is great, although somw rough edges still exist, but I would say that Haiku contains lots of superb work and I am eager to install it in some real hardware.

But more changes apart from software releases happened: in a more personal note, I am now using Fedora 11 in a daily basis at my laptop. Initially I wanted to try out Foresight, because the Conary package manager looks like an interesting piece of software, but unfortunately the installer does not have support for LUKS-encrypted volumes in the installer, and I did not want to bootstrap it manually. Interestingly enough, Fedora does have such support using the same Anaconda installer. I did not like Fedora back in version 6, but I must admit that the community did an impressive improvement (at least comparing version 6 to version 11!) and I am very happy with my current setup. I am even considering Fedora 11 for installing it on my brand new PlayStation 3: I bought one of the old “fat” models, because the new “slim” ones do not officially support installing third-party operating systems.

Finally, a quick note to finish this “I am alive” post: I am glad that we have decided to push Linux-vServer in our servers, because we are getting some interesting benefits thanks to it, being the main one the ability to easily clone a running machine and use the clone for testing purposes before applying changes in the production environment. Also, we are now able of easily provide sandboxed environments in which users have almost-full administrative privileges without having to worry about other services being affected in case something goes wrong. And we are getting those niceties with a minimal overhead (~1.5%) in terms of kernel CPU usage. As we are moving services which were previously run on physical machines into virtual machines, we are saving power and contributing to the environment while providing a better service and support to our staff :-D


Bad Behavior has blocked 257 access attempts in the last 7 days.