Integrate Spamassassin into Postfix/Dovecot

As I stated before, I really like Christoph Haas’ ISPMail setup for Debian-based mailservers. I was quite fine without any server-side spam filtering solution until now, but somehow the spam amount in my inboxes increased more and more and I was looking for a decent and simple solution to filter out all that bullshit which is distracting me day after day.

I clearly wanted to go with Spamassassin (SA), as I made good experiences with it in the past and it’s more or less the standard spamfilter on linux based mailservers. The most common solutions to integrate SA into a Postfix based mailserver are the following:

  • Using amavisd-new
  • Using Postfix´ content_filter

I don’t really like both of them. Amavis is quite heavy for the pure spam filtering purpose and the content filter checks both ingoing and outgoing mails by default which is obviously not in my interest. Amavis avoids checking outgoing mail just by checking if the sender domain is managed by the same system, but spammers can bypass this quite easily by faking the sender’s address to be the same as the recipient’s one (which is done quite often). There’s a discussion about this on the ISPMail page, so head there for more information. All this can be improved by using multiple Postfix instances and different ports (e.g. using 587/submission for authenticated clients and 25/smtp for normal SMTP traffic), but I want my mailserver to be as interoperable as possible without the need of any special setups on the client side.

So I was looking for another solution. I read some tutorials where people used procmail in user scripts to pass incoming mail to spamc before delivering it to the mailbox. I like this approach as the MTA isn’t involved into the spam filtering process, outgoing mail isn’t touched and you don’t need any complicated setups on the MTA side. All alias and transport definitions work fine and the final mail is checked right before being delivered to the user’s inbox.

First I thought about Sieve, which is already running through Dovecot’s Sieve implementation until I noticed that Sieve is not able to call any external programs (correct me if I’m wrong). Then I had a look at spamc and Postfix’ master.cf. spamc is capable to pipe its output to another program and in the ISPMail setup, Postfix passes the mail directly to Dovecot’s deliver, so why not just let Spamassassin check the mail right before it’s getting passed to Dovecot? I gave it a try and seems to work fine. I still need some automation in training SA databases (might follow in a later post), but the plain SA checking is working reliably and mails can easily be filtered with Sieve afterwards.

So much for the backstory, let’s get our hands dirty. Note: I’m running Debian Lenny.

read more »

Continuous Integration with phpUnderControl and Git

Continuous Integration with phpUnderControl and Git

I was looking for a decent continuous integration solution for my PHP projects for some time now, but always had the problem that most of the described solutions used SVN instead of Git as VCS system. Yesterday I found an article which describes the setup exactly as I needed it: phpUnderControl with Git on a Debian/Ubuntu system. Using the article, I managed to set up a working system quickly, which basically works as expected: CruiseControl checks the repository for modifications and starts the build process if there are any new commits. The build process includes generating API documentation (phpdocumentor), running static code analysis (php-codesniffer) and executing unit tests (phpunit). If the build succeeds, the results are published and can be accessed through a nice webinterface powered by phpUnderControl (see screenshot above which I stole from the phpUnderControl site).

However, the described setup has a few issues which bugged me:

  1. CruiseControl runs from the shellscript as root, posts all output to the console and is not automatically started at boot time.
  2. CruiseControl runs on port 8080, but I wanted to manage access to the webinterface through the apache which is already running on the box
  3. There’s no authentication – everybody can access my CI server, see the build details and start new builds through the webinterface.
read more »

Windows 7 RC auf älterem PC installieren: Code Error 5

Als ich den Windows 7 RC gerade auf einem älteren PC (S. 939) installieren wollte, brach die Installation bzw. der Bootvorgang von der DVD mit folgendem Fehler ab: Cannot boot from CD - Code error: 5. Das Problem liegt anscheinend an einem zu alten BIOS, das den Bootsektor der DVD nicht korrekt auslesen kann. Nach etwas Recherche bin ich auf diesen Beitrag gestoßen, der erklärt, wie man die DVD dennoch mittels einem zusätzlichen Bootloader namens gujin booten kann – mit einer Boot-Diskette. Als Alternative zur Boot-Diskette wird auf ein Tutorial zur Konvertierung des Floppy-Images in eine Boot-CD mittels Nero verwiesen.

