Headlines | Linux | Apps | Coding | BSD | Admin | News
Information for Linux System Administration 

Install a Mail Server with Antivirus and Antispam in minutes


This article illustrates a situation where you need to set up your own mail server (be it your home mail server, or a small office one). It actually shows that, if using an integrated service mail server, anyone can do the job, all in a matter of minutes.

AXIGEN Mail Server, the solution chosen for this example, can send and receive e-mails securely via "" and is able to retrieve them in a WebMail interface - this means that it includes all mail services needed for a fully functional mail server (SMTP, IMAP, POP3, WebMail, WebAdmin).

To get an idea of the amount of time you can spare by installing such a solution, just think of all the different open source applications you would need to install instead (i.e. an MTA, Squirrelmail for Webmail, QmailAdmin for web configuration, Courier for IMAP and POP3 and many others.)

AXIGEN Mail Server can virtually integrate with any Antivirus/Antispam application and it comes with built-in connectors ClamAV Antivirus and SpamAssassin. The second part of this article shows you how to install these applications and configure these connectors for use with AXIGEN.

Thus, at the end of this process which can take up half an hour at most, you will not only have your mail server up and running, but also virus and spam protection for your incoming and outgoing mail traffic.

AXIGEN runs on several Linux distributions (Gentoo, Redhat/Fedora Core, Slackware, Debian, Ubuntu, Mandrake/Mandriva, SUSE), on BSD versions (FreeBSD, OpenBSD and NetBSD) and on Solaris but for the purpose of this article, let's suppose you are setting up your mail system on a Fedora Core 6 platform.In five easy steps, you will have your server installed, your primary domain running and access to the Web configuration interface (WebAdmin).

1. Download / unpack corresponding package

Download AXIGEN rpm package from the AXIGEN website (packages are available as 30 day evaluation versions). Save the corresponding package for Fedora Core 6 "axigen-2.0.4.i386.rpm.gcc4.tar.gz" on your local machine and unpack the file, by issuing in the same directory as the download file:
tar xzvf axigen-2.0.4.i386.rpm.gcc4.tar.gz

2. Install command

Then, in order to install the RPM package, issue (while logged in as root) the following command, from the same directory as the rpm file:
rpm -ivh axigen-2.0.4.gcc4-1.i386.rpm
This will create the entire directory structure needed for AXIGEN to run. After the installation, no daemons or related application will be started.

3. Configuration options

AXIGEN provides several configuration options (configuration file, Command Line Interface), but the most intuitive and comprehensive one is WebAdmin, the Web configuration interface.

The corresponding WebAdmin service is enabled by default, as well as the other default services: IMAP, Logging, POP3, Processing and SMTP.

4. Initial configuration

The first configuration steps take place using the configuration wizard. You will set the administrator's password, select which services are started and what interfaces will be used. In this stage of the setup you also create the primary domain that your server will use.

The wizard can be run by issuing the following command in the console right after the installation of the package has finished:
NOTE: You have to make sure you do not start the mail server before the initial configuration.

5. Start AXIGEN

You can then start AXIGEN, using its initscript, by issuing this command:
/etc/init.d/axigen start
Now that your server is running, you can connect the antivirus and anti-spam applications. By default, AXIGEN comes with connectors for the ClamAV Antivirus and SpamAssasin Antispam application. The setup process below describes how to make these two applications work with AXIGEN. However, note that AXIGEN implements a proprietary filter scripting language that allows you to implement connectors for any third party Antivirus and Antispam applications.

Connecting to ClamAV

A. Install ClamAV (daemon), on the same machine on which AXIGEN Mail Server is installed. Follow these steps in order to configure ClamAv for use with AXIGEN and start the clamd daemon.

