Unix Guide

Table of Contents

1 Apache

1.1 Software

  • apache2
  • libapache2-mod-php5
  • libapache2-mod-python
  • libapache2-mod-perl2
  • libapache2-mod-ruby

1.2 Setup mod_ruby

Add the following lines to /etc/apache2/httpd.conf:

<IfModule mod_ruby.c>
    RubyRequire apache/ruby-run
    <Location /ruby>
        SetHandler ruby-object
        RubyHandler Apache::RubyRun.instance
    <Files *.rbx>
        SetHandler ruby-object
        RubyHandler Apache::RubyRun.instance
<Directory /var/www/ruby>
    Options ExecCGI

1.3 Setup mod_python

Add the following lines to /etc/apache2/httpd.conf:

<Directory /var/www>
    AddHandler mod_python .py
    PythonHandler index
    PythonDebug On

1.4 Obscure Module Information

Add the following line to /etc/apache2/httpd.conf:

ServerTokens ProductOnly

1.5 Setup HTTP Over SSL

Run the following program to generate an SSL certificate:

$ sudo apache2-ssl-certificate

Enter the appropriate information. Now copy the default site setup to another one specific to HTTP over SSL; enable the new SSL site:

$ cp /etc/apache2/sites-available/default \
$ ln -s /etc/apache2/sites-available/ssl \

Edit the defqault site to only handle HTTP and the SSL site to handle only HTTPS. Change the NameVirtualHost and Virtual Host directives to include the appropriate port, like so in the default site file:

NameVirtualHost *:80
<VirtualHost *:80>

Do the same in the SSL site file, and also enable the SSL engine and tell it where to find the cert: NameVirtualHost *:443

<VirtualHost *:443>
    SSLEngine On
    SSLCertificateFile /etc/apache2/ssl/apache.pem

Lastly, you have to tell Apache to listen on port 443, by adding the following to /etc/apache2/ports.conf:

Listen 443

Now load the SSL module into Apache, and force the server to reload its configuration:

$ sudo a2enmod ssl
$ sudo /etc/init.d/apache2 force-reload

2 Yaws

2.1 Description

Yaws is "Yet Another Web Server" and is available from http://yaws.hyber.org/. I recommend always building this from source, as the Debian repositories have versions that are usually quite out of date.

2.2 Required Packages

  • libssl-dev
  • libpam0g-dev

2.3 Procedure on Ubuntu

The following probably works on Debian as well, but I don't use Debian itself.

$ tar -zxvf yaws-1.74.tar.gz
$ cd yaws-1.74
$ ./configure --prefix=/opt/yaws
$ make && sudo make install
$ sudo addgroup yaws
$ sudo adduser --home /home/yaws --shell /bin/false --ingroup yaws --disabled-password yaws
$ sudo chown -R yaws:yaws /opt/yaws
$ sudo -u yaws vim /opt/yaws/etc/yaws/yaws.conf
$ sudo -u yaws /usr/bin/env HOME=/home/yaws /opt/yaws/etc/init.d/yaws start
$ sudo -u yaws /usr/bin/env HOME=/home/yaws /opt/yaws/etc/init.d/yaws stop

2.4 Procedure on OpenBSD

OpenBSD doesn't support PAM like Linux (and even FreeBSD I think) does, and the configure script doesn't check to see if it's there or not, so we have to disable it manually so we don't accidentally try to compile with it.

$ tar -zxvf yaws-1.89.tar.gz
$ cd yaws-1.89
$ ./configure --prefix=/opt/yaws --disable-pam
$ gmake
$ sudo gmake install
$ sudo groupadd yaws
$ sudo useradd -m -d /home/yaws -g yaws -L daemon -s /bin/false yaws
$ sudo chown -R yaws:yaws /opt/yaws

Be careful when you start Yaws the first time; if there are problems (for example, creating the byte-compiled files) it may end up going into an infinite loop of the erl program crashing and being restarted by the heart process. If this happens, you will see the erl process showing back up in ps with a different PID every time you kill it. Yaws is a vampire now — you gotta aim for the heart to kill it!

A further note: running Yaws 1.89 with OTP R14B01 on OpenBSD 4.8 causes strange behaviour when using --heart; the heart and erl processes will start, but something goes awry somewhere and from outside it appears that nothing is happening. No logs are created, no sockets are opened for listening, and no files in .yaws are touched (if the directory doesn't exist, it's not created). Omitting the --heart option fixes this, and the server runs as normal. I'm not sure where the problem lies, and it may even be something I have in the user's configuration. I don't yet know.

3 Subversion

As in all good software, Subversion is completely painless to install and configure. One place you might fall down initially is user privileges. I've created a subversion group for users that will be allowed to write into the Subversion repository.

$ groupadd subversion
$ adduser taylor subversion
$ sudo svnadmin create /var/svn
$ sudo chgrp -R subversion /var/svn
$ cd /var/svn
$ sudo chmod -R g+w locks/ db/revprops/ db/revs/ db/transactions/
$ sudo chmod g+w db/ db/current db/fs-type db/uuid db/write-lock

4 Trac

Like all my services, I run Trac as a special user with no permissions. Let's add it to the subversion group so that it can read subversion information. Note that on systems that support login classes (e.g. OpenBSD) you should set this to the same class that other services run as, because tracd will be running as this user.

$ groupadd trac
$ useradd -m -d /home/trac -G subversion -g trac -L daemon -s /sbin/nologin trac

Now let's get Trac going. OpenBSD has a package for it, so installing it is simple. Otherwise you'll have to download the archive and do the usual sudo python setup.py install procedure. Either way, it's easy as pie. Next you need to initialize a project location, say in /var/trac. Since we set up Subversion in /var/svn earlier, configure it as the repository. (Note: since we're going to be doing so much work here as the trac user, I've set up an alias so we don't have to type as much.)

$ sudo mkdir /var/trac
$ sudo chown trac:trac /var/trac
$ alias as-trac-user='sudo -u trac /usr/bin/env HOME=/home/trac'
$ as-trac-user trac-admin /var/trac initenv

Permissions are going to be important, obviously. I run a locked-down configuration where anonymous users can't add to or modify anything on the site. Not great for feedback, but it does eliminate spam. Maybe later I'll re-enable these things but for now, it's going to get turned off. Also, I need to make a user account for myself, using htpasswd to store the hash of the password. On OpenBSD you'll need to run htpasswd with the -m option so that tracd can understand the type of hashing being used. Next, we can grant that user TRACADMIN privileges so that they are effectively the administrator of the system. Lastly, we can start the standalone trac daemon, providing the information it needs to do authentication, along with the port and path to the Trac project directory.

$ as-trac-user trac-admin /var/trac permission remove anonymous TICKET_CREATE TICKET_MODIFY WIKI_CREATE WIKI_MODIFY
$ as-trac-user htpasswd -m -c /var/trac/.htpasswd taylor
$ as-trac-user trac-admin /var/trac permission add taylor TRAC_ADMIN

Of course, with this configuration, all the logs are going to get dumped to the screen. You would probably like these put into an actual log file, and there's a good way to do that (when running from bash anyway).

$ touch /var/log/trac
$ chown trac:wheel /var/log/trac
$ chmod 640 /var/log/trac
$ as-trac-user /bin/bash -c 'tracd --basic-auth=trac,/var/trac/.htpasswd,metasyntax.net --port 4916 /var/trac &>/var/log/trac' &

If you want syntax highlighting for less-common programming languages, you'll need to install Pygments through easyinstall after installing Trac. If tracd is already running, just restart it to see the effects.

4.1 Lisp Colorization

Sure Trac automatically highlights a lot of programming languages for you, but Lisp is not among them. Fortunately, John Wiseman came up with a clever way to tie together the highlighting system that runs paste.lisp.org with the Trac highlighting system. The result is a very cool little Lisp rendering system. (NOTE: I have not tried this on OpenBSD yet. Presumably it would all stay the same, only you'd have to run the XML-RPC service on another machine, since OpenBSD doesn't support SBCL.)

4.1.1 The Lisp XML-RPC Side

First you'll need to fetch a few things, namely the ability to run an XML-RPC server in Lisp, and the actual highlighting program, Brian Mastenbrook's "colorize". Here I do so with SBCL, which I assume you've already got installed. You'll probably have to get colorize from Subversion, and while the Cliki entry for it claims it doesn't officially support ASDF, it does work if you use the included file.

$ svn co http://unmutual.info/colorize
$ rm -rf colorize/.svn
$ tar -zcvf colorize.tar.gz colorize

Then from within SBCL do something like:

(require 'asdf)
(require 'asdf-install)
(asdf-install:install "colorize.tar.gz")
(asdf-install:install 's-xml-rpc)

What you'll be doing is essentially running colorize as an XML-RPC service from within Lisp.

4.1.2 The Python Trac Side

The flip side of this is how Trac contacts the colorize service, and gets the highlighted code back as a response. We can use John Wiseman's Trac renderer (plus a few modifications) to do the job. First grab the file from http://lemonodor.com/code/trac-lisp.py and apply the following patch:

--- trac-lisp.py    2006-04-03 12:52:05.000000000 -0400
+++ /usr/share/python-support/trac/trac/mimeview/lisp.py    2008-05-05 23:25:21.000000000 -0400
@@ -8,7 +8,7 @@
 import re

 from trac.core import *
-from trac.mimeview.api import IHTMLPreviewRenderer
+from trac.mimeview.api import IHTMLPreviewRenderer, content_to_unicode
 from trac.web.chrome import add_stylesheet

 from xmlrpclib import *
@@ -154,6 +154,8 @@
             add_stylesheet(req, 'common/css/lisp.css')
             if not (cache_key in self.cache):
                 colorizer = ServerProxy(COLORIZER_URL)
+                content = content_to_unicode(self.env, content, mimetype)
+                content = content.encode('utf-8')
                 html = colorizer.colorize("lisp", content, 0)
                 html = html.replace("\n", "")
                 html = html.replace("<br>", "\n")

This will bring it up-to-date to comply with the way newer versions of Trac handle the content variable. The times, they are a-changing.

Next you'll need to install the new features. Copy the Lisp renderer into the common Trac directory. This is under Ubuntu, so tweak path names accordingly for your setup.

$ sudo cp trac-lisp.py /usr/share/python-support/trac/trac/mimeview/lisp.py
$ cd /usr/share/python-support/trac/trac
$ Modify mimeview/api.py to add a MIME entry for Lisp source code in the MIME_MAP variable.
$ Modify db_default.py and add "trac.mimeview.lisp" to the default_components variable.
$ Copy the value of coloring-css from colorize/coloring-css.lisp into /usr/share/trac/htdocs/css/lisp.css
$ cd /var/lib/python-support/python2.5/trac/mimeview
$ sudo ln -s /usr/share/python-support/trac/trac/mimeview/lisp.py

5 Redmine

5.1 Software

  • ruby1.8
  • ruby1.8-dev
  • rubygems1.8
  • libhttpclient-ruby1.8

5.2 Configure PostgreSQL

$ sudo -u postgres /opt/postgresql/bin/createdb redmine

5.3 Install Gems

$ sudo gem install rails -v=2.3.5
$ sudo gem install i18n -v=0.4.2
$ sudo gem install pg
$ export PATH=/var/lib/gems/1.8/bin:$PATH

5.4 Configure Redmine

$ rake generate_session_store
$ RAILS_ENV=production rake db:migrate
$ RAILS_ENV=production rake redmine:load_default_data
$ ruby script/server webrick -e production


First, since CL-WIKI doesn't have any innate capability to handle users, we're going to put it behind a proxy which does. Lighttpd is a great light-weight web server which can do proxying, SSL, and digest authentication; it's ideal for this situation. Under Ubuntu, just install it from Apt, and then enable the SSL, proxy, and auth configurations.

Now, CL-WIKI has a special URL configuration for editing existing pages, but not for making new ones (which go into edit mode automatically). So we can easily enforce authentication for the first case, but for new pages we have to be a little more low-level by removing the write privileges into the Wiki directory. Fortunately, CL-WIKI does not support nesting, so we don't have to worry about somebody making a rogue Wiki/Home/Foo by keeping write privileges for Wiki/Home/ – simply removing the write privileges from Wiki/ will be enough.

For authentication, we're going to need to create the htdigest file that Lighttpd will use to authorize people who try to edit a page. We'll also need to generate the key and certificate used for SSL. The digest method hashes the password before it is sent across the network, so the password itself won't be discovered, but it does not in any way decrease the chance of a replay attack, so we want to use SSL when we send login credentials. These are the two commands you need:

$ htdigest -c lighttpd.htdigest edit someuser
$ openssl req -outform PEM -out lighttpd.pem -new -nodes -keyout lighttpd.pem \
  -newkey rsa:4096 -sha1 -x509 -days 365

For setting up SSL, you just need to provide the path to the key / cert file you just created above. To set another port for SSL use, just replace 443 with your chosen port below.

$SERVER["socket"] == "" {
    ssl.engine = "enable"
    ssl.pemfile = "/path/to/keys/lighttpd.pem"

Authentication is a bit more complicated, and requires you to set up a filter for when authentication will be required. Since we want to block people from editing pages, we can trigger an auth requirement for the action GET paramter when it is set to edit.

server.modules                += ( "mod_auth" )

auth.backend = "htdigest"
auth.backend.htdigest.userfile = "/var/lighttpd.htdigest"

# filter out the ability to edit wiki entries
$HTTP["querystring"] =~ "action=edit" {
    auth.require = (
        "" => (
            "method"  => "digest",
            "realm"   => "edit",
            "require" => "user=someuser"

Setting up the proxy is easy as well. Just have it point to where CL-WIKI is running internally, and then configure your firewall to allow users to access the proxy. Simple!

server.modules   += ( "mod_proxy" )

proxy.server = (
    "" =>
        ( ( "host" => "",
            "port" => 5757 ) ) )

7 OpenSSH

7.1 Software

  • openssh-server

7.2 Configuration

OpenSSH is a secure way of working on a remote host, offering a shell service which is encrypted. What's more, you can configure the SSH server to accept only public key authentication, making password cracking against such a system irrelevant. This is not the default configuration out of the box; to disable password logins, set this configuration option:

PasswordAuthentication no

Public key authentication should be on by default. For even more security, set the following options in /etc/ssh/sshdconfig:

AllowedUsers <USER>
PermitRootLogin no
Protocol 2

To login to SSH using public key authentication, you need to generate a keypair. For this, you use the ssh-keygen program:

$ ssh-keygen -t rsa -b 4096

Then answer the questions the program asks. This will generate public and private 4096-bit RSA keys for SSH protocol 2. You may want to add a passphrase, but for convenience when using naive programs operating over SSH, entering a passphrase each time may be more hassle than it's worth. To enable yourself to log in to this machine using a private key, add the public key (idrsa.pub) to the authorized keys file ~/.ssh/authorizedkeys). Note that your public key and authorized keys files should be world-readable, but the ~/.ssh directory itself should be chmod 700. (The SSH server doesn't need to do a listing on ~/.ssh, so it works out that all the server can read is your authorized keys file and any public keys that are listed therein.)

On a security-related note, it would probably be a good idea to use a passphrase on all your SSH keys that is different from your login password. That way, if anybody gains access to your machine via SSH, they have to learn another password to take action via sudo. Or, if they gain access via a normal password login, they won't be able to use SSH to interact with other machines without learning the passphrase. Defense in depth!

On each client machine, have a copy of your private key, chmod 600, inside your ~/.ssh directory, which should still be chmod 700.

8 Mail Server

8.1 Software

  • postfix
  • popa3d
  • courier-imap-ssl
  • procmail
  • spamassassin

8.2 Postfix SMTP Client Authentication

Add the following lines to /etc/postfix/main.cf:

# Enable SASL client support
smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
smtp_sasl_security_options =
smtp_sasl_type = cyrus

Then enter username and password information into /etc/postfix/saslpasswd, like so:

smtp.smarthost.com          username:password

Make sure the password file is chmod 600. Hash the file into the proper database format, and reload the configuration into the mail server:

$ sudo postmap sasl_passwd
$ sudo /etc/init.d/postfix reload

8.3 IMAP Server

Install the courier-imap-ssl package, telling it not to create web administration folders, and it will generate its SSL certificates. Next, use the following commands to tell Postfix where to deliver the messages so they are suitable for the IMAP format:

$ sudo postconf -e 'home_mailbox = Maildir/'
$ sudo postconf -e 'mailbox_command ='

Now restart Postfix. The IMAP server should be listening on ports 143 and 993 (SSL). To convert your old mbox-format messages to the Maildir-format used by IMAP, use the mb2md script:

$ mb2md -s MBOX_DIR -R

The hierarchy of the mbox-format folders will be retained.

8.4 Spam Filtering

With Procmail and SpamAssassin, you can adaptively filter incoming email for spam. To do so, pass all incoming mail through Procmail by adding the following to ~/.forward:

"|/usr/bin/procmail || exit 75"

Now you need to set up Procmail to filter the messages it receives through SpamAssassin, and then decide what to do with the results. Procmail is very complicated, and can be used to do some pretty amazing things. Read the procmailex manual for more details. But for this application, we can be pretty basic; add the following to your ~/.procmailrc file:

DEFAULT = $HOME/Maildir/

:0fw: spamassassin.lock
* < 256000
| spamassassin

* ^X-Spam-Status: Yes

This will put any messages flagged as spam in your Spam directory, otherwise they'll go to your IMAP inbox. SpamAssassin is pretty good by itself, but you can train it on existing spam so it will become even more intelligent. After you've built up a collection of spam in your Spam directory, run the following command:

$ sa-learn --spam $HOME/Maildir/.Spam/cur/

And SpamAssassin will use information about those messages to help influence later decisions about what exactly constitutes spam.

9 File Sharing

9.1 Software

  • NFS Kernel Server
  • OpenSSH (openssh-server)
  • FUSE (sshfs)

9.2 Using NFS

NFS is an older filesystem-sharing protocol that makes working with remote filesystems seem transparent. NFS exports are handled from /etc/exports. User info is based on UID, so if the client and server UIDs don't match up, full read-write access might not work right. Here's an example export file:


To refresh export list after modification, run

$ sudo exportfs -a


There is a good alternative to NFS, and that's a more secure remote filesystem called SSHFS. It uses the SFTP on the server-side, together with FUSE (Filesystem in User-Space) on the client-side, to present a transparent filesystem stored remotely and encrypted over SSH.

On the server, install and enable OpenSSH with the SFTP subsystem. To do the latter, add the following to your /etc/ssh/sshdconfig, if it's not already there:

Subsystem sftp /usr/lib/openssh/sftp-server

9.3.1 Debian Client

On the client, install the sshfs package (this will install FUSE automatically by dependencies). You'll need to add yourself to the "fuse" group on the client:

$ sudo adduser <NAME> fuse

9.3.2 FreeBSD Client

Like above, you need to install fuse and sshfs support. This comes in the form of a kernel module: you can build it from /usr/ports/sysutils/fusefs-sshfs. Once built, you should probably enable normal user mounts for convenience:

$ sudo sysctl vfs.usermount=1

If this is the first time you've done it, you can manually load the kernel module with:

$ sudo kldload fuse

Once you're sure its working, set it to load on boot by adding the appropriate line to /etc/rc.conf:


9.3.3 All Clients

Once you have an account set up on the server, simply run.


10 MySQL

10.1 Port Listening

By default, the MySQL server will only bind to and not listen to outside connections. To fix this, adjust the following line in /etc/mysql/my.cnf:

bind-address =

10.2 phpMyAdmin

First, organize /var/www into multiple directories: one for each website you want to host. If you were using /var/www as a global document root, make sure to change its value in the correct site files. Then install the phpmyadmin package, which will place its files into /var/www/phpmyadmin. Create a new site by copying /etc/apache2/sites-available/default to a new site called phpmyadmin.

$ cd /etc/apache2
$ cp sites-available/default sites-available/phpmyadmin
$ cd sites-enabled
$ ln -s /etc/apache2/sites-available/phpmyadmin 002-phpmyadmin

Now edit the phpmyadmin site file to change the document root (to /var/www/phpmyadmin) and the listening port (to something like 8080). Add this port value to /etc/apache2/ports.conf:

Listen 8080

Now restart Apache using /etc/init.d/apache2 restart.

10.3 New User

$ mysql -u root -p

11 PostgreSQL

11.1 Compilation

./configure --prefix=/opt/postgresql

11.2 Installation

$ sudo adduser postgres
$ sudo mkdir -p /var/db/pgsql
$ sudo chown postgres /var/db/pgsql
$ sudo touch /var/log/pgsql.log
$ sudo chown postgres /var/log/pgsql.log
$ sudo -u postgres /opt/postgresql/bin/initdb -D /var/db/pgsql
$ sudo -u postgres /opt/postgresql/bin/pg_ctl -D /var/db/pgsql -l /var/log/pgsql.log start

12 Firewall

12.1 Firestarter

On Linux systems, you can use Firestarter (Debian package firestarter) to make Firewall configuration easier. You can very easily configure incoming port restrictions in the policy tab. However, this simplicity is indeed simple, and advanced configuration will only be possible by using the ipchains utility.

12.2 FreeBSD's IPFW

IPFW is the vanilla firewall that lives in the FreeBSD kernel. Outside of an independent, stand-alone hardware firewall, this is usually your first line of defense. IPFW can work with natd for Network Address Translation services, or it can be used as a generic firewall tool. Configuring support in the kernel is easy, but setting up firewall rules obviously takes some knowledge of how IP works. I'll throw in some examples from my own configuration to help you out.

The basic ipfw addition command looks something like this:

add ( allow | deny ) proto from address [ port ] to address [ port ] [ options ]

You can also use the shortcut phrase "me" to refer to any IP address on a local interface, which makes for more readable rules. The options refers to various extraneous options, the most popular of which is keep-state. This means that when the rule is evaluated for a connection, that evaluation is kept in memory as long as that connection persists. It's a bit of an optimization, in other words. Here are some example rules, which allows SSH traffic out, and HTTP traffic in, blocking everything else:

add allow tcp from me     to any 22 keep-state
add allow tcp from any    to me 80
add allow tcp from me  80 to any
add deny  all from any    to any

The basic ipfw delete command looks like:

ipfw rulenum delete

12.3 OpenBSD's PacketFilter

(Packet Filter), the modern firewall used in OpenBSD, and which is now finding its way into FreeBSD and NetBSD, is arguably the most powerful firewall in the world. Harnessing just a little bit of it's potential is enough to secure most systems, although there is a lot to explore. PF rules live in a configuration file; by default, it's located at /etc/pf.conf. A PF configuration has several sections, which occur in a certain order in the file. They are:

12.3.1 Macro Definitions

These play a role similar to that played by C language macros. Essentially, the make the rest of the file more readable. They are expressed in the form MACRO = definition and are substituted by prefixing the macro name with a dollar sign. In other words, saying this

IF = fxp0
drop all in $IF

is the same thing as saying this

drop all in fxp0

12.3.2 Options

These lines set global PF options. They take the following form:

set option value

The most common options are block-policy, which tells PF what to do when a packet should be dropped, and loginterface, which tells pflogd which interface it should log. My default block-policy is drop, which means that all blocked packets are simply dropped and ignored; the sending machine's connection will time out. An alternative is return, which returns a packet to the sending machine informing it that it is not allowed to connect. One last option to set here is skip on, which allows packets coming in on the specified interface to circumvent PF. This is used on lo0, which is (usually) considered secure. (Note: the "skip" option is unfortunately not available on NetBSD 3.0; instead, simply include rule lines to pass all packets on the loopback device.)

12.3.3 Scrubbing

Packet Filter has a variety of tricks up its sleeve when it comes to rendering broken-packet attacks invalid:

"Scrubbing" is the normalization of packets so there are no ambiguities in interpretation by the ultimate destination of the packet. The scrub directive also reassembles fragmented packets, protecting some operating systems from some forms of attack, and drops TCP packets that have invalid flag combinations. — The OpenBSD PF FAQ

The syntax is simple: scrub in all

There is a warning about scrubbing NFS packets coming from non-OpenBSD platforms. As a note on that, my FreeBSD workstation is connected to an NFS share on an OpenBSD server with scrubbing enabled, and I have experienced no problems.

12.3.4 NAT & Redirection

NAT is a way of making packets that are actually coming from a block of addresses look like their originating from a single address. While originally developed to try and conserve the global address space, it's also a relatively useful security mechanism. Using NAT in OpenBSD isn't that hard:


This performs NAT on all packets coming from ADDRESS1 (usually a block, sometimes phrased like interface:network) and going to ADDRESS2 through INTERFACE. This explicit rule is for outbound traffic (since technically that's what NAT works on); reverse translation back into actual internal addresses is done automatically.

Redirection, which passes connections on to another machine, works in pretty much the same way:


This sends packets coming into the firewall on the given interface and matching the criteria for protocol, source, destination, and port be passed on to the given address instead of being received locally. Any redirected packets still have to pass through the filter rules below, unless the optional "pass" keyword is used in the redirection rule, in which case the packets are automatically passed through.

12.3.5 Filter Rules

With behaviour that is opposite of IPFW, in the PF firewall the last rule to match "wins". As such, your first rule should always be block all. This ensures that unless you explicitly let traffic through later on, it will automatically be blocked. The general format for a PF rule is:

[ block | drop ] [ in | out ] on INTERFACE \
from [ SOURCE | any ] to [ DESTINATION | any ] [ OPTIONS ]

The second thing we should do with our firewall is block any bad people who are trying to spoof internal addresses in packets coming in from the Wild Internet. To do this you need to have a list of internal addresses, which we can do easily enough using known internal address blocks. The second line prevents us from sending packets to machines we think are internal but for whatever reason are passing outside the firewall (which may be a form of "extrusion").

block drop in on EXTERNAL_INTERFACE from { , } to any
block drop out on EXTERNAL_INTERFACE from any to { , }

Lastly we can create specific acceptance rules. The most basic firewall could allow in certain types of ICMP messages like those generated by "ping". It would also allow any outbound traffic, keeping the connection's state so that incoming information on that same connection can return:

pass in inet proto icmp all icmp-type echoreq keep state
pass out on EXTERNAL_INTERFACE proto tcp all modulate state flags S/SA
pass out on EXTERNAL_INTERFACE proto { udp , icmp } all keep state

12.3.6 Further Reading

This is by no means an exhaustive list of everything that Packet Filter is capable of handling. For more information check out the official PF FAQ from the OpenBSD project.

12.4 Remote Procedure Calls

Remote procedure call services use a mix of fixed and random ports. The random ones, of course, are trouble for firewalls. Portmap uses fixed port 111 and the NFS server uses fixed port 2049, so these are fine, but mountd uses a random port. You can change this by setting a variable in /etc/default/nfs-kernel-server:

RPCMOUNTDOPTS="--port 4002"
SMTP25Local Network
POP3110Local Network
portmap111Local Network
CUPS631Local Network
IMAP (SSL)993Internet
NFS2049Local Network
MySQL3306Local Network
mountd4002Local Network
phpMyAdmin8080Local Network

13 GTK & Qt Themes

13.1 Switching The GTK Theme

Whenever an application using GTK starts, the toolkit reads an initialization file in the user's home directory. If that file doesn't exist, GTK uses a system-wide configuration file. This runtime-control file is where theme information lives, so this is what you need to edit to change the way your GTK applications look. For GTK2+, the name of the file is .gtkrc-2.0 and it is stored in your home directory.

Each theme comes with its own gtkrc file, which details how that theme should be drawn. It's kind of like a stylesheet for GTK applications. What you need to do is pull this code into your personal ~/.gtkrc-2.0 file. This is easily enough provided by the include directive, which when given the path to another file, will read its contents into the current configuration. You just need to give include the path to the theme's gtkrc file. Here's an example:

include "/usr/X11R6/share/themes/Clearlooks/gtk-2.0/gtkrc"

It's just that easy: include followed by the path to the theme's gtkrc file. The next time you start an application that uses GTK2+, the toolkit will use whatever theme you have told it about.

13.2 GTK Themes & NetBSD Linux Emulation

If you try following these instructions on NetBSD you'll soon realize that applications running under emulation (like firefox-bin) won't be affected by your theme change. In fact, execution from the command-line yields an error message indicating that the correct theme engine couldn't be found in the module-path. Huh?

Well, the thing is that NetBSD's Linux emulation installation includes GTK2 but not the GTK2 engines, which are needed for lots of cool themes (like Clearlooks, as above). So we need to alter the listing of RPM files to download when installing the Linux emulation GTK2 and add the engines to that list. For example, when using NetBSD 3.0.1, the fetch list for SUSE 10.0 GTK2 is located in /usr/pkgsrc/emulators/suse100gtk2/Makefile.i386, where you can replace i386 with whatever your architecture is. Continuing to follow this example, add the following line to the file:


And now run "make [NOCHECKSUM=yes] update" for the SUSE GTK2 package. You'll need to give the option NOCHECKSUM=yes if you choose not to add the checksum for the GTK2 engines RPM to the distinfo file.

Now that the theme engine is installed, it should work perfectly, right? No, not necessarily. Again, by the example given above (NetBSD 3.0.1 with SUSE 10.0 emulation), the non-emulated GTK2 Clearlooks theme contains some features not supplied by the older emulated GTK2 Clearlooks engine. So you may have to change your ~/.gtkrc-2.0 file to reflect the emulated theme rather than the "real" one.

In the event that you don't like the font used by the emulated theme, you can add another line to your ~/.gtkrc-2.0 file to change it. In summation, here's an example GTK configuration file to use the emulated Clearlooks theme with the default GNOME font:

include "/usr/pkg/emul/linux/opt/gnome/share/themes/Clearlooks/gtk-2.0/gtkrc"
gtk-font-name = "Bitstream Vera Sans 10"

13.3 Using A Different Qt Theme

NOTE: This article was written for Qt3 and some things may be different in Qt4.

Let me first disclaim that Qt themes are not the same as KDE themes; in other words, you won't be able to make your Qt applications use the Plastik theme if you aren't using KDE. But there are some Qt themes out there that (in my opinion) look a lot better than the default Motif one. Telling Qt to use them is pretty easy.

Like GTK, the Qt system uses a configuration file in the user's home directory to determine what properties the toolkit uses. One of these files contains the path to the theme, but it's a little more daunting to edit this than it is to change your gtkrc file. So instead, use the qtconfig program, which offers a graphical alternative. Note that any themes you may want to use should be installed into a recognized directory (which is usr/X11R6/lib/plugins/styles on my FreeBSD system) to be discovered by the configuration program. But once the theme is found, just select it and hit save; that theme will now be used for all your Qt applications.

If the qtconfig program is not available (it should be there, but it may be in some weird inaccessible directory), it is possible to edit the configuration file ~/.qt/qtrc by hand. If you don't seem to have this file, it's located somewhere else on your system; just copy this default system-wide configuration file to the path indicated above. You can change any of the settings by hand, but the line you really want to change is the "style" option in the "General" category. Modify this to be the name of the theme you want to use. If you are trying to use a theme not a default part of Qt (for example, the BlueCurve theme), then you may need to add that theme library's parent directory to the libraryPath variable.

Note: Some applications (for example, Opera) don't use many features to which Qt themes apply; in these programs you may see little or no change in appearance after changing themes. However, others (like LyX) are strongly influenced by the theme change.

14 Compiling Software

14.1 Mutt

14.1.1 Required Packages

  • libssl-dev
  • libsasl2-dev
  • libncursesw5-dev
  • libgdbm-dev
  • libgpgme11-dev

14.1.2 Configure Command

./configure --prefix=/opt/mutt              \
            --enable-hcache                 \
            --enable-gpgme                  \
            --enable-pop                    \
            --enable-imap                   \
            --enable-smtp                   \
            --with-sasl=/usr/lib/sasl2      \

14.1.3 FreeBSD Port

Set the following options in your /etc/make.conf:


14.2 Vim

14.2.1 Requirements

  • tcl8.4-dev
  • tk8.4-dev
  • python-dev
  • ruby
  • ruby1.8-dev
  • libperl-dev
  • mzscheme

14.2.2 TCL Header Location

On Debian, you'll need to specify the location of the include files with the TCLINC environment variable. Additionally, to ensure these are actually searched at compile time, add -I/usr/include/tcl8.4 to the CPPFLAGS variable. You'll probably have to install the tcl-dev package in order to get Vim's configure script to find the tclConfig.sh file.

NOTE: Actually, this was fixed shortly after I reported it, so if you're using a patched version (like with my Vim builder) there should be nothing to worry about.

14.2.3 PLT Scheme File Layout

The Debian package for PLT Scheme (mzscheme) throws the library files and collections into /usr/lib/plt whereas development headers go into /usr/include/plt which is all well and good, except the Vim configure script expects to find the include files in a sub-directory of the collections directory. So, to allow Scheme support in Vim, make a symlink:

$ sudo ln -s /usr/include/plt /usr/lib/plt/include

14.2.4 Out of Date Interfaces

While Vim's interfaces to other programming languages work with fairly recent code, the latest Ruby 1.9 and versions of MzScheme greater than or equal to 370 won't work with Vim right now. TCL 8.5 and Python 2.5 do work, however.

14.2.5 Patching & Configuring

Because of the difficulty of downloading all the patches and applying them individually, I wrote a script that handles it all automatically. I recommend you download the script from http://real.metasyntax.net:2357/?section=code&page=devel#vim-builder, then simply execute it to automatically download, patch, and configure the latest Vim source.

14.2.6 FreeBSD Port

MzScheme 370 is broken on FreeBSD, so we can't use Scheme scripting support in Vim. Use the following options when building from Ports:


15 GDM

15.1 Themed Login Configuration



15.2 Plain Login Configuration




16 Multi-Booting

16.1 Installation Order

The order in which you install operating systems can be key when using proprietary systems. Windows likes to wipe out whatever happens to already reside in the MBR, and can make your Unix system unbootable. So always install your Windows system before adding any other operating systems.

16.2 GRUB

There are a couple different multi-boot managers out there, in the Linux world notably LILO and GRUB. I recommend using GRUB because it's easy and functional. GRUB works in several "stages". The first is installed into the MBR and triggers stage 1.5 to be loaded. This loads support for various file systems and then invokes stage 2 which is loaded next. This shows the menu and presents the GRUB shell. Because stage 1.5 can read many different types of filesystems (including ext1, UFS, and FFS) the higher GRUB functions can be installed on many different types of operating systems.

16.2.1 GRUB Disks

GRUB has it's own way of addressing disks and partitions. It works roughly as follows: a drive is indicated by (hdx), where the x is a zero-based number. Partitions (or slices, in BSD parlance) are indicated like (hdx,y) where y is also a zero-based number. Finally, BSD partitions can be addressed by adding a third part, as in (hdx,y,z) where z is a letter, corresponding to the label on the partition.

16.2.2 GRUB Configuration

Each entry in your /boot/grub/menu.lst specifies the commands to run before issuing boot to start the operating system. As a consequence, if you're ever stuck at the GRUB shell with no configuration, you can also issue these commands manually, then enter boot. FreeBSD

The following method passes control off to the FreeBSD bootloader rather than booting the kernel itself. While GRUB claims to be able to boot the FreeBSD kernel directly, the way I figured one would go about this (setting kernel to /boot/kernel/kernel) doesn't seem to work.

title       FreeBSD
root        (hd0,0,a)
kernel      /boot/loader GNU/Linux
title       GNU/Linux
root        (hd0)
kernel      /boot/vmlinuz

17 Dell Inspiron 1501

17.1 WLAN 1390 MiniCard

17.1.1 GNU/Linux

Ubuntu has "restricted" firmware for this one, but it doesn't work all that well (frequent disconnects from the network, and signal strength metering is messed up [all access points show up as being 100% strong]). So we must use ndiswrapper instead. Following these instructions to get it going:

  1. Add "blacklist bcm43xx" to /etc/modprobe.d/blacklist.
  2. Reboot.
  3. Make sure you have a compiler and the libc and kernel development files (install the build-essential package in Debian).
  4. Download the ndiswrapper source, and extract it.
  5. Run "sudo make uninstall" until no "removing" messages show up.
  6. Now do "sudo make" and "sudo make install".
  7. Make a new directory and download the ZIP file for the Windows drivers into it.
  8. In that directory, "unzip -a" the driver archive.
  9. Go to the DRIVER subdirectory.
  10. Run "sudo ndiswrapper -i bcmwl5.inf".
  11. Execute "sudo ndiswrapper -l"; you should see your wireless device listed.
  12. Now do "sudo ndiswrapper -m" to alias the device.
  13. Load the ndiswrapper module with "sudo modprobe ndiswrapper".
  14. Check the functionality by doing a "sudo iwlist scanning" to enumerate nearby wireless networks.
  15. If it works, add "ndiswrapper" to /etc/modules to load ndiswrapper on boot.

Newer versions of the kernel use the b43 driver instead of the older bcm43xx driver, which actually works for my setup. Installing it is significantly easier, seems less prone to error, and probably uses more free software. Rather than using ndiswrapper as above, instead:

  1. Install the b43-fwcutter package through synaptic.
  2. Download and extract the proprietary Broadcom firmware.
  3. Go to the kmod subdirectory.
  4. Run "b43-fwcutter -w /lib/firmware wlapsta.o" to extract the firmware.

Your wireless indicator should now light up on your laptop and you should be good to go! It seems that this isn't as sensitive in using the Dell driver with ndiswrapper, but I'm never in a situation where I really want to use an access point at 10% anyway, so it's all good.

17.1.2 BSD Systems

There is an NDIS module for FreeBSD, as well as one in development (stable for a few cards) in NetBSD. You'll probably be trying it at your peril, but you'll never know unless you try. Since I was already running a version of the AMD64 NetBSD-current kernel that didn't correspond with the rest of the system (due to build failures) I wasn't feeling quite that adventurous.

17.2 ACPI Problems

Under FreeBSD the system would not poweroff or reboot (for example, using shutdown -p or shutdown -r). The solution was to disable the wireless hotkey and "USB Legacy Mode" support in the BIOS. Under Ubuntu and Debian, it sometimes fails to shut down completely - the screen blanks, the disk stops, but the power light remains on and the fan keeps running. I think this is a Linux-only problem, because it never happened with either FreeBSD or NetBSD.

18 Debian Testing

When upgrading from Debian Etch to Lenny, some things get broken. Here's how to work around or fix them:

18.1 Kernel Hang

Booting after upgrading causes the kernel to hang very early at boot time with the message "NET: Registered protocol family 2" as the last thing you see. To work around this, reboot using the old kernel and install the i686 kernel; use that instead.

18.2 Font Size / DPI

The upgrade to the newest version of GNOME somehow fails to find the current screen resolution for font rendering. To fix this, open up the "Appearance" tool in the preferences, then go to "Font" and click "Details." Adjust the DPI up to 96 or whatever your system uses. If you're not using a desktop environment, you can specify the DPI of most fonts in most applications by using the Xft.dpi property in your .Xresources file. Mysteriously (or probably not), I had this same problem using X.Org 7.3 on NetBSD - the solution was to manually set the Xft.dpi value to "90" which seemed to look the best.



Date: 2013-07-03T20:42-0400

Author: Taylor Venable

Org version 7.9.3f with Emacs version 24

Validate XHTML 1.0