Da ich hier weder ein Floppy-Laufwerk (glaub das wär noch in irgendeinem Schrank aufzutreiben gewesen), funktionierende Disketten (die schon schwieriger) oder Nero installiert hatte, habe ich mich nach einer Alternativlösung umgesehen. Abhilfe schafft hier wieder mal Linux und mkisofs, mit dem sich das Floppy-Image einfach in ein CD-ISO umwandeln lässt. Diese Lösung setzt natürlich voraus, dass man in dem zu installierenden PC 2 optische Laufwerke hat, eines für die Windows7-DVD und eines für die Bootloader-CD. Also flugs eine Ubuntu-VM gebootet und darin das gujin-ISO gebastelt. Dazu lädt man sich in der VM zuerst die standard-Version von gujin herunter und entpackt das Archiv. In dem Archiv befindet sich eine Datei full.img.gz, die man wiederum entpackt. Die darin befindliche Datei floppy.144 schiebt man in einen Arbeitsordner (bei mir z.B. /tmp/floppyimage) und öffnet anschließend ein Terminal. Darin macht man dann ca. folgendes:

$ cd /tmp/floppyimage
$ mkisofs -pad -b floppy.144 -R -o /tmp/gujin.iso floppy.144

Und schon liegt in dem Ordner eine Datei gujin.iso, die sich auf CD brennen und booten lässt. Anschließend legt man die Bootloader-CD in das eine, die Win7-DVD in das andere Laufwerk und bootet von der soeben gebrannten CD. Nach kurzer Erkennungszeit lassen sich in gujin die verschiedenen zur Verfügung stehenden Bootoptionen auswählen. Wählt man hier das Laufwerk mit der Win7-DVD, bootet die DVD ohne Probleme und man kann sich daran machen, (wieder mal) ein neues System auf die Platte zu packen. Ist zumindest bei mir so, auf der doch recht betagten Hardware ist der Installer durchgelaufen, während ich diesen Post hier verfasst habe.

ATI Catalyst Setup stürzt bei Installation ab

ATI Catalyst Setup stürzt bei Installation ab

Ich wollte gerade auf meinem Vista 64 System den neuen 9.7er Catalyst Treiber für meine Radeon 4870 installieren. Leider quittierte der Installer den Dienst sowohl beim Treiber selbst als auch beim CCC mit obigem Bild. Kurze Suche im Internet brachte mich auf benedikts Blog, wo eine simple Lösung für das Problem beschrieben wird: einfach via Commandline installieren. Wer öfter in diesem Blog stöbert, wird wahrscheinlich gemerkt haben, dass ich Commandlines nicht ganz abgeneigt bin – also los gehts ;)

Zuerst die heruntergeladenen Dateien ausführen, wodurch die Installer entpackt werden. Im meinem Fall waren das die 2 Dateien 9-7_vista64_win7_64_dd.exe (display driver) und 9-7_vista32-64_ccc_lang2.exe (control center). Danach befinden sich in C:\ATI die entsprechenden Setup-Dateien in Unterordnern, die gleich benannt sind wie die heruntergeladenen Dateien. Um jetzt den display driver zu installieren sind folgende Schritte nötig:

  1. Im Startmenü nach Zubehör, Rechtsklick auf Eingabeaufforderung und dann “Als Administrator ausführen”. Dadurch öffnet sich eine CMD mit administrativen Rechten
  2. cd C:\ATI
  3. cd 9-7_vista64_win7_64_dd (je nach Treiberversion, Sprache und Betriebssystem)
  4. cd Bin64 (bei 64-Bit Betriebssystemen, bei 32-Bit Systemen heißt der Ordner wahrscheinlich Bin)
  5. ATISetup.exe -install -output screen

Analog funktioniert das auch mit dem CCC und dem Avivo Video Converter (Hydravision hab ich nicht getestet, da ichs nicht brauche).

Backup Xen virtual machines with LVM snapshots and ftplicity/duplicity

Some time ago, I updated the backup system on a Server running multiple Xen VM instances (DomUs). Before changing the system, each virtual machine ran its own backup scripts to backup data to an external FTP server. Now, VMs are centrally backed up to FTP from the Dom0 using LVM (Logical Volume Manager) snapshots. As a backup solution I chose duplicity and ftplicity in combination with a shellscript to create automated LVM snapshots. Duplicity is a tool to create GPG-encrypted (this way you can store your backups at remote servers without having to worry about who has access to your data) incremental backups to remote servers, ftplicity is a wrapper script for duplicity which allows running duplicity without interaction (e.g. without the need to type any passwords). Ftplicity was originally published by the German computer magazine c’t, but has been undergone further development and is now hosted at SourceForge.