1. Install clamav-server, using yum (Yellow Dog Updater, Modified):
yum install clamav-server
2. Copy the sample config file shipped with clamav-server:
cp /usr/share/doc/clamav-server-*/clamd.conf /etc/clamd.d/axigen.conf
3. Edit: /etc/clamd.d/axigen.conf
# comment out the Example line 
# Example
# insert/modify the following lines:
LogFile /var/log/clamd.axigen
PidFile /var/run/clamd.axigen/
LocalSocket /var/run/clamd.axigen/clamd.sock
User axigen
4. Create a link to the clamd binary:
ln -s /usr/sbin/clamd /usr/sbin/clamd.axigen
5. Create the run directory, where the PID file and clamd socket will be stored, and change its permissions:
mkdir -p /var/run/clamd.axigen chown axigen:axigen /var/run/clamd.axigen
6. Create and setup the initscript:
cp /usr/share/doc/clamav-server-*/clamd.init /etc/init.d/clamd.axigen 
chmod 755 /etc/init.d/clamd.axigen /sbin/chkconfig clamd.axigen on
7. Edit: /etc/init.d/clamd.axigen and modify the following lines, as specified below:
# description: The clamd server running for axigen CLAMD_SERVICE=axigen
8. Finally, start the clamd daemon:

B. Configure AXIGEN antivirus filter at server level using WebAdmin

In order to activate the ClamAV filter, go through the following steps:

In the "Server" context, click on the Add new filter button. This will open up and display the Active Filter list. It is empty right now, so we need to add the clamav filter to the list.

In the Priority field, enter a priority between 0 and 500 (a filter with priority 0 will be applied first and the one with 500, last).

Important - the domain-level filters have the priority limited to range 100-400 and the user-level filters are limited to the 200-300 range. A value of "10" should be fine, leaving you space to apply some other future filters before this one.

After setting the filter priority, select the socket value from in the Filter type dropdown list and the clamav value from the Filter Name list.

In the Apply on checklist, select the relay option, to apply the filter on outgoing mails. To make sure you scan both incoming and outgoing mails, you have to create the filter and select both values, local and relay.

In AXIGEN, it is possible to enable filters either at domain or user level, in the corresponding WebAdmin tabs. The filters activated at server level will be automatically applied for all domains and accounts. However, you have the possibility to add additional filters at domain or account level.

Connecting to SpamAssasin

The process for Connecting SpamAssassin is similar and even less time-consuming as no configurations are necessary after the product installation.

C. Install SpamAssassin using the yum application:
yum install spamassassin
No further configurations are necessary.

D. Configure SpamAssassin at server level, using Webadmin

The connector for SpamAssassin is a socket filter for AXIGEN, so the configuration procedure is the same as for ClamAV. The difference would be that for SpamAssassin, a TCP socket is more likely to be used.

Also, when activating the SpamAssassin filter, you need to keep in mind the following:
  • Enter a different priority value for the SpamAssasin filter (if you have chosen 10 for ClamAV, choose a higher value for SpamAssassin in order to apply this filter after ClamAV in the filtering chain)
  • Select the corresponding filter name, spamassassin in the Filter name list

Access AXIGEN WebMail

At this step of the way, your mail server is ready to go, and you can also you can access the AXIGEN WebMail to send and receive test messages. Then, use the full email address and password to log on to AXIGEN WebMail, at the default address:, or use the address you specified in the initial configuration phase when you ran the setup wizard.

Now you're really done: you can securely send and receive messages from your home domain and easily make any further configurations, to accommodate your specific network requirements. As you have seen, installing all mail services from one single executable and an intuitive Web configuration interface make things a lot easier and a lot less time-consuming.

Liviu Anghel, Chief Security Officer, Gecad Technologies
Ciprian Negrila, Technical Support Engineer, Gecad Technologies

mail this link | permapage | score:9311 | -Kayla Vincent, February 6, 2007

Librenix T-Shirts and Coffee Mugs!


For today's example of my (semi)elite C programming skilz, I submit for your inspection the Librenix T-Shirts! Yes, I created the images on these shirts and coffee mugs entirely with C code. While the code isn't up to the standards *cough* of my open source Space Tyrant project, at least the output is colorful and not entirely textual!

