11h.net

The blog of 11h

March 25th, 2007

Using cloop in FreeBSD

There are lots of Linux distributions that have a ‘Live CD’ that allow you to rescue your system or try before you bu… install.

Let’s take a look at Knoppix. It is one of the most popular Live CD’s. In the CD structure of Knoppix there is a file that contains the root file system (rootfs). That file is a cloop image file. Each block is compressed individually which allows decompression on the fly or at a specific point in the file.

This allows a rootfs to be about 1 GB in actual size but compressed it will fit into about 700 MB.

When a system boots from this CD [image], a kernel loads the cloop device and then opens the rootfs cloop file. Viola! The root file system is loaded into a ramdisk and is accessible as if it was an installed distribution.

This is great for Linux – not so great for FreeBSD. There are many Linux only or FreeBSD only file types and differences that make using the two systems on the same network very difficult.

I prefer FreeBSD because of its sheer solidness. It’s like comparing a car that uses a gasoline engine (Linux) versus a diesel engine (BSD). Linux is the new hot-ness; fast, sleek, portable, adaptable, pump-n-go. FreeBSD is like the 80s era of cars; cast aside because they aren’t sexy, requires the right glow plugs, needs patience, but it will run on any thing that has enough compression and it will go forever.

By default, FreeBSD lacks the ability to mount cloop images. Luckily, Klaus Knopper wrote a FreeBSD module that allows mounting of a cloop image. This allows someone that uses FreeBSD to modify a cloop image with out needing a Linux box.

To install the cloop module for FreeBSD, build and install the cloop-utils.

# cd /usr/ports/sysutils/cloop-utils/
# make && make install

Now to mount the cloop image.

In this example I am using Damn Small Linux tftpboot.

# unzip dsl-1.5-tftpboot.zip

Unzips the PXE Damn Small Linux release

# gunzip minirt24.gz

Gunzips the root file system

# mdconfig –a –t vnode –f minirt24

Creates a virtual device from the minirt24

# mount –t ext2fs /dev/md0 /mnt/dsl

Mounts the ext2 file system inside the minirt24 file that was created from mdconfig as /dev/md0

#kldload geom_uzip

Loads the cloop device so FreeBSD can rw cloop files

# mdconfig –a –t vnode –f /mnt/dsl/cdrom/KNOPPIX/KNOPPIX

Creates a virtual device from the KNOPIX root file system inside minirt24

# mount –t cd9660 /dev/md1.uzip /dev/dslcdrom

Mounts the cloop device from md1 using the geom._uzip device

Now you should have access to the cloop ‘KNOPPIX’ root file system in /mnt/dslcdrom. Follow the steps in reverse to close and re-zip the files I my case, it allows me to update any part of the rootfs from the PXE server which is not Linux.

March 7th, 2007

Visual Studio 2005

After working with Visual Studio 2005 since before its release, I have compiled a list of “issues” I have encountered with it, and in some places compare these “features” to that of other similar products I’ve used. Note that some of these may have been fixed/changed in Service Pack 1 (but all are valid in its final release, not beta, version), as I have been compiling this list over a long period of time.

Intellisense requires too much CPU. Prior versions were fast and efficient. Eclipse is likewise very fast too on the same machine. I also frequently see “Please wait while the documentation cache is being generated” in the tooltip for intellisense’s documentation tooltip. Intellisense also comes up immediately while typing, which wouldn’t necessarily be a bad thing if it didn’t always try to force its suggestions upon you. Eclipse tends to only auto-complete if you tell it to (i.e. “Tab” or “Enter” key is pressed). Worse yet, intellisense’s suggestions are outright bogus! It frequently tries to show suggestions for out-of-context terms, which makes it very difficult to use it efficiently. Eclipse always puts in-context items at the top of the list, complete with method signature checking. Furthermore, they over-complicated intellisense by making ctrl-shift-space necessary to bring it up in function parameters, rather than the regular ctrl-shift hotkey.

