darkness

Thursday, 20 July 2006

Installing RT on CentOS

darkness @ 15:41:55

Versions: CentOS 4.3, RT 3.6.0, PostgreSQL 8.1.3, Postfix 2.2.10, Perl 5.8.5, mod_perl 2.0.1. (Mind you, not using MySQL.) That PostgreSQL and probably Postfix are not the versions that ship with CentOS 4.3 I’m afraid, but they were probably built from Fedora RPMs. The origins of that mod_perl are filled in below.

I’ve installed RT in the past, and I’m somewhat used to how it works. I’m also aware (but not “used to”) how many Perl dependencies it requires.

I mostly followed the instructions at http://wiki.bestpractical.com/index.cgi?ManualInstallation. I’ll show my configure command line since it gives me the opportunity to explain a bit about how I structured the installation:

./configure --prefix=/srv/www/support.domain.com/apps/rt3 \
--with-db-host='' --with-db-type=Pg --with-db-database=domain_rt3 \
--with-db-rt-user=domain_rt3 --with-db-rt-pass='sekret' \
--with-web-user=apache --with-web-group=apache \
--with-rt-group=support_domain_com \
--with-bin-owner=support_domain_com \
--with-libs-owner=support_domain_com \
--with-libs-group=support_domain_com --with-db-dba=postgres
  • Everything gets installed in a directory specific to the virtual host I’m working with. This might be even more useful if RT supports multiple instances and one or more of my customers wants their own ticketing system. But mostly just because I consider RT a web application, and I consider web applications to be bound to their particular web site (I can’t think of any exceptions to this thinking, but I bet there are some).
    • All the files in /srv/www/support.domain.com are owned by the support_domain_com user. I create my virtual hosts with some scripts that create a new user for every web site we host. Creating separate users is necessary for giving clients SFTP access to modify their web sites. In this case it’s not really necessary, but it doesn’t seem altogether wrong that there should be someone other than root owning RT’s myriad files.
    • DocumentRoot actually points to /srv/www/support.domain.com/root. Note that RT is not being installed in the DocumentRoot (which is completely proper as far as I know).
  • --with-db-host='' makes the DBD::Pg driver connect via Unix domain sockets.
    • Setting --with-db-dba is important for using RT’s installation scripts to create your initial database.
  • domain_rt3 basically indicates (to me) “this is the user that RT uses for the installation on domain.com.” (Sorry if “domain” is a poor example domain for these purposes.)

With that out of the way, you get right into the fun part: make testdeps.

You’re missing everything. (OK, not literally.)

Go get cpan2rpm and use it for most of RT’s dependencies. cpan2rpm will make everything into (mostly) nice little RPMs. cpan2rpm doesn’t work right with packages that use Module::Build (I think that’s what causes it) and you end up having to use the --version X.Y... argument to cpan2rpm. So my typically cpan2rpm invocation might look like:

cpan2rpm --no-upgrade-chk --install Foo::Bar [--version ...]
         [--make-no-test]

--make-no-test comes in when make test fails for a particular CPAN package. I had to do this on a handful of packages and my RT installation thus far seems no worse for it.

Installation of some of the resulting RPMs will fail because they need to update some files on the system that belong to the perl package. You’ll need to use rpm -Uvh --replacefiles on these (and if someone has a cleaner solution that’s easier than “rebuild the perl RPM without those files” please let me know). Additionally, some packages will have their auto-dependencies miscalculated; for example, one package claimed it required something like Win32::Registry. For these sorts of cases, you’ll need to give --nodeps to RPM, or else fix the dependencies with the appropriate cpan2rpm arguments.

