11.26.06

HOWTO: Setup SYMPA, WWS with Apache2/FastCGI on Debian/Ubuntu Edgy

Posted in Unix / Linux, Tips and Documentation at 10:24 am by skoobi

Debian/Ubuntu sympa packages rely on apache1, so one may have problems running sympa on Ubuntu Edgy, for instance.

This simple HOWTO explains how to configure Sympa and WWS to run with Apache2 and FastCGI. FastCGI is used instead of CGI because of the performance impact it has. (Basically, CGI forks a new instance of the CGI script wheareas a FastCGI-enabled script runs as a daemon to handle requests, much like a decent system like Java Servlet API.)
Installation

Install the sympa package, and copy the installed apache1 configuration files to apache2 folder

# apt-get install sympa libapache2-mod-fastcgi

# ln -s /etc/sympa/httpd.conf-fcgi /etc/apache2/conf.d/sympa-fcgi

# dpkg-reconfigure -plow sympa

A wizzard will come up, make sure to :

  • Use a database if you want to use WWS
  • Select “Other” when asked what type of web server you are running
  • Tell the wizzard that you want FastCGI enabled

Once this is done, check the /etc/sympa/wwsympa.conf file, and make sure

use_fast_cgi is set to 1

and the last step is to restart apache :

/etc/init.d/apache2 restart

Now, my personal thoughts about mailing-list systems. My impression is that there is no perfect Open Source mailing-list system (however, there are several ones that “do the job”). The characteristics of a good mailing-list system would be, to my opinion :

  • Be entirely configurable through a Web UI. Sympa does a pretty good job at this, since most of the settings are tweakable from WWS. However, the UI is pretty ugly (sure, one can tweak the templates, but…)
  • Would provide a Mailing-List system as well as a Web forum. To make it simple, something like Google Groups, that also allows to post (and subscribe/unsubscribe orders) via email. It is then up to each subscriber to choose between email and Web.
  • Re-uses a well-known templating system ( Smarty in the PHP world, or Freemarker in the Java world, …). Why re-inventing yet another templating language if very good ones already exist ? Having to learn a templating language per web-application is pretty much cumbersome.
  • Be extensible : It should provide a decent plugin system, that people can use to provide additional modules without touching a single line of the current base code. Requiring the modification of a 9980-line (cat /usr/lib/cgi-bin/sympa/wwsympa.fcgi | wc -l) perl script is, In my humble opinion, very bad practice. This implies coding against interfaces, and using some kind of IoC framework like the Spring Framework.
  • Would be independant of the persistence layer, through the use of a sophisticated persistence engine such as Hibernate. Anyone can then configure it to use his preferred database engine
  • Authentication would also be extensible. A security framework such as Acegi could be used so that anyone can easily have the mailing list system authenticate the users against the configured authentication backend. (be it database, system/PAM, Single-Sign-On, etc..). It doesn’t make sense to re-implement every authentication backend in every webapp, since some frameworks already do the job.

HOWTO: Use more than 3 virtual interfaces with Xen (by using IP Aliasing)

Posted in Unix / Linux, Tips and Documentation at 8:11 am by skoobi

Prerequisite : You have Xen running correctly for less than 3 virtual interfaces. This HOWTO explains how to get it to work on Ubuntu Edgy.

Xen does not support using more than 3 virtual interfaces on the guest machines (the so-called DomU). It is stated in the Xen FAQ, and attempting to use more results  in what Ernie Fontes experienced in this post.
The usual trick for having more interfaces in a stand-alone system is to use IP Aliasing. Ubuntu Linux, among others, support IP Aliasing without any problem. However, IP Aliasing seems not to work (according to my tests) for a Xen DomU.

For some reason that I cannot explain nor understand, there is still a way to use more than 3 virtual interfaces in a Xen DomU by using the offical Xen way of adding interfaces, and by using IP Aliasing on top of that. It is weird, but it works :

  • using Xen virtual interfaces is limited to 3 interfaces.
  • using IP aliasing interfaces makes interfaces that are not pingable from the outside
  • BUT using exactly 3 Xen virtual interfaces, and adding more interfaces thanks to IP Aliasing works beautifully….

Here is a quick HOWTO explaining this procedure :

Xen Configuration

Add 3 interfaces for the DomU (you might replace xenbr1 by xenbr0 if your bridge name is the standard one) :