You can find tutorials on ftplicity/duplicity here (Note: they use the original c’t version of ftplicity):

Basically you can use this setup for any kind of LVM snapshot based system, but I’m focusing on backing up Xen VMs here. I assume you got your LVM and Xen system up and running so far. I did this on a Debian Lenny system, but it should be similar on other distros. I did all steps as root.

read more »

Build a FlashMessenger system in ASP.NET MVC

Build a FlashMessenger system in ASP.NET MVC

Usually, I’m using PHP for web projects, but currently I’m working on an application using ASP.NET’s MVC framework. In many frameworks (e.g. Zend Framework or CakePHP) there is some kind of messaging system (flash messages), which allows to save a message to the session and to display it on the next request. This is useful in many situations, but mostly used after saving forms. So for example you recieve a POST request to create a new record, you save the record, redirect the user to the overview page and inform him about successful creation through a flash message which you saved before doing the redirect. As I didn’t find a way how to achieve this in ASP.NET MVC, I started to build an own solution. The result is a combination of a base controller, an action filter and a flashmessenger object which is stored in the session. Please note that I’m not too familiar neither with ASP.NET nor with C#/.NET in general, so if there are things to improve please feel free to correct me.

read more »

Set up a Zend Framework application using Zend_Application (including PHPUnit setup)

Today I spent some time setting up a new Zend Framework application using ZF 1.8.0 Beta 1 and the new component Zend_Application. Using that component, all bootstrapping is done by Zend_Application_Bootstrap and so-called resource plugins. Such resource plugins are responsible for initialization of single components such as front controller, database or the view. This way, the whole bootstrapping is nicely modularized and keeps some headache away. In addition, the majority of settings can be set in the application config file. As I ran into some issues, I’d like to note the required steps and hope that it’s useful so someone. I won’t explain the files in detail, you can find enough information about components and parameters on the manual and the quickstart, but you should get to a working setup with just copy&pasting the code here ;)

Basically a big part of this setup can be done using the new Zend_Tool CLI, however I had some problems setting it up, so I’ve done it manually (however most of the code is the one generated by Zend_Tool).

read more »

Upgrade from Debian Etch/Xen 3.0 to Debian Lenny/Xen 3.2 (AMD64)

I was running a Xen server with Debian Etch as dom0 (Linux 2.6.18-6 with Xen 3.0.3-1 on AMD64) for some time now. Today, I decided to upgrade the dom0 to Debian Lenny (Linux 2.6.26-2 with Xen 3.2.1-2). The domUs are all running a Debian-based OS (3x Lenny, 1x Ubuntu Hardy). The upgrade was quite straightforward, however there were some pitfalls you can avoid in advance.

read more »

Authenticate Apache against Redmine with AuthMySQL

For a student project we needed to authenticate an apache host against a MySQL database, in this a case we wanted to handle authentication for a Subversion repository with a Redmine database. I know that Redmine has its own solution for this problem using Redmine.pm, but for some reason that approach didn’t work and we didn’t have the time to bug around with it. This howto is written for the use with Redmine (especially the database view), but you should get the point how to set it up on other environments. The howto was done on an Ubuntu 8.10 box but should work on any other distro as well (except for the module installation). I assume that you got all the other stuff (apache, mysql, …) up and running.

read more »

Set up symfony 1.2 on Debian/Ubuntu

Just wanted to give symfony a try and ran into some issues to set it up the way I wanted. Therefore I’d like to note the required steps.

First, install symfony via PEAR.

pear channel-discover pear.symfony-project.com
pear install symfony/symfony-1.2.4

This sould install symfony and make the symfony executable available in your PATH.

~$ symfony -V
symfony version 1.2.4 (/usr/share/php/symfony)

Create a directory for your vhost and create a new project.

mkdir /var/www/myproject
cd /var/www/myproject
symfony generate:project myproject

Create an example application in your project.

symfony generate:app frontend

Link the symfony resources to the project’s document root.

cd web
ln -s /usr/share/php/data/symfony/web/sf/

This should get you up and running with symfony. You just need to configure your server for the vhost. For personal preference, I’d like to have my document root directory named public instead of web. The following steps are needed to achive this.

Rename the document root directory.

mv web public

Add this line to config/ProjectConfiguration.class.php:

<?php
public function setup()
{
    $this->setWebDir($this->getRootDir() . '/public');

    // for compatibility / remove and enable only the plugins you want
    $this->enableAllPluginsExcept(array('sfDoctrinePlugin', 'sfCompat10Plugin')$
}