<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>mafflog</title>
	
	<link>http://ailoo.net</link>
	<description>IT stuff and more</description>
	<lastBuildDate>Tue, 17 Jan 2012 22:55:50 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/mafflog" /><feedburner:info uri="mafflog" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><image><link>http://maff.ailoo.net</link><url>http://maff.ailoo.net/assets/images/mafflog.jpg</url><title>mafflog</title></image><feedburner:feedFlare href="http://add.my.yahoo.com/rss?url=http%3A%2F%2Ffeeds.feedburner.com%2Fmafflog" src="http://us.i1.yimg.com/us.yimg.com/i/us/my/addtomyyahoo4.gif">Subscribe with My Yahoo!</feedburner:feedFlare><feedburner:feedFlare href="http://www.newsgator.com/ngs/subscriber/subext.aspx?url=http%3A%2F%2Ffeeds.feedburner.com%2Fmafflog" src="http://www.newsgator.com/images/ngsub1.gif">Subscribe with NewsGator</feedburner:feedFlare><feedburner:feedFlare href="http://feeds.my.aol.com/add.jsp?url=http%3A%2F%2Ffeeds.feedburner.com%2Fmafflog" src="http://o.aolcdn.com/favorites.my.aol.com/webmaster/ffclient/webroot/locale/en-US/images/myAOLButtonSmall.gif">Subscribe with My AOL</feedburner:feedFlare><feedburner:feedFlare href="http://www.bloglines.com/sub/http://feeds.feedburner.com/mafflog" src="http://www.bloglines.com/images/sub_modern11.gif">Subscribe with Bloglines</feedburner:feedFlare><feedburner:feedFlare href="http://www.netvibes.com/subscribe.php?url=http%3A%2F%2Ffeeds.feedburner.com%2Fmafflog" src="http://www.netvibes.com/img/add2netvibes.gif">Subscribe with Netvibes</feedburner:feedFlare><feedburner:feedFlare href="http://fusion.google.com/add?feedurl=http%3A%2F%2Ffeeds.feedburner.com%2Fmafflog" src="http://buttons.googlesyndication.com/fusion/add.gif">Subscribe with Google</feedburner:feedFlare><feedburner:feedFlare href="http://www.pageflakes.com/subscribe.aspx?url=http%3A%2F%2Ffeeds.feedburner.com%2Fmafflog" src="http://www.pageflakes.com/ImageFile.ashx?instanceId=Static_4&amp;fileName=ATP_blu_91x17.gif">Subscribe with Pageflakes</feedburner:feedFlare><item>
		<title>Enable Twig debug in Symfony2</title>
		<link>http://feedproxy.google.com/~r/mafflog/~3/cTzvC6OOBfY/</link>
		<comments>http://ailoo.net/2012/01/enable-twig-debug-in-symfony2/#comments</comments>
		<pubDate>Fri, 13 Jan 2012 08:17:05 +0000</pubDate>
		<dc:creator>Mathias</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[How-Tos]]></category>
		<category><![CDATA[Snippets]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[symfony2]]></category>

		<guid isPermaLink="false">http://ailoo.net/?p=1961</guid>
		<description><![CDATA[To enable the debug tag in Twig, add the following to app/config/config_dev.yml services: twig.extension.debug: class: Twig_Extensions_Extension_Debug tags: - { name: twig.extension } Afterwards clear the cache and use the debug extension: {% debug my_var %} Sources http://groups.google.com/group/symfony2/browse_thread/thread/40df2ca0b22b0166]]></description>
			<content:encoded><![CDATA[<p>To enable the debug tag in Twig, add the following to <kbd>app/config/config_dev.yml</kbd></p>
<pre>services:
    twig.extension.debug:
        class: Twig_Extensions_Extension_Debug
            tags:
                - { name: twig.extension }</pre>
<p>Afterwards clear the cache and use the debug extension:</p>
<pre>{% debug my_var %}</pre>
<h2 id="sources">Sources</h2>
<ul>
<li><a href="http://groups.google.com/group/symfony2/browse_thread/thread/40df2ca0b22b0166">http://groups.google.com/group/symfony2/browse_thread/thread/40df2ca0b22b0166</a></li>
</ul>
<img src="http://feeds.feedburner.com/~r/mafflog/~4/cTzvC6OOBfY" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://ailoo.net/2012/01/enable-twig-debug-in-symfony2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://ailoo.net/2012/01/enable-twig-debug-in-symfony2/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=enable-twig-debug-in-symfony2</feedburner:origLink></item>
		<item>
		<title>HTC Desire Windows 7 64-Bit adb driver</title>
		<link>http://feedproxy.google.com/~r/mafflog/~3/fBJs7-dzRls/</link>
		<comments>http://ailoo.net/2011/06/htc-desire-windows-7-64-bit-adb-driver/#comments</comments>
		<pubDate>Tue, 14 Jun 2011 00:25:46 +0000</pubDate>
		<dc:creator>Mathias</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[How-Tos]]></category>
		<category><![CDATA[adb]]></category>
		<category><![CDATA[android-sdk]]></category>
		<category><![CDATA[htc desire]]></category>
		<category><![CDATA[windows-7]]></category>

		<guid isPermaLink="false">http://ailoo.net/?p=1943</guid>
		<description><![CDATA[I just had some troubles to get adb to work together with my HTC Desire on Windows 7 64-Bit. When attaching the phone in USB debugging mode, it showed up as &#8220;My HTC&#8221; device, but adb couldn&#8217;t connect to it. First of all, you need to install HTC Sync and the included USB drivers to [...]]]></description>
			<content:encoded><![CDATA[<p>I just had some troubles to get <kbd>adb</kbd> to work together with my HTC Desire on Windows 7 64-Bit. When attaching the phone in USB debugging mode, it showed up as &#8220;My HTC&#8221; device, but <kbd>adb</kbd> couldn&#8217;t connect to it.</p>
<p>First of all, you need to install HTC Sync and the included USB drivers to get your device working normally with your computer (e.g. showing up as disk drive). Then install the Android SDK and the USB drivers package (from SDK manager) and add the following lines to the file <kbd>extras\google\usb_driver\android_winusb.inf</kbd> inside the <kbd>[Google.NTamd64]</kbd> section (before <kbd>[USB_Install]</kbd> around line 65):</p>
<pre>;HTC Desire
%CompositeAdbInterface%     = USB_Install, USB\VID_0BB4&#038;PID_0C87&#038;MI_01</pre>
<p>Use this driver for the &#8220;My HTC&#8221; device. It should install, show up as &#8220;Android Composite ADB Interface&#8221; afterwards and work with adb (do an <kbd>adb devices</kbd> to check).</p>
<h3 id="sources">Sources</h3>
<ul>
<li><a href="http://www.freneticrapport.com/2010/10/htc-desire-windows-7vista-64bit-adb.html">frenetic rapport: HTC Desire Windows 7/Vista 64bit ADB Driver</a></li>
</ul>
<img src="http://feeds.feedburner.com/~r/mafflog/~4/fBJs7-dzRls" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://ailoo.net/2011/06/htc-desire-windows-7-64-bit-adb-driver/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		<feedburner:origLink>http://ailoo.net/2011/06/htc-desire-windows-7-64-bit-adb-driver/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=htc-desire-windows-7-64-bit-adb-driver</feedburner:origLink></item>
		<item>
		<title>Shorewall logcheck pattern</title>
		<link>http://feedproxy.google.com/~r/mafflog/~3/pp2wuBdXRIg/</link>
		<comments>http://ailoo.net/2011/06/shorewall-logcheck-pattern/#comments</comments>
		<pubDate>Sun, 05 Jun 2011 13:14:31 +0000</pubDate>
		<dc:creator>Mathias</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Snippets]]></category>
		<category><![CDATA[debian]]></category>
		<category><![CDATA[firewall]]></category>
		<category><![CDATA[logcheck]]></category>
		<category><![CDATA[logging]]></category>
		<category><![CDATA[shorewall]]></category>

		<guid isPermaLink="false">http://ailoo.net/?p=1937</guid>
		<description><![CDATA[A logcheck ignore pattern to filter out shorewall REJECT and DROP entries (net is defined as eth0). /etc/logwatch/ignore.d.server/shorewall: ^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ kernel:( \[ *[[:digit:]]+\.[[:digit:]]+\])? Shorewall:net2([a-z0-9]*):(REJECT&#124;DROP) Test if the regex works for your config: sed -e 's/[[:space:]]*$//' /var/log/syslog &#124; egrep '^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ kernel:( \[ *[[:digit:]]+\.[[:digit:]]+\])? Shorewall:net2([a-z0-9]*):(REJECT&#124;DROP)']]></description>
			<content:encoded><![CDATA[<p>A logcheck ignore pattern to filter out shorewall REJECT and DROP entries (<kbd>net</kbd> is defined as <kbd>eth0</kbd>). <code>/etc/logwatch/ignore.d.server/shorewall</code>:</p>
<pre>^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ kernel:( \[ *[[:digit:]]+\.[[:digit:]]+\])? Shorewall:net2([a-z0-9]*):(REJECT|DROP)</pre>
<p>Test if the regex works for your config:</p>
<pre>sed -e 's/[[:space:]]*$//' /var/log/syslog | egrep '^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ kernel:( \[ *[[:digit:]]+\.[[:digit:]]+\])? Shorewall:net2([a-z0-9]*):(REJECT|DROP)'</pre>
<img src="http://feeds.feedburner.com/~r/mafflog/~4/pp2wuBdXRIg" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://ailoo.net/2011/06/shorewall-logcheck-pattern/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://ailoo.net/2011/06/shorewall-logcheck-pattern/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=shorewall-logcheck-pattern</feedburner:origLink></item>
		<item>
		<title>Install Windows Server 2008 on KVM/VirtIO</title>
		<link>http://feedproxy.google.com/~r/mafflog/~3/4qQTyo-oFL4/</link>
		<comments>http://ailoo.net/2011/03/install-windows-server-2008-on-kvmvirtio/#comments</comments>
		<pubDate>Sun, 13 Mar 2011 23:31:54 +0000</pubDate>
		<dc:creator>Mathias</dc:creator>
				<category><![CDATA[How-Tos]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Server]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[kvm]]></category>
		<category><![CDATA[virtualization]]></category>
		<category><![CDATA[win2k8]]></category>

		<guid isPermaLink="false">http://ailoo.net/?p=1930</guid>
		<description><![CDATA[An example how to install a Windows Server 2008 guest on KVM with VirtIO (on a LVM volume in the example). Besides the installation medium you need the VirtIO drivers for windows in order to be able to access the disk device. You can get signed binary drivers here. Then set up a Windows VM [...]]]></description>
			<content:encoded><![CDATA[<p>An example how to install a Windows Server 2008 guest on KVM with VirtIO (on a LVM volume in the example). Besides the installation medium you need the <a href="http://www.linux-kvm.org/page/WindowsGuestDrivers/Download_Drivers">VirtIO drivers for windows</a> in order to be able to access the disk device. You can get signed binary drivers <a href="http://alt.fedoraproject.org/pub/alt/virtio-win/latest/images/">here</a>. Then set up a Windows VM with a command like this:</p>
<pre class="shell">virt-install --connect qemu:///system --arch=x86_64 -n win2k8 -r 1024 --vcpus=2 \
--disk pool=vmstore,size=50,bus=virtio,cache=none -c /path/to/win2k8.iso --vnc \
--noautoconsole --os-type windows --os-variant win2k8 --network network=subnet,model=e1000 \
--disk path=/path/to/virtio-win-1.1.16.iso,device=cdrom,perms=ro</pre>
<p>When the guest is running, shut it down and edit the os section of the XML file to look like this (otherwise Windows setup won&#8217;t let you install on the disk):</p>
<pre class="shell">virsh destroy win2k8
virsh edit win2k8</pre>
<pre class="standalone">&lt;os&gt;
  ...
  &lt;boot dev='cdrom'/&gt;
  &lt;boot dev='hd'/&gt;
&lt;/os&gt;</pre>
<pre class="shell">virsh start win2k8</pre>
<p>Connect to the VNC console and start the installation process. When you reach the form to select a disk device you won&#8217;t see any devices available. Click on &#8220;Load drivers&#8221; at the bottom left and load the drivers from <kbd>E:\viostor\wlh\{amd64|x86}</kbd>. After the drivers are installed, you&#8217;ll see a disk device and can continue with the installation.</p>
<h3 id="sources">Sources</h3>
<ul>
<li><a href="https://www.nnbfn.net/2011/01/installing-win-server-2008-r2-as-a-kvm-guest-with-virtio/">Installing Win Server 2008 R2 as a KVM Guest with VirtIO</a></li>
<li><a href="http://wp.libpf.com/?p=186">Installing Windows 7 as a KVM virtualized guest on Debian 6.0 Squeeze</a></li>
</ul>
<img src="http://feeds.feedburner.com/~r/mafflog/~4/4qQTyo-oFL4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://ailoo.net/2011/03/install-windows-server-2008-on-kvmvirtio/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://ailoo.net/2011/03/install-windows-server-2008-on-kvmvirtio/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=install-windows-server-2008-on-kvmvirtio</feedburner:origLink></item>
		<item>
		<title>Fetchmail/Sieve on ISPMail setup – update</title>
		<link>http://feedproxy.google.com/~r/mafflog/~3/QpWcc7uLu6I/</link>
		<comments>http://ailoo.net/2011/03/fetchmail-sieve-on-ispmail-setup-update/#comments</comments>
		<pubDate>Wed, 02 Mar 2011 00:10:28 +0000</pubDate>
		<dc:creator>Mathias</dc:creator>
				<category><![CDATA[How-Tos]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Server]]></category>
		<category><![CDATA[dovecot]]></category>
		<category><![CDATA[fetchmail]]></category>
		<category><![CDATA[mailserver]]></category>
		<category><![CDATA[sieve]]></category>
		<category><![CDATA[update]]></category>

		<guid isPermaLink="false">http://ailoo.net/?p=1917</guid>
		<description><![CDATA[Quite some time ago I wrote a tutorial on how to integrate fetchmail and sieve into virtual mail with Postfix and Dovecot. As time passes and things change, here&#8217;s an update: I don&#8217;t use the sieve part anymore. Instead, I use the ManageSieve server provided by Dovecot. It integrates with Dovecot&#8217;s authentication system and you [...]]]></description>
			<content:encoded><![CDATA[<p>Quite some time ago I wrote a tutorial on <a href="http://ailoo.net/2008/08/fetchmail-sieve-virtual-mail-debian-etch/">how to integrate fetchmail and sieve</a> into virtual mail with Postfix and Dovecot. As time passes and things change, here&#8217;s an update:</p>
<ol>
<li>I don&#8217;t use the sieve part anymore. Instead, I use the <a href="http://wiki.dovecot.org/ManageSieve">ManageSieve</a> server provided by Dovecot. It integrates with Dovecot&#8217;s authentication system and you can use all kinds of clients supporting the managesieve protocol, e.g. Thunderbird or Roundcube.</li>
<li>The ISPMail database structure changed since I wrote that tutorial which still relied on the DB structure for the Debian Etch structure. I updated the script to reflect both environments (take a look at the config file). However, it does not rely on any DB views anymore.</li>
<li>The script (only the Fetchmail part) is now hosted on <a href="https://github.com/maff/fetchmailgen">GitHub</a> as I rarely use SVN anymore and the SVN may go offline in the near future. If anybody is interested in the Sieve part, just drop me a line.</li>
</ol>
<img src="http://feeds.feedburner.com/~r/mafflog/~4/QpWcc7uLu6I" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://ailoo.net/2011/03/fetchmail-sieve-on-ispmail-setup-update/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://ailoo.net/2011/03/fetchmail-sieve-on-ispmail-setup-update/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=fetchmail-sieve-on-ispmail-setup-update</feedburner:origLink></item>
		<item>
		<title>Restore MySQL databases from raw *.frm files</title>
		<link>http://feedproxy.google.com/~r/mafflog/~3/2ll2KGjYE6A/</link>
		<comments>http://ailoo.net/2011/03/restore-mysql-databases-from-raw-frm-files/#comments</comments>
		<pubDate>Tue, 01 Mar 2011 17:57:58 +0000</pubDate>
		<dc:creator>Mathias</dc:creator>
				<category><![CDATA[How-Tos]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Server]]></category>
		<category><![CDATA[backup]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[raw]]></category>
		<category><![CDATA[restore]]></category>

		<guid isPermaLink="false">http://ailoo.net/?p=1907</guid>
		<description><![CDATA[I recently needed to restore data from a MySQL server where the host machine crashed and where I unfortunately didn&#8217;t have a proper dump backup &#8211; all I had was a backup of the MySQL data directory (/var/lib/mysql in case of Debian). After some googling I didn&#8217;t find a simple solution how to restore databases [...]]]></description>
			<content:encoded><![CDATA[<p>I recently needed to restore data from a MySQL server where the host machine crashed and where I unfortunately didn&#8217;t have a proper dump backup &#8211; all I had was a backup of the MySQL data directory (<kbd>/var/lib/mysql</kbd> in case of Debian). After some googling I didn&#8217;t find a simple solution how to restore databases out of this backup. The solution which worked in the end was the following: I installed a fresh MySQL server in a virtual machine and replaced its data directory with the one from my backup (I had exactly the same MySQL versions on both machines). This allowed me to access the databases and create proper dumps which I could import in my real server later.</p>
<p>So, step one: in a virtual machine/spare server/local pc/whatever install a MySQL server and replace its data directory:</p>
<pre class="shell">$ aptitude install mysql-server
$ /etc/init.d/mysql stop
$ mv /var/lib/mysql /var/lib/mysql.orig
$ cp -pr /tmp/backup/mysql /var/lib
$ chown -R mysql.mysql /var/lib/mysql</pre>
<p>I also checked that file permissions match the normal permissions on Debian MySQL installations. Should be like this:</p>
<pre class="shell">root@host:/var/lib/mysql# ls -al
drwx------  5 mysql mysql     4096 Mar  1 18:20 .
drwxr-xr-x 33 root  root      4096 Mar  1 18:20 ..
-rw-r--r--  1 root  root         0 Mar  1 18:07 debian-5.1.flag
-rw-rw----  1 mysql mysql 27262976 Mar  1 18:21 ibdata1
-rw-rw----  1 mysql mysql  5242880 Mar  1 18:21 ib_logfile0
-rw-rw----  1 mysql mysql  5242880 Mar  1 18:21 ib_logfile1
drwx------  2 mysql mysql     4096 Mar  1 18:20 database1
drwx------  2 mysql mysql     4096 Mar  1 18:21 database2
drwx------  2 mysql root      4096 Mar  1 18:08 mysql
-rw-------  1 root  root         6 Mar  1 18:08 mysql_upgrade_info

root@host:/var/lib/mysql# ls -al database1
drwx------ 2 mysql mysql 4096 Mar  1 18:20 .
drwx------ 5 mysql mysql 4096 Mar  1 18:20 ..
-rw-rw---- 1 mysql mysql   65 Mar  1 18:20 db.opt
-rw-rw---- 1 mysql mysql 8668 Mar  1 18:20 table1.frm
-rw-rw---- 1 mysql mysql  879 Mar  1 18:20 table2.frm
-rw-rw---- 1 mysql mysql 1520 Mar  1 18:20 table3.frm</pre>
<p>Now you can try to start the server and look if your databases are readable:</p>
<pre class="shell">$ /etc/init.d/mysql start
$ mysql -uroot -p -e "show databases;"
Enter password:
+--------------------+
| Database           |
+--------------------+
| information_schema |
| database1          |
| database1          |
| mysql              |
+--------------------+</pre>
<p>Alright, if this works, simply dump your needed databases with <kbd>mysqldump</kbd>, transfer them to your server and import them normally.</p>
<pre class="shell">$ mysqldump -uroot -p database1 > /tmp/database1.sql
$ scp /tmp/database1.sql user@server:/tmp</pre>
<p>On the server:</p>
<pre class="shell">$ mysql -uroot -p -e "create database database1;"
$ mysql -uroot -p database1 < /tmp/database1.sql</pre>
<p>And don't forget to restore the temporary MySQL server to normal operation in case you need it later.</p>
<pre class="shell">$ /etc/init.d/mysql stop
$ rm -rf /var/lib/mysql
$ mv /var/lib/mysql.orig /var/lib/mysql
$ /etc/init.d/mysql start</pre>
<img src="http://feeds.feedburner.com/~r/mafflog/~4/2ll2KGjYE6A" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://ailoo.net/2011/03/restore-mysql-databases-from-raw-frm-files/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://ailoo.net/2011/03/restore-mysql-databases-from-raw-frm-files/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=restore-mysql-databases-from-raw-frm-files</feedburner:origLink></item>
		<item>
		<title>Use a LVM volume group with libvirt</title>
		<link>http://feedproxy.google.com/~r/mafflog/~3/TE6Rbi1LCNk/</link>
		<comments>http://ailoo.net/2011/02/use-a-lvm-volume-group-with-libvirt/#comments</comments>
		<pubDate>Sat, 26 Feb 2011 17:54:10 +0000</pubDate>
		<dc:creator>Mathias</dc:creator>
				<category><![CDATA[How-Tos]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Server]]></category>
		<category><![CDATA[kvm]]></category>
		<category><![CDATA[libvirt]]></category>
		<category><![CDATA[lvm]]></category>
		<category><![CDATA[virtualization]]></category>
		<category><![CDATA[volume group]]></category>

		<guid isPermaLink="false">http://ailoo.net/?p=1903</guid>
		<description><![CDATA[A short howto how to use a LVM volume group with libvirt on Debian Squeeze (used for KVM VMs in my case). I assume your VG already exists and is dedicated for libvirt usage. In my case it&#8217;s /dev/vg1. First of all, create the XML definition for the storage pool in /etc/libvirt/storage/vg1.xml. This is the [...]]]></description>
			<content:encoded><![CDATA[<p>A short howto how to use a LVM volume group with libvirt on Debian Squeeze (used for KVM VMs in my case). I assume your VG already exists and is dedicated for libvirt usage. In my case it&#8217;s <kbd>/dev/vg1</kbd>.</p>
<p>First of all, create the XML definition for the storage pool in <kbd>/etc/libvirt/storage/vg1.xml</kbd>. This is the minimal configuration needed, libvirt will extend it with things like UUID when you define it.</p>
<pre class="code prettyprint xml">
&lt;pool type=&#039;logical&#039;&gt;
  &lt;name&gt;vg1&lt;/name&gt;
  &lt;target&gt;
    &lt;path&gt;/dev/vg1&lt;/path&gt;
  &lt;/target&gt;
&lt;/pool&gt;
</pre>
<p>Now you can tell libvirt about the new storage pool and let it start automatically.</p>
<pre class="shell">$ virsh pool-define /etc/libvirt/storage/vg1.xml
$ virsh pool-start vg1
$ virsh pool-autostart vg1
$ virsh pool-info vg1</pre>
<p>Creating virtual machines inside that storage pool is easy as pie:</p>
<pre class="shell">$ virt-install -d --hvm --vnc --name=vm01 \
    --ram 512 --disk pool=vg1,size=10,bus=virtio,cache=none \
    --network network=default,model=virtio \
    --location=http://ftp.debian.org/debian/dists/squeeze/main/installer-amd64/ \
    --os-type=linux --os-variant=debiansqueeze
</pre>
<p>Cheers!</p>
<img src="http://feeds.feedburner.com/~r/mafflog/~4/TE6Rbi1LCNk" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://ailoo.net/2011/02/use-a-lvm-volume-group-with-libvirt/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<feedburner:origLink>http://ailoo.net/2011/02/use-a-lvm-volume-group-with-libvirt/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=use-a-lvm-volume-group-with-libvirt</feedburner:origLink></item>
		<item>
		<title>eZPublish access/change user account from PHP</title>
		<link>http://feedproxy.google.com/~r/mafflog/~3/kTuVsmqJOfQ/</link>
		<comments>http://ailoo.net/2011/02/ezpublish-access-change-user-account/#comments</comments>
		<pubDate>Tue, 15 Feb 2011 12:05:58 +0000</pubDate>
		<dc:creator>Mathias</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[How-Tos]]></category>
		<category><![CDATA[cms]]></category>
		<category><![CDATA[ezpublish]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[user account]]></category>

		<guid isPermaLink="false">http://ailoo.net/?p=1892</guid>
		<description><![CDATA[It took me some time to figure out how to access and change a user account in eZPublish from PHP. Here&#8217;s an example how to achieve this: // user node $node = eZContentObjectTreeNode::fetch($nodeID); // user object $dataMap = $node-&#62;dataMap(); // change attribute $firstname = $dataMap[&#039;firstname&#039;]; $firstname-&#62;setAttribute(&#039;data_text&#039;, &#039;Foo&#039;); $firstname-&#62;sync(); // user account attribute $user = $dataMap[&#039;user_account&#039;]; [...]]]></description>
			<content:encoded><![CDATA[<p>It took me some time to figure out how to access and change a user account in eZPublish from PHP. Here&#8217;s an example how to achieve this:</p>
<pre class="code prettyprint php">
// user node
$node = eZContentObjectTreeNode::fetch($nodeID);

// user object
$dataMap = $node-&gt;dataMap();

// change attribute
$firstname = $dataMap[&#039;firstname&#039;];
$firstname-&gt;setAttribute(&#039;data_text&#039;, &#039;Foo&#039;);
$firstname-&gt;sync();

// user account attribute
$user = $dataMap[&#039;user_account&#039;];
$userData = $user-&gt;content();

// user settings
$userSetting = eZUserSetting::fetch($user-&gt;ContentObjectID);

// get account status
$isEnabled = $userSetting-&gt;attribute(&#039;is_enabled&#039;);

// enable user account
$userSetting-&gt;setAttribute(&#039;is_enabled&#039;, 1);
$userSetting-&gt;store();
</pre>
<p>Or if you just want to access the user account object or the user setting directly:</p>
<pre class="code prettyprint php">
// user account object
$user = eZUser::fetch($objectID);

// user settings
$userSetting = eZUserSetting::fetch($objectID);
</pre>
<img src="http://feeds.feedburner.com/~r/mafflog/~4/kTuVsmqJOfQ" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://ailoo.net/2011/02/ezpublish-access-change-user-account/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://ailoo.net/2011/02/ezpublish-access-change-user-account/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=ezpublish-access-change-user-account</feedburner:origLink></item>
		<item>
		<title>LaTeX build server with Git and Hudson on Ubuntu 10.04</title>
		<link>http://feedproxy.google.com/~r/mafflog/~3/Ij780ZtaCwI/</link>
		<comments>http://ailoo.net/2010/06/latex-build-server-git-hudson-ubuntu-10-04/#comments</comments>
		<pubDate>Sun, 06 Jun 2010 09:25:25 +0000</pubDate>
		<dc:creator>Mathias</dc:creator>
				<category><![CDATA[How-Tos]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Server]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[ci]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[hudson]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[latex]]></category>
		<category><![CDATA[tomcat]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://maff.ailoo.net/?p=1776</guid>
		<description><![CDATA[I&#8217;m currently working on a bigger paper for university using LaTeX. As it&#8217;s necessary to compile source files multiple times (especially when using BibTeX or TOCs), build runs can take quite some time. As an example, my current build script: #!/bin/bash BN=paper pdflatex -interaction=nonstopmode $BN.tex bibtex $BN pdflatex -interaction=nonstopmode $BN.tex bibtex $BN pdflatex -interaction=nonstopmode $BN.tex [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m currently working on a bigger paper for university using LaTeX. As it&#8217;s necessary to compile source files multiple times (especially when using BibTeX or TOCs), build runs can take quite some time. As an example, my current build script:</p>
<pre class="code prettyprint bash">
#!/bin/bash
BN=paper
pdflatex -interaction=nonstopmode $BN.tex
bibtex $BN
pdflatex -interaction=nonstopmode $BN.tex
bibtex $BN
pdflatex -interaction=nonstopmode $BN.tex
makeindex -s $BN.ist -t $BN.glg -o $BN.gls $BN.glo
pdflatex -interaction=nonstopmode $BN.tex
pdflatex -interaction=nonstopmode $BN.tex
rm -rf $BN.aux
rm -rf $BN.lof
rm -rf $BN.lot
rm -rf $BN.out
rm -rf $BN.toc
rm -rf $BN.bbl
rm -rf $BN.blg
rm -rf $BN.brf
rm -rf $BN.idx
rm -rf $BN.glo
rm -rf $BN.ist
rm -rf $BN.glg
rm -rf $BN.gls
rm -rf texput.log
</pre>
<p>This is OK on my workstation, but running a build on my notebook using a small 1.4 GHz single core processor can take up to a minute which is definitely too long. So I looked for solutions how to move the build process to a central server. As I was already using Git for source control on the project, I tried setting up a remote repository on the server which triggered a build using a post-receive script. This basically worked fine, but I wanted to go a step further. I had a look at CI servers and gave <a href="http://hudson-ci.org/">Hudson</a> a try as it seems to have a lot of features while being quite easy to set up.</p>
<p>The result is the following: Hudson is polling the Git repository (can be remote or local, in my case it&#8217;s a self-hosted remote gitosis installation, but could be github too), starting a new build on changes and publishing the resulting PDF if successful. Hudson is accessible over <kbd>https</kbd> using an Apache2 server as frontend to a Tomcat installation.</p>
<p>Ready? Let&#8217;s go.</p>
<p><span id="more-1776"></span></p>
<h3 id="installing-the-toolset">Installing the toolset</h3>
<p>First of all, install some basic tools (including git).</p>
<pre class="shell">aptitude install nano curl wget git-core</pre>
<p>We need Java to run Hudson, but Sun&#8217;s Java has moved to the partner repository which is not enabled by default. Add the repository and install the Java JDK:</p>
<pre class="shell">echo "deb http://archive.canonical.com/ubuntu  lucid partner" >> /etc/apt/sources.list
aptitude update
aptitude install sun-java6-jdk</pre>
<p>To build LaTeX papers, we need (of course) a TeX distribution. Texlive should provide you with all you need. I simply installed the full distribution as I didn&#8217;t want to hassle with missing packages. Be aware that <kbd>texlive-full</kbd> is quite heavy:</p>
<pre>Need to get 1035MB of archives. After unpacking 1862MB will be used.</pre>
<p>If you are not lazy and are limited on disk space, just install the texlive-* packages you need.</p>
<pre class="shell">aptitude install texlive-full</pre>
<p>Install the web server stack:</p>
<pre class="shell">aptitude install apache2 tomcat6 libapache2-mod-jk libapache2-mod-gnutls ssl-cert</pre>
<p>We&#8217;ll use <kbd>ant</kbd> build files to build our projects, so install ant:</p>
<pre class="shell">aptitude install ant</pre>
<h3 id="configure-apache-and-mod_jk">Configure Apache and mod_jk</h3>
<p>First of all, activate needed apache modules:</p>
<pre class="shell">a2enmod rewrite jk gnutls</pre>
<p>Enable name-based virtual hosts on SSL. Edit <kbd>/etc/apache2/ports.conf</kbd> and add a <kbd>NameVirtualHost *:443</kbd> in the mod_gnutls section:</p>
<pre class="code prettyprint xml">
...
&lt;IfModule mod_gnutls.c&gt;
    NameVirtualHost *:443
    Listen 443
&lt;/IfModule&gt;
</pre>
<p>Disable and remove the default apache config:</p>
<pre class="shell">a2dissite default
rm /etc/apache2/sites-available/default
rm /etc/apache2/sites-available/default-ssl</pre>
<p>Create a new virtual host file in <kbd>/etc/apache2/sites-available/hudson</kbd>. Mine looks like this (you&#8217;ll probably want to adjust the SSL certificates or omit the SSL part by removing the *:80 vhost, changing the *:443 vhost to *:80 and removing the gnutls lines):</p>
<pre class="code prettyprint xml">
&lt;VirtualHost *:80&gt;
        ServerName hudson.example.com

        RewriteEngine On
        RewriteRule ^(.*)$ https://hudson.example.com$1  [R,L]
&lt;/VirtualHost&gt;
&lt;VirtualHost *:443&gt;
        ServerName hudson.example.com

        GnuTLSEnable on
        GnuTLSCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem
        GnuTLSKeyFile         /etc/ssl/private/ssl-cert-snakeoil.key
        GnuTLSPriorities NORMAL

        DocumentRoot /var/lib/tomcat6/webapps/ROOT/
        &lt;Directory &quot;/var/lib/tomcat6/webapps/ROOT/&quot;&gt;
                Options Indexes FollowSymlinks +Includes
                AllowOverride All
        &lt;/Directory&gt;

        JkMount /* hudson

        ErrorLog /var/log/apache2/hudson.error.log
        CustomLog /var/log/apache2/hudson.access.log combined
        LogLevel error
&lt;/VirtualHost&gt;
</pre>
<p>Create the file <kbd>/etc/apache2/mods-available/jk.conf</kbd> with the following content:</p>
<pre class="code prettyprint bash">
JkWorkersFile /etc/apache2/workers.properties
JkLogFile /var/log/apache2/mod_jk.log
JkLogLevel info
</pre>
<p>Disable and re-enable the jk module to let apache use <kbd>jk.conf</kbd></p>
<pre class="shell">a2dismod jk
a2enmod jk</pre>
<p>Create the file <kbd>/etc/apache2/workers.properties</kbd>:</p>
<pre class="code prettyprint bash">
workers.tomcat_home=/usr/share/tomcat6
workers.java_home=/usr/lib/jvm/java-6-sun
ps=/
worker.list=hudson

worker.hudson.port=8009
worker.hudson.host=localhost
worker.hudson.type=ajp13
worker.hudson.lbfactor=1
</pre>
<p>Enable the virtual host and restart apache. When you try to connect to your server through your browser you should get redirected to the SSL vhost. The site should say <kbd>503 Service Temporarily Unavailable</kbd> as tomcat is not configured yet.</p>
<pre class="shell">a2ensite hudson
/etc/init.d/apache2 restart</pre>
<h3 id="configure-tomcat">Configure Tomcat</h3>
<p>Edit <kbd>/etc/tomcat6/server.xml</kbd> and enable the AJP connector on port 8009 by uncommenting the following line  (somewhere around line 93):</p>
<pre class="code prettyprint xml">
    &lt;!-- Define an AJP 1.3 Connector on port 8009 --&gt;
    &lt;Connector port=&quot;8009&quot; protocol=&quot;AJP/1.3&quot; redirectPort=&quot;8443&quot; /&gt;
</pre>
<p>Bind the direct access to tomcat on port 8080 to the local interface. Edit line 71 and add the <kbd>address</kbd> attribute:</p>
<pre class="code prettyprint xml">
    &lt;!-- A &quot;Connector&quot; represents an endpoint by which requests are received
         and responses are returned. Documentation at :
         Java HTTP Connector: /docs/config/http.html (blocking &amp; non-blocking)
         Java AJP  Connector: /docs/config/ajp.html
         APR (HTTP/AJP) Connector: /docs/apr.html
         Define a non-SSL HTTP/1.1 Connector on port 8080
    --&gt;
    &lt;Connector port=&quot;8080&quot; address=&quot;127.0.0.1&quot; protocol=&quot;HTTP/1.1&quot;
               connectionTimeout=&quot;20000&quot;
               URIEncoding=&quot;UTF-8&quot;
               redirectPort=&quot;8443&quot; /&gt;
</pre>
<p>Restart tomcat and connect to your apache virtual host defined before. You should see tomcat&#8217;s &#8220;It works!&#8221; page.</p>
<h3 id="deploy-hudson">Deploy hudson</h3>
<p>As hudson is the only application running on this tomcat instance, I deployed it as root application.</p>
<pre class="shell">/etc/init.d/tomcat6 stop
rm -rf /var/lib/tomcat6/webapps/ROOT
wget http://hudson-ci.org/latest/hudson.war -O /var/lib/tomcat6/webapps/ROOT.war</pre>
<p>Hudson needs the env variable <kbd>HUDSON_HOME</kbd> to run. Edit <kbd>/etc/tomcat6/context.xml</kbd> and add the following line inside the <kbd>Context</kbd> element:</p>
<pre class="code prettyprint xml">
&lt;Environment name=&quot;HUDSON_HOME&quot; value=&quot;/var/lib/tomcat6/webapps/ROOT&quot; type=&quot;java.lang.String&quot; override=&quot;false&quot; /&gt;
</pre>
<p>Now start tomcat and reload the page. You should see a running hudson instance.</p>
<h3 id="configure-hudson">Configure hudson</h3>
<p>Go to Manage/Configuration and set all options you need (e.g. email settings). If you are running this on a public server, make sure you set some kind of hudson security (I use the internal hudson user database with projectmatrix security). In addition set the environment variable <kbd>HOME</kbd> with <kbd>/usr/share/tomcat6</kbd> as value (this is needed for git to work properly).</p>
<p>Next, go to the plugin management site and install the plugins you need. I installed &#8220;Hudson GIT plugin&#8221; and &#8220;Green balls&#8221;. After installation restart hudson.</p>
<h4 id="hudson-and-git">Hudson and Git</h4>
<p>To make hudson work with git, we need to configure git for the tomcat user. First, create a <kbd>.gitconfig</kbd> file in <kbd>/usr/share/tomcat6</kbd> (tomcat6&#8242;s homedir):</p>
<pre class="code prettyprint bash">
[user]
        name = Hudson
        email = hudson@example.com
</pre>
<p>If you want to use repositories only accessible via SSH, tomcat needs a SSH keypair. Create a keypair with an empty passphrase:</p>
<pre class="shell">cd /usr/share/tomcat6
mkdir .ssh
ssh-keygen -t rsa -f .ssh/id_rsa
chown tomcat6.tomcat6 .ssh -R</pre>
<p>Hudson git cloning will fail if the server you are connecting to is not in tomcat&#8217;s <kbd>known_hosts</kbd> file. For each server you want to connect to, clone a random repository. This will add the host and avoid later problems. Of course, tomcat has to have access to that server you are cloning from (you need set up the public key we created before on the server &#8211; e.g. add it to your public keys on github). For example:</p>
<pre class="shell">cd /tmp
sudo -u tomcat6 git clone git@example.com:testrepo.git
# answer with yes
rm -rf testrepo</pre>
<h4 id="create-a-new-job">Create a new job</h4>
<p>Hudson provides different methods to specify how to build a job &#8211; I&#8217;m using ant build files. My git repository layout is basically the following:</p>
<pre>.gitignore
src/paper.tex</pre>
<p>I created a sample project on github to test the build process. You can find it at <a href="http://github.com/maff/sampletex">http://github.com/maff/sampletex</a>.</p>
<p>To reflect the build process listed above in the shell script, I created the following buildfile and saved it as <kbd>/var/lib/tomcat6/webapps/ROOT/build-latex.xml</kbd>. The file expects a parameter <kbd>basename</kbd>, which is the base name of the tex source to be compiled. In my case, it&#8217;s set to <kbd>paper</kbd> (see job configuration below). Of course, you&#8217;ll have to adapt the build file if you need a different build process</p>
<pre class="code prettyprint xml">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;project name=&quot;latex&quot; default=&quot;build&quot; basedir=&quot;.&quot;&gt;
  &lt;property environment=&quot;env&quot;/&gt;
  &lt;property name=&quot;workspace&quot; value=&quot;${env.WORKSPACE}&quot;/&gt;

  &lt;target name=&quot;build&quot;&gt;
    &lt;antcall target=&quot;clean&quot; /&gt;
    &lt;antcall target=&quot;cleanoutput&quot; /&gt;
    &lt;antcall target=&quot;compile&quot; /&gt;
    &lt;antcall target=&quot;clean&quot; /&gt;
  &lt;/target&gt;

  &lt;target name=&quot;pdflatex&quot;&gt;
    &lt;exec executable=&quot;pdflatex&quot; dir=&quot;${workspace}/src&quot;&gt;
      &lt;arg line=&quot;-interaction=nonstopmode ${basename}.tex&quot; /&gt;
    &lt;/exec&gt;
  &lt;/target&gt;

  &lt;target name=&quot;bibtex&quot;&gt;
    &lt;exec executable=&quot;bibtex&quot; dir=&quot;${workspace}/src&quot;&gt;
      &lt;arg line=&quot;${basename}&quot; /&gt;
    &lt;/exec&gt;
  &lt;/target&gt;

  &lt;target name=&quot;makeindex&quot;&gt;
    &lt;exec executable=&quot;makeindex&quot; dir=&quot;${workspace}/src&quot;&gt;
      &lt;arg line=&quot;-s ${basename}.ist -t ${basename}.glg -o ${basename}.gls ${basename}.glo&quot; /&gt;
    &lt;/exec&gt;
  &lt;/target&gt;

  &lt;target name=&quot;compile&quot;&gt;
    &lt;antcall target=&quot;pdflatex&quot; /&gt;
    &lt;antcall target=&quot;bibtex&quot; /&gt;
    &lt;antcall target=&quot;pdflatex&quot; /&gt;
    &lt;antcall target=&quot;bibtex&quot; /&gt;
    &lt;antcall target=&quot;pdflatex&quot; /&gt;
    &lt;antcall target=&quot;makeindex&quot; /&gt;
    &lt;antcall target=&quot;pdflatex&quot; /&gt;
    &lt;antcall target=&quot;pdflatex&quot; /&gt;
  &lt;/target&gt;

  &lt;target name=&quot;clean&quot;&gt;
    &lt;delete&gt;
      &lt;fileset dir=&quot;${workspace}/src&quot; includes=&quot;${basename}.aux, ${basename}.lof, ${basename}.lot, ${basename}.out, ${basename}.toc, ${basename}.bbl, ${basename}.blg, ${basename}.brf, ${basename}.idx, ${basename}.glo, ${basename}.ist, ${basename}.glg, ${basename}.gls, texput.log&quot; /&gt;
    &lt;/delete&gt;
  &lt;/target&gt;

  &lt;target name=&quot;cleanoutput&quot;&gt;
    &lt;delete&gt;
      &lt;fileset dir=&quot;${workspace}/src&quot; includes=&quot;${basename}.pdf, ${basename}.log&quot; /&gt;
    &lt;/delete&gt;
  &lt;/target&gt;
&lt;/project&gt;
</pre>
<p>Switch to the web interface and create a new job. Choose &#8220;Free style&#8221; software project and click next. Using the default settings, I changed the following (labels may differ a bit as my interface is in german, but you&#8217;ll find what you need):</p>
<dl>
<dt>Source-Code-Management</dt>
<dd>Choose Git and set the repo-URL (can be local or remote, e.g. <kbd>/tmp/project.git</kbd>, <kbd>git://example.com/project.git</kbd> or <kbd>git@example.com:project.git</kbd>)</dd>
<dt>Build trigger</dt>
<dd>Select &#8220;poll SCM&#8221; and set the value to a valid cron-style line. <kbd>* * * * *</kbd> would poll the repository every minute and build the project if it finds changes.</dd>
<dt>Build process</dt>
<dd>Add an ant task, click on advanced and specify <kbd>../../../build-latex.xml</kbd> as buildfile. Additionally enter <kbd>basename=paper</kbd> in the properties input (specifies the file basename mentioned before).</dd>
<dt>Post-build</dt>
<dd>I only chose &#8220;archive artifacts&#8221; and set the pattern to <kbd>src/paper.pdf, src/paper.log</kbd>. This depends on your environment and your needs.</dd>
</dl>
<h4 id="build">Build!</h4>
<p>Alright, time to test our setup. Select the newly created job and click build in the left menu. If all goes well, the build will succeed and you can access the built PDF directly from the web interface. Take a look at the job&#8217;s console output to identify potential errors. Happy building :)</p>
<img src="http://feeds.feedburner.com/~r/mafflog/~4/Ij780ZtaCwI" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://ailoo.net/2010/06/latex-build-server-git-hudson-ubuntu-10-04/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<feedburner:origLink>http://ailoo.net/2010/06/latex-build-server-git-hudson-ubuntu-10-04/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=latex-build-server-git-hudson-ubuntu-10-04</feedburner:origLink></item>
		<item>
		<title>Brownies</title>
		<link>http://feedproxy.google.com/~r/mafflog/~3/ATcgrod67gs/</link>
		<comments>http://ailoo.net/2010/05/brownies/#comments</comments>
		<pubDate>Sat, 22 May 2010 20:35:16 +0000</pubDate>
		<dc:creator>Mathias</dc:creator>
				<category><![CDATA[Cooking]]></category>
		<category><![CDATA[brownies]]></category>
		<category><![CDATA[dessert]]></category>
		<category><![CDATA[kuchen]]></category>
		<category><![CDATA[schokolade]]></category>
		<category><![CDATA[vanilleeis]]></category>

		<guid isPermaLink="false">http://maff.ailoo.net/?p=1764</guid>
		<description><![CDATA[Fast schon pervers schokoladig :) Am besten außen knusprig und innen noch schön saftig und weich. Zutaten (reicht für ca. 16-20 kleine Quadrate) 125g Zartbitterschokolade (mindestens 70% Kakao) 100g Vollmilchschokolade 75g Weiße Schokolade 125g Butter 125g Zucker 125g Mehl 125ml Sahne 60g Kakaopulver 2 Eier 1 Schuss Rum Nach Belieben Nüsse o.Ä. Backofen auf 200°C [...]]]></description>
			<content:encoded><![CDATA[<p>Fast schon pervers schokoladig :) Am besten außen knusprig und innen noch schön saftig und weich.</p>
<p><span id="more-1764"></span></p>
<h4 id="zutaten-reicht-fr-ca-16-20-kleine-quadrate">Zutaten (reicht für ca. 16-20 kleine Quadrate)</h4>
<ul>
<li>125g Zartbitterschokolade (mindestens 70% Kakao)</li>
<li>100g Vollmilchschokolade</li>
<li>75g Weiße Schokolade</li>
<li>125g Butter</li>
<li>125g Zucker</li>
<li>125g Mehl</li>
<li>125ml Sahne</li>
<li>60g Kakaopulver</li>
<li>2 Eier</li>
<li>1 Schuss Rum</li>
<li>Nach Belieben Nüsse o.Ä.</li>
</ul>
<p>Backofen auf 200°C Ober-/Unterhitze vorheizen. Weiße und Vollmilchschokolade hacken oder fein raspeln. Zartbitterschokolade über dem Wasserbad schmelzen, dann die Butter hinzufügen. Eier mit dem Zucker schaumig schlagen, dann langsam Mehl und Kakao einrühren. Sahne und geschmolzene Schokolade hinzufügen und zu einer gleichmäßigen Masse verarbeiten. Zum Schluss die geraspelten Schokoladestückchen untermischen. Nach Belieben mit Rum oder Nüssen (z.B. Pinienkerne oder Cashews) verfeinern.</p>
<p>Eine kleine Backform ausfetten und die Masse ca. 3 cm hoch in die Form füllen. Ab in den Ofen und ca. 20-25 min backen, bis sich oben eine knusprige Schicht gebildet hat, die Brownies innen aber noch schön feucht sind (zum Testen einfach mit einem trockenen Zahnstocher hineinstechen &#8211; es sollte noch etwas daran kleben bleiben). Aus dem Ofen nehmen, aufschneiden und lauwarm oder ausgekühlt servieren (z.B. mit Vanilleeis, Minze und Sauerkirschen).</p>
<img src="http://feeds.feedburner.com/~r/mafflog/~4/ATcgrod67gs" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://ailoo.net/2010/05/brownies/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://ailoo.net/2010/05/brownies/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=brownies</feedburner:origLink></item>
		<item>
		<title>Check broken links/rewrites with curl</title>
		<link>http://feedproxy.google.com/~r/mafflog/~3/198hKZunTGY/</link>
		<comments>http://ailoo.net/2010/04/check-broken-linksrewrites-with-curl/#comments</comments>
		<pubDate>Fri, 16 Apr 2010 16:55:01 +0000</pubDate>
		<dc:creator>Mathias</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[How-Tos]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[404]]></category>
		<category><![CDATA[broken]]></category>
		<category><![CDATA[check]]></category>
		<category><![CDATA[curl]]></category>
		<category><![CDATA[link]]></category>
		<category><![CDATA[rewrite]]></category>

		<guid isPermaLink="false">http://maff.ailoo.net/?p=1746</guid>
		<description><![CDATA[I just did a change in the URL structure of a bigger site and had to check if all existing URLs are rewritten correctly to the new structure. First I extracted a list of all URLs from the CMS of the old version and wrote them to a text file, each line containing an URL. [...]]]></description>
			<content:encoded><![CDATA[<p>I just did a change in the URL structure of a bigger site and had to check if all existing URLs are rewritten correctly to the new structure. First I extracted a list of all URLs from the CMS of the old version and wrote them to a text file, each line containing an URL. Then I changed the structure and used the following shellscript to check each URL with curl and output the result. Afterwards it&#8217;s easy to analyze the results and check for broken links.</p>
<pre class="code prettyprint bash">
#!/bin/sh
while read f
do
  echo $f
  echo &quot;&quot;
  curl -IL --silent $f
  echo &quot;------------------&quot;
  echo &quot;&quot;
done &lt; $1
</pre>
<p>Usage:</p>
<pre class="shell">$ ./checklinks.sh links.txt > stats.txt</pre>
<img src="http://feeds.feedburner.com/~r/mafflog/~4/198hKZunTGY" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://ailoo.net/2010/04/check-broken-linksrewrites-with-curl/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://ailoo.net/2010/04/check-broken-linksrewrites-with-curl/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=check-broken-linksrewrites-with-curl</feedburner:origLink></item>
		<item>
		<title>Chicken Curry mit Mangochutney</title>
		<link>http://feedproxy.google.com/~r/mafflog/~3/PcR9Wwn8fGs/</link>
		<comments>http://ailoo.net/2010/01/chicken-curry-mit-mangochutney/#comments</comments>
		<pubDate>Thu, 28 Jan 2010 21:28:24 +0000</pubDate>
		<dc:creator>Mathias</dc:creator>
				<category><![CDATA[Cooking]]></category>
		<category><![CDATA[chutney]]></category>
		<category><![CDATA[curry]]></category>
		<category><![CDATA[huhn]]></category>
		<category><![CDATA[mango]]></category>

		<guid isPermaLink="false">http://maff.ailoo.net/?p=1720</guid>
		<description><![CDATA[Hatte noch ne Mango und 2 Hühnerfilets im Kühlschrank und hab mal experimentiert, wie man das so kombinieren könnte. Ergebnis war gut, auch wenn ichs mit dem Chili leicht übertrieben habe. Die Mengen hier sind grob geschätzt, kann also gut abweichen. Das Ganze braucht seine Zeit, da man zuerst das Chutney kochen und dann das [...]]]></description>
			<content:encoded><![CDATA[<p>Hatte noch ne Mango und 2 Hühnerfilets im Kühlschrank und hab mal experimentiert, wie man das so kombinieren könnte. Ergebnis war gut, auch wenn ichs mit dem Chili leicht übertrieben habe. Die Mengen hier sind grob geschätzt, kann also gut abweichen. Das Ganze braucht seine Zeit, da man zuerst das Chutney kochen und dann das Fleisch marinieren muss. Ich hab am Vortag das Chutney gekocht und am Tag danach den Rest.</p>
<p><span id="more-1720"></span></p>
<h3 id="mangochutney">Mangochutney</h3>
<h4 id="zutaten">Zutaten</h4>
<ul>
<li>1 Mango (500 &#8211; 600g)</li>
<li>2-3 Schalotten oder &frac12; Zwiebel</li>
<li>1 rote Paprika</li>
<li>1 Limette</li>
<li>Chili</li>
<li>Salz</li>
<li>Zucker</li>
<li>Safran</li>
<li>Paprikapulver</li>
<li>1-2 Knoblauchzehen</li>
<li>schwarzer Pfeffer, grob gemahlen</li>
<li>etwas Grün von einer Frühlingszwiebel</li>
<li>Butter</li>
</ul>
<p>Butter in einem Topf zergehen lassen. Schalotten/Zwiebel und Paprika sehr fein schneiden und langsam in der Butter weich dünsten. Mit etwas Zucker bestäuben und leicht ankaramellisieren lassen. Mango schälen, vom Stein befreien und in kleine Würfel schneiden. Die Knoblauchzehen schälen, anquetschen, mit der Mango in den Topf geben und langsam andünsten. Abrieb und Saft von der Limette hinzugeben und mit ca. &frac12; Liter Wasser aufgießen. Paprikapulver und &frac12; TL Safranfäden hinzufügen und mit Salz, Pfeffer, Zucker und Chili abschmecken. Langsam für 30-45 Minuten köcheln lassen, damit das Ganze eindickt und die Mangos weich werden. Kurz vor Ende das feingeschnittene Grün einer Frühlingszwiebel hinzufügen. Mit einer Gabel die Mangostücke leicht zerquetschen.</p>
<p>Chutney durch ein feines Sieb drücken und den Saft aufbehalten.</p>
<h3 id="chicken-curry">Chicken Curry</h3>
<h4 id="zutaten1">Zutaten</h4>
<ul>
<li>~500g Hühnerfilet</li>
<li>1 rote Paprika</li>
<li>2 Frühlingszwiebeln</li>
<li>2 Karotten</li>
<li>2 Lorbeerblätter</li>
<li>ein paar Zuckerschoten</li>
<li>Kokosmilch</li>
<li>Sahne</li>
<li>Currypulver</li>
<li>1 Reihe Schokolade</li>
</ul>
<p>Hühnerfilet in Stücke schneiden und in dem Chutneysaft 2-3 Stunden marinieren. Paprika in Streifen schneiden, scharf anbraten, nach ein paar Minuten das Fleisch hinzugeben und ebenfalls kurz scharf anbraten. Currypulver hinzugeben, Hitze reduzieren und in feine Scheiben/Streifen geschnittene Karotten, Frühlingszwiebeln und Zuckerschoten hinzufügen. Ein paar Minuten dünsten lassen, 2-3 EL Chutney hinzufügen und mit etwas Kokosmilch und Sahne zum köcheln bringen. Lorbeerblätter hinzugeben und mit Salz, Pfeffer und fein geraspelter Schokolade abschmecken. Ca. 20min köcheln lassen, bis das Gemüse bissfest ist. Mit Reis servieren.</p>
<img src="http://feeds.feedburner.com/~r/mafflog/~4/PcR9Wwn8fGs" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://ailoo.net/2010/01/chicken-curry-mit-mangochutney/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://ailoo.net/2010/01/chicken-curry-mit-mangochutney/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=chicken-curry-mit-mangochutney</feedburner:origLink></item>
		<item>
		<title>/dev/pts errors on newly created Xen DomUs (Debian Lenny)</title>
		<link>http://feedproxy.google.com/~r/mafflog/~3/OXvSeQzSxqk/</link>
		<comments>http://ailoo.net/2009/12/devpts-errors-on-newly-created-xen-domus-debian-lenny/#comments</comments>
		<pubDate>Thu, 10 Dec 2009 11:56:06 +0000</pubDate>
		<dc:creator>Mathias</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Server]]></category>
		<category><![CDATA[debian]]></category>
		<category><![CDATA[devpts]]></category>
		<category><![CDATA[error]]></category>
		<category><![CDATA[lennyl]]></category>
		<category><![CDATA[xen]]></category>

		<guid isPermaLink="false">http://maff.ailoo.net/?p=1691</guid>
		<description><![CDATA[Today was the first time I had to create a new DomU after upgrading my Xen setup to Debian Lenny. When I booted the VM and logged in via xm console I got some strange errors when installing packages: Can not write log, openpty() failed (/dev/pts not mounted?) Additionally, after setting up SSH, I got [...]]]></description>
			<content:encoded><![CDATA[<p>Today was the first time I had to create a new DomU after <a href="http://ailoo.net/2009/04/upgrade-from-debian-etch-xen-30-to-debian-lenny-xen-32-amd64/">upgrading my Xen setup to Debian Lenny</a>. When I booted the VM and logged in via <kbd>xm console</kbd> I got some strange errors when installing packages:</p>
<pre class="shell">Can not write log, openpty() failed (/dev/pts not mounted?)</pre>
<p>Additionally, after setting up SSH, I got the following error when logging in with SSH:</p>
<pre class="shell">Server refused to allocate pty</pre>
<p>Solution: install <kbd>udev</kbd>, reboot the VM and you&#8217;re good to go.</p>
<img src="http://feeds.feedburner.com/~r/mafflog/~4/OXvSeQzSxqk" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://ailoo.net/2009/12/devpts-errors-on-newly-created-xen-domus-debian-lenny/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://ailoo.net/2009/12/devpts-errors-on-newly-created-xen-domus-debian-lenny/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=devpts-errors-on-newly-created-xen-domus-debian-lenny</feedburner:origLink></item>
		<item>
		<title>Thunderbird + Lightning on Ubuntu 9.10: unable to add new calendar</title>
		<link>http://feedproxy.google.com/~r/mafflog/~3/q2H5WB4HPGY/</link>
		<comments>http://ailoo.net/2009/11/thunderbird-lightning-on-ubuntu-9-10-unable-to-add-new-calendar/#comments</comments>
		<pubDate>Thu, 26 Nov 2009 12:44:57 +0000</pubDate>
		<dc:creator>Mathias</dc:creator>
				<category><![CDATA[How-Tos]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[bug]]></category>
		<category><![CDATA[calendar]]></category>
		<category><![CDATA[karmic]]></category>
		<category><![CDATA[lightning]]></category>
		<category><![CDATA[thunderbird]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://maff.ailoo.net/?p=1677</guid>
		<description><![CDATA[Just tried to setup Thunderbird + Lightning on Ubuntu Karmic, but somehow I couldn&#8217;t add a new calendar as the field was greyed out. Solution: install libstdc++5 (here from the Debian Lenny repository), un- and reinstall lightning and you&#8217;re good to go.]]></description>
			<content:encoded><![CDATA[<p>Just tried to setup Thunderbird + Lightning on Ubuntu Karmic, but somehow I couldn&#8217;t add a new calendar as the field was greyed out. Solution: install <kbd><a href="http://packages.debian.org/lenny/libstdc++5">libstdc++5</a></kbd> (here from the Debian Lenny repository), un- and reinstall lightning and you&#8217;re good to go.</p>
<img src="http://feeds.feedburner.com/~r/mafflog/~4/q2H5WB4HPGY" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://ailoo.net/2009/11/thunderbird-lightning-on-ubuntu-9-10-unable-to-add-new-calendar/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://ailoo.net/2009/11/thunderbird-lightning-on-ubuntu-9-10-unable-to-add-new-calendar/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=thunderbird-lightning-on-ubuntu-9-10-unable-to-add-new-calendar</feedburner:origLink></item>
		<item>
		<title>Integrate Spamassassin into Postfix/Dovecot</title>
		<link>http://feedproxy.google.com/~r/mafflog/~3/dBKBN_hN70s/</link>
		<comments>http://ailoo.net/2009/11/integrate-spamassassin-into-postfix-dovecot/#comments</comments>
		<pubDate>Wed, 25 Nov 2009 16:07:53 +0000</pubDate>
		<dc:creator>Mathias</dc:creator>
				<category><![CDATA[How-Tos]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Server]]></category>
		<category><![CDATA[dovecot]]></category>
		<category><![CDATA[ispmail]]></category>
		<category><![CDATA[postfix]]></category>
		<category><![CDATA[sieve]]></category>
		<category><![CDATA[spam]]></category>
		<category><![CDATA[spamassassin]]></category>

		<guid isPermaLink="false">http://maff.ailoo.net/?p=1641</guid>
		<description><![CDATA[As I stated before, I really like Christoph Haas&#8217; 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 [...]]]></description>
			<content:encoded><![CDATA[<p>As I <a href="http://ailoo.net/2008/08/fetchmail-sieve-virtual-mail-debian-etch/">stated before</a>, I really like <a href="http://workaround.org/ispmail">Christoph Haas&#8217; ISPMail setup</a> 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.</p>
<p>I clearly wanted to go with Spamassassin (SA), as I made good experiences with it in the past and it&#8217;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:</p>
<ul>
<li>Using <kbd>amavisd-new</kbd></li>
<li>Using Postfixs <kbd>content_filter</kbd></li>
</ul>
<p>I don&#8217;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&#8217;s address to be the same as the recipient&#8217;s one (which is done quite often). There&#8217;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.</p>
<p>So I was looking for another solution. I read some tutorials where people used procmail in user scripts to pass incoming mail to <kbd>spamc</kbd> before delivering it to the mailbox. I like this approach as the MTA isn&#8217;t involved into the spam filtering process, outgoing mail isn&#8217;t touched and you don&#8217;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&#8217;s inbox.</p>
<p>First I thought about Sieve, which is already running through Dovecot&#8217;s Sieve implementation until I noticed that Sieve is not able to call any external programs (correct me if I&#8217;m wrong). Then I had a look at <kbd>spamc</kbd> and Postfix&#8217; <kbd>master.cf</kbd>. <kbd>spamc</kbd> is capable to pipe its output to another program and in the ISPMail setup, Postfix passes the mail directly to Dovecot&#8217;s <kbd>deliver</kbd>, so why not just let Spamassassin check the mail right before it&#8217;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.</p>
<p>So much for the backstory, let&#8217;s get our hands dirty. Note: I&#8217;m running Debian Lenny.</p>
<p><span id="more-1641"></span></p>
<h3 id="installing-and-configuring-spamassassin">Installing and configuring Spamassassin</h3>
<p>First of all, let&#8217;s install our magic little helpers.</p>
<pre class="shell">$ aptitude install spamassassin pyzor razor</pre>
<h4 id="dcc">DCC</h4>
<p>Additionally, I want to use DCC, which is not in the Lenny repositories. First, let&#8217;s create a user for DCC.</p>
<pre class="shell">$ groupadd dcc
$ useradd -g dcc -s /bin/false -d /var/dcc dcc</pre>
<p>Then download and build it manually (you might need some additional Debian packages like <kbd>build-essential</kbd>). Just ignore the sendmail warnings during <kbd>configure</kbd>. The DCC version may vary.</p>
<pre class="shell">$ mkdir ~/build
$ cd ~/build
$ wget http://www.dcc-servers.net/dcc/source/dcc-dccproc.tar.Z
$ tar xzvf dcc-dccproc.tar.Z
$ cd dcc-dccproc-1.3.116
$ ./configure --with-uid=dcc
$ make
$ make install
$ chown -R dcc.dcc /var/dcc
$ ln -s /var/dcc/libexec/dccifd /usr/local/bin/dccifd</pre>
<h4 id="configuring-spamassassin">Configuring Spamassassin</h4>
<p>We make use of <kbd>spamd</kbd> to let SA run as daemon. To do this, we need a user for SA.</p>
<pre class="shell">$ groupadd spamd
$ useradd -g spamd -s /bin/false -d /var/lib/spamassassin spamd</pre>
<p>Then, edit <kbd>/etc/default/spamassassin</kbd> to look like the following listing (changed ENABLED to 1, added SAHOME and edited OPTIONS). The <kbd>virtual-config-dir</kbd> allows us to have separate user preferences and bayes databases for each virtual user. An improvement would be to save this data directly to the virtual user&#8217;s &#8220;home&#8221; directory in  <kbd>/var/vmail</kbd>, but for now I got it like this. The bayes database for <kbd>user@example.org</kbd> would therefore be stored in <kbd>/var/lib/spamassassin/users/example.org/user/</kbd>.</p>
<pre class="code prettyprint bash">
[...]

# Spamassassin home
SAHOME=&quot;/var/lib/spamassassin&quot;

# Change to one to enable spamd
ENABLED=1

# Options
# See man spamd for possible options. The -d option is automatically added.

# SpamAssassin uses a preforking model, so be careful! You need to
# make sure --max-children is not set to anything higher than 5,
# unless you know what you&#039;re doing.

OPTIONS=&quot;--create-prefs -x --max-children 3 --username spamd --helper-home-dir ${SAHOME} -s ${SAHOME}/spamd.log --virtual-config-dir=${SAHOME}/users/%d/%l&quot;

[...]
</pre>
<p>The home directory:</p>
<pre class="shell">$ mkdir -p /var/lib/spamassassin/users
$ chown spamd.spamd /var/lib/spamassassin -R</pre>
<p>Now, let&#8217;s do some configuring. You can find all relevant config files in <kbd>/etc/spamassassin</kbd>. First of all, <kbd>local.cf</kbd>:</p>
<pre class="code prettyprint bash">
[...]

#   Save spam messages as a message/rfc822 MIME attachment instead of
#   modifying the original message (0: off, 2: use text/plain instead)
#
report_safe 0

[...]

use_dcc 1
dcc_path /usr/local/bin/dccproc

use_pyzor 1
pyzor_path /usr/bin/pyzor

use_razor2 1
razor_config /etc/razor/razor-agent.conf
</pre>
<p>Afterwards, edit <kbd>v310.pre</kbd> and check that the DCC, Razor and Pyzor plugins are enabled (DCC is disabled by default).</p>
<p>You can check your Spamassassin configuration with lint (use the <kbd>-D</kbd> flag for output):</p>
<pre class="shell">$ spamassassin --lint</pre>
<p>And you can update SA&#8217;s rules with <kbd>sa-update</kbd>:</p>
<pre class="shell">$ sa-update --no-gpg</pre>
<p>Now we are ready to start the SA daemon (will be automatically started at boot time):</p>
<pre class="shell">$ /etc/init.d/spamassassin start</pre>
<h3 id="configure-postfix">Configure Postfix</h3>
<p>This step is quite easy. First, edit <kbd>/etc/postfix/master.cf</kbd>, copy the existing <kbd>dovecot</kbd> transport and edit it to look as follows (you can change the name ;)):</p>
<pre class="code prettyprint bash">
dovecot-spamass   unix  -       n       n       -       -       pipe
    flags=DRhu user=vmail:vmail argv=/usr/bin/spamc -u ${recipient} -e /usr/lib/dovecot/deliver -d ${recipient}
</pre>
<p>This transport will pass the mail to <kbd>spamc</kbd> which will pass it to <kbd>deliver</kbd> after checking.</p>
<p>Now just change the transport in <kbd>/etc/postfix/main.cf</kbd>. I used the second transport to be flexible. In case anything should go wrong with Spamassassin you just need to change the transport in <kbd>main.cf</kbd> and you get your mails without the SA step.</p>
<pre class="code prettyprint bash">
virtual_transport = dovecot-spamass
</pre>
<p>That&#8217;s all you need on the Postfix side. Just restart it to use the new transport.</p>
<pre class="shell">$ /etc/init.d/postfix restart</pre>
<h3 id="finishing-touches">Finishing touches</h3>
<p>Now let&#8217;s do some testing. Send yourself a mail and take a look at the mail headers. There should be quite a lot of new mail headers which get injected by Spamassassin (you can configure the headers in Spamassassin&#8217;s configuration). A normal non-spam mail could look like this:</p>
<pre>X-Spam-Checker-Version: SpamAssassin 3.2.5 (2008-06-10) on mail.example.com
X-Spam-Level: *
X-Spam-Status: No, score=1.2 required=5.0 tests=ALL_TRUSTED,AWL,
	TVD_SPACE_RATIO autolearn=no version=3.2.5</pre>
<p>Now cross your fingers and hope that a friendly spammer sends you new crap or just use the <a href="http://spamassassin.apache.org/gtube/">GTUBE</a> test (include that line in your mail). SA should recognize it as junk and give detailed information about it in its headers:</p>
<pre>X-Spam-Flag: YES
X-Spam-Checker-Version: SpamAssassin 3.2.5 (2008-06-10) on mail.example.com
X-Spam-Level: **************************************************
X-Spam-Status: Yes, score=1000.0 required=5.0 tests=ALL_TRUSTED,AWL,GTUBE
	autolearn=no version=3.2.5
X-Spam-Report: =?ISO-8859-1?Q?
	* 1000 GTUBE BODY: Test zur Pr=fcfung von Anti-Spam-Software</pre>
<p>Other example for a real spam mail:</p>
<pre>X-Spam-Flag: YES
X-Spam-Checker-Version: SpamAssassin 3.2.5 (2008-06-10) on mail.example.com
X-Spam-Level: *******************
X-Spam-Status: Yes, score=19.6 required=5.0 tests=BAD_ENC_HEADER,DCC_CHECK,
	DIGEST_MULTIPLE,HELO_LOCALHOST,HTML_MESSAGE,PYZOR_CHECK,
	RAZOR2_CF_RANGE_51_100,RAZOR2_CF_RANGE_E8_51_100,RAZOR2_CHECK,RDNS_NONE,
	URIBL_RHS_DOB,URIBL_SBL,URIBL_WS_SURBL autolearn=spam version=3.2.5
X-Spam-Report: =?ISO-8859-1?Q?
	*  0.9 URIBL_RHS_DOB Contains an URI of a new domain (Day Old Bread)
	*      [URIs: spammersdomain.com]
	*  2.1 URIBL_WS_SURBL Enth=e4lt URL in WS-Liste (www.surbl.org)
	*      [URIs: spammersdomain.com]
	*  4.5 HELO_LOCALHOST HELO_LOCALHOST
	*  2.9 BAD_ENC_HEADER Message has bad MIME encoding in the header
	*  0.0 HTML_MESSAGE BODY: Nachricht enth=e4lt HTML
	*  1.5 RAZOR2_CF_RANGE_E8_51_100 Razor2 gives engine 8 confidence level
	*      above 50%
	*      [cf:  58]
	*  0.5 RAZOR2_CHECK Gelistet im "Razor2"-System (http://razor.sf.net/)
	*  0.5 RAZOR2_CF_RANGE_51_100 Razor2 Spam-Bewertung liegt zwischen 51 und
	*      100
	*      [cf:  58]
	*  2.8 PYZOR_CHECK Gelistet im Pyzor-System (http://pyzor.sf.net/)
	*  1.4 DCC_CHECK Gelistet im DCC-System
	*      (http://rhyolite.com/anti-spam/dcc/)
	*  2.5 URIBL_SBL Enth=e4lt URL in SBL-Liste (http://www.spamhaus.org/sbl/)
	*      [URIs: spammersdomain.com]
	*  0.0 DIGEST_MULTIPLE Mehrere Internettests (Razor, DCC, Pyzor, etc.)
	*      treffen zu
	*  0.1 RDNS_NONE Delivered to trusted network by a host with no rDNS?=</pre>
<p>If you are wondering about the <kbd>autolearn</kbd> flag in the mail headers: SA triggers autolearning only starting from a certain treshold. For more information see <a href="http://wiki.apache.org/spamassassin/AutolearningNotWorking">Spamassassin Wiki/AutolearningNotWorking</a>.</p>
<h4 id="filtering">Filtering</h4>
<p>Using SA&#8217;s mail headers, you can easily filter your mails. A simple Sieve filter could look like this:</p>
<pre>require "fileinto";

if header :contains "X-Spam-Flag" ["YES"] {
  fileinto "Spam";
  stop;
}</pre>
<p>If you are using Thunderbird, you can even configure it to filter mail using SA&#8217;s headers (in your account settings), however this shifts the filtering a bit too much on the client side for my taste.</p>
<h4 id="per-user-preferences">Per-user preferences</h4>
<p>As we use SA&#8217;s <kbd>virtual-config-dir</kbd>, we have a separate bayes db for each virtual user and can additionally specify user preferences (like blacklists) on a per-user basis. To make use of this, create a file called <kbd>user_prefs</kbd> in the virtual user directory for SA and add individual rules there.</p>
<p>Example: add a blacklist entry for all mails which are recieved for <kbd>joe@example.com</kbd> (assuming joe has received any mail before and spamd created the needed directories):</p>
<pre class="shell">$ echo "blacklist_from jane@example.com" > /var/lib/spamassassin/users/example.com/joe/user_prefs</pre>
<p>You can try adding yourself to your blacklist and sending yourself a mail. If all is working fine, the mail should be classified as spam. Example:</p>
<pre>X-Spam-Flag: YES
X-Spam-Checker-Version: SpamAssassin 3.2.5 (2008-06-10) on mail.example.com
X-Spam-Level: **************************************************
X-Spam-Status: Yes, score=101.4 required=5.0 tests=ALL_TRUSTED,AWL,
	TVD_SPACE_RATIO,USER_IN_BLACKLIST autolearn=no version=3.2.5
X-Spam-Report: =?ISO-8859-1?Q?
	*  100 USER_IN_BLACKLIST From: address is in the user's black-list
[...]</pre>
<h3 id="conclusion">Conclusion</h3>
<p>This setup seems to me quite straightforward and lightweight, but it still needs some improvements like automated bayes database training (take a look at the first source) or moving user&#8217;s preferences to the database. However, the stock Spamassassin installation does its work quite reliably and is working fine at the moment.</p>
<h4 id="sources">Sources</h4>
<ul>
<li><a href="http://hints.jeb.be/2008/12/17/per-virtual-user-sa-learn-training/">http://hints.jeb.be/2008/12/17/per-virtual-user-sa-learn-training/</a></li>
<li><a href="http://www.dovecot.org/list/dovecot/2008-June/031175.html">http://www.dovecot.org/list/dovecot/2008-June/031175.html</a></li>
<li><a href="http://www.howtoforge.com/virtual-users-domains-postfix-courier-mysql-squirrelmail-debian-lenny-p3">http://www.howtoforge.com/virtual-users-domains-postfix-courier-mysql-squirrelmail-debian-lenny-p3</a></li>
<li><a href="http://www.debianhelp.co.uk/spam.htm">http://www.debianhelp.co.uk/spam.htm</a></li>
<li><a href="http://spamassassin.apache.org/full/3.1.x/doc/Mail_SpamAssassin_Conf.html">http://spamassassin.apache.org/full/3.1.x/doc/Mail_SpamAssassin_Conf.html</a></li>
</ul>
<img src="http://feeds.feedburner.com/~r/mafflog/~4/dBKBN_hN70s" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://ailoo.net/2009/11/integrate-spamassassin-into-postfix-dovecot/feed/</wfw:commentRss>
		<slash:comments>25</slash:comments>
		<feedburner:origLink>http://ailoo.net/2009/11/integrate-spamassassin-into-postfix-dovecot/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=integrate-spamassassin-into-postfix-dovecot</feedburner:origLink></item>
		<item>
		<title>Windows 2000 48-Bit-LBA</title>
		<link>http://feedproxy.google.com/~r/mafflog/~3/CeyMOzeOoIE/</link>
		<comments>http://ailoo.net/2009/09/windows-2000-48-bit-lba/#comments</comments>
		<pubDate>Thu, 17 Sep 2009 21:20:06 +0000</pubDate>
		<dc:creator>Mathias</dc:creator>
				<category><![CDATA[Hardware]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[48-bit lba]]></category>
		<category><![CDATA[hdd]]></category>
		<category><![CDATA[raid]]></category>
		<category><![CDATA[win2k]]></category>

		<guid isPermaLink="false">http://maff.ailoo.net/?p=1261</guid>
		<description><![CDATA[Mich hätte gerade fast der Schlag getroffen. Ein Fileserver hier läuft trotz recht aktueller Hardware (Gigabyte GA-P35-DS3, C2D E4500) noch unter Windows 2000, weils das einfach noch tut. Da der Platz auf den momentan via Software gespiegelten 400GB IDE-Platten langsam recht knapp wird, wurden zwei 1TB SATA-Platten angeschafft, die ich gerade einbauen und über das [...]]]></description>
			<content:encoded><![CDATA[<p>Mich hätte gerade fast der Schlag getroffen. Ein Fileserver hier läuft trotz recht aktueller Hardware (Gigabyte GA-P35-DS3, C2D E4500) noch unter Windows 2000, weils das einfach noch tut. Da der Platz auf den momentan via Software gespiegelten 400GB IDE-Platten langsam recht knapp wird, wurden zwei 1TB SATA-Platten angeschafft, die ich gerade einbauen und über das onboard RAID des Mainboards laufen lassen wollte. Im Prinzip ja kein Problem. Neue Platten rein, den Controller (und zwar nur den Controller, an dem die neuen Platten hängen) auf RAID umgestellt, ins RAID-Setup und ab geht die Post. Denkste. Bis zum RAID-Setup hat alles problemlos gelappt. Als ich dann Windows bootete poppten auf einmal jede Menge Treiberinstallationsfenster für IDE-Kanäle und alles andere mögliche auf. Hab das mal durchlaufen lassen, aber nach einem Blick in die Datenträgerverwaltung war zwar das neue RAID-Array da, jedoch wurden die 2 alten Platten als unformatiert und mit nur 128GB Kapazität dargestellt. Habe dann auf Verdacht mal die Mainboard-CD rausgekramt und alle Chipsatztreiber nochmals drübergebügelt, nach einem Reboot jedoch das selbe Bild. Über big Google habe ich dann <a href="http://support.microsoft.com/default.aspx?scid=kb;de;305098">das hier</a> gefunden, was eigentlich nur für Win2k kleiner SP3 gilt. Habs aber trotzdem versucht und als nach dem mittlerweile 3ten Reboot das auf der IDE-Platte liegende Hintergrundbild erschien war die Welt wieder in Ordnung. Jetz läuft gemütlich robocopy, der die alten Daten hoffentlich über Nacht auf die neuen Platten schiebt&#8230;ich hasse Computer(probleme) ;)</p>
<img src="http://feeds.feedburner.com/~r/mafflog/~4/CeyMOzeOoIE" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://ailoo.net/2009/09/windows-2000-48-bit-lba/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://ailoo.net/2009/09/windows-2000-48-bit-lba/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=windows-2000-48-bit-lba</feedburner:origLink></item>
		<item>
		<title>Continuous Integration with phpUnderControl and Git</title>
		<link>http://feedproxy.google.com/~r/mafflog/~3/NCDA6VqAD8w/</link>
		<comments>http://ailoo.net/2009/09/continuous-integration-phpundercontrol-git/#comments</comments>
		<pubDate>Tue, 08 Sep 2009 13:50:01 +0000</pubDate>
		<dc:creator>Mathias</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[How-Tos]]></category>
		<category><![CDATA[Server]]></category>
		<category><![CDATA[agile]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[continuous integration]]></category>
		<category><![CDATA[cruisecontrol]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[phpundercontrol]]></category>
		<category><![CDATA[unit testing]]></category>

		<guid isPermaLink="false">http://maff.ailoo.net/?p=1190</guid>
		<description><![CDATA[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 [...]]]></description>
			<content:encoded><![CDATA[<p>I was looking for a decent <a href="http://en.wikipedia.org/wiki/Continuous_integration">continuous integration</a> 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: <a href="http://jpablobr.com/php-staging-environment-for-continuous-integration-part-2/">phpUnderControl with Git on a Debian/Ubuntu system</a>. 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).</p>
<p>However, the described setup has a few issues which bugged me:</p>
<ol>
<li>CruiseControl runs from the shellscript as root, posts all output to the console and is not automatically started at boot time.</li>
<li>CruiseControl runs on port 8080, but I wanted to manage access to the webinterface through the apache which is already running on the box</li>
<li>There&#8217;s no authentication &#8211; everybody can access my CI server, see the build details and start new builds through the webinterface.</li>
</ol>
<p><span id="more-1190"></span></p>
<p>I solved these issues with 2 steps.</p>
<h3 id="init-script-for-cruisecontrol">Init script for CruiseControl</h3>
<p>I wrote a simple init script which allows me to control CC. I&#8217;m not really into shellscripting and just hacked around on the apache init script until I got a working solution, so if you have any suggestions how to improve this script please let me know. The script implements the following functions: <code>start</code>, <code>stop</code>, <code>restart</code>, <code>status</code>. Save it to <code>/etc/init.d/cruisecontrol</code> and make it executable (<code>chmod +x /etc/init.d/cruisecontrol</code>).</p>
<pre class="code prettyprint bash">
#!/bin/sh
### BEGIN INIT INFO
# Provides:          cruisecontrol
# Required-Start:    $local_fs $remote_fs $network $syslog
# Required-Stop:     $local_fs $remote_fs $network $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Start/stop cruisecontrol CI server
### END INIT INFO
#
# cruisecontrol         This init.d script is used to start cruisecontrol.
#                       It basically just calls cruisecontrol.sh.

# ENV=&quot;env -i LANG=C PATH=/usr/local/bin:/usr/bin:/bin&quot;

CCON_PATH=/opt/cruisecontrol
CCON_USER=www-data
PIDFILE=$CCON_PATH/cc.pid
LOGFILE=/var/log/cruisecontrol.log

. /lib/lsb/init-functions

ccon_is_running() {
    if [ -f $PIDFILE ]; then
       PID=`cat $PIDFILE`
       PID_COUNT=`ps aux | grep -E $PID | grep -v grep | wc -l`
       if [ $PID_COUNT = 1 ]; then
         return 1
       fi
    fi

    return 0
}

ccon_start() {
        ccon_is_running
        rc=$?
        if [ $rc -eq 1 ]; then
                log_failure_msg &quot;CruiseControl is already running&quot;
        else
                log_daemon_msg &quot;Starting CI server&quot; &quot;CruiseControl&quot;
                cd $CCON_PATH
                sudo -E -H -u $CCON_USER ./cruisecontrol.sh &gt;&gt; $LOGFILE 2&gt;&amp;1
                log_end_msg $?
        fi
}

ccon_stop() {
        ccon_is_running
        rc=$?
        if [ $rc -eq 1 ]; then
                log_daemon_msg &quot;Stopping CI server&quot; &quot;CruiseControl&quot;
                PID=`cat $PIDFILE`

                retval=0
                i=0
                while $(kill &quot;$PID&quot; 2&gt; /dev/null);  do
                        if [ $i = &#039;60&#039; ]; then
                                echo &quot;&quot;
                                log_failure_msg &quot;CruiseControl is taking too long to shutdown&quot;
                                retval=1
                                break
                        else
                                if [ $i = &#039;0&#039; ]; then
                                        echo -n &quot; ... waiting &quot;
                                else
                                        echo -n &quot;.&quot;
                                fi
                                i=$(($i+1))
                                sleep 1
                      fi
                 done

                log_end_msg $retval
        else
                log_failure_msg &quot;CruiseControl is not running&quot;
        fi
}

ccon_status() {
        ccon_is_running
        rc=$?
        if [ $rc -eq 1 ]; then
                PID=`cat $PIDFILE`
                log_success_msg &quot;CruiseControl is running (pid $PID).&quot;
        else
                log_failure_msg &quot;CruiseControl is not running.&quot;
        fi

}

case $1 in
        start)
                ccon_start
        ;;
        stop)
                ccon_stop
        ;;
        restart)
                ccon_stop
                ccon_start
        ;;
        status)
                ccon_status
        ;;
        *)
                log_success_msg &quot;Usage: /etc/init.d/cruisecontrol {start|stop|restart|status}&quot;
                exit 1
        ;;
esac
</pre>
<p>Then change the ownership of the cruisecontrol installation to the user you specified in the init script (in my case <code>www-data</code>):</p>
<pre class="shell">$ chown -R www-data.www-data /opt/cruisecontrol-bin-2.8.2/</pre>
<p>You can now control CC just by using the init script.</p>
<pre class="shell">$ /etc/init.d/cruisecontrol status
 * CruiseControl is not running.
$ /etc/init.d/cruisecontrol start
 * Starting CI server CruiseControl                        [ OK ]
$ /etc/init.d/cruisecontrol status
 * CruiseControl is running (pid 13721).
$ /etc/init.d/cruisecontrol stop
 * Stopping CI server CruiseControl
 ... waiting ..                                            [ OK ]
$ /etc/init.d/cruisecontrol status
 * CruiseControl is not running.</pre>
<p>Additionally you can add it to the default runlevels to start it automatically on system boot.</p>
<pre class="shell">$ update-rc.d cruisecontrol defaults</pre>
<h3 id="access-the-webinterface-via-apache">Access the webinterface via Apache</h3>
<p>I wanted to use my existing apache installation to serve the webinterface. Doing this you can make the webinterface accessible through port 80, control authentication through apache&#8217;s various auth modules and eventually even use SSL to encrypt the traffic. The first thing I did was to bind the CruiseControl&#8217;s webserver (Jetty) to the local IP. Open <code>/opt/cruisecontrol/etc/jetty.xml</code> and find the following line:</p>
<pre class="code prettyprint xml">&lt;Set name=&quot;host&quot;&gt;&lt;SystemProperty name=&quot;jetty.host&quot; /&gt;&lt;/Set&gt;</pre>
<p>Add the default attribute to that line and afterwards restart CC.</p>
<pre class="code prettyprint xml">&lt;Set name=&quot;host&quot;&gt;&lt;SystemProperty name=&quot;jetty.host&quot; default=&quot;127.0.0.1&quot; /&gt;&lt;/Set&gt;</pre>
<p>Now try to access CruiseControl through the external IP, you should not get a connection. But if you try to open a connection from the same host, you should get a response:</p>
<pre class="shell">$ curl http://127.0.0.1:8080/cruisecontrol/</pre>
<p>To serve this instance via apache you need 3 apache modules (install them via apt if you don&#8217;t have them installed):</p>
<pre class="shell">$ a2enmod proxy proxy_http ext_filter</pre>
<p>Create a new virtual host config file in <code>/etc/apache2/sites-available/</code>. Modify <code>ServerName</code> and <code>ExtFilterDefine</code> to match your environment.</p>
<pre class="code prettyprint xml">
&lt;VirtualHost *:80&gt;
        ServerName cruisecontrol.example.org

        ProxyRequests Off

        &lt;Proxy *&gt;
                Order deny,allow
                Allow from all
        &lt;/Proxy&gt;

        ProxyPass / http://127.0.0.1:8080/
        ProxyPassReverse / http://127.0.0.1:8080/

        ExtFilterDefine fixurls mode=output intype=text/html cmd=&quot;/bin/sed s%http://127.0.0.1:8080%http://cruisecontrol.example.org%g&quot;
        SetOutputFilter fixurls
&lt;/VirtualHost&gt;
</pre>
<p>As a last step, enable the virtual host and restart apache (I named the config file <code>cruisecontrol</code>):</p>
<pre class="shell">$ a2ensite cruisecontrol
$ /etc/init.d/apache2 restart</pre>
<p>Now you should have access to your phpUnderControl installation via <code>http://cruisecontrol.example.org/cruisecontrol</code>. As a last step, we add basic apache authentication (replace with your preferred apache auth method). Edit the vhost config file and modify as follows:</p>
<pre class="code prettyprint xml">
        &lt;Proxy *&gt;
                Order deny,allow
                Allow from all

                AuthName        &quot;phpUnderControl&quot;
                AuthType        Basic
                AuthUserFile    /etc/apache2/cruisecontrol.htpasswd
                require         valid-user
        &lt;/Proxy&gt;
</pre>
<p>As a last step, you have to create the <code>.htpasswd</code> file, which contains the user map.</p>
<pre class="shell">$ htpasswd -c /etc/apache2/cruisecontrol.htpasswd myuser</pre>
<p>Add additional users with the following command (same command but without the <code>-c</code> switch):</p>
<pre class="shell">$ htpasswd /etc/apache2/cruisecontrol.htpasswd otheruser</pre>
<p>Finally, restart apache and you are done:</p>
<pre class="shell">$ /etc/init.d/apache2 restart</pre>
<h3 id="sources">Sources</h3>
<ul>
<li><a href="http://jpablobr.com/php-staging-environment-for-continuous-integration-part-2/">PHP Staging environment for continuous integration part 2</a></li>
<li><a href="http://www.maxhorvath.com/2008/08/making-phpundercontrol-cruisecontrol-accessible-via-a-proxy.html">Making phpUnderControl (CruiseControl) accessible via a Proxy</a></li>
</ul>
<img src="http://feeds.feedburner.com/~r/mafflog/~4/NCDA6VqAD8w" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://ailoo.net/2009/09/continuous-integration-phpundercontrol-git/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		<feedburner:origLink>http://ailoo.net/2009/09/continuous-integration-phpundercontrol-git/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=continuous-integration-phpundercontrol-git</feedburner:origLink></item>
		<item>
		<title>Windows 7 RC auf älterem PC installieren: Code Error 5</title>
		<link>http://feedproxy.google.com/~r/mafflog/~3/6yTD3BTrHYg/</link>
		<comments>http://ailoo.net/2009/07/windows-7-rc-auf-alterem-pc-installieren-code-error-5/#comments</comments>
		<pubDate>Mon, 27 Jul 2009 21:37:51 +0000</pubDate>
		<dc:creator>Mathias</dc:creator>
				<category><![CDATA[How-Tos]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[boot]]></category>
		<category><![CDATA[bootloader]]></category>
		<category><![CDATA[gujin]]></category>
		<category><![CDATA[install]]></category>
		<category><![CDATA[setup]]></category>
		<category><![CDATA[windows7]]></category>

		<guid isPermaLink="false">http://maff.ailoo.net/?p=1064</guid>
		<description><![CDATA[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 [...]]]></description>
			<content:encoded><![CDATA[<p>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: <kbd>Cannot boot from CD - Code error: 5</kbd>. Das Problem liegt anscheinend an einem zu alten BIOS, das den Bootsektor der DVD nicht korrekt auslesen kann. Nach etwas Recherche bin ich auf <a href="http://www.sevenforums.com/installation-setup/2591-boot-error-code-5-a-2.html#post31719">diesen Beitrag</a> gestoßen, der erklärt, wie man die DVD dennoch mittels einem zusätzlichen Bootloader namens <a href="http://sourceforge.net/projects/gujin/">gujin</a> booten kann &#8211; 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.</p>
<p>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 <kbd>mkisofs</kbd>, 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 <kbd>standard</kbd>-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 <kbd>floppy.144</kbd> schiebt man in einen Arbeitsordner (bei mir z.B. <kbd>/tmp/floppyimage</kbd>) und öffnet anschließend ein Terminal. Darin macht man dann ca. folgendes:</p>
<pre class="shell">$ cd /tmp/floppyimage
$ mkisofs -pad -b floppy.144 -R -o /tmp/gujin.iso floppy.144</pre>
<p>Und schon liegt in dem Ordner eine Datei <kbd>gujin.iso</kbd>, 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 ;)</p>
<img src="http://feeds.feedburner.com/~r/mafflog/~4/6yTD3BTrHYg" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://ailoo.net/2009/07/windows-7-rc-auf-alterem-pc-installieren-code-error-5/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		<feedburner:origLink>http://ailoo.net/2009/07/windows-7-rc-auf-alterem-pc-installieren-code-error-5/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=windows-7-rc-auf-alterem-pc-installieren-code-error-5</feedburner:origLink></item>
		<item>
		<title>ATI Catalyst Setup stürzt bei Installation ab</title>
		<link>http://feedproxy.google.com/~r/mafflog/~3/dwd3nm5z0x4/</link>
		<comments>http://ailoo.net/2009/07/ati-catalyst-setup-stuerzt-bei-installation-ab/#comments</comments>
		<pubDate>Fri, 24 Jul 2009 17:03:27 +0000</pubDate>
		<dc:creator>Mathias</dc:creator>
				<category><![CDATA[How-Tos]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[ati]]></category>
		<category><![CDATA[catalyst]]></category>
		<category><![CDATA[crash]]></category>
		<category><![CDATA[install]]></category>
		<category><![CDATA[vista]]></category>
		<category><![CDATA[workaround]]></category>
		<category><![CDATA[x64]]></category>

		<guid isPermaLink="false">http://maff.ailoo.net/?p=1050</guid>
		<description><![CDATA[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 [...]]]></description>
			<content:encoded><![CDATA[<p>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 <a href="http://india.termindoc.de/index.php/2008/12/07/vista-catalyst-install-manager-funktioniert-nicht-mehr/">benedikts Blog</a>, 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 &#8211; also los gehts ;)</p>
<p>Zuerst die heruntergeladenen Dateien ausführen, wodurch die Installer entpackt werden. Im meinem Fall waren das die 2 Dateien <kbd>9-7_vista64_win7_64_dd.exe</kbd> (display driver) und <kbd>9-7_vista32-64_ccc_lang2.exe</kbd> (control center). Danach befinden sich in <kbd>C:\ATI</kbd> 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:</p>
<ol>
<li>Im Startmenü nach Zubehör, Rechtsklick auf Eingabeaufforderung und dann &#8220;Als Administrator ausführen&#8221;. Dadurch öffnet sich eine CMD mit administrativen Rechten</li>
<li><kbd>cd C:\ATI</kbd></li>
<li><kbd>cd 9-7_vista64_win7_64_dd</kbd> (je nach Treiberversion, Sprache und Betriebssystem)</li>
<li><kbd>cd Bin64</kbd> (bei 64-Bit Betriebssystemen, bei 32-Bit Systemen heißt der Ordner wahrscheinlich Bin)</li>
<li><kbd>ATISetup.exe -install -output screen</kbd></li>
</ol>
<p>Analog funktioniert das auch mit dem CCC und dem Avivo Video Converter (Hydravision hab ich nicht getestet, da ichs nicht brauche).</p>
<img src="http://feeds.feedburner.com/~r/mafflog/~4/dwd3nm5z0x4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://ailoo.net/2009/07/ati-catalyst-setup-stuerzt-bei-installation-ab/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://ailoo.net/2009/07/ati-catalyst-setup-stuerzt-bei-installation-ab/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=ati-catalyst-setup-stuerzt-bei-installation-ab</feedburner:origLink></item>
		<item>
		<title>Backup Xen virtual machines with LVM snapshots and ftplicity/duplicity</title>
		<link>http://feedproxy.google.com/~r/mafflog/~3/iYTLsVODDY4/</link>
		<comments>http://ailoo.net/2009/07/backup-xen-virtual-machines-lvm-snapshots-ftplicity-duplicity/#comments</comments>
		<pubDate>Wed, 08 Jul 2009 18:47:23 +0000</pubDate>
		<dc:creator>Mathias</dc:creator>
				<category><![CDATA[How-Tos]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Server]]></category>
		<category><![CDATA[administration]]></category>
		<category><![CDATA[duplicity]]></category>
		<category><![CDATA[encryption]]></category>
		<category><![CDATA[ftp]]></category>
		<category><![CDATA[ftplicity]]></category>
		<category><![CDATA[gpg]]></category>
		<category><![CDATA[lvm]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[snapshot]]></category>
		<category><![CDATA[vm]]></category>
		<category><![CDATA[xen]]></category>

		<guid isPermaLink="false">http://maff.ailoo.net/?p=1018</guid>
		<description><![CDATA[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 [...]]]></description>
			<content:encoded><![CDATA[<p>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 <a href="http://duplicity.nongnu.org/">duplicity</a> and <a href="http://sourceforge.net/projects/ftplicity/">ftplicity</a> 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 <a href="http://www.heise.de/ct/">c&#8217;t</a>, but has been undergone further development and is now hosted at SourceForge.</p>
<p>You can find tutorials on ftplicity/duplicity here (Note: they use the original c&#8217;t version of ftplicity):</p>
<ul>
<li><a href="http://www.weareroot.de/2007/08/17/ftplicity-inkrementelle-backups-sicher-ablegen/">http://www.weareroot.de/2007/08/17/ftplicity-inkrementelle-backups-sicher-ablegen/</a> (German)</li>
<li><a href="http://www.howtoforge.com/ftp-backups-with-duplicity-ftplicity-debian-etch">http://www.howtoforge.com/ftp-backups-with-duplicity-ftplicity-debian-etch</a></li>
</ul>
<p>Basically you can use this setup for any kind of LVM snapshot based system, but I&#8217;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 <kbd>root</kbd>.</p>
<p><span id="more-1018"></span></p>
<h3 id="setup-and-goal">Setup and Goal</h3>
<p>My setup is the following: I got 1 volume group (VG) which contains all logical volumes (LV) used for virtual machines. Every virtual machine has 2 LVs, <kbd>vm01-disk</kbd> and <kbd>vm01-swap</kbd>, where <kbd>vm01</kbd> is the name of the VM. Of course I want to backup only the <kbd>*-disk</kbd> LVs.</p>
<p>Goal: automatically create a LVM snapshot, mount it and back up the VM to the remote FTP server. Afterwards unmount the snapshot and remove it.</p>
<h3 id="lvm-snapshots">LVM snapshots</h3>
<p>To automatically create LVM snapshots, I wrote a simple bash script which does all the needed steps. As my bash mojo isn&#8217;t too advanced, I got some ideas from <a href="http://wiki.sepsoftware.com/wiki/index.php/Online_Sicherung_von_virtuellen_XEN_Maschinen#Einrichten_der_Pre-_und_Post-Schnittstellen">here</a> ;). You can download the script at <a href="http://github.com/maff/lvmsnapshot/">Github</a>.</p>
<p class="warning"><strong>Disclaimer:</strong> I do neither issue any guarantee that the script will work for you nor do I take any responsibility for potential data loss caused by this script. So please use with care.</p>
<p>The script has some options to configure:</p>
<dl>
<dt><kbd>LVMPATH</kbd></dt>
<dd>Path to your volume group (VG), e.g. <kbd>/dev/lvmstore</kbd>.</dd>
<dt><kbd>LVMEXTENSION</kbd></dt>
<dd>Extension which will be added to LV names, e.g. if you specify <kbd>vm01</kbd> as LV name and <kbd>LVMEXTENSION</kbd> is set to <kbd>-disk</kbd>, the snapshot will be created from <kbd>/dev/lvmstore/vm01-disk</kbd> (using the <kbd>LVMPATH</kbd> example from before).</dd>
<dt><kbd>MOUNTPATH</kbd></dt>
<dd>Path where snapshots will be mounted to.</dd>
<dt><kbd>SNAPSHOTSIZE</kbd></dt>
<dd>Size of the snapshot.</dd>
<dt><kbd>IDENTIFIER</kbd></dt>
<dd>An identifier, which will be used to create the snapshot name (useful to distinguish automatic backups from others). Using the examples from the other options, the snapshot will be named as follows: <kbd>vm01-disk-snapshot-backupscript</kbd> (with <kbd>IDENTIFIER</kbd> set to <kbd>backupscript</kbd>)</dd>
</dl>
<p>Edit the options according to your needs, make the script executable and drop it somewhere on your system. Example:</p>
<pre class="shell">$ nano lvmsnapshot.sh
[ ... edit options ...]
$ chmod 700 lvmsnapshot.sh
$ mv lvmsnapshot.sh /usr/sbin/lvmsnapshot</pre>
<p>Assuming all options are set correctly for your system, you can use the script as follows. Create and mount a snapshot of virtual machine <kbd>vm01</kbd>, located at <kbd>/dev/lvmstore/vm01-disk</kbd>:</p>
<pre class="shell">$ lvmsnapshot create vm01
Checking if /dev/lvmstore/vm01-disk is mounted...No
Checking availability of Volume '/dev/lvmstore/vm01-disk'...
  ...successful

Creating LVM snapshot at /dev/lvmstore/vm01-disk-snapshot-backupscript...
  Logical volume "vm01-disk-snapshot-backupscript" created
...successful

Mounting LVM snapshot for backup...
  Creating mount directory at /mnt/lvm/vm01...OK
...successful</pre>
<p>Umount and remove the snapshot:</p>
<pre class="shell">$ lvmsnapshot remove vm01
Checking if /dev/lvmstore/vm01-disk is mounted...Yes
Checking availability of Volume '/dev/lvmstore/vm01-disk'...
  ...successful

Unmounting LVM snapshot after backup...
  Deleting mount directory at /mnt/lvm/vm01...OK
...successful

Deleting LVM snapshot vm01-disk-snapshot-backupscript
  Logical volume "vm01-disk-snapshot-backupscript" successfully removed
...successful</pre>
<p>If this works, we are able to automatically create snapshots and mount them. So we can pass to the next step: setting up ftplicity and configuring it to use the script to get access to our VM data.</p>
<h3 id="install-ftplicityduplicity">Install ftplicity/duplicity</h3>
<p>First of all, install duplicity:</p>
<pre class="shell">$ aptitude install duplicity ncftp</pre>
<p>Get ftplicity from the <a href="http://sourceforge.net/projects/ftplicity/files/">SourceForge project site</a> and make it executable:</p>
<pre class="shell">
$ wget http://downloads.sourceforge.net/sourceforge/ftplicity/ftplicity_1.4.2.tgz
$ tar xvzf ftplicity_1.4.2.tgz
$ cp ftplicity_1.4.2/ftplicity /usr/sbin/ftplicity
$ chmod 700 /usr/sbin/ftplicity
$ rm -rf ftplicity_1.4.2 ftplicity_1.4.2.tgz
</pre>
<p>Afterwards, create <kbd>/etc/ftplicity</kbd>. This way, ftplicity profiles will be stored in <kbd>/etc</kbd> instead of <kbd>root</kbd>&#8216;s home directory.</p>
<pre class="shell">mkdir /etc/ftplicity</kbd></pre>
<p>Calling <kbd>ftplicity</kbd> should now work and tell you to specify a valid profile.</p>
<h3 id="create-a-gpg-key">Create a GPG key</h3>
<p>In order to be able to encrypt your backups, you have to create a GPG key. The tutorials mentioned at the beginning explain this in detail, so here&#8217;s only the short version. Open a second shell and run the following command (this generates some &#8220;randomness&#8221; on your system, which will be useful to create a secure key). Kill the command with <kbd>CTRL+C</kbd> when you are done with key generation.</p>
<pre class="shell">while /bin/true; do cat /var/log/syslog > ~/temp.txt; sleep 1; done;</pre>
<p>On your other shell, create your GPG key. Be sure to use a secure passphrase and to copy/write down the key ID which is displayed at the end of the generation process (we&#8217;ll need it for ftplicity). Also, make sure to backup the key to a secure location outside your server. As all your backups will be encrypted, they will be worthless if your server crashes and you lose the key.</p>
<pre class="shell">gpg --gen-key</pre>
<p>Default options should be fine. This will create your key in <kbd>~/.gnupg/</kbd>.</p>
<h3 id="set-up-ftplicity-profiles">Set up ftplicity profiles</h3>
<p>Now it&#8217;s time to set up a ftplicity profile for a virtual machine. The virtual machine is called <kbd>vm01</kbd> and is running a webserver stack using Apache/MySQL. Call ftplicity to initialize the profile <kbd>vm01</kbd>:</p>
<pre class="shell">$ ftplicity vm01 create

Warning:

The profile's folder
'/etc/ftplicity/vm01'
permissions were not safe (drwxr-xr-x). Secured them to 700.

Congratulations. You just created the profile 'vm01'.
The initial config file has been created as
'/etc/ftplicity/vm01/conf'.
For ftplicity to work you have to insert details on
the gpg key to use and the ftp server for the backup
in this config file.

IMPORTANT:
  Copy the _whole_ profile folder after the first backup to a safe place.
  It contains everything needed to restore your backups. You will need
  it if you have to restore the backup from another system (e.g. after a
  system crash). Keep access to these files restricted as they contain
  _all_ informations (gpg data, ftp data) to access and modify your backups.

  Repeat this step after all configuration changes. Some configuration
  options are crucial for restoration.</pre>
<p>Ftplicity creates a config file for your profile in <kbd>/etc/ftplicity/vm01/conf</kbd>, which you will have to edit to match your system. I changed the following options:</p>
<pre># gpg key data
GPG_KEY='keyid'
GPG_PW='keypassphrase'

# ...

# credentials &#038; server address of the ftp server (URL-Format)
TARGET='ftp://username@ftpserver/vm01'
TARGET_PW='ftppassword'

# base directory to backup
SOURCE='/mnt/lvm/vm01'

# ...

# activates duplicity --full-if-older-than option (since duplicity v0.4.4.RC3)
# forces a full backup if last full backup reaches a specified age, for the
# format of MAX_FULLBKP_AGE see duplicity man page, chapter TIME_FORMATS
MAX_FULLBKP_AGE=6D
DUPL_PARAMS="$DUPL_PARAMS --full-if-older-than $MAX_FULLBKP_AGE "</pre>
<p>Make sure the directory on the FTP server exists. If you get any Python problems when running the backups, try to create an empty file in your backup directory on the FTP server (there is or was a Python bug which caused problems with empty directories when connecting to FTP).</p>
<p>Next, we have to tell ftplicity to use the snapshot-script to get access to <kbd>vm01</kbd>&#8216;s data. Fortunately, ftplicity supports <kbd>pre</kbd> and <kbd>post</kbd> scripts, which are executed before and after a backup job. Create these scripts and make them executable:</p>
<pre class="shell">$ cd /etc/ftplicity/vm01
$ touch pre
$ touch post
$ chmod 700 pre
$ chmod 700 post</pre>
<p><kbd>pre</kbd></p>
<pre class="code prettyprint bash">
#!/bin/bash
/usr/sbin/lvmsnapshot create vm01
</pre>
<p><kbd>post</kbd></p>
<pre class="code prettyprint bash">
#!/bin/bash
/usr/sbin/lvmsnapshot remove vm01
</pre>
<p>As a last step, create a file <kbd>/etc/ftplicity/vm01/exclude</kbd> which tells ftplicity which files to exclude from the backup. Note that I excluded <kbd>/var/lib/mysql</kbd> too, as backing up the MySQL data directory could lead to inconsistent results. To solve this, I use <a href="http://sourceforge.net/projects/automysqlbackup/">automysqlbackup</a> inside VMs which dumps SQL data regularly. These dumps are included in my FTP backup. I&#8217;ll write more on automysqlbackup in a later tutorial.</p>
<pre>/mnt/lvm/vm01/var/run/**
/mnt/lvm/vm01/var/tmp/**
/mnt/lvm/vm01/tmp/**
/mnt/lvm/vm01/dev/**
/mnt/lvm/vm01/sys/**
/mnt/lvm/vm01/proc/**
/mnt/lvm/vm01/floppy/**
/mnt/lvm/vm01/cdrom/**
/mnt/lvm/vm01/var/lib/mysql/**</pre>
<h3 id="run-ftplicity">Run ftplicity</h3>
<p>OK, all is set up and should be working now. So let&#8217;s try using ftplicity. You can see all ftplicity commands by calling <kbd>ftplicity usage</kbd>.</p>
<p>Check status of our profile:</p>
<pre class="shell">$ ftplicity vm01 status
Start ftplicity v1.4.2, time is 07/08/09 20:09:47.
Using profile '/etc/ftplicity/vm01'.
Using installed duplicity version 0.4.11, gpg 1.4.9 (Home: ~/.gnupg)
Test - Encryption with key xxxxxxxx (OK)
Test - Decryption with key xxxxxxxx (OK)
Test - Compare Original w/ Decryption (OK)
Cleanup - Delete '/tmp/ftplicity.xxxxx.xxxxxxxxxx_*'(OK)

--- Start running command STATUS (20:09:47.943) ---
Running duplicity - OK
Output: NcFTP version is 3.2.1
Last full backup date: none
Connecting with backend: ftpBackend
Archive dir: None

Found 0 backup chains without signatures.
No backup chains with active signatures found
No orphaned or incomplete backup sets found.
--- Finished (20:09:48.206) - Runtime 00:00:00.263 ---</pre>
<p>OK, profile seems to work. Let&#8217;s try to make a backup.</p>
<pre class="shell">ftplicity vm01 backup
Start ftplicity v1.4.2, time is 07/08/09 20:14:57.
Using profile '/etc/ftplicity/vm01'.
Using installed duplicity version 0.4.11, gpg 1.4.9 (Home: ~/.gnupg)
Test - Encryption with key xxxxxxxx (OK)
Test - Decryption with key xxxxxxxx (OK)
Test - Compare Original w/ Decryption (OK)
Cleanup - Delete '/tmp/ftplicity.xxxxx.xxxxxxxxxx_*'(OK)

--- Start running command PRE (20:14:58.152) ---
Running '/etc/ftplicity/vm01/pre' - OK
Output: Checking if /dev/lvmstore/vm01-disk is mounted...No
Checking availability of Volume '/dev/lvmstore/vm01-disk'...
  ...successful

Creating LVM snapshot at /dev/lvmstore/vm01-disk-snapshot-backupscript...
  Logical volume "vm01-disk-snapshot-backupscript" created
...successful

Mounting LVM snapshot for backup...
  Creating mount directory at /mnt/lvm/vm01...OK
...successful
--- Finished (20:14:58.490) - Runtime 00:00:00.338 ---

--- Start running command BKP (20:14:58.498) ---
Running duplicity - OK
Output: NcFTP version is 3.2.1
Reading globbing filelist /etc/ftplicity/vm01/exclude
Last full backup date: none
Last full backup is too old, forcing full backup
--------------[ Backup Statistics ]--------------
StartTime 1247076898.77 (Wed Jul  8 20:14:58 2009)
EndTime 1247076977.92 (Wed Jul  8 20:16:17 2009)
ElapsedTime 79.15 (1 minute 19.15 seconds)
SourceFiles 12398
SourceFileSize 276924030 (264 MB)
NewFiles 12398
NewFileSize 276924030 (264 MB)
DeletedFiles 0
ChangedFiles 0
ChangedFileSize 0 (0 bytes)
ChangedDeltaSize 0 (0 bytes)
DeltaEntries 12398
RawDeltaSize 130935522 (125 MB)
TotalDestinationSizeChange 101194951 (96.5 MB)
Errors 0
-------------------------------------------------
--- Finished (20:16:19.864) - Runtime 00:01:21.365 ---

--- Start running command POST (20:16:19.872) ---
Running '/etc/ftplicity/vm01/post' - OK
Output: Checking if /dev/lvmstore/vm01-disk is mounted...Yes
Checking availability of Volume '/dev/lvmstore/vm01-disk'...
  ...successful

Unmounting LVM snapshot after backup...
  Deleting mount directory at /mnt/lvm/vm01...OK
...successful

Deleting LVM snapshot vm01-disk-snapshot-backupscript
  Logical volume "vm01-disk-snapshot-backupscript" successfully removed
...successful
--- Finished (20:16:20.718) - Runtime 00:00:00.846 ---</pre>
<p>Perfect. The LVM snapshot is created and mounted, backuped and afterwards all gets cleaned up. As this was the first backup, ftplicity created a full backup. Following backups will be incremental until the full backup is too old (see ftplicity config for details).</p>
<h4 id="restore">Restore</h4>
<p>Ftplicity allows simple restoring of your backups. Some examples:</p>
<p>Restore the complete last state to <kbd>/tmp/vm01restore</kbd>:</p>
<pre class="shell">$ ftplicity vm01 restore /tmp/vm01restore</pre>
<p>Restore <kbd>/etc/passwd</kbd> from the last backup state to <kbd>/tmp/vm01restore/etc/passwd</kbd>:</p>
<pre class="shell">$ ftplicity vm01 fetch etc/passwd /tmp/vm01restore/etc/passwd</pre>
<p>The same as before, but take the state from four days before:</p>
<pre class="shell">$ ftplicity vm01 fetch etc/passwd /tmp/vm01restore/etc/passwd 4D</pre>
<p>Perfect.</p>
<h3 id="set-up-cronjobs">Set up cronjobs</h3>
<p>To run a backup automatically every night, I set up cronjobs to do this. Example:</p>
<pre>0 1 * * * /usr/sbin/ftplicity vm01 cleanup --force ; /usr/sbin/ftplicity vm01 backup
0 2 * * 1 /usr/sbin/ftplicity vm01 purge-full --force ; /usr/sbin/ftplicity vm01 purge --force</pre>
<p>This will run ftplicity on <kbd>vm01</kbd> every night at 1:00 and purge old backups every monday night at 2:00.</p>
<h3 id="conlusion">Conlusion</h3>
<p>The above setup gives you a secure and handy solution to run automated backups on LVM snapshots. Ftplicity is quite simple to use and gives you many possibilities to restore your files. To add more VMs, just create a new profile (or copy the existing one) and adjust the config files to match the new VM paths. Any suggestions are welcome :)</p>
<img src="http://feeds.feedburner.com/~r/mafflog/~4/iYTLsVODDY4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://ailoo.net/2009/07/backup-xen-virtual-machines-lvm-snapshots-ftplicity-duplicity/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		<feedburner:origLink>http://ailoo.net/2009/07/backup-xen-virtual-machines-lvm-snapshots-ftplicity-duplicity/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=backup-xen-virtual-machines-lvm-snapshots-ftplicity-duplicity</feedburner:origLink></item>
		<item>
		<title>MySQL backup user</title>
		<link>http://feedproxy.google.com/~r/mafflog/~3/06meVYgvYfA/</link>
		<comments>http://ailoo.net/2009/07/mysql-backup-user/#comments</comments>
		<pubDate>Tue, 07 Jul 2009 18:44:31 +0000</pubDate>
		<dc:creator>Mathias</dc:creator>
				<category><![CDATA[Server]]></category>
		<category><![CDATA[Snippets]]></category>
		<category><![CDATA[administration]]></category>
		<category><![CDATA[backup]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[privileges]]></category>
		<category><![CDATA[user]]></category>

		<guid isPermaLink="false">http://maff.ailoo.net/?p=1015</guid>
		<description><![CDATA[To create a backup user for MySQL you need at least the following privileges (to use mysqldump): GRANT SELECT, SHOW VIEW, LOCK TABLES ON *.* TO 'backup'@'localhost';]]></description>
			<content:encoded><![CDATA[<p>To create a backup user for MySQL you need at least the following privileges (to use <kbd>mysqldump</kbd>):</p>
<pre class="shell">GRANT SELECT, SHOW VIEW, LOCK TABLES ON *.* TO 'backup'@'localhost';</pre>
<img src="http://feeds.feedburner.com/~r/mafflog/~4/06meVYgvYfA" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://ailoo.net/2009/07/mysql-backup-user/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://ailoo.net/2009/07/mysql-backup-user/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=mysql-backup-user</feedburner:origLink></item>
		<item>
		<title>Repack a .deb-archive with dpkg-deb</title>
		<link>http://feedproxy.google.com/~r/mafflog/~3/rDyvYtTwNDE/</link>
		<comments>http://ailoo.net/2009/06/repack-a-deb-archive-with-dpkg-deb/#comments</comments>
		<pubDate>Mon, 29 Jun 2009 12:44:09 +0000</pubDate>
		<dc:creator>Mathias</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Server]]></category>
		<category><![CDATA[apt]]></category>
		<category><![CDATA[debian]]></category>
		<category><![CDATA[dpkg]]></category>
		<category><![CDATA[package]]></category>
		<category><![CDATA[repack]]></category>

		<guid isPermaLink="false">http://maff.ailoo.net/?p=1010</guid>
		<description><![CDATA[I just needed to repack a Debian package to solve this problem. After a quick spin to #debian I got this solution: $ mkdir -p extract/DEBIAN $ dpkg-deb -x package.deb extract/ $ dpkg-deb -e package.deb extract/DEBIAN [...do something, e.g. edit the control file...] $ mkdir build $ dpkg-deb -b extract/ build/ -x extracts the package [...]]]></description>
			<content:encoded><![CDATA[<p>I just needed to repack a Debian package to solve <a href="http://src.enomaly.com/ticket/123">this</a> problem. After a quick spin to <kbd>#debian</kbd> I got this solution:</p>
<pre class="shell">$ mkdir -p extract/DEBIAN
$ dpkg-deb -x package.deb extract/
$ dpkg-deb -e package.deb extract/DEBIAN
[...do something, e.g. edit the control file...]
$ mkdir build
$ dpkg-deb -b extract/ build/
</pre>
<ul>
<li><kbd>-x</kbd> extracts the package contents</li>
<li><kbd>-e</kbd> extracts the control files</li>
<li><kbd>-b</kbd> builds the new package</li>
</ul>
<p>Done.</p>
<img src="http://feeds.feedburner.com/~r/mafflog/~4/rDyvYtTwNDE" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://ailoo.net/2009/06/repack-a-deb-archive-with-dpkg-deb/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		<feedburner:origLink>http://ailoo.net/2009/06/repack-a-deb-archive-with-dpkg-deb/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=repack-a-deb-archive-with-dpkg-deb</feedburner:origLink></item>
		<item>
		<title>Pure Semesterabschluss Special</title>
		<link>http://feedproxy.google.com/~r/mafflog/~3/1Ge-vJk3kRA/</link>
		<comments>http://ailoo.net/2009/06/pure-semesterabschluss-special/#comments</comments>
		<pubDate>Wed, 24 Jun 2009 12:50:49 +0000</pubDate>
		<dc:creator>Mathias</dc:creator>
				<category><![CDATA[Cooking]]></category>
		<category><![CDATA[No Comment]]></category>
		<category><![CDATA[drink]]></category>
		<category><![CDATA[energy]]></category>
		<category><![CDATA[pure coffain]]></category>
		<category><![CDATA[sleep]]></category>

		<guid isPermaLink="false">http://maff.ailoo.net/?p=991</guid>
		<description><![CDATA[Für Zeiten, in denen Kaffee längst zu einem Genussmittel ohne spezielle Wirkung degradiert wurde, die Wirkung herkömmlicher Energydrinks zu wünschen übrig lässt, Schlaf zu einem Luxusgut geworden ist und die Situation trotzdem langes und konzentriertes Arbeiten fordert: der Pure Semesterabschluss Special. Zutaten: 125 ml Pure Cofain 699 200 ml Sprite 1 Spritzer Zitronensaft ½ TL [...]]]></description>
			<content:encoded><![CDATA[<p>Für Zeiten, in denen Kaffee längst zu einem Genussmittel ohne spezielle Wirkung degradiert wurde, die Wirkung herkömmlicher Energydrinks zu wünschen übrig lässt, Schlaf zu einem Luxusgut geworden ist und die Situation trotzdem langes und konzentriertes Arbeiten fordert: der Pure Semesterabschluss Special.</p>
<p>Zutaten:</p>
<ul>
<li>125 ml <a href="http://www.cofain.at/">Pure Cofain 699</a></li>
<li>200 ml Sprite</li>
<li>1 Spritzer Zitronensaft</li>
<li>½ TL Rohrzucker</li>
</ul>
<p>Alle 3-5h ein Gläschen sollte für &#8220;3 Tage wach&#8221; reichen. Achtung bei Sprite und Zucker: die Mischung schäumt dadurch ziemlich hoch auf, also am besten in einem ausreichend dimensionerten Glas anmischen (siehe Foto).</p>
<p>Im Gegensatz zu Pure Cofain existieren zu diesem Drink weder wissenschaftliche Studien noch Feldtests, die die Verträglichkeit dieses Drinks garantieren. Ich übernehme daher keine Haftung für etwaige, durch den Konsum des Drinks entstandene, gesundheitliche Schäden ;). Mehr Infos zu Gefahren, Wirkung und allem weiteren gibt es auf der <a href="http://www.cofain.at/">Webseite</a> des Herstellers.</p>
<p>Viel Spaß ;)</p>
<img src="http://feeds.feedburner.com/~r/mafflog/~4/1Ge-vJk3kRA" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://ailoo.net/2009/06/pure-semesterabschluss-special/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		<feedburner:origLink>http://ailoo.net/2009/06/pure-semesterabschluss-special/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=pure-semesterabschluss-special</feedburner:origLink></item>
		<item>
		<title>FH Raumbelegung: iCal Support für Wochenübersicht</title>
		<link>http://feedproxy.google.com/~r/mafflog/~3/F5_De0g9d0Q/</link>
		<comments>http://ailoo.net/2009/06/fh-raumbelegung-ical-support-fuer-wochenuebersicht/#comments</comments>
		<pubDate>Fri, 19 Jun 2009 15:06:08 +0000</pubDate>
		<dc:creator>Mathias</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[fh kufstein]]></category>
		<category><![CDATA[infoscreen]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[raumbelegung]]></category>
		<category><![CDATA[webservice]]></category>
		<category><![CDATA[zend framework]]></category>

		<guid isPermaLink="false">http://maff.ailoo.net/?p=979</guid>
		<description><![CDATA[Ab sofort gibt es in meinem Raumbelegung-Webservice die Möglichkeit, die Wochenübersicht via iCal abzurufen. Dadurch lässt sich der Service komfortabel in Kalenderapplikationen (z.B. der Thunderbird-Extension Lightning) verwenden. Verwendung: einfach an eine Wochenübersicht den Parameter format/ical anhängen oder die entsprechenden Links am Ende der Übersicht verwenden. Um zum Beispiel immer die aktuelle Woche des Studiengangs WI07 [...]]]></description>
			<content:encoded><![CDATA[<p>Ab sofort gibt es in meinem <a href="http://ailoo.net/projects/fh-kufstein-raumbelegung-webservice/">Raumbelegung-Webservice</a> die Möglichkeit, die Wochenübersicht via <a href="http://de.wikipedia.org/wiki/ICal">iCal</a> abzurufen. Dadurch lässt sich der Service komfortabel in Kalenderapplikationen (z.B. der Thunderbird-Extension Lightning) verwenden. Verwendung: einfach an eine Wochenübersicht den Parameter <kbd>format/ical</kbd> anhängen oder die entsprechenden Links am Ende der Übersicht verwenden.</p>
<p>Um zum Beispiel immer die aktuelle Woche des Studiengangs WI07 als Kalender in meinem Thunderbird anzeigen zu können, habe ich dort folgende URL als iCal-Quelle angegeben:</p>
<p><kbd><a href="http://raumbelegung.stud.ailoo.net/week/show/class/wi07-vz/format/ical">http://raumbelegung.stud.ailoo.net/week/show/class/wi07-vz/format/ical</a></kbd></p>
<p>Vorschläge sind wie üblich willkommen :)</p>
<img src="http://feeds.feedburner.com/~r/mafflog/~4/F5_De0g9d0Q" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://ailoo.net/2009/06/fh-raumbelegung-ical-support-fuer-wochenuebersicht/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://ailoo.net/2009/06/fh-raumbelegung-ical-support-fuer-wochenuebersicht/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=fh-raumbelegung-ical-support-fuer-wochenuebersicht</feedburner:origLink></item>
		<item>
		<title>Build a FlashMessenger system in ASP.NET MVC</title>
		<link>http://feedproxy.google.com/~r/mafflog/~3/4X3i0mNjplo/</link>
		<comments>http://ailoo.net/2009/06/build-a-flashmessenger-system-in-aspnet-mvc/#comments</comments>
		<pubDate>Mon, 01 Jun 2009 14:45:06 +0000</pubDate>
		<dc:creator>Mathias</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[How-Tos]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[flashmessenger]]></category>
		<category><![CDATA[framework]]></category>
		<category><![CDATA[mvc]]></category>

		<guid isPermaLink="false">http://maff.ailoo.net/?p=739</guid>
		<description><![CDATA[Usually, I&#8217;m using PHP for web projects, but currently I&#8217;m working on an application using ASP.NET&#8217;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 [...]]]></description>
			<content:encoded><![CDATA[<p>Usually, I&#8217;m using PHP for web projects, but currently I&#8217;m working on an application using ASP.NET&#8217;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&#8217;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&#8217;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.</p>
<p><span id="more-739"></span></p>
<p>I&#8217;m working with the default application which is generated when creating a new ASP.NET MVC project in Visual Studio.</p>
<h3 id="flashmessenger">FlashMessenger</h3>
<p>To store all the messages, I created a class called <kbd>FlashMessenger</kbd> which is responsible to store the messages. I created a new folder <kbd>LibrarySession</kbd> and saved the class as <kbd>FlashMessenger.cs</kbd>. The class allows saving of messages to 3 namespaces (success, notice, error) by default &#8211; to add more namespaces just edit the enum.</p>
<pre class="code prettyprint csharp">
using System;
using System.Collections;
using System.Collections.Generic;

namespace MyProject.Library.Session
{
    public class FlashMessenger
    {
        public enum MessageType
        {
            Success,
            Notice,
            Error
        };

        private Dictionary&lt;MessageType, Queue&lt;string&gt;&gt; _messages;
        public Dictionary&lt;MessageType, Queue&lt;string&gt;&gt; Messages
        {
            get { return _messages; }
            private set { _messages = value; }
        }

        public FlashMessenger()
        {
            Messages = new Dictionary&lt;MessageType, Queue&lt;string&gt;&gt;();
            foreach (MessageType type in Enum.GetValues(typeof(MessageType)))
            {
                Messages[type] = new Queue&lt;string&gt;();
            }
        }
    }
}
</pre>
<h3 id="basecontroller">BaseController</h3>
<p>The next element is the <kbd>BaseController</kbd> which initializes the FlashMessenger and implements methods to easily create new messages. All my controllers inherit from this controller, so I can use messaging everywhere. The <kbd>[Messaging]</kbd> attribute on the class level ensures all actions use the <kbd>MessagingAttribute</kbd> we&#8217;ll create in the next step. I created the controller as <kbd>BaseController.cs</kbd> in <kbd>LibraryControllers</kbd>.</p>
<pre class="code prettyprint csharp">
using System;
using System.Web;
using System.Web.Mvc;
using MyProject.Library.Session;

namespace MyProject.Library.Controllers
{
    [Messaging]
    public class BaseController : Controller
    {
        protected override void Initialize(System.Web.Routing.RequestContext requestContext)
        {
 	    base.Initialize(requestContext);
            this.InitializeFlashMessenger();
        }        

        # region FlashMessenger
        public FlashMessenger Messenger
        {
            get { return (FlashMessenger)Session[&quot;FlashMessenger&quot;]; }
            private set { }
        }

        protected void InitializeFlashMessenger()
        {
            if (Messenger == null)
                Session[&quot;FlashMessenger&quot;] = new FlashMessenger();
        }

        public void FlashMessage(string message)
        {
            FlashMessage(message, FlashMessenger.MessageType.Success);
        }

        public void FlashMessage(string message, FlashMessenger.MessageType type)
        {
            Messenger.Messages[type].Enqueue(message);
        }
        # endregion
    }
}
</pre>
<p>This allows us to use the FlashMessaging system in every controller which inherits from <kbd>BaseController</kbd>. For example:</p>
<pre class="code prettyprint csharp">
public ActionResult Foo()
{
    FlashMessage(&quot;You have been redirected to Bar from Foo&quot;, FlashMessenger.MessageType.Notice);
    return RedirectToAction(&quot;Bar&quot;, &quot;Home&quot;);
}
</pre>
<h3 id="messagingattribute">MessagingAttribute</h3>
<p>Our messaging system is set up, but we still need to display our messages. To achieve this, I created an action filter called <kbd>MessagingAttribute</kbd> which injects the messages into the <kbd>ViewData</kbd> object. The output are simple unordered lists which get the <kbd>MessageType</kbd> as class name. As the attribute is set up on the class level of <kbd>BaseController</kbd>, the filter gets executed on every action and messages are available in every view. I saved the filter as <kbd>MessagingAttribute.cs</kbd> in <kbd>LibraryControllersFilters</kbd>.</p>
<pre class="code prettyprint csharp">
using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using MyProject.Library.Session;

namespace MyProject.Library.Controllers
{
    public class MessagingAttribute : ActionFilterAttribute, IActionFilter
    {
        void IActionFilter.OnActionExecuting(ActionExecutingContext filterContext)
        {
            FlashMessenger Messenger = (FlashMessenger) filterContext.HttpContext.Session[&quot;FlashMessenger&quot;];
            StringBuilder output = new StringBuilder();

            foreach (KeyValuePair&lt;FlashMessenger.MessageType, Queue&lt;string&gt;&gt; kvp in Messenger.Messages)
            {
                if (kvp.Value.Count &gt; 0)
                {
                    output.AppendLine(&quot;&lt;ul class=&quot;&quot; + kvp.Key.ToString() + &quot;&quot;&gt;&quot;);

                    while(kvp.Value.Count &gt; 0)
                    {
                        output.AppendLine(&quot;&lt;li&gt;&quot; + kvp.Value.Dequeue() + &quot;&lt;/li&gt;&quot;);
                    }

                    output.AppendLine(&quot;&lt;/ul&gt;n&quot;);
                }
            }

            filterContext.Controller.ViewData[&quot;FlashMessenger&quot;] = output;
        }
    }
}
</pre>
<h3 id="view-and-css">View and CSS</h3>
<p>To display the messages in your application, edit the following. In your <kbd>Site.master</kbd>, display the output from the action filter:</p>
<pre class="code prettyprint html">
&lt;div id=&quot;main&quot;&gt;
    &lt;div id=&quot;messages&quot;&gt;
        &lt;%= ViewData[&quot;FlashMessenger&quot;] %&gt;
    &lt;/div&gt;            

    &lt;asp:ContentPlaceHolder ID=&quot;MainContent&quot; runat=&quot;server&quot; /&gt;

    &lt;div id=&quot;footer&quot;&gt;
    &lt;/div&gt;
&lt;/div&gt;
</pre>
<p>In your <kbd>Site.css</kbd>, add some styling for your messages:</p>
<pre class="code prettyprint css">
#messages {
    margin-bottom: 2em;
}

#messages ul {
    list-style: none;
    margin: 0;
    padding: 0;
}

#messages ul li {
    display: block;
    margin: .75em 0;
    padding: 10px;
    border: 2px solid #ddd;
    background-color: #eee;
    color: #222;
}

#messages ul.Notice li {
    background: #FFF6BF;
    color: #817134;
    border-color: #FFD324;
}

#messages ul.Success li {
    background: #E6EFC2;
    color: #529214;
    border-color: #C6D880;
}

#messages ul.Error li {
    background: #FBE3E4;
    color: #D12F19;
    border-color: #FBC2C4;
}
</pre>
<h3 id="example-usage">Example usage</h3>
<p>As an example, we modify the <kbd>AccountController</kbd> to show a nice confirmation message on login and logout.</p>
<p>First of all, import the <kbd>Library.Session</kbd> namespace and let the controller inherit from <kbd>BaseController</kbd>.</p>
<pre class="code prettyprint csharp">
@@ -8,11 +8,13 @@ using System.Web.Mvc;
 using System.Web.Security;
 using System.Web.UI;
 using MyProject.Models;
+using MyProject.Library.Controllers;
+using MyProject.Library.Session;

 namespace MyProject.Controllers
 {
     [HandleError]
-    public class AccountController
+    public class AccountController : BaseController
     {

         // This constructor is used by the MVC framework to instantiate the controller using
</pre>
<p>Add a flash message to your logon action:</p>
<pre class="code prettyprint csharp">
@@ -63,6 +63,7 @@ namespace MyProject.Controllers
             }

             FormsAuth.SignIn(userName, rememberMe);
+            FlashMessage(&quot;Logged on successfully&quot;, FlashMessenger.MessageType.Success);^M

             if (!String.IsNullOrEmpty(returnUrl))
             {
</pre>
<p>And to your logoff action:</p>
<pre class="code prettyprint csharp">
@@ -78,6 +78,7 @@ namespace MyProject.Controllers
         public ActionResult LogOff()
         {
             FormsAuth.SignOut();
+            FlashMessage(&quot;Logged off successfully&quot;, FlashMessenger.MessageType.Success);^M
             return RedirectToAction(&quot;Index&quot;, &quot;Home&quot;);
         }
</pre>
<h3 id="conclusion">Conclusion</h3>
<p>So far the system is finished and allows easy flashing of messages between page requests. However, I&#8217;m not completeley happy with the solution of having to use a base controller to initialize and use the messaging system. If anyone knows a better solution, please let me know.</p>
<img src="http://feeds.feedburner.com/~r/mafflog/~4/4X3i0mNjplo" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://ailoo.net/2009/06/build-a-flashmessenger-system-in-aspnet-mvc/feed/</wfw:commentRss>
		<slash:comments>22</slash:comments>
		<feedburner:origLink>http://ailoo.net/2009/06/build-a-flashmessenger-system-in-aspnet-mvc/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=build-a-flashmessenger-system-in-aspnet-mvc</feedburner:origLink></item>
	</channel>
</rss>