click either image to see the T-Shirts, Coffee Mugs, etc.

(If you like the images but don't care for 'librenix' on your shirt, these same styles are available for all 50 US state names as well as with the signs of the zodiac here)

(and here are some modern prints)
mail this link | permapage | score:9283 | -Ray, June 6, 2010 (Updated: April 24, 2012)

How to install Ubuntu Linux on the decTOP SFF computer


I recently bought a decTOP small form factor (SFF) computer. My goal was to build a cheap, fanless, quiet, and low power consumption Linux server. For $99 plus the cheapest available shipping, $40, my machine arrived 11 days after I placed the order.

This is a tiny computer, about the size of a Mac Mini. But, because it has no fan, it runs a bit quieter and, with the help of a 1-watt, 366 MHz CPU, consumes only 8 watts. For comparison, the G4 Mac Mini consumes about 20-30 watts, depending on load.

The decTOP comes with 128 MB of RAM in its sole SO-DIMM slot and a 10 GB 3.5 inch hard drive. I understand that it's a simple matter to replace the drive and to upgrade the memory to a maximum of 512MB.

It also comes with no operating system and the ability to boot only from a USB drive. This article details the steps I used to build the USB boot/installation drive and install Ubuntu 6.06 on the decTOP.

There is another article -- with additional decTOP links -- here on installing Ubuntu 6.06 on the decTOP with the aid of a Windows system. Fortunately ;), I run Mac OS X and Linux (Ubuntu 7.04), so that article didn't work for me. I did the installation of the Ubuntu 6.06 LTS Server Edition using my Ubuntu Linux box and a 1 GB USB flash drive -- although a 512 MB USB drive should work as well.

  1. Download the Ubuntu 6.06 server ISO image from the Ubuntu download page. Depending on your plans for the decTOP, you might want to choose the desktop version. Unless you have already upgraded your decTOP's memory, however, you'll want to stick with the 6.06 releases.

  2. Install the mbr, mtools, and syslinux packages on the Linux system you'll be using to prepare the USB drive. If you run Ubuntu or some other Debian-derived system, the following commands may do the work for you.
    apt-get install mbr
    apt-get install mtools
    apt-get install syslinux
  3. Partition the USB drive with a single FAT-16 partition. I used the fdisk 'n' command to make the new primary partition 1. The fdisk 't' command can be used to change the partition type to FAT-16. My device name was /dev/sda.
    fdisk /dev/sda
  4. Make the FAT-16 partition the active partition. I used the fdisk 'a' command.

  5. Install a master boot record on the USB drive.
    install-mbr /dev/sda
  6. Install syslinux on the USB drive. Note that the USB drive should not be mounted when you do this.
    syslinux -s /dev/sda1
  7. Create a mountpoint and mount the ubuntu ISO image using the loopback device.
    mkdir /iso
    mount -o loop -t iso9660 ubuntu.iso /iso
  8. Create a mountpoint and mount the USB flash drive.
    mkdir /usb
    mount /dev/sda1 /usb
  9. Copy the contents of the ISO image to the USB drive. This will take some time.
    cd /iso
    cp -r . /usb/
  10. Copy the /usb/dists/dapper directory into a new /usb/dists/stable directory.
    cd /usb/dists/
    cp -r dapper/* stable
  11. Copy several files from /usb/install to the /usb root directory.
    cp /usb/install/vmlinuz /usb/
    cp /usb/install/mt86plus /usb/
    cp /usb/install/initrd.gz /usb/
  12. Install the following text into a file named syslinux.cfg in the /usb root directory.
    default vmlinuz
    append initrd=initrd.gz ramdisk_size=24000 root=/dev/ram rw
  13. Flush all writes, unmount, and remove the USB drive. After the sync step, wait for all of the data to be written to the USB drive.
    umount /usb
  14. Connect the ethernet adapter to the decTOP and connect it to your network to allow automatic configuration of the network interface.

  15. Insert the USB drive into the decTOP and power it up. The decTOP should automatically boot from the USB drive and start the Ubuntu installation.

  16. Answer only the first two questions concerning language selection and go to the next step, below.

  17. Press Alt-F2 (hold down the Alt key and press the F2 function key) to open a shell. Then press enter to start the shell.

  18. Create a /cdrom and a /dev/cdroms directory in the installation ramdisk
    mkdir /cdrom /dev/cdroms
  19. Go to the /dev/cdroms directory and build a symlink from /dev/sda1 (that is likely the device name of your USB boot partition) to /dev/cdroms/cdrom0.
    cd /dev/cdroms
    ln -s ../sda1/cdrom0
  20. While still in the shell, mount the USB drive to mimic an installation CD-ROM.
    mount -t vfat /dev/cdroms/cdrom0 /cdrom
  21. Return to the installation program with Alt-F1 and continue the installation.

From this point, the process should be identical to a routine CD-ROM installation.

For a grand total of $140 and 8 watts of power consumption, I now have a near-silent Linux server running 24/7. You can telnet to it here and marvel at its blinding speed running a 250,000-sector Space Tyrant game.

mail this link | permapage | score:9274 | -Ray, August 16, 2007 (Updated: April 26, 2011)

Space Tyrant: Multithreading lessons learned on SMP hardware


There is much to report in this update of Space Tyrant. Before getting into the new features and functions, I’ll dispense with the crisis of The Bug.

For a couple of weeks, we had been noticing odd anomalies with Space Tyrant (ST) running on the virtual server at (now offline -Ed.). We never saw the problem on any other box -- and it was tested on at least four other Linux boxes and a Mac OS X system. We did all manner of stress testing, locally and over the Internet, script based and even feeding the game the output of /dev/random. Nothing caused the anomaly on any other box.

At first, I suspected that it might just be an obscure problem with the virtual server itself; after all, I had been forced to modify the TLR code to get it to run properly there. That problem turned out to be merely a limitation of NFS, not a bug with the virtual server software. However, the environment was clearly different from any other system I had used which raised my suspicions -- and reduced my urgency about looking for the bug.

While the bug wasn’t frequent, it was persistent. The bug appeared to be related to corrupted buffers or corrupted buffer indexes. Out of idle curiosity, I lowered the number of buffers used by ST to see if that affected the bug. Somewhat counter-intuitively, it substantially raised the frequency of the problem.

Brian Estabrooks (the hero of this release) and I spent more and more of our efforts hunting this incredibly elusive bug until that was all we were doing. I implemented various diagnostic routines hunting for clues. The all seemed to point to buffer indexes being changed incorrectly. Both Brian and I audited the code. It seemed impossible for the indexes to be changed improperly. Brian even went so far as to replace the ring buffer scheme with a high watermark approach but to no avail.

While I continued to suspect it to be a simple logic error in the code, Brian turned his efforts elsewhere. What he came up with was quite interesting. It seems that on many hardware architectures (most? all?), modifying a bit field can temporarily modify other bit fields in the same word! Now, this isn’t a problem on a single-CPU system; it repairs the damage in the same operation, making it, effectively, atomic. On an SMP machine, however, two different CPU’s working on different bit fields of the same word simultaneously create havoc. The operation isn’t really atomic and it doesn’t work.

Did I mention that the virtual server is a 4-way Xeon system?

The ring buffer indexing in ST relies on unsigned integer bit fields to automate wrapping back around to the first buffer after using the last one. My parsimonious programming, of course, packed all the bit fields together, several to a word. Brian’s test version of ST added a pad after each buffer index to round it out so that each bit field lived alone in its own complete word. We abused the new version for nearly an hour before either of us would dare say it. The bug was gone.


So, the moral of this story is: Operations on sub-word fields affect other bits in that word (at least on many hardware architectures). Tread very carefully if multiple threads are accessing different bits in shared words. It may appear to work perfectly, only to crumble into a pile of smoldering rubble the first time it's loaded on a multiple CPU system!

Other than the primary lesson, some other good things came out of (the search for) the bug. Several other latent bugs were found and fixed and Brian and I are both much more intimate with the code.

And, on to the enhancements. ST is starting to look like an actual playable game. The following functions implement the new major features.

players(): We now have player rankings. It works by adding all the players’ ship resources to an integer array. Then it scans the universe looking for deployed fighters and adds those to the array as well. Currently, those two items comprise the total strength of a player.

It then sorts the array with a recursive bit-plane sort that I wrote for Starship Traders in 1998. The qsort() function in the C library was plenty fast, but took too much memory for my taste. Memory was a bit scarcer in those days and, worse, the SST software model gave each player his own copy of the server.

The sort reorders the array in place as follows. It scans the high-order bit in each element of the array. It then moves all elements starting with ‘1’ bits to the top and all starting with ‘0’ bits to the bottom. Next, it calls itself twice to reorder the first and second chunks of the array on the second bit. Each of those two instances of the sort then call the sort twice again, now giving 4 new sorts for the third bit, and so on. When all 32 bits are accounted for, the array is in the correct order with the top player on top, etc.

Scanning the entire universe can be expensive with a large map. Therefore, the player rankings function keeps the result and time stamps it. If another player asks for a player ranking within five seconds, the system just gives them the old one. After five seconds, however, any new request triggers a fresh listing.

autopilot(): We’ve added an autopilot to let a player find a specific sector -- or to locate the nearest planet. If you type a ‘0’ (zero), you’ll be prompted for a sector number within 1000 of the sector you’re currently in. You then will have the option of pressing ‘/’ to automatically warp to the destination sector.

If you’re looking for a planet, type the ‘L’ command that you would normally use to land on a planet in your sector. In the absence of a planet, the L key will engage the autopilot which will search for the nearest planet and give you a ‘/’ command to autowarp to it.

The new autopilot function consists of two other functions in addition to autopilot(), which is merely a control function. I had intended to use the old shortest path algorithm function from TLR but it was big and complicated. I decided to try to write a simpler, recursive shortest path algorithm instead. The new recursive function is much simpler but not quite as efficient as the giant for loop in TLR.

The actual algorithm is implemented in two functions called pathdepth() and pathcalc(). The pathdepth() function repeatedly calls pathcalc() with an increasing ‘depth’ parameter. ‘Depth’ tells pathcalc() how many levels deep to search before giving up.

The pathcalc() function simply looks to see if the sector it is looking at is the target sector. If not, it calls itself for each new sector that the current sector connects to. If the current sector is the target sector, it starts filling in an array for the autowarp() function to follow to reach the target sector. As the previous recursive calls to the pathcalc() function exit, they fill in the remainder of the path array.

And, yes, I seem to like reinventing the wheel. ;-)

The other interesting addition to the code is the backup thread. It is implemented by a function called backupdata() and works as follows: It scans the player data, the map data, and the history data looking for ‘dirty’ flags. (Whenever any persistent data is changed anywhere in the game, a dirty flag is set to tell the backup thread to write it out to disk.) This process is quite fast for a small game, but for a game with millions of sectors, it’s a significant waste of resources to scan the dirty flag array frequently.

Therefore, for the map and history data, I’ve implemented a ‘dirty block’ scheme as well. When a dirty flag is set, its corresponding dirty block flag is set too. Then, the backup thread need only scan the dirty block arrays, typically only about one percent the size of the arrays it represents. When a dirty block is found, only the hundred or so records it points to are scanned to find the actual dirty records for backup.

The backup file, named ‘st.9999.dat’ -- where ‘9999’ varies with the port number you run the game on -- goes into the current working directory from where you start the daemon. If the file doesn’t exist, a new game is started. Also, if you’ve modified the game in a way that changes the size of the data -- by increasing the map size, for example -- it will start a new game upon startup.

The game can be shut down from the command line by sending a signal 15 (kill -15 pid) or by the admin with the ^ command. Note that the first player to create an account in a new game automatically becomes the admin of the game!

makehistory(): The storing of historical data is new as well. Whenever another player attacks your ship while you’re logged off, you’ll get a report of the action and any losses when you next log on. Also, for remote deployed fighters, you never get immediate notification, so that information is stored in the history log even if you're logged on when it happens. You can view any accumulated event information since your login time by pressing the ‘e’ key.

deploy(): This simple function allows a player to deploy, or retrieve, guard fighters in a sector. Those fighters will not let another player pass through or view any of the contents of that sector. Any ships parked under the fighters are automatically protected against all attacks except for an attack by the fighters’ owner. Once the fighters are destroyed, of course, all ships there are visible and can be attacked.

There is also a newly implemented time limit in the game to limit the total online time of a day’s sessions to 4 hours. Like most other parameters, it can be changed by modifying a #define statement near the top of the code.

command(): The help page, a menu of available commands that a player can perform, has been redesigned and rewritten. This menu is attached to the '?' key.

The old debugger thread is gone, replaced by an in-game command function called showdata(). Press the ‘z’ key to see information on buffers, buffer indexes, and the backup thread’s state and history. Only if you’re serious about modifying the code will this information be useful.

The section of the gameloop thread that broadcasts radio and news messages has been modified to show only one of each type of message per pass. That way, replaying a long radio history won’t flood the output buffers and longer radio and news histories can therefore be retained.

The old jumprtn() movement function has been consolidated into the warprtn() function. It’s only slightly more complicated than having them separate.

The current source code can be downloaded from and the original article in this series is here. As usual, the compile script is embedded in the comments at the top of the source file. You’ll have to rename the source st.c for the script to work unchanged.

[A Space Tyrant home page has been created as a central index to the various ST articles, links, and files.]
mail this link | permapage | score:9157 | -Ray, June 26, 2005 (Updated: July 26, 2008)
More articles...
Buy Art Online with Satisfaction Guaranteed

More features

Linux vs. Windows: Why Linux will win

Space Tyrant: A threaded game server project in C

Microsoft to push unlicensed users to Linux

Space Tyrant: A threaded C game project: First Code

MiniLesson: An introduction to Linux in ten commands

Apple to Intel move no threat to Linux

Space Tyrant: A multiplayer network game for Linux

Tutorial: How to Block Ads With Adzap

Writing syslog messages to MySQL

Mono-culture and the .NETwork effect

Scripting: A parallel Linux backup script A simple directory shadowing script for Linux

Tutorial: Introduction to Linux files

Review: DevelopGo: A Linux Live CD for Programmers

Why software sucks

The short life and hard times of a Linux virus

The Supreme Court is wrong on Copyright Case

Why Programmers are not Software Engineers

SSL Encrypting Syslog via Stunnel

Missing the point of the Mac Mini

Hacker Haiku

Closed Source Linux Distribution Launched

Download: Linux 3D Client for Starship Traders

No, RMS, Linux is not GNU/Linux

Programming Language Tradeoffs: 3GL vs 4GL

The Real Microsoft Monopoly

The Network Computer: An opportunity for Linux

The life cycle of a programmer

SquirrelMail and AXIGEN WebMail

Beneficial Computer Viruses

Graffiti Server Download Page

The BSD License and the GPL: Why we need both

Create mobile Web apps with HTML5

Be an Engineer AND an Artist

myServer: How to build up a personal web server

Opinion: Seeing Linux for the first time...

Opinion: What Linux Needs (or doesnt need)

Retrofit with JTip tooltips and GreyBox lightboxes

Put our headlines on your site using RSS files

Librenix Sitemap

News Websites

Apps Websites

Monthly Visitors to

Sysadmin Websites

Monthly Visitors to

About Privacy Policy, Contact Info, etc.

Call for Linux software review articles

Posting Guidelines

Coding Websites


Firefox sidebar

Site map

Site info

News feed


(to post)


Articles are owned by their authors.   © 2000-2012 Ray Yeargin