vif = [ ‘bridge=xenbr1′,’bridge=xenbr1′,’bridge=xenbr1′ ]

And you can create your domain using the usual xm create command.

xm create config.cfg

xm console

DomU Network configuration

You can now configure your domain interfaces and the aliases. For the sake of giving a complete example, here is how to achieve that under Debian/Ubuntu :

Let’s say that we want to configure the 216.240.153.78, 216.240.138.247, 216.240.146.76 IPs for, respectively, eth0, eth1 and eth2, and 216.240.134.6 as well as 216.240.128.182 for the 2 aliases eth0:0 and eth0:1.

/etc/network/interfaces

auto eth0
iface eth0 inet static
address 216.240.153.78
netmask 255.255.255.0
gateway 216.240.153.1

auto eth1
iface eth1 inet static
address 216.240.138.247
netmask 255.255.255.0
gateway 216.240.138.1

auto eth2
iface eth2 inet static
address 216.240.146.76
netmask 255.255.255.0
gateway 216.240.146.1

auto eth0:0
iface eth0:0 inet static
address 216.240.134.6
netmask 255.255.255.0
gateway 216.240.134.1

auto eth0:1
iface eth0:1 inet static
address 216.240.128.182
netmask 255.255.255.0
gateway 216.240.128.1

You can now tell the system to reconfigure the network (/etc/init.d/networking restart), and if it still doesn’t work (especially for the aliases), you can restart the DomU (xm reboot domU-name).

Now, if someone has an idea of why this tip works, I am really really interested to know. Because right now, it looks like magical stuff that I’m not even sure of how I discovered ;-)

11.22.06

Awstats, Libperl-Storage, and endianness (Byte Order) issues

Posted in Unix / Linux, Tips and Documentation at 9:12 am by skoobi

If you have recently migrated your AWstats to a different Architecture (Pentium4 to AMD64, for instance), awstats may report you the following error :

Warning: Error while retrieving hashfile: Byte order is not compatible at ../../lib/Storable.pm (autosplit into ../../lib/auto/Storable/_retrieve.al) line 331, at (eval 8) line 1

This is caused by the fact that awstats/perl caches DNS Entries in a machine-dependant way. Others have experienced the same problems, like on this forum.

The solution is actually quick. Let’s say your stats are in /stats, you can do :

find /stats -name ‘*.hash’ -exec rm {} \;

HOWTO: Apache2 + Awstats setup on Debian/Ubuntu (Edgy Eft)

Posted in Unix / Linux, Tips and Documentation at 9:07 am by skoobi

Here is a simple HOWTO explaining how to configure AWstats to analyze Apache2 logs, and provide detailed statistics, under Ubuntu Edgy Eft. This should also work for other Ubuntu versions, as well as any Debian derivative.

Apache

The first step is to activate Logging in Apache, so that Awstats has something to analyze. For instance, you can add something similar in your VirtualHost configuration :

ErrorLog /var/log/apache2/sirika.com-error.log
CustomLog /var/log/apache2/sirika.com-access.log combined

Another important thing is to configure a few things for awstats in apache, like where the icons are, and more importantly, to activate CGI-scripts (since AWstats is written in perl…) . This can be done thanks to the following /etc/apache2/conf/awstats.conf :

# This provides worldwide access to everything below the directory
# Security concerns:
# * Raw log processing data is accessible too for everyone
# * The directory is by default writable by the httpd daemon, so if
# any PHP, CGI or other script can be tricked into copying or
# symlinking stuff here, you have a looking glass into your server,
# and if stuff can be uploaded to here, you have a public warez site!

Options None
AllowOverride None
Order allow,deny
Allow from all
# This provides worldwide access to everything below the directory
# Security concerns: none known

Options None
AllowOverride None
Order allow,deny
Allow from all

# This provides worldwide access to everything in the directory
# Security concerns: none known
Alias /awstats-icon/ /usr/share/awstats/icon/

# This (hopefully) enables _all_ CGI scripts in the default directory
# Security concerns: Are you sure _all_ CGI scripts are safe?
ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/

Awstats

The next step is to install awstats, with all the necessary perl modules.. Using several optional modules implies that you have installed them. liburi-perl is useful if you use the “decodeutfkeys” module, even though it is NOT listed as recommended or suggested in the awstats package.

sudo apt-get install awstats libnet-dns-perl libnet-ip-perl libgeo-ipfree-perl liburi-perl libnet-xwhois-perl