Intellisense also can not suggest classes from assemblies not referenced with the using keyword in the source file. This makes routine operations very tedious. How do you get eclipse-like-functionality to auto-add the using keyword and suggest the reference you needed? Ctrl-Shift-F10. That’s right, another cryptic key combination where Ctrl-Space would suffice. What’s worse, it won’t auto-complete the references until I type its full name (so in reality, it only auto-completes the namespace, making the “feature” about 90% useless).

The XML Code Documentation will not show up in a tooltip if there are any parse or syntax errors in the XML comment. At least eclipse will show something, even if formatted badly. Additionally, the tooltip appears for a fixed 30-seconds in the code editor until it times out, regardless of how long the documentation comment is. This is almost never enough time to read docs within the code editor. Oh, does it get worse? Yeah, the tool-tip in Intellisense for the same information is limited to 10 seconds.

The Online F1 Help feature is incredibly slow. Worse yet, while it’s loading, it forces its (incompletely drawn) window to the front focus at least three different times, obstructing my ability to even multitask while that monstrosity loads.

Autoformat is too aggressive and intrusive to forcing its code-style ways. Eclipse’s auto-format works much more friendly to the programmer. And Ctrl-I is easier to type than Ctrl-E, wait, f.

Right-click, “Go to Definition” simply does not work on overloaded members. It’s too stupid to take me to the implementation I clicked on (unlike eclipse, which knows precisely where I want to go with a very simple “Ctrl-Click”). Furthermore, the window that “pops-up” is so freaking verbose that it takes forever to decide which member to take me to. Do you really have to add the full filename+namespace+class+params to every single freaking piece of text the compiler generates and shows in the IDE when the difference is a simple overloaded function? I think I can manage without, thank you.

The code editor does not automatically compile source code as I type/save. The basic “parsing” of the source code is next-to-useless too. This makes typo-error detection much more difficult to find, especially if you forget to compile your solution after every single stupid change.

The IDE is very slow when switching from source code files and the GUI Designer. This is in part to the toolbar redrawing itself too often to show/hide the relevant icons for the context. The screen flashing as a result of the toolbar shifting and resizing every other window is also a huge distraction and consumes a lot of CPU power for a very routine operation.

Also, on more than one occasion, and with more people than me, the GUI Design Editor has lost consistency between that of the GUI and source code, rendering the GUI source code unusable. In each instance that this occurred to us, it ended up being easier to delete the source file and recreate the GUI from scratch [note: version control really helped us out here, but oh wait, VS doesn’t have a minimal type of it built in, unlike eclipse and its local history feature].

I imported a project built for the .NET Compact Framework. I couldn’t for the life of me figure out how to convert it to a standard .NET 2.0 project. I ended up deleting the project and manually importing the source files and references.

AnkhSVN really sucks; it is buggy, slow, hard to use, feels like a hack, and doesn’t provide many useful features that TortoiseSVN alone already couldn’t provide.

Want to refactor a namespace used in the project? I couldn’t find an easy way to do it… I ended up using a primitive “Find & Replace in Files” word search “feature”. Also, renaming an Application Settings file doesn’t update any code references. Furthermore, Right-Click->Refactor shows several options, most of which are irrelevant to the current selection (i.e. it is not context sensitive). Is this 1992 still?

Using the Solution Explorer is a pain. Anything you do that causes it to need refreshed causes the treeview to completely refresh; it removes all items from the tree and adds them back during the update. This causes the solution explorer window to go completely white for several seconds. This is bad for productivity because it causes the user to very easily lose track of his/her place as well as difficult to confirm his/her actions.

