Tag Archives: configuring

Selective sendmail relaying based on self-signed keys

Back in the early days of the Internet, people trusted one another not to abuse email. Sure, there were accidents. A badly configured mailing list could fill up with traffic as two vacation programs talked to one another, each informing the other that his latest message would not be read until some later date, because the recipient was out of the office.

In those days, you set up your sendmail to relay messages for others. Many people had email addresses that weren’t on a full-time connection to the network, they might be on a BBS that did a nightly download of email, or down some Bitnet rabbit hole. Email was relayed from one intermediate post to another, rather than being simply sent directly from the sender to the receiver. A sendmail daemon that relayed messages for others was helpful to the community, everybody pitched in to get everyone’s email where it was ultimately intended.

Then came new developments. Canter & Siegel, the September that never ended, and the presence of people who would buy things they saw in an unsolicited email message. Spam started to appear in mailboxes. Suddenly, being a helpful person and relaying messages was no longer beneficial to the community, as commercial email senders used relays to hide the origins of their messages. People started turning off open relays on their boxes as a defensive move.

So, now you’ve got a domain set up with a sendmail daemon at home, and you’re traveling with a laptop. To make this a bit more complicated, let’s say your laptop is a work computer, and you send email from its sendmail, but with a different domain than your home computer. Everything’s working fine, until you find that the coffee shop in Beijing where you’re using your laptop has made it onto a list of spamming IP numbers. Some recipients of your messages may not receive them because their sendmail is set up to refuse messages from computers on these bad IP numbers. You know that your home computer is not on a banned IP number, so it would be nice if you could forward your laptop-generated work-related messages through your home computer. It would be even nicer if people selling generic pharmaceuticals could not do the same thing, otherwise your home computer’s IP number will very quickly find itself on one of those banned lists. So, you want to allow relaying from your laptop, but only from your laptop, and do it easily even if you move to another coffee shop.

What you want, then, is a way for your home computer to recognize your laptop, and permit only that computer to relay messages through the home sendmail. This will be done with sendmail’s TLS facility. You will create a private certificate authority, one you don’t have to pay to sign your keys. You’ll then use a signed certificate to verify the identity of the laptop. The following procedure will be performed on the home computer, only at the end of this process will the laptop be involved.

We’ll start by creating two directories on your home computer, one for the certificate authority, and the other for the signed certificates. I’ll use the directory locations that are found in the default OpenSSL configuration file, so that you don’t have to edit too many files.

mkdir /etc/mail/CA /etc/mail/certs /etc/mail/CA/demoCA /etc/mail/CA/demoCA/private

Copy the OpenSSL openssl.cnf file into /etc/mail/CA.

Next, we will create the signing certificate.

$ cd /etc/mail/CA
$ openssl req -new -x509 -keyout demoCA/private/cakey.pem -out demoCA/cacert.pem -days 1000 -config openssl.cnf

You will be prompted for several fields, such as country code, location, name. Here’s a sample dialogue:

$ openssl req -new -x509 -keyout demoCA/private/cakey.pem -out demoCA/cacert.pem -days 1000 -config openssl.cnf
Generating a 1024 bit RSA private key
.............++++++
.........++++++
writing new private key to 'demoCA/private/cakey.pem'
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:CA
State or Province Name (full name) [Some-State]:Ontario
Locality Name (eg, city) []:Toronto
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Example
Organizational Unit Name (eg, section) []:
Common Name (eg, YOUR name) []:Bert Ificate
Email Address []:bertificate@example.com

When prompted, you will have to enter a pass phrase twice. Remember this phrase, you will need it if you ever want to sign certificates with this signing certificate.

This command creates new files: /etc/mail/CA/demoCA/cacert.pem and /etc/mail/CA/demoCA/private/cakey.pem. The file contains encoded information related to a certificate signing authority that will be valid for 1000 days.

Next, you must create the certificate that you will use to validate your laptop. You enter the commands:

$ cd /etc/mail/CA
$ openssl req -nodes -new -x509 -keyout laptopcert.pem -out laptopcert.pem -days 365 -config openssl.cnf

Again, you will have to answer some questions. Here is a sample dialogue:

$ openssl req -nodes -new -x509 -keyout laptopcert.pem -out laptopcert.pem -days 365 -config openssl.cnf
Generating a 1024 bit RSA private key
....++++++
............................................++++++
writing new private key to 'laptopcert.pem'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:CA
State or Province Name (full name) [Some-State]:Alberta
Locality Name (eg, city) []:Calgary
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Example
Organizational Unit Name (eg, section) []:
Common Name (eg, YOUR name) []:Rhoda Warrior
Email Address []:rhoda-warrior@example.com

Now, you have a certificate for your laptop, but it hasn’t yet been signed. You use the signing certificate to vouch for the laptop certificate. First, we have to set up a bit more information for the signing process:

$ mkdir /etc/mail/CA/demoCA/newcerts
$ touch /etc/mail/CA/demoCA/index.txt
$ echo 01 > /etc/mail/CA/demoCA/serial

You’ll only have to do this the first time you set up a signing authority.

Now, we issue two commands to sign the laptop certificate:

$ openssl x509 -x509toreq -in laptopcert.pem -signkey laptopcert.pem -out tmp.pem
$ /usr/local/ssl/bin/openssl ca -config openssl.cnf -policy policy_anything -out signed-laptopcert.pem -infiles tmp.pem

Once again, there will be a brief dialogue when the second command is run, something like this:

$ openssl ca -config openssl.cnf -policy policy_anything -out signed-laptopcert.pem -infiles tmp.pem
Using configuration from openssl.cnf
Enter pass phrase for ./demoCA/private/cakey.pem:
Check that the request matches the signature
Signature ok
Certificate Details:
Serial Number: 1 (0x1)
Validity
Not Before: Mar 12 00:46:43 2008 GMT
Not After : Mar 12 00:46:43 2009 GMT
Subject:
countryName = CA
stateOrProvinceName = Alberta
localityName = Calgary
organizationName = Example
commonName = Rhoda Warrior
emailAddress = rhoda-warrior@example.com
X509v3 extensions:
X509v3 Basic Constraints:
CA:FALSE
Netscape Comment:
OpenSSL Generated Certificate
X509v3 Subject Key Identifier:
67:11:5A:25:6F:5C:70:36:03:14:3B:04:4A:8C:30:C9:CF:60:51:AE
X509v3 Authority Key Identifier:
keyid:F4:CE:58:BD:82:8A:E3:EC:0F:89:C6:60:E2:45:58:A4:CA:79:C8:89

Certificate is to be certified until Mar 12 00:46:43 2009 GMT (365 days)
Sign the certificate? [y/n]:y


1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated

Now, it’s time to tell the home machine’s sendmail that it should relay messages received from this key. Add a line to the /etc/mail/access.src file that looks like this:

CertIssuer:/C=CA/ST=Ontario/L=Toronto/O=Example/CN=Bert+20Ificate/emailAd
dress=bertificate@example.com RELAY

You’ll have to make that file readable by sendmail:

makemap hash access.db < access.src

And now we have to make sure that the home machine’s sendmail knows where to find its certificates and access file. Build a new sendmail.cf using a sendmail.mc something like this:

divert(0)dnl
VERSIONID(`sendmail.mc for example.com version 01')
OSTYPE(linux)dnl
DOMAIN(example.com)dnl
FEATURE(`nouucp', `reject')
FEATURE(`virtusertable', `hash /etc/sendmail/virtusertable')dnl
FEATURE(`genericstable', `hash /etc/sendmail/genericstable')dnl
FEATURE(`local_procmail', `/usr/local/bin/procmail')
FEATURE(`access_db', `hash -T /etc/mail/access')
FEATURE(`mailertable')
MAILER(local)
MAILER(smtp)
define(`CERT_DIR', `MAIL_SETTINGS_DIR`'certs')dnl
define(`confCACERT_PATH', `CERT_DIR')dnl
define(`confCACERT', `CERT_DIR/CAcert.pem')dnl
define(`confSERVER_CERT', `CERT_DIR/MYcert.pem')dnl
define(`confSERVER_KEY', `CERT_DIR/MYkey.pem')dnl
define(`confCLIENT_CERT', `CERT_DIR/MYcert.pem')dnl
define(`confCLIENT_KEY', `CERT_DIR/MYkey.pem')dnl

Now, we move some things around a bit. We copy the signing certificate and laptop signed certificate like this:

$ cd /etc/mail/CA
$ /bin/cp signed-laptopcert.pem /etc/mail/certs
$ /bin/cp demoCA/cacert.pem /etc/mail/certs/CAcert.pem
$ cd /etc/mail/certs
$ ln -s signed-laptopcert.pem `openssl x509 -noout -hash < signed-laptopcert.pem`.0

The three files, demoCA/cacert.pem, laptopcert.pem and signed-laptopcert.pem get copied onto the laptop, in its /etc/mail/certs directory. Now, you must tell the laptop’s sendmail that these are its certificates. This is done by building (on the laptop) the sendmail.cf file from a sendmail.mc file that looks roughly like this:

divert(0)dnl
VERSIONID(`$Id: generic-linux.mc,v 8.1 1999/09/24 22:48:05 gshapiro Exp $')
OSTYPE(linux)dnl
DOMAIN(example.net)dnl
define(`confCACERT_PATH', `/etc/mail/certs/')
define(`confCACERT', `/etc/mail/certs/cacert.pem')
define(`confCLIENT_CERT', `/etc/mail/certs/laptopcert.pem')
define(`confCLIENT_KEY', `/etc/mail/certs/signed-laptopcert.pem')
define(`confSERVER_CERT', `/etc/mail/certs/laptopcert.pem')
define(`confSERVER_KEY', `/etc/mail/certs/signed-laptopcert.pem')
FEATURE(`genericstable')
FEATURE(`virtusertable')
FEATURE(`local_procmail', `/usr/local/bin/procmail')
MAILER(local)dnl
MAILER(smtp)dnl

Finally, you’ll have to decide when you want to relay through the home computer. You really have two choices. You could set it up so that all messages are always relayed through the home computer, by setting a smart relay in your sendmail.cf, or you could relay them explicitly. There are other places that identify the technique for setting up a smart relay, so I’ll just describe the second, on-demand version.

If you are trying to send email from your laptop to the user somebody@example.net, but want to relay it through your home computer at example.com, you would send the message to this email address:

somebody%example.net@example.com

And there you go, on-demand secure relaying of messages through your home computer.

Why don’t I get spam?

I have an anti-spam trick. It won’t work for most people, but there might be some people out there who are inclined to take advantage of it. For the rest, this might be educational.

The trick that I use depends on the fact that I have my own domain. That means I can run sendmail on my computer, and I can create email addresses quickly and easily. I will use the domains example.com, example.net, and example.org for this document, as recommended in RFC 2606.

The basic idea is this: instead of having one email address, I have dozens. I create a new email address for every person with whom I exchange messages, as well as addresses for websites and companies when necessary. If an email address is accidentally revealed, or if one of the companies decides to start sending annoying amounts of unsolicited mail, I simply expire the email address and, if desired, contact the sending party to tell them about the new address. I don’t have to contact all of my friends whenever I turn off one address, only the one person who uses that address to talk to me.

OK, how is this implemented? There are two things I have to do. First, I need my sendmail to accept the messages for the active addresses, and send them all to me. Second, I have to ensure that my outbound email has the correct Reply-To: address for the particular recipient of the message.

If you’re familiar with sendmail, you can probably guess how I do the first thing. I set up a virtual user table. Here’s the sendmail.mc file used to make this work:

divert(0)dnl
VERSIONID(`sendmail.mc for example.com version 01')
OSTYPE(linux)dnl
DOMAIN(example.com)dnl
FEATURE(`nouucp', `reject')
FEATURE(`virtusertable', `hash /etc/sendmail/virtusertable')dnl
FEATURE(`genericstable', `hash /etc/sendmail/genericstable')dnl
FEATURE(`local_procmail', `/usr/local/bin/procmail')
FEATURE(`access_db', `hash -T /etc/mail/access')
FEATURE(`mailertable')
GENERICS_DOMAIN(mailhost.example.com)
MAILER(local)
MAILER(smtp)
define(`CERT_DIR', `MAIL_SETTINGS_DIR`'certs')dnl
define(`confCACERT_PATH', `CERT_DIR')dnl
define(`confCACERT', `CERT_DIR/CAcert.pem')dnl
define(`confSERVER_CERT', `CERT_DIR/MYcert.pem')dnl
define(`confSERVER_KEY', `CERT_DIR/MYkey.pem')dnl
define(`confCLIENT_CERT', `CERT_DIR/MYcert.pem')dnl
define(`confCLIENT_KEY', `CERT_DIR/MYkey.pem')dnl
Cw mailhost.example.com
Cw example.com

Then, I create a file called /etc/mail/virtusertable.src. It contains entries similar to this:

hotels@example.com                      error:nouser Spammers found this address

disposable0000@example.com myself

ebay@example.com myself
electronics@example.com myself
slashdot@example.com myself
thinkgeek@example.com myself

mail-default-0000-r2@example.com myself
mail-0000-r7@example.com myself
mail-0001-q3@example.com myself
mail-0002-a4@example.com myself
mail-0003-c8@example.com error:nouser Spammers found this address
mail-0004-d7@example.com myself

The addresses I create for regular correspondance are just successive numbers, plus an unpredictable sequence of two characters to avoid dictionary attacks.

Now, recall that sendmail doesn’t read the virtusertable.src file, it reads another file called virtusertable.db. I’ve got a little Makefile in /etc/mail that I use to keep things up to date:

all : genericstable.db virtusertable.db mailertable.db aliases.db access.db

%.db : %.src
makemap hash $* < $<

aliases.db : aliases
newaliases

hup : all
killall -HUP sendmail

Now, I can change the virtusertable file, and when it looks correct, issue (as root) the command:

make -C /etc/mail hup

This will update the appropriate database file, and send a SIGHUP to sendmail, telling that program to reload its databases.

So, that’s the receiving side. How about sending? There may be a way to configure sendmail to rewrite the outbound addresses according to a database of recipients, but I haven’t figured one out. Instead, I have written a bit of code for my email client, which is rmail mode in Emacs. Here are the relevant bits of Emacs Lisp:

(setq user-mail-address "bounces0000@example.com")
(setq mail-specify-envelope-from t)

(setq outbound-address-alist
'(
("joe@example.org" "mail-0000-r7@example.com")
("frank@example.org" "mail-0001-q3@example.com")
("wilbur@example.net" "mail-0002-a4@example.com")
("euripedes@example.net" "mail-0004-d7@example.com")
(nil "mail-default-0000-r2@example.com")
)
)
(setq full-name "Winter Toad")

;; a function to parse out the header and send email as if from
;; different usernames. That way, I can obsolete a username if it
;; gets spam.
(add-hook 'mail-send-hook
'(lambda ()
(narrow-to-region 1 (mail-header-end))
(beginning-of-buffer)
(expand-mail-aliases 1 (mail-header-end))
(re-search-forward "^To: ")
;; parse out the recipient address
(let (recipient from-whom)
(cond
((looking-at "\\([^ \\t]*\\)$")
(setq recipient (match-string 1)))
((looking-at "[^<]*<\\([^>]*\\)>$")
(setq recipient (match-string 1))))
(setq from-whom (or (cadr (assoc recipient outbound-address-alist))
(cadr (assoc nil outbound-address-alist))))
(end-of-line)
(newline)
(insert "From: " full-name " <" from-whom ">")

(re-search-forward "^Reply-to: ")
(let ((namestart (point-marker)))
(end-of-line)
(kill-region namestart (point-marker))
(insert from-whom)))

(narrow-to-region 1 (1+ (buffer-size)))))


What this does is to insert a hook into the mail system when I hit send. A bit of elisp locates the email address in the “To:” field, and tries to match that string to one of the names in the ‘outbound-address-alist’. If it finds a match, it inserts the corresponding data into the “Reply-to:” field. If no match is found, or if there are multiple recipients, it uses the default fallback address.

It also sets the sender address to bounces0000@example.com, which means that automated replies, such as sendmail daemon warnings and errors, will be delivered to that address. It should be redirected in the virtusertable to some appropriate address so that you can be notified of problems at the recipient’s end (though many systems no longer generate bounce messages, because of spam abuse).

Anyway, with all this, I get really no spam. Every few months I may get one message on one of my email addresses, typically one that I used for a forum post or to send a bug report or patch to a mailing list. I retire the address, set up a new one, and never get spam at that address again.

Some time later I’ll describe the cryptographic certificates in the mail configuration, and how they allow secure relaying.

Installing in non-standard places

I mentioned earlier the possibility of choosing an install prefix like /usr/local/samba, which installs the Samba libraries in a directory that may not commonly exist on distribution-managed machines. One possible effect of this is that you may turn up bugs in configuration and compilation scripts of other packages.

A configure script for another package may accept arguments related to the location of Samba libraries and header files, but compiling the package with these options set might not work. This isn’t very surprising, it’s a compilation option that is probably rarely used, so bit rot has a tendency to set in. A change somewhere that accidentally breaks the compilation when Samba is installed in an unusual place might not be noticed for some time. By putting Samba in its own directory, you are setting yourself up to test a valid, but rarely exercised option. You may find yourself submitting bug reports and patches to the package maintainers.

As I’ve said before, maintaining your box without a package manager and distribution is not easy. It’s quite a bit more work, but it does force you to understand more about how the system is set up and what it’s doing. For people who like the extra control and understanding this provides, this is a useful technique.

Choosing an install prefix

As noted in this posting, you generally will have to choose an install prefix for software that you are compiling yourself. Most packages you encounter will be configured to install under /usr/local, though some will be configured for /usr.

The first thing you’ll want to do is to see if you already have an older version of the software installed anywhere. If the software was previously installed under /usr/local, and you install the new package under /usr, not only will you needlessly consume disk space, but the version that is run will depend on the setting of your PATH environment variable. A user may report that he can’t use a certain feature in the new version, and it may take you a while to notice that his environment variable differs from yours, and that he’s still running the old software. So, find the name of an executable that you expect will be installed. For example, if you’re installing the binutils software, you will expect that the ld binary should be installed somewhere. Next, type the command:

which ld

to see where it is currently installed. If you see it in “/usr/bin/ld”, then you’ll probably want to use a prefix of “/usr”, so that your new versions install over top of the old ones. If, on the other hand, it’s in “/usr/local/bin/ld”, you’ll want a prefix of “/usr/local”.

Sometimes a package installs only one or a few binaries. You may decide to install this into its own directory. For example, I install firefox into the prefix /usr/local/firefox, SBCL into the prefix /usr/local/sbcl, and the apache httpd into /usr/local/apache2. These get their own directories because, while they may install a very small number of executables, they come with a large set of ancillary files. Rather than installing over top of the old directory, I move the old directory to a new location, say “/usr/local/sbcl.old”, and then install and test the new version. If the new version doesn’t work properly, I can revert to the old one by deleting the new install and renaming the “.old” directory. Alternatively, I can compare the two installations, the previously working one against the new one, and see if there are any obvious differences that could account for problems.

Of course, you probably won’t be able to type the command firefox and expect it to run if it’s installed in /usr/local/firefox/bin/. You will either want to add that directory to the PATH variable, or, more conveniently, put a symbolic link to the appropriate executable from a directory that is in your PATH. This command:

ln -s /usr/local/firefox/bin/firefox /usr/X11/bin/firefox

puts the firefox executable into your PATH, piggy-backing on the /usr/X11/bin entry that is probably there already. Note, however, that if you re-install X11 (we’ll get to that in another posting), you might destroy this symbolic link, and you’ll have to re-create it then.

So, you really have a couple of choices. Put the program into a standard place, like /usr or /usr/local (and if upgrading try to install over top of the old version by using the same prefix that was used then), or installing the software in its own dedicated directory, like /usr/local/firefox or /usr/local/sbcl.

Now, when you set the prefix in an autoconf configure script, it also sets a number of derived values which can be separately overridden. Configuration files are, by default, put in /etc, libraries in /lib, headers in /include, man pages in /share/man (sometimes omitting the ‘share’ component), log files in <prefix&gt/var/log, and so on. The configure program lets you override these defaults separately, so that you can put configuration files into, say, /etc/http with the option “–sysconfdir=/etc/http”, and so on. Think carefully about whether you want these additional directories to keep their defaults. You probably don’t want your X-server log to be in /usr/X11/var/log, nobody will know where to look for it.

Compiling and installing by hand

If you’re not using a package manager, or if you are, but there is no package available for a piece of software you’d like to install, you’ll find yourself compiling the software by hand. Generally, you start by locating the official web page of the software, downloading an appropriate version of the source code, and extracting the tar file to a directory somewhere.

At this point in the process, you are not doing anything as the root user. You’ll become root much later in this process.

The next thing you’ll do is look in the top level of the extracted directory for promising looking files, like README, INSTALL, or Makefile. It is likely that you will see an executable script called “configure”. It’s always a good idea to start by looking at the README and INSTALL files, if present. They may be in the toplevel directory, or in a documentation directory, which will often have a name like “doc”, “docs”, or “documentation”, possibly with different capitalizations.

If The Package Came With A Makefile

If there’s a Makefile in the toplevel, that’s usually because the software package is fairly small. You will want to look over the Makefile to ensure that it is correct for your intended installation. The most important things to look for are the installation directory and any optional features that might have to be turned on by editing the Makefile. If you can’t find the installation directory, type the command:

make -n install

This will ask “make” to print out the sequence of commands that it will be using to install the package. Since you haven’t compiled anything yet, it will start with the sequence of commands required to compile your software, so look for the installation commands to occur near the end of the output generated by this command.

If your package came with a Makefile, you will now modify the Makefile if necessary, perhaps changing the installation directory of the product. You should do this before compiling it, because sometimes character strings holding the pathnames of configuration files are inserted into the compiled binary, so changing the installation target after compiling may result in an installation that doesn’t work correctly. Editing the Makefile will usually not force a recompilation of the objects under its control, that is the Makefile is not, by default, considered a dependency for the targets in the file.

After this, you will, still as your non-root user, compile the package. This is usually done by simply entering the command make. If errors are encountered during the compile, you’ll have to figure out what happened and how to fix it. The most common causes of errors are:

  • missing include files – you might have to add a “-I” to the CFLAGS, CXXFLAGS, or CPPFLAGS variables in your Makefile.
  • missing libraries – you might have to add a “-L” to the LDFLAGS variable in your Makefile.
  • bad version – the compilation may depend on a library you have on your machine, but the version you have may not be compatible with the software package. You might have to download a different version of that library and install it before you can continue with the software package.
  • apparent code errors – the compiler may generate errors related to missing variables, bad function declarations, or syntax errors. Resist the urge to correct these immediately, and try to understand why you are seeing these errors. Remember, this package probably compiled for somebody before they released it, why doesn’t it work for you? Is it that your compiler is a different version, and flags as errors things that used to be warnings? Is the Makefile configured for the wrong architecture or platform? Something else?

Once you get a clean compile, you’re almost ready for the install. I usually prefer to run the command

make -n install | less

once and read through the output, just to make sure that the install isn’t going to do something weird. Look for things like configuration files going into /usr/etc, which might not be what you expect, or binaries going into /bin (you should try to keep in that directory only those executables that are necessary to get the computer to boot through its startup scripts up to the point where the network starts up).

At this point, move down to the section of the text called “Installing The Software”.

You Have A “configure.am” Script, But No “configure” Script

If you have a “configure.am” script, but no “configure” script, you’ll have to generate the configure script. If there is an executable in this directory with a name like “autogen.sh”, run it. This should be sufficient to set up the configure script. If you don’t have an autogen script, you should run the commands automake then autoconf. This will often generate warnings, but unless the configure script you generate doesn’t run, you can ignore those. So, now you have a configure script, you continue to the next section.

You Have A “configure” Script

If you generated the configure script yourself, you know that it’s an autoconf configure script. Sometimes, though, software is produced that has a completely different script that happens to be called “configure”. This can be confusing if it doesn’t recognize the switch “–help”. Start by typing:

./configure --help | less

and look at the output. If it produces a list of options that are available to you, review them carefully and see if there are any optional behaviours that you would like to turn on, or unwanted options that you want to remove (possibly you don’t have library support for these, and don’t need them). If, instead, the configure script appears to run and do things, you don’t have an autoconf configure script, go back and look at the documentation again to see how to use their particular configuration script.

There are a few things to look at in the options you get from “configure”. One of them is the prefix location, and choosing that properly can require some care, which is discussed here. For now, let’s assume that you’ve chosen a set of options that look suitable. You re-run the configure script with those options, and without the “–help” option. It will do some things, it may take a considerable amount of time to run. Eventually, the script should exit, sometimes generating a list of all options and whether or not they are active. Examine this list if present, there might be an option that you want to enable that has been turned off because the configure script failed to find a particular library, in which case you’ll have figure out why that option was disabled and figure out how to get it working. When you’re satisfied with the compilation options, type “make”. If an error is encountered, see the possibilities mentioned in the earlier section referring to building from a Makefile. If you succeed in compiling the software package, go to next section, “Installing The Software”.

Installing The Software

Now, you can become the root user. Change directory to the location where you compiled the binary, and run

make install

If the thing you’re installing has any shared objects (libraries, usually with names that end in “.so”, possibly followed by more dots and numerals), you should type

ldconfig

to make sure that the dynamic linker knows where to find the libraries you’ve just installed.

Many packages these days produce a pkg-config file. This is usually a filename that ends in “.pc”, and is installed in a directory like “…/lib/pkgconfig/”. The pkg-config application often looks for these files when “configure” is being run, but it has a fairly definite idea of where to look. If your .pc file was installed into a directory where pkg-config doesn’t normally look, you’ll have to find some way to make this file visible to that program. There are three ways you can handle this:

  • Add the appropriate directory to the system-wide environment variable PKG_CONFIG_PATH. Usually this means editing /etc/profile. You likely want it set at least to “/usr/lib/pkgconfig:/usr/local/lib/pkgconfig:/usr/X11/lib/pkgconfig”, but you may want to add more search directories to it, if you expect many packages to be installed in the same prefix.
  • Copy the .pc file into a directory that pkg-config searches. This is unwise, you may install another version of the software some time later, and unless you remember this step your .pc file will still be the old one, causing much aggravation as “configure” insists you still have a version of the package that you know you just replaced.
  • Put a symbolic link to the file from a directory that is searched by pkg-config. Do this if you’ve got only one or two .pc files in this prefix, and don’t expect to put in more.

Test your newly-installed software. It’s best to find problems now, when you’ve just finished installing it and remember what you did, than two weeks from now and have to go through the whole thing again just to figure out how it’s set up.

Two more hints: “configure” writes its command line into a comment near the top of the file “config.log”. If you need to remember how you last ran “configure”, you will find the options you used there.

If you have a particularly detailed set of configure options, you might want to record them in a directory somewhere for future reference, both to see quickly what options you enabled when you compiled the software and to re-use the command the next time you recompile it after downloading a new version.