Once this is working, it is now necessary to configure awstats, to tell it which logs it should monitor, and where it should write its working files (stats). This is done by creating a file /etc/awstats/awstats.website.conf (replace website by your apache2 virtual host name, for instance, and do NOT forget the .conf !).

sudo cp /etc/awstats/awstats.conf /etc/awstats/awstats.website.conf

Editing this file should be pretty straightforward, since it is well commented. In particular, pay attention to the following entries

LogFile=”/var/log/apache2/sirika.com-access.log”

SiteDomain=”sirika.com”

HostAliases=”www.sirika.com”

DirData=”/srv/data/stats/sirika.com”

LogFile should point to the log file configured in Apache2.

SiteDomain is the main domain name, as configured in Apache2.

HostAliases should list ALL the aliases listed in Apache2’s VirtualHost configuration. Usually, you will want the same domain prefixed with www, (or without the www prefix if is it already specified in the main domain name). This is really annoying, error-prone and not having a global definition of a “virtual host” on the system is one of the issues I pointed in “10 things that still suck under linux“. Virtual hosts and aliases should be defined once, globally. Every single concept/thing should be repeated/configured once, and only once, on a perfect system. Anyways…

DirData should point to an empty directory, whose content will be managed by Awstats.
Cron

Everything is now configured. On a perfect system, the setup would stop now. Awstats could be automagically notified for every change in the logs (awstats could register to a so-called “http access event”, and its internal behaviour could define its policy for updating the stats (update synchronously, update asynchronously when the system is idle, etc..). This is one of the things I pointed out in “10 things that still suck under linux“. However, we’re not there yet, so, we need to run the script every day to update the stats. (yeah, that’s the reality today..)

So, this can be done thanks to the following /etc/cron.daily/awstats (do not forget to chmod +x /etc/cron.daily/awstats after creating it) :

#!/bin/sh

/usr/share/doc/awstats/examples/awstats_updateall.pl -awstatsprog=/usr/lib/cgi-bin/awstats.pl now > /dev/null

This will update all the statistics for all the hosts defined in /etc/awstats/*, on a daily basis. Yes, it’s not as beautiful as having a full-featured event-system for which every application could attach to events generated by others, but it has the merits of working…

Logrotate

What happens when your apache logs get rotated (and possibly gzipped, etc) by logrotate (apt-cache show logrotate for more information), and awstats still hasn’t analyzed the end of the logs that is about to be rotated ?

To avoid this situation, it is necessary to tell logrotate to launch awstats BEFORE rotating the logs. This can be done by adding the following lines to /etc/logrotate.d/apache2 :

prerotate
/etc/cron.daily/awstats
endscript

Permissions

And of course, permissions must be tweaked :

  • Since Awstats runs as the web users for viewing stats (CGI-script), the web user needs read access to /srv/data/stats/*
  • Additionnally, you may want to provide the “update now” button on your website stats. So, the web user also needs write access to /srv/data/stats/*
  • Finally, awstats needs access to the apache2 logs to create the stats. This is not a problem when it is run from a cron script, since it is run as root. But, in the case of “update now”, it runs as the web server, so the web server needs read access to its logs. (the default permissions are 660 with root:adm), so www-data doesn’t have access to its logs

The problem with traditional permissions is that there is no decent way of specifying default permissions. So, we are going to use ACLs for that. You can find more information about them here (Using POSIX ACLs to complement traditional Linux permissions). So, this gives, for instance :

# read write execute access for web user to the stats directories
find /srv/data/stats -type d -exec setfacl -m “g:www-data:rwx” {} \;

# read write execute access for FUTURE stats files for the web users

find /srv/data/stats -type d -exec setfacl -d -m “g:www-data:rwx” {} \;

# read write access to the stats files for the web user
find /srv/data/stats -type f -exec setfacl -d -m “g:www-data:rw-” {} \;

# read only access to the logs directory for the web user
find /var/log/apache2 -type d -exec setfacl -m “g:www-data:r-x” {} \;

# read only access to the logs for the web user, for future files

find /var/log/apache2 -type d -exec setfacl -d -m “g:www-data:r-x” {} \;

# read only access to the apache2 logs for the web user
find /var/log/apache2 -type f -exec setfacl -m “g:www-data:r–” {} \;

And it should work.. The last thing would be to protect access to your logs, if you don’t want your users to see them. This can be done using a .htaccess file, and there are plenty of tutorials on the web that explain how to achieve that.

02.07.06

Adding db4o OO database support for Spring.NET Transactions

Posted in .NET, Tips and Documentation at 3:19 pm by skoobi

Compared to its Java peer, Spring.NET’s transaction support is still in its infancy and somewhat undocumented.
According to some posts in the forum, Transaction support should come with version 1.1 (currently in CVS).

In the meantime, those of us who have to deal with transactions still have to find a solution.. The first step is to get a nightly snapshot build of the CVS and copy the Spring.Data classes from the sandbox.

The second step is to understand how Transactions are supported and the last step is to add support for your Data backend if it is not yet supported (only ADO.NET is supported, as far as I know.. Maybe iBatis.Net is too, at least partially).
So, concerning the second step, this thread should help to understand once people give some answers…

This post is to give more details of what I understand in the hope that it will help someone else in the same position :

  • First of all, It is necessary to understand the real problem, so here is a scenario :
    • A Database maintains all data for a website
    • A website has several visitors working concurrently (Several threads will be concurrently accessing the database at the same time, each one serving a visitor)
    • It is NOT acceptable (for performance reasons) to open a new connection every time something must be SELECT’ed or UPDATE’d, then closed.
    • Database sessions can either be commit’ed (successful registration on the website) or rollback’ed (client gone before the end of the registration).
  • Then, it is important to read about Spring (Java) Transaction support, since Spring.NET is highly inspired about its Java counterpart. It’s basically the only documentation we have, so let’s read it, it’s way easier to understand than API documentation ;-)
  • So, to sum-up Spring Transaction Support: The PlatformTransactionManager (e.g. AdoPlatformTransactionManager for ADO.NET), TransactionSynchronizationManager and Template (AdoTemplate) classes are particularly important.
    • All Data access code should be run by PlatformTemplate.Execute (AdoTemplate) that will take care of all the resources initializasation/cleanup, as well as transaction synchronization if necessary (the Template still works if there is no transaction to synchronize to).
    • TransactionSynchronizationManager takes care of managing resources and transaction synchronizations per thread. In fact, the problem to solve is about assigning a Transaction and its corresponding connection to every thread that wants to access the database. Depending on the underlying infrastructure and configuration, we may reuse already existing connections -instead of creating and closing systematically - (connection pool such as Commons-DBCP in the Java World) and synchronize them to a transaction. However, this class does not deal with anything else than just keeping the resources of each thread. All the connection/transaction to thread assignment logic is done by the PlatformTransactionManager
    • PlatformTransactionManager (AdoPlatformTransactionManager) : this component returns a currently active transaction or creates a new one based on the given parameters (Isolation level, etc).
    • TransactionTemplate complements AdoTemplate. While AdoTemplate is used to make sure data access code will be synchronized to a currently used transaction, TransactionTemplate is used to demarcate transactions. In other words, it can be used in non-data access code (higher-level services that use DAOs directly or indirectly), to tell where a transaction begins and where it ends.
      • The use of TransactionTemplate is not mandatory, but not using it will imply that calling AdoPlatformTransactionManager methods will be up to the user…
      • Declarative TransactionDemarcation can also be used (and is recommended), but for the sake of clarity, we won’t add another layer of complexity here. Spring.NET’s AOP-style declarative transaction demarcation can be seen as the dynamic creation of a proxy around a service class that will just wrap the method calls inside the previously described TransactionTemplate. Then, other beans must use the generated proxy instead of the actual class. But as you can see, the underlying principle concerning Transaction stays the same : we rely on a TransactionTemplate.

So, overall, things do not seem that complex.. Let’s analyze a bit more.

PlatformTransactionManager is the main actor on the scene. Its role is to Create/Reuse transactions, commit and rollback transactions. It conforms to the IPlatformTransactionManager interface that defines the following methods :

  • ITransactionStatus GetTransaction( ITransactionDefinition definition );
  • void Commit( ITransactionStatus transactionStatus );
  • void Rollback( ITransactionStatus transactionStatus );

ITransactionDefinition defines all the gory details of the transaction (Propagation behavior, Isolation Level, Timeout, etc). See Wikipedia for more information about these general Database concepts.

So basically, when we want to perform a transacted set of tasks, the code should look like (taken from Spring Java documentation) :

DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);

TransactionStatus status = txManager.getTransaction(def);
try {
// execute your business logic here
}
catch (MyException ex) {
txManager.rollback(status);
throw ex;
}
txManager.commit(status);

In other words, this is the manual way of demarcating transactions (e.g. the “wrong” way). But at least, things are pretty clear about what’s done on the system. (txManager is the platform transaction manager, AdoPlatformTransactionManager, for example).

The good news is that it is exactly how TransactionTemplate wraps service code, in the Execute() method :

public object Execute(ITransactionCallback callback)
{
ITransactionStatus status = _platformTransactionManager.GetTransaction( this );
object result = null;
try
{
result = callback.DoInTransaction( status );
}
catch ( Exception ex )
{
rollbackOnException( status, ex );
throw ex;
}
_platformTransactionManager.Commit( status );
return result;
}

As you can see from the code no magic is done here, we purely rely on the PlatformTransactionManager to perform some logic that will make sure the connections and transactions don’t get mixed and matched between threads…

So, let’s see how PlatformTransactionManager works.. Of course, you can already envision that a lot of things are going to be pretty much the same no matter what the concrete platformTransactionmanager is. In fact, no matter whether you use ADO.Net, iBatis.Net, or whatever else, the following workflow handling is hardcoded into AbstractPlatformTransactionSupport, from which all concrete PlatformTransactionsupport should inherit :

  • Determines if there is an existing transaction
  • Applies the appropriate propagation behavior
  • Suspends and resumes transactions if necessary
  • Checks the rollback-only flag on commit
  • Applies the appropriate modification on rollback (actual rollback or setting rollback-only)
  • Triggers registered synchronization callbacks (if transaction synchronization is active)

The basic idea here is that the three methods (GetTransaction(), Commit() and Rollback() are implemented and use the Strategy Design Pattern to delegate actual processing to the concrete subclasses (All the Do*() methods).
So, all the dirty work of complying with the API is already done, and the real work left is about coding the parts that are different with each system, such as beginning a transaction (DoBegin()).

The link with TransactionSynchronizationManager is done, for example in DoBegin by :

TransactionSynchronizationManager.BindResource(DbProvider,
txMgrStateObject.ConnectionHolder);

The ConnectionHolder (which represents the Connection + Transaction) is bound to the thread by the static BindResource which will use a [ThreadStatic] Collection to take care of the Threading stuff. (See more information about the TreadStatic Attribute on MSDN).

However, one thing that I am still unsure about is how connection ressources are disposed. After committing, we do not want to close the session, we just want to tell the PlatformTransactionManager that the resource is now free to reuse for some other thread.

To put it in a nutshell, in order to add support for a new transaction system, here are the required elements :

  • a Template class
  • A transaction Manager
  • Utils class (used by the template and Manager to create/open/close connections)

This should be enough to get a working implementation. I’ll create one for db4o OO database.

01.26.06

ServiceMix JBI Container and PXE BPEL: Theory and practice..

Posted in Java, Tips and Documentation at 12:18 pm by skoobi

While speaking about a work I achieved last summer, related to ServiceMix (a JBI container) and PXE ( a BPEL engine that can be embedded inside ServiceMix), a friend of mine came up to the following conclusion :

In theory, theory and practice are the same whereas in practice, they are not.

I love that sentence :-)

So, here is a small HOWTO, taken from the email I sent to ServiceMix mailing list :

How to get a BPEL process running with ServiceMix JBI Container and Fivesight's
PXE :
===

1) The first step is to create a BPEL process with the corresponding WSDL files.
Examples bundled with PXE can serve as a quickstart.

2) Remove any concrete bindings in the WSDL Files (
binding and service XML tags). Indeed, the endpoints are JBI proxies, so the
SOAP over HTTP bindings are useless here. PXE and ServiceMix will take care of
registering ports as JBI Service endopints.

3) Compile your BPEL process and WSDL files
let's say the main WSDL file describing the process is in the
MissionPlanningProcess.wsdl (this file must import the other WSDL files that
are
used :

REM add the resources to PXE's Resources Repository MissionPlanning.rr
rradd -wsdl file:MissionPlanningProcess.wsdl MissionPlanning.rr

REM compile the BPEL
bpelc -rr MissionPlanning.rr -wsdl file:MissionPlanningProcess.wsdl
file:MissionPlanning.bpel

4) Create a pxe-system.xml file that describes how to bind the BPEL process to
actual JBI endpoints. (PXE's deployment descriptor)

Let's say that the MissionPlanning process provides 3 portTypes :
proc:ProcessPT, proc:CallbackPT, resp:ResponderPT.

We want to expose 2 services :
ProcessSVC that exposes the proc:processPT and proc:CallbackPT porttypes
and
ResponderSVC that exposes the resp:ResponderPT portType.

(same names as the Async example bundled with PXE)

the corresponding pxe-system.xml file would be :

http://www.w3.org/2001/XMLSchema-instance";
xsi:schemaLocation="http://www.fivesight.com/pxe/system-descriptor/
http://www.fivesight.com/pxe/system-descriptor/”;
wsdlUri=”file:MissionPlanningProcess.wsdl”
xmlns=”http://www.fivesight.com/pxe/system-descriptor/”;
xmlns:proc=”uri:concordia.ciise.weather.process”
xmlns:resp=”uri:concordia.ciise.weather.responder”>







Pay attention to use the same value for the “name” attribute in the
system-descriptor tag, as the name of the BPEL process. (current limitations
with PXE, should be fixed in the future)

5) We now have all the necessary artifacts to create a SAR (System Archive) file
that is just a container for all these files :

sarcreate -common MissionPlanning.rr -sysd pxe-system.xml MissionPlanning.cbp
pxe.sar

6) JBI needs deployable components (the SAR in this case) to be contained in a
zip file. The zip file is referred later as a Service Unit. (hence the -su)

=> create the output directory
=> jar cf outputMissionPlanning-su.zip pxe.sar
(or use any tool that can create a .zip)

7) Package this service unit inside a so-called Service Assembly (SA), which is
just a set of service units with a jbi.xml
For example, create the following outputMETA-INFjbi.xml file :

http://java.sun.com/xml/ns/jbi  ./jbi.xsd”
xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”;
xmlns=”http://java.sun.com/xml/ns/jbi”;>

MissionPlanningSA
Service Assembly containing just the BPEL
deployment.

MissionPlanning
BPEL Service Unit

MissionPlanning-su.zip
PxeBpelEngine

and create the jar :
cd output
echo creating Service Assembly
jar cf ..MissionPlanning-sa.jar *
cd ..

component-name refers to the name of the BPEL engine deployed in the JBI
container.

8) Create a servicemix.xml file that launches a JBI container.
An example is bundled with ServiceMix’s AsyncDemo example :
Pay attention to :

and

in the installationDirPath, you will have to drop the PXE’s JBI component.
(bundled with ServiceMix). If ServiceMix doesn’t detect PXE nor install it, then
it means there is a problem in your installationDirPath. (For example, if
ServiceMix is integrated inside Geronimo, the “.” directory refers to
GERONIMO_HOME

the deploy directory is where you will drop the Service Assembly

9) launch service mix (either standalone, or by sourcing the spring file.
If you source the spring file, make sure you use ServiceMix’s Spring version.
The XML extension mechanism is not yet available from upstream Spring, so
Spring won’t recognize servicemix’s specific spring syntax.

10) Here you go, you can then talk to your BPEL process from other JBI
components (more information in another HOWTO)
I hope that this HOWTO will help someone some day...

01.19.06

Horde3 and Imp4 HOWTO under Ubuntu/Debian

Posted in Unix / Linux, Tips and Documentation at 12:58 pm by skoobi

This post is a simple set of guidelines (a mini-HOWTO) on How to setup Horde3 and Imp4 Webmail. In fact, the official documentation lacks a few important things, so here are a few tricks.

First of all, install the horde3 and Imp4 packages (Ubuntu/Debian)

apt-get install horde3 imp4

It is then necessary to setup an Alias for Apache. If you’re using Apache2, add a file /etc/apache2/conf.d/horde3.conf containing

Alias /horde3 /usr/share/horde3

Also, allow Apache to write horde configuration files :

chown -R www-data:www-data /etc/horde

Or, if you prefer to use ACLs

setfacl -m “g:www-data:rwx” /etc/horde

setfacl -d -m “g:www-data:rwx” /etc/horde

setfacl -m “g:www-data:rwx” /etc/horde/*

setfacl -d -m “g:www-data:rwx” /etc/horde/*

setfacl -m “g:www-data:rw-” /etc/horde/*/*

and restart apache

/etc/init.d/apache2 restart

You can then browse http://server/horde3

Important parameters to change are (in Horde setup) :

  • Horde URL (change it to /horde3)
  • Enable Database Access. Do Not use MySQL Improved (4+), my attempts at using it failed. MySQL Standard runs fine however
  • Enable Authentication. I recommend IMAP authentication (something like {localhost:143/imap/notls}. Do not forget the /notls, not specifying failed on my setup). Also make sure to add your username to the list of Administrators, otherwise, you won’t have access to horde/imp4 parameters. Using anything else than IMAP seeemed to fail on my setup
  • Generate the configuration

Horde should now be setup. You now have to configure imp4

  • generate a configuration using the horde administration panel
  • modify the /etc/horde/imp4/servers.php file. Instruction are given inside the file concerning the syntax. If you run Courier-IMAP, and want Imp to automatically authenticate using horde credentials :

$servers[’imap’] = array(
‘name’ => ‘IMAP Server’,
’server’ => ‘localhost’,
‘hordeauth’ => true,
‘protocol’ => ‘imap/notls’,
‘port’ => 143,
‘folders’ => ‘INBOX.’,
‘namespace’ => ‘’,
‘maildomain’ => ‘domain.com’,
’smtphost’ => ‘localhost’,
’smtpport’ => 25,
‘realm’ => ‘’,
‘preferred’ => ‘’,
‘dotfiles’ => false,
‘hierarchies’ => array()
);

You should now have a working setup.. Good luck !

01.15.06

2 things to make Grub work for you

Posted in Unix / Linux, Tips and Documentation at 3:36 pm by skoobi

No matter how better Grub is compared to Lilo, it still has its flaws, making it sometimes hard to use.
Here are two important things to check :

  • That you have a “boot” symlink pointing to “.” in your /boot directory. Grub sometimes refer to /boot/boot/.., so it is safer to have this symlink
  • That you are having the right “groot” option defined in your menu.lst. It often happens that Grub mappings at boot time are not the same as Linux Grub mappings. For example, you might ask your BIOS to boot on a specific Hard Disk, that is not (hd0). The BIOS will make Grub believe that your (hdX) device is actually (hd0), so your menu.lst will not work. Change your menu.lst accordingly, and re-run update-grub to take the changes into consideration.

Running Ubuntu GNU/Linux on a FakeRAID/1 (mirroring) array

Posted in Unix / Linux, Tips and Documentation at 3:27 pm by skoobi

Edit: These information work for Ubuntu Breezy. Things may have changed with Dapper Drake
Most cheap hardware RAID controllers such as the VIA VT6421 are not purely hardware RAID systems, but should be seen as semi-soft, or FakeRAID controllers.

In order to install an Operating System on a FakeRAID array, it is thus necessary to setup a few things, since the underlying array is not completly transparent to the Operating System.

This short article, based on the Ubuntu Wiki FakeRaid HOWTO explains how to install Ubuntu Linux on such a FakeRAID array.

First of all, be aware that is it not currently possible (well, it is, actually, but one would have to revert to applying hacking changes in the Initial Ramdisk Image, so it is currently better to forget about it) to setup an LVM Volume on top of a FakeRAID array.

Since the Ubuntu Wiki FakeRaid HOWTO already explains how to install Ubuntu on a FakeRAID/0 array, I am just going to highlight the differences for a FakeRAID/1 array here.

The only difference is the creation of the Initial Ramdisk, which should load the dm-mirror module to allow the OS to read / write from the FakeRAID array.

The /etc/mkinitramfs/scripts/local-top/dmraid should be replaced by

#!/bin/sh

PREREQ=”"

prereqs()
{
echo “$PREREQ”
}

case $1 in
# get pre-requisites
prereqs)
prereqs
exit 0
;;
esac