The Help program for .NET 2.0 has a “Language Filter” feature. I set it to filter only for the C# language. When I opened a new help link, then clicked the “Back” button, the filter didn’t take effect (causing sample code to show up for Visual Basic, C#, C++, J#, and JScript, cluttering up the help file tremendously), yet the filter still says “C#” only as my selection! To add to this, why would the language filter NOT default to C# only when help is invoked on a C# keyword from a C# source file in a C# project within a C# solution???? Honestly, if I’m programming in C#, I “DO NOT WANT NOR CARE ABOUT VISUAL BASIC CODE EXAMPLES“.

Nullable Types? This is such a poorly-implemented hack upon poorly-designed structs that probably should have been classes in the first place.

Whenever I open up one of my forms in the Form Designer that has made use of any resources (i.e. an icon), it always comes up as needing saved even though I haven’t made any modifications to the form (I only opened it)!

Back to productivity loss, consider this scenario: I have a Tab-Pane with several controls. I try binding the default values of some of those controls to an ApplicationSettings object using the Form Designer and the Properties Window. Every time I set a property, the entire form refreshes (several seconds). By the it finishes refreshing, my tab-pane shows ON TOP of the controls in which it contains! I have to close & reopen the form in the designer to make them visible again (several more seconds). Rinse, lather, repeat dozens of times for each control I need to bind.

Consider this scenario, too: I set one of the application properties to save the window position. As soon as the form designer refreshes, I see the screen in Screenshot 1. Okay…. I close the form, rebuild the project, and see even more errors when reopening the form (screenshot 2). Hmm… I check the code and it looks OK. I rebuild the whole solution and it builds OK. I even execute the program and it executes OK. Won’t open the form designer though.

Out of a last attempt of desperation, I close down Visual Studio, reopen it, and reopen the solution. Next, I rebuild the solution again and receive the compile errors in screenshot 3. HUH?? How can it not even find the “System” namespace? Guess what I do next: Open the form again. Guess what happens: The form opens perfectly and all the compile errors go away. I can’t believe this software is even considered professional. Pre-alpha crack-job hobbyist is more accurate. Definitely not worth the $800+ it costs to buy this buggy pile of bloat ware. The free csc.exe compiler and Crimson Editor (or Mono on Linux) would have been much better suited for programming in this POS language.

Here’s another scenario: I was working on a solution with only two projects. The 2nd project references the 1st project. The 1st project wouldn’t compile because its assembly DLL was in use by the 2nd project, and thus couldn’t overwrite the file. Nothing was running (no debuggers, or anything). Process Explorer showed that devenv.exe simply had an exclusive handle on the file. Piece of junk. Meanwhile, I’ve used eclipse with dozens of projects all referencing each other in weird, complicated ways without a hitch nor a slowdown (remember: eclipse is smart enough to only recompile projects that have actually changed, where VS has to build every project before it can run/debug anything).

Crystal Reports caused the IDE to crash while trying to browse data in a data source. As much as I hate Visual Studio, this is the first time I’ve had it actually crash on me. Also, Crystal Reports’ designer/preview window gives extremely vague error messages like “The field is incorrect“. Or, slightly more informative, but completely unacceptable, “crdb_adoplus : To access classes in your project at design-time, please build your project first, and then try again“. Wow. Yes, I’ve built my project. Instead of trying to be smarter than me, why not just tell me what the real problem is so I can have a chance at solving it?

Crystal Reports can’t reference a custom data class contained in a separate project (but of the same solution, and yes, the project in question does reference the data class project). It forced me to try to link directly to the assembly DLL. (this turned out to be the cause of the deadlock in the above scenario — why a lock was held is beyond me). Also, Crystal Reports likes to, at random intervals, show dummy data in lieu of the real report’s data (i.e. Days of the week, random color names, random numbers), without even telling the user why nor how to fix it in the designer.

The Document Outline window mysteriously changes its name to Field Explorer when in Crystal Reports’ design mode. Yeah, now THAT is intuitive.