It’s unfortunate that cpan2rpm apparently does not automatically get and build dependencies of the package you’re installing. What this means is that you’ll basically have a text editor open for use as a “stack” while you install RT dependencies: try to cpan2rpm an RT dependency, find out it has three unmet dependencies, push the RT dependency onto the stack, try to install one of the three dependencies, find it has its own unmet dependency, so push the package onto the stack and try the next one… and so on. Also, sometimes cpan2rpm Foo::Bar doesn’t find what distribution Foo::Bar is in, and I’m not sure why. I think MailTools is one such distribution. So instead of doing cpan2rpm Mail::Mailer (or whatever package I was looking for) I had to search CPAN to find the distribution name (MailTools) then cpan2rpm MailTools.

One RT dependency of note is Apache::Request. I’ve always had a problem finding this package in an RPM. The package name you’ll need to request is libapreq if you use mod_perl, or libapreq if you use mod_perl2. But you know what? Don’t try doing that through cpan2rpm because it doesn’t work. Moreover, CentOS 4.3 includes mod_perl 1.99. That’s some scary shit: closer to mod_perl 2, but not quite there yet. So here’s what I did: take the mod_perl SRPM from Fedora Core 4 updates and the libapreq2 SRPM from Fedora Core 5 Extras (I wanted to use mod_perl from FC5 but it required Apache 2.2, and I wasn’t about to go there), rebuild them on CentOS 4, and install the results. It seems to work just fine on my system so far.

[root@host rt3]# rpm -q mod_perl libapreq2
mod_perl-2.0.1-1.fc4
libapreq2-2.07-2.el4
[root@host rt3]# cat /etc/redhat-release
CentOS release 4.3 (Final)

One more note: install Apache::DBI. Somehow I didn’t have this, but if you’re going to use mod_perl, you’ll need it.

And that’s it for installing all of RT’s dependencies! It’s just that easy. Except it took me several hours to do this. But anyway…

Moving on, I’ll note that when you make install, you’ll need to go in and make a few directories under apps/rt3 mod 755, such as share and lib for example. Maybe var. I think RT’s installation thinks of itself as going into /usr/local, where you’ve already got those directories created with the proper permissions; so RT won’t “fix” the permissions on those directories, even when you ask it to make fixperms.

I did have to poke at /var/lib/pgsql/data/pg_hba.conf a bit since I only had rules for the postgres user to access stuff, and at the time doing sudo -u postgres make initialize-database wasn’t working very well. So I ended up jamming a temporary trust statement in pg_hba.conf while I did make initialize-database. Note that when using PostgreSQL, RT does everything for you including making the DB and the user RT will use to access that DB.

From here on it’s more or less a matter of following the directions. Some people have had problems running RT with SELinux in play, hence the page http://wiki.bestpractical.com/index.cgi?SELinux. Thus far I’ve had only one such problem I can think of: apache isn’t allowed to poke about in /usr/sbin, which makes running /usr/sbin/sendmail hard. (Note: it might work if you specify /usr/sbin/sendmail.postfix in the case of Postfix users; the first error I got was just trying to read the link. From reading the SELinux policy a little bit, though, I’m pretty sure things in the httpd_whatever_t context can’t get at /usr/sbin at all.) My solution (from apps/rt3/etc/RT_SiteConfig.pm:

Set($MailCommand, 'smtp');
Set($SMTPServer, 'localhost');

These tell Mail::Internet (or is it Mail::Mailer?) to talk SMTP to localhost instead of trying to invoke sendmail. Of course, once I did this I had some other problems, as described in this bug report send to Best Practical regarding problems with the Sender header in mail originated from RT. It includes a very small patch you can make if you have the problem described. Hopefully it might be fixed by the time you read this, either in RT or in MailTools (or both).

While we’re on the subject of SELinux, I’ll add that all the RT files seem to be in the httpd_sys_content_t context, and I have the httpd_unified boolean on in SELinux.

Also, in my default installation I’ll note I didn’t need $DatabaseRequireSSL turned on to talk to PostgreSQL. In fact, I think turning it on caused breakage.

My Apache configuration looks basically like what they have there, but with a few more directives to turn on SSL and make sure everyone gets pushed through the SSL version of the site. One change that I did make, and which I noted on the RT Wiki’s ManualInstallation page, is:

PerlModule Apache2::compat

instead of:

PerlModule Apache2 Apache::compat

It is suggested that use of Apache 2 requires inclusion of a directive such as:

RedirectMatch permanent (.*)/$ http://example.com$1/index.html

I did not have to use that. Everything worked right out of the box. (Ha. Ha.)

Just a few words about my mail setup. (I hope to talk more about all the mail services I’ve set up on this same server.) First of all, I only have one RT queue currently, and it’s named “Support.” I set up support.domain.com in virtual_alias_domains (referring to the Postfix main.cf directive). Then I put /etc/postfix/virtual in virtual_alias_maps, and set up these aliases:

postmaster@support.domain.com      some-postmaster@domain.com
abuse@support.domain.com           some-abuse@domain.com

support@support.domain.com         domain-support
support-comment@support.domain.com domain-support-comment

So e-mails to support@support.domain.com will go to the local user domain-support. By directing to a local user, I can then make entries in /etc/aliases such as:

domain-support: "|/srv/www/support.domain.com/apps/rt3/bin/rt-mailgate
         --queue support --action correspond
         --url https://support.domain.com"
domain-support-comment: "|/srv/www/support.domain.com/apps/rt3/bin/rt-mailgate
             --queue support --action comment
             --url https://support.domain.com"

(Wrapping added by me for readability.) To use https URLs you might need to install Crypt::SSLeay, and of course make sure you have the perl-libwww-perl RPM installed. Some postmap, newaliases, and we’re off to the races: RT now accepts e-mail.


A few more words on exactly how we’re currently using RT.

Now, ideally RT would work like this:

  • My company’s employees can sign in, see, and modify all tickets in the Support queue.
  • My client’s administrators can log in, see, and modify all tickets requested by their employees, but cannot see or modify tickets for other clients, all in the Support queue.
  • Employees at my client submit tickets normally through e-mail. (An optional interface to submit through the Web would be nice; maybe SelfService does this.)

That middle point is the problem. There doesn’t seem to be a way to do something such as “force a filter” on my client’s in-house IT people so that they can only see tickets that involve their company. I suppose another way to do that would be to make per-ticket permissions, and when you’re displaying a queue you check the permissions on each ticket. That might make RT run even slower than it already seems to be (when I say “slow” I mean “less than super speedy like some of the other apps on that server, which are quite possibly less complex and even poorly written”), but I’d write a Scrip that identifies what client a ticket belongs to and presumably sets the proper permissions on it.

Instead I’m using a custom “Client” field and variants on the OnCreateSetDeptHeadCc and AutogeneratedPassword recipes. When a ticket comes in a Scrip tries to match the sender’s e-mail domain to a particular client and then sets the Client field (see AutoSetOwnerForQueue for some idea of how to do that; I actually keep a table corresponding domain to client name in the Scrip which is kind of ugly). When the Client field gets set, another Scrip fires and adds the appropriate per-client administrators group to the ticket’s Cc list.

So RT isn’t exactly suited for what I want to do here. One client has already commented that he wishes he could “take” a ticket (especially since he can see the ticket, and RT gives him the “Take” link, which then presumably fails). The use case is: one of his users submits a ticket, then he decides he wants to fix it, so he’d rather take it. But he’d like the ticketing system to keep track of it, possibly. I had to explain to him that this is a system for submitting support requests to my company, not within his own, but I don’t think that’s really a satisfactory solution. Another solution would be to make a separate queue for each client, and then I can give the various administrators at each client full access to their respective per-company queues. The biggest problem with this is having my company’s employees try to keep track of all these support requests potentially scattered across many different queues. It seems very error-prone.

RT’s methods for clean customization are nice; be sure to use them if you make some of these changes above. (And if you notice that link above, RT’s Wiki really needs a “revert” function.)

Powered by WordPress