modprobe -q dm-mod
modprobe -q dm-mirror

/sbin/dmraid -ay

In addition to the dm-mod module, the previous script launches the dm-mirror module. This means that the dm-mirror module should be copied. This is done by adding the line

dm-mirror

to the /etc/mkinitramfs/modules file.

The rest of the Ubuntu FakeRaid Howto gives a good explanation of the tasks that should be done in order to configure the FakeRaid array.

01.14.06

Using POSIX ACLs to complement traditional Linux permissions

Posted in Unix / Linux, Tips and Documentation at 9:33 am by skoobi

Anyone who has been using Linux in a multi-user environment has been confronted to the limits of the traditional 12-bit based UNIX permission system.

For instance, you are likely to get into trouble if you have a repository (e.g. a folder containing a website) that may be modified by a set of users. Indeed, if a user (bob) has a restrictive mask (077 for instance), here is what might happen :

bob@samlaptop:/tmp $ ls -ld repository
drwxr-xr-x 2 bob repository 4096 2006-01-14 17:46 repository
bob@samlaptop:/tmp $ umask 077
bob@samlaptop:/tmp $ cd repository/
bob@samlaptop:/tmp/repository $ mkdir folder
bob@samlaptop:/tmp/repository $ ls -ld folder/
drwx—— 2 bob repository 4096 2006-01-14 17:46 folder/