Speaking of tool windows, when I have the left-hand panels (Toolbox, Server Explorer, and Data Sources) set to Auto-Hide mode, every time I start VS2005 and load a solution, the “Data Sources” panel unhides and blocks any windows beneath it. The only way to get it to Automatically Hide again is to click on another panel to make it visible, then move the mouse away, which hides both panels again.

Speaking of loading visual studio, the Title-bar Focus is always reversed from whether it actually has focus or not. For example, if I start VS2005 normally, it comes up as “focused” in the Windows Task Bar, but the titlebar for the application is in light-blue, indicating “unfocused”. However, if I start VS2005 and switch to another program while its still loading, when the main window is drawn in the background, it comes up properly as “unfocused” in the task bar, but the titlebar is drawn dark-blue, indicating it is “focused”. In this case, both the program I was using and VS2005 “think” they have focus but in reality only the program I was actually using has focus.

Modifying the app.config file from within code must be done by manually parsing the XML document. While I most definitely understand the reasons for this, it makes it very difficult to create an Administrative Tool that lets you set the system-wide defaults or a Windows Installer Custom Action to set site-wide defaults. Microsoft admitted it didn’t include an easier way because it might cause bad programming habits (read: make bad programmers worse out of their own stupidity).

And finally, my saga in upgrading VS to Service Pack 1:

Trying to install VS2005 Service Pack 1, Windows update spent a couple hours downloading it, and the install failed. No reason given (except some cryptic error code found after digging through some log files and the Windows Update website). So I tried installing a 2nd time, and during the install I realized it was because I ran out of disk space. Granted, I wasn’t doing too good on disk space to begin with, I still want to point out the inefficiencies of Windows Update:

  • Windows Update downloaded the file (dated a few days before I even started the download) to C:\WINDOWS\SoftwareDistribution\Download\d4b5c73253a7a4f5b4b389f41b94fea4a7247b57 - 431MB
  • Windows Update then copied the file to C:\WINDOWS\SoftwareDistribution\Download\Install\VS80sp1-KB926601-X86-ENU.exe - 431MB
    Proof (md5sum):
    19194baf126fdd7cfbe4f09697db609f *d4b5c73253a7a4f5b4b389f41b94fea4a7247b57
    19194baf126fdd7cfbe4f09697db609f *Install\VS80sp1-KB926601-X86-ENU.exe
  • Windows Update then executed the latter, which extracted itself to C:\Documents and Settings\Brian\Local Settings\Temp\ZNW20F\VS80sp1-KB926601-X86-ENU.msp - 455MB
  • At some point, this file was created: C:\WINDOWS\Installer\580c9cba.msp - 455MB
  • You guessed it, copies of each other:
    (md5sum)
    c0f76019179ed25d23fa2bae65357367 *580c9cba.msp
    c0f76019179ed25d23fa2bae65357367 *VS80sp1-KB926601-X86-ENU.msp
  • During the install, backups (”Rollback Script Files”) are created in C:\Config.Msi. This grew to 1606 files totaling 1.04GB before being deleted just prior to the install finishing.
  • For good measure, a log file created during the install in C:\Documents and Settings\Brian\Local Settings\Temp\VS80sp1-KB926601-X86-ENU\VS80sp1-KB926601-X86-ENU-msi.0.log grew to over 40MB.
  • All of this took 2+ hours with this un-minimizable window as my only clue: screenshot.
  • Total disk space used for temporary files: 2.8 Gigabytes. Wow.

March 1st, 2007

Postfix

w00t! I finally got the Postfix MTA running on my home network! I was using qmail on my old faithful Slackware 9.0 router, decided against using it again since it was a bit complex for my needs. Postfix is simple, very configurable, and lets me use a MySQL database for all of my virtual e-mail clients!

Unfortunately, like most Linux MTA’s, documentation and tutorials that somebody with no formal knowledge of e-mail servers are a bit hard to find. After reading nearly all of the Postfix docs and several random tutorials and howto’s, I finally got a setup that works perfectly for my needs. And I’ll be adding server-side spam checking in the future, too!