As a result, the folder created by bob is not accessible by other members of the repository group. However, it is not possible nor desirable to force a set of users to keep a non-restrictive mask. Additionally, several repositories on the system might have different policies.

This is where ACLs come in. ACLS, or Access Control Lists are a new set of permissions that recent UNIXes such as Linux now support. (Windows has been supporting ACLs for quite a long time). It is now possible to define fine-grained permissions and forget the numerous hacks that everybody has been imaginating in order to survive with the current system.
This post is not a step-by-step HOWTO that explains how ACLs work under Linux, since it has already been covered by alo’s blog, or Andreas Grünbacher white paper and HOWTO. In fact, this article is only a simple introduction that shows how easy it can be to use ACLs, and was written in the hope that ugo+rwx addicts take some time to change their habits.

First of all, you need a decent distribution, such as Ubuntu Linux, that ships an ACL-enabled kernel. Most filesystems (ext3, reiserfs, …) now support ACLs, so these guidelines should work no matter which filesystem you choose. The only requirement is to mount your filesystems with the “acl” option. For instance, your /etc/fstab should look like :

/dev/hdb1 /home reiserfs defaults,acl 0 0

Once this is enabled, you can start playing with acls. One of the most interesting aspects, often under-documented, is the “default” ACL.

To introduce this concept, let’s consider that our repository should be accessible by both the samokk user and by Apache’s user www-data. Any HOWTO about ACLs will tell you that you should use the getfacl command to query the current ACLs of a filesystem object (directory / file).

samokk@bluerock:/tmp$ getfacl repository/
# file: repository
# owner: samokk
# group: samokk
user::rwx
group::r-x
other::r-x

samokk@bluerock:/tmp$ ls -ld repository/
drwxr-xr-x 2 samokk samokk 4096 2006-01-14 09:19 repository/

getfacl reports the same information as ls -l. This means that there are currently no ACLs defined, besides the traditional ugo+rwx permissions.

We want the repository to be unreadable by others, but accessible by Apache :

samokk@bluerock:/tmp$ chmod 750 repository/
samokk@bluerock:/tmp$ setfacl -m “g:www-data:rwx” repository/
samokk@bluerock:/tmp$ getfacl repository/
# file: repository
# owner: samokk
# group: samokk
user::rwx
group::r-x
group:www-data:rwx
mask::rwx
other::—

The setfacl command has been used to add ACLs to the repository object, in order to allow the www-data group (see the g: keyword) to r, w and x on the directory. getfacl’s output reflects this.

However, we still haven’t solved the mask problem we cited above. Allowing www-data to access the repository does not mean www-data will be given permission to access files that will be created in the future. Default ACLs are there to solve this issue. Default ACLs are inherited from the parent directory and can only be applied to directories (it is not possible to create files inside files…).

samokk@bluerock:/tmp$ setfacl -d -m “g:www-data:rwx” repository/
samokk@bluerock:/tmp$ umask 700
samokk@bluerock:/tmp$ >repository/file
samokk@bluerock:/tmp$ getfacl repository/
# file: repository
# owner: samokk
# group: samokk
user::rwx
group::r-x
group:www-data:rwx
mask::rwx
other::—
default:user::rwx
default:group::r-x
default:group:www-data:rwx
default:mask::rwx
default:other::—
samokk@bluerock:/tmp$ getfacl repository/file
# file: repository/file
# owner: samokk
# group: samokk
user::rw-
group::r-x #effective:r–
group:www-data:rwx #effective:rw-
mask::rw-
other::—

Wha we have just done is simple : the repository has been given a default ACLs that will be inherited by directories and that will be used to set the permission of files created inside it. An example repository/file has been created to show that the files actually inherit the permissions.

This is it ! ACLs are actually quite simple to use, so do not hesitate to ease your life !