Basically, I installed the following on my Slackware 11.0 server, which is a dual-processor, dual-core Xeon 3.6GHz system with hyper-threading, 4GB RAM, 1TB+ of HD space, and lots of little goodies:

Below are very brief notes of how I installed it. I already installed MySQL 5, PHP5, and Apache2 a while back so they were already in working order. I didn’t want quotas (yes, I have plenty of space for my 3 users), and don’t care (as of yet) about SSL.

Preparations

Create a MySQL database for postfix give privileges in the database for a postfix user. I set my database up like this, but you’ll (and I’ll) probably want to add some additional fields, like IDs, and relationship fields, like Domain, to be shared between the tables (make queries from a management script, for example, much easier and logical).

Table structure for table alias

Field

Type

Null

Default

address

varchar(255)

Yes

goto

text

Yes

active

tinyint(1)

Yes

1

I set a few aliases like this:

address goto active
postmaster@11h.net joe123@11h.net 1
logs@11h.net joe123@11h.net 1
@myserversname.11h.net @11h.net 1

That last one will keep the username the same changing only the virtual domain it is redirected to. The first two simply redirect postmaster and logs to the e-mail joe123@11h.net.

Table structure for table domain

Field

Type

Null

Default

domain

varchar(255)

Yes

active

tinyint(1)

Yes

1

My 2 domains are merely “11h.net” and “myserversname.11h.net”. If you host any other domains, add them here.

Table structure for table mailbox

Field

Type

Null

Default

username

varchar(255)

Yes

password

varchar(255)

Yes

name

varchar(255)

Yes

maildir

varchar(255)

Yes

active

tinyint(1)

Yes

1

This one gets a little more complicated because of the password field. Here’s an example for “joe123″:

username: joe123@11h.net

password: $1$WmD/q3et$Hiz97VoENZ0q2Lm49V3ax.

name: Joe User

maildir: joe123@11h.net/

active: 1

First, the username is the full e-mail address.

Second, the password is in hashed form. For the most part, Courier-IMAP can recognize these types of passwords, depending on what they look like in the database (from man pages):

  • A traditional triple-DES crypted password, or a MD5+salt-hashed password, as used in Linux.
  • “{MD5}” followed by a base64-encoded MD5 hash of the password.
  • “{SHA}” followed by a base64-encoded SHA1 hash of the password.

In my case, since I was “upgrading” from qmail on one server to postfix on this server, I simply copied the users passwords on the old system from /etc/shadow. For new users, its easier to just use MySQL’s ENCRYPT function. The password in my example above is from /etc/shadow for an old user, it is the hash of “example”.

Third, maildir is the directory under /var/spool/postfix/virtual where the user’s e-mail is stored. This must end with a slash for it to be in “Maildir” format. I simply use the e-mail address, others may wish to separate them into domains. For example: “11h.net/joe123/”.

Finally, 1 in active indicates this e-mail can receive mail…

Table structure for table transport

Field

Type

Null

Default

domain

varchar(255)

Yes

transport

varchar(128)

Yes

I also created a user account and group “postfix” (for the postfix daemon’s to run as), a group (no associated user) named “postdrop”, and a user account and group “vmail” (the owner of the Maildirs in /var/spool/postfix/virtual/).

Courier-Auth

Did a usual install according to the instructions. The ./configure script auto-detected MySQL and whatever else it needed. It installed to the /usr/local prefix and stuck its configuration files in /usr/local/etc/authlib (don’t forget to rename the copied files so as to lose the .dist extension). Its daemon was put in /usr/local/sbin, but I start it via the scripts it put in /usr/local/libexec/courier-authlib.

In the authdaemonrc configuration file, I just set the authmodulelist to only include “authmysql”. I don’t want my local system users to have e-mail; only virtual addresses stored in the mysql table, so this works out for me.

In authmysqlrc, I basically set it up with these settings:

MYSQL_SERVER localhost
MYSQL_USERNAME postfix
MYSQL_PASSWORD password
MYSQL_DATABASE postfix
MYSQL_USER_TABLE mailbox
MYSQL_CRYPT_PWFIELD password
DEFAULT_DOMAIN 11h.net
MYSQL_UID_FIELD ‘1006′
MYSQL_GID_FIELD ‘107′
MYSQL_LOGIN_FIELD username
MYSQL_HOME_FIELD ‘/var/spool/postfix/virtual’
MYSQL_NAME_FIELD name
MYSQL_MAILDIR_FIELD maildir

# MYSQL_CLEAR_PWFIELD clear


Essentially, the way this configuration file works, for the fields, is it wants the name of the Database field. If the entry is “static” (i.e. don’t look it up in the database, but specify the value directly in the file) it is enclosed in single-quotes ('’). So the authdaemon will obtain the Mailbox information from the “mailbox” table in the “postfix” SQL database. Within that table, the user’s hashed (encrypted) password in the “password” field, the user’s username/e-mail address in the “username” field, the user’s real name in the “name” field, and the user’s Maildir directory in the filesystem in the “maildir” field. The UID and GUI on my system are 1006 and 107, which are for the “vmail” system user account and group. This is who the maildir directory is owned by — it shouldn’t be readable by anybody except this user.

The default domain is specified so the user’s may log in as “joe123″ instead of having to specify “joe123@11h.net”. I also left out the clear password field since I don’t consider it good practice to store plain-text user passwords inside a database (or anywhere for that matter). Note that this does, however, sacrifice the ability to use CRAM-MD5 Authentication.

Courier-IMAP

Did the usual install in accordance w/ the instructions… well almost, one of the tutorials I read said to compile it like this:

$ ./configure –prefix=/usr/local/courier –enable-unicode

So it stuck everything in its own directory. How nice. The daemons are started from /usr/local/courier/libexec, and the configurations in /usr/local/courier/etc. Don’t forget to rename the default config files as you had to do with the authdaemon.

In the etc dir, Peek thru “imapd” and make sure it all looks good. Options to pay attention are, as I did:

DEFDOMAIN=”@11h.net”
IMAP_CAPABILITY=”IMAP4rev1 UIDPLUS CHILDREN NAMESPACE THREAD=ORDEREDSUBJECT THREAD=REFERENCES SORT QUOTA IDLE”
IMAP_IDLE_TIMEOUT=5
IMAP_EMPTYTRASH=Trash:90
IMAP_MOVE_EXPUNGE_TO_TRASH=1
IMAPDSTART=YES

On the capabilities part, you’ll want to use the other one if you store a clear-text password and want CRAM-MD5 authentication. I didn’t care, so I left it as that. Also, configure pop3d if you want that, too.

Postfix

I’m sure I did a pretty basic installation, which picked up on MySQL and everything I needed. Configuring it was the most difficult for me since I had (well still have) no idea how this MTA even works.

Once installed, at least the way I set it up, the configuration files are in /etc/postfix, and mail spool stuff in /var/spool/postfix. I created a directory in there called “virtual” which is where all the e-mail goes.

First, I renamed all the config files to get rid of the “dist” or “.default” extensions. Then I edited “main.cf” to contain something like this:

queue_directory = /var/spool/postfix
command_directory = /usr/sbin
daemon_directory = /usr/libexec/postfix
mail_owner = postfix
myhostname = mail.11h.net
mydomain = 11h.net
myorigin = $mydomain
local_recipient_maps = $virtual_mailbox_maps
unknown_local_recipient_reject_code = 550
mynetworks_style = host
mynetworks = 10.0.0.0/16, 127.0.0.0/8
relayhost = [my.isps.mail.server]
home_mailbox = Maildir/
debug_peer_level = 2
debugger_command =
PATH=/bin:/usr/bin:/usr/local/bin:/usr/X11R6/bin
xxgdb $daemon_directory/$process_name $process_id & sleep 5
sendmail_path = /usr/sbin/sendmail
newaliases_path = /usr/bin/newaliases
mailq_path = /usr/bin/mailq
setgid_group = postdrop
html_directory = no
manpage_directory = /usr/local/man
sample_directory = /etc/postfix
readme_directory = no
local_transport = virtual:11h.net
transport_maps = mysql:/etc/postfix/mysql_transport_maps.cf
virtual_alias_maps = mysql:/etc/postfix/mysql_virtual_alias_maps.cf
virtual_gid_maps = static:107
virtual_mailbox_base = /var/spool/postfix/virtual
virtual_mailbox_domains = mysql:/etc/postfix/mysql_virtual_domains_maps.cf
virtual_mailbox_limit = 1073741824
virtual_mailbox_maps = mysql:/etc/postfix/mysql_virtual_mailbox_maps.cf
virtual_minimum_uid = 1006
virtual_transport = virtual
virtual_uid_maps = static:1006
message_size_limit = 268435456

Phew, the most important ones are at the bottom… note that I set my “local” transport to always assume a virtual transport with @11h.net as the defaut domain (so e-mails to “joe123″ and “joe123@11h.net” both go to joe123@11h.net rather than attempt the linux system account “joe123″). I also set obsenly high message size limits. Make sure to set the virtual_gid_maps, virtual_uid_maps, and virtual_minimum_uid to the user/group ID of “vmail”, as they’re used to write to the Maildir directories to deliver mail.

The extra files I created are these:

mysql_relay_domains_maps.cf
user = postfix
password = password
hosts = localhost
dbname = postfix
table = domain
select_field = domain
where_field = domain
additional_conditions = and backupmx = ‘1′
mysql_transport_maps.cf
user=postfix
password=
password
dbname=postfix
hosts=localhost
table=transport
select_field=transport
where_field=domain
mysql_virtual_alias_maps.cf
user = postfix
password =
password
hosts = localhost
dbname = postfix
table = alias
select_field = goto
where_field = address
mysql_virtual_domains_maps.cf
user = postfix
password =
password
hosts = localhost
dbname = postfix
table = domain
select_field = domain
where_field = domain
additional_conditions = and active = ‘1′
mysql_virtual_mailbox_maps.cf
user = postfix
password =
password
hosts = localhost
dbname = postfix
table = mailbox
select_field = maildir
where_field = username
additional_conditions = and active = ‘1′

Start and stop the daemon with “postfix” commands… i.e.:

# postfix start
# postfix reload
# postfix stop
# postfix help

And check /var/log/maillog for any problems!

RoundCube

This web-mail front end is very simple to use, has just enough features to make me happy, has a very nice ajaxy interface, and fully supports IMAP, which means I can keep my gigs of e-mail on my server and access them from my Windows IMAP client, a Linux IMAP client, or via RoundCube via the web interface! Very cool. I just created a VHOST in apache and dumped the latest SVN copy into it (its PHP). Its easy to configure and can use multiple IMAP servers, local or remote. Read the docs and play with their online demo.

Final Notes

Postfix will create the “Maildir” structure under /var/spool/postfix/virtual automatically when the user’s first e-mail is delivered. Until then, Courier-IMAP will not allow the user to login. Roundcube will also just hang and eventually time out with an access deined message. For simplicity, I just send a dummy e-mail to the user. Transferring existing users from qmail was a peice of cake — just tarred the user’s Maildir on the old server, copied it to the new server, and extracted it (w/o the Maildir part) to their virtual directory and changed the owner to vmail:vmail.

I know I left out some very important details, as this was supposed to be brief. Remember: read the man pages… and probably buy a book on it so you can figure out what all those new-fangled terms mean!