## Scott Wiersdorf ## Created: Fri Aug 24 16:58:17 MDT 2001 ## $Id: virtual_lists.pod,v 1.9 2001/09/19 23:32:07 scottw Exp $ ## ## print with: ## pod2man --center="VPS Documentation" virtual_lists.pod | groff -t \ ## -man -Tps | lpr -P ## ## manify with: ## pod2man --center="VPS Documentation" virtual_lists.pod > ## virtual_lists.1 ## ## htmlify with: ## pod2html --infile=virtual_lists.pod --outfile=virtual_lists.html \ ## --title="Virtually Hosted Mailing Lists" =head1 NAME B - Virtually hosted mailing lists for virtual servers =head1 SYNOPSIS B is a suite of programs written in Perl to help automate the management of mailing lists. This document describes how to setup B on a virtual server and use it to manage mailing lists under virtually hosted domains. =head1 DESCRIPTION Many people like to use B for the management of their mailing lists, but find that setting it up to manage lists for virtual hosts is too complex or confusing. This document describes what steps are necessary to create virtually hosted mailing lists using B. In this document we call the set of programs that runs a mailing list 'Majordomo' with an upper-case 'M' and the program in this suite that handles mail requests 'majordomo' with a lower-case 'm'. We have a virtually hosted domain (which we call F) on our server (which we call F) and we want to set up a recipe mailing list for the exchange of popular cooking recipes using the F domain. We assume that the domain F already has a DNS record pointing to this virtual server and that B has been configured to accept mail for the domain (using the F<~/etc/local-host-names> mechanism or the B lines in F<~/etc/sendmail.cf>). Throughout this document we will point out the steps that need to be done for first-timers as well as steps for those who simply want to add an additional mailing list to a virtually hosted domain. =head2 Installing Majordomo on a virtual server To install B on your virtual server, at your shell prompt, type: server:~ $ vinstall majordomo The only thing you need to know during installation is your hostname which you may discover by typing C: server:~ $ hostname server.com The default hostname that the B installation program suggests is usually correct. Once B has been installed, we're ready to create a virtually hosted mailing list by following these four steps: =over 4 =item 1. set up the mailing list administrative files for the virtual host =item 2. set up the virtual user table or "virtmaps" entries =item 3. set up the aliases for our list =item 4. create the mailing list =back =head2 1. Set up the mailing list administrative files for the virtual host First we must create some files and directories that B needs to be able to handle our new mailing list for this virtual host (if you already have Majordomo mailing lists for this virtual host, you may skip to step 2): =over 4 =item * an archive directory (F) Necessary if you want to keep an archive of your messages. If you do not wish to keep an archive of messages sent to the recipe mailing list, skip this directory. This is an optional directory, but we will use it in this example. =item * a lists directory (F) All mailing list information (for all mailing lists under this virtual host) is stored in this directory. This directory is not optional. =item * a B log file (F) All B administrative actions are logged here. This is an important log to keep for security purposes; you should periodically review the contents of this file. This file is not optional. =item * a digests directory (F) Necessary if you want to do I for your mailing list. A I is a collection of many messages over a period of time compiled into one single message. You may use B to create weekly or monthly digests of the messages sent to the recipe mailing list. Digest subscribers will receive this periodic digest message instead of each message sent to the list. This is an optional directory and we will not use it in this example. =item * a B configuration file (F) Contains information for B to work correctly. In this configuration file we tell B what the name of our virtual host is, where our home directory is located, where our F directory is located, and other such things. This file is not optional. =back We suggest placing these files in the root directory (F<~/www/vhosts/vhost1>) of the virtual host for added security and portability (i.e., if you ever decide to move the host to another server, etc.). =over 4 =item B One reason we would I want to put these things in the root of the virtual host is if we did not trust the owner of the virtual host to put the correct information in the B configuration files. For example, a malicious subhost could tell B to save the messages archive in F<~/etc/passwd>, which would effectively clobber our server's password file. We would not give our subusers their own F file for the same reasons we would not give them their own F or ability to execute their own cgi scripts: their scripts run at the same privilege and file system view as our own server scripts. If you trust your users to leave these files alone, or access the configuration files using methods you prescribe, you will probably be fine leaving these files in the root of the virtual host. If you don't have any subusers who have virtual hosted domains on your server, you're also safe. If you are at all uncomfortable with another user deciding where files will be saved on your server, make another directory somewhere (maybe under F<~/usr/local/majordomo/vhosts>) and use that hierarchy for the remainder of this document. =back When we originally set up our virtual host, we wanted an area for files we didn't want to be publicly available over the world wide web so we created a 'www' directory in the root of the virtual host and made that our DocumentRoot in our Apache httpd.conf file: ServerName www.vhost1.com ServerAdmin webmaster@vhost1.com DocumentRoot /usr/local/etc/httpd/vhosts/vhost1/www TransferLog logs/vhost1.com/access_log ... Everything in our virtual host root directory (F<~/www/vhosts/vhost1>) that does not lie under our Apache document root directory (F<~/www/vhosts/vhost1/www>) is not accessible via the web. The directory root of our virtual host looks something like this: server:~/www/vhosts/vhost1 $ ls -lF total 1 drwxr-xr-x 3 server vuser 512 Apr 25 22:08:24 2001 www/ =over 4 =item B If you did not originally set up your virtual host this way and your virtual host root is the same as your Apache document root, you may either create a 'www' directory (or 'htdocs' or 'web', etc.), copy all your web documents there, and change your Apache document root I follow the suggestion in B above and create your B files in another directory hierarchy elsewhere on your server. =back Let's create the files that B needs to run a mailing list. We'll create two directories F and F, create a file called F, and copy the system F file to this directory: server:~/www/vhosts/vhost1 $ mkdir Archive Lists server:~/www/vhosts/vhost1 $ touch Log server:~/www/vhosts/vhost1 $ cp -p ~/usr/local/majordomo/majordomo.cf . server:~/www/vhosts/vhost1 $ ls -lF total 25 drwxr-xr-x 2 server vuser 512 Aug 23 08:35 Archive/ drwxr-xr-x 2 server vuser 512 Aug 23 08:35 Lists/ -rw-r--r-- 1 server vuser 0 Aug 23 08:35 Log -rw-r--r-- 1 server vuser 10460 Aug 20 17:26 majordomo.cf drwxr-xr-x 5 server vuser 1024 Feb 20 2001 www/ To finish this step we need to edit this new F file and make the following changes using our favorite editor (B, B, B, B, etc.). Note that your line numbers may vary slightly depending on the version of B you're using and other modifications. line 9: old config file: $whereami = "server.com"; --- new config file: $whereami = "vhost1.com"; line 27 (add this line): old config file: (empty line) --- new config file: $myhomedir = "/www/vhosts/vhost1"; new config file: (empty line) line 31: old config file: $listdir = "$homedir/Lists"; --- new config file: $listdir = "$myhomedir/Lists"; line 39: old config file: $digest_work_dir = "$homedir/Digests"; --- new config file: $digest_work_dir = "$myhomedir/Digests"; line 43: old config file: $log = "$homedir/Log"; --- new config file: $log = "$myhomedir/Log"; =head2 2. Set up the virtual user table or "virtmaps" entries This step allows the world (or just members of our mailing list) to send mail to our virtual host. By adding entries in our F<~/etc/virtmaps> file our server knows to translate virtual host aliases to real server aliases found in F<~/etc/aliases> (which aliases we add in step 3). Let's get right into it by changing directories to our F<~/etc> directory: server:~/www/vhosts/vhost1 $ cd ~/etc server:~/etc $ Open up F<~/etc/virtmaps> in your favorite editor and prepare to append some new lines to the bottom of the file. =over 4 =item B You may skip this section if B is already configured for this virtual host. If this is your first B installation for this virtual host, you will need to do this section. We need to add some essential B mappings: ## essential majordomo aliases majordomo@vhost1.com vhost1~majordomo majordomo-owner@vhost1.com vhost1~majordomo-owner owner-majordomo@vhost1.com vhost1~owner-majordomo These mappings direct mail sent to 'majordomo@vhost1.com' to a locally defined alias (which we will add in step 3) called 'vhost1~majordomo'. We use a tilde (~) to separate our hostname from the alias; you may wish to use a different character (or no character at all). =back Let's add the mappings for our recipe mailing list. The following lines will need to be added for each mailing list on this virtual host. In this example we are only creating one mailing list called I, but we could add many more lists just as easily. ## vhost1.com: recipe list recipe@vhost1.com vhost1~recipe recipe-going-out@vhost1.com vhost1~recipe-going-out recipe-request@vhost1.com vhost1~recipe-request recipe-owner@vhost1.com vhost1~recipe-owner owner-recipe@vhost1.com vhost1~owner-recipe If you're setting up a moderated list, you'll also need: recipe-approval@vhost1.com vhost1~recipe-approval (thanks to Miomir Besarabic Emiomir-at-besarabic.comE for pointing this out). Save and close the virtmaps file; be sure to run B when you're done. We're ready to add our new aliases now. =head2 3. Set up the aliases for our list This step takes the messages that are forwarded by the mappings in our F<~/etc/virtmaps> file and forwards them to actual B commands. Open F<~/etc/aliases> in your favorite editor and prepare to append some new lines to the bottom of the file. =over 4 =item B You may skip this section if B is already configured for this virtual host. If this is your first B installation for this virtual host, you will need to do this section. Add the following four lines (the second line is long and wraps around to the second line. You may continue long lines on another line if you indent the wrapping lines. Portions enclosed by quotes must have a backslash '\' if you decide to wrap your alias lines): ## vhost1.com lists vhost1~majordomo: "|/usr/local/majordomo/wrapper majordomo \ -C /www/vhosts/vhost1/majordomo.cf" vhost1~majordomo-owner: vhost1~owner-majordomo vhost1~owner-majordomo: mylogin Notice left-side alias matches the right-side alias of the virtmaps we added earlier. The first line after the comment (which wraps with the '\' and continues with the B<-C> option) is the main B virtual host alias. When this alias receives an email message it sends the email message to the B program (B is actually called by B which sets special environment variables for B to run properly). The B<-C> option tells B to use an alternative configuration file named F which we finished editing in the first step. The next line ('majordomo-owner') is there for historical reasons and usually isn't necessary. The last line is the 'owner-majordomo' alias for this virtual host. You should replace I with the username or email address of the person you want to handle non-automated B responses and errors. This person is known as the "Majordomo owner" or "Majordomo administrator" and is responsible for setting up new lists for this virtual host and other administrative tasks. This person is currently B since you're setting up B. These three aliases are necessary for basic B administration for the entire virtual host (e.g., if you had multiple lists for this virtual host). =back Let's add the necessary lines for our new mailing list. There are five (5) aliases in total and three of the aliases wrap. ## vhost1.com: recipe list vhost1~recipe: "|/usr/local/majordomo/wrapper resend -l recipe \ -C /www/vhosts/vhost1/majordomo.cf vhost1~recipe-going-out, null" vhost1~recipe-going-out: :include:/www/vhosts/vhost1/Lists/recipe, "|/usr/local/majordomo/wrapper archive2.pl -a -m \ -f /www/vhosts/vhost1/Archive/recipe.archive" vhost1~recipe-request: "|/usr/local/majordomo/wrapper majordomo -l recipe \ -C /www/vhosts/vhost1/majordomo.cf" vhost1~recipe-owner: vhost1~owner-recipe vhost1~owner-recipe: mylogin For moderated lists you'll also need: vhost1~recipe-approval: moderator@somewhere.tld Notice that the left-side of these aliases match the right side of the virtual host alias mappings we did in step 2 for this mailing list. We'll explain in detail what each line is doing: =over 4 =item * Line 1: The first line after the comment is the main mailing list alias. Mail sent to this address will be sent to every member on the mailing list. Many people typically put a simple F<:include:/path/list> here which is fine for most purposes, until a spammer or other unwanted outsider uses your mailing list for free advertising. Depending on the options we specify, B allows us to clean up or strip out email headers before they're sent to the list, catch errors before they're posted to the list, make sure that only members of the list may post, and other useful things (see the man page for B). The B<-l> (ell) option tells the B program that we're sending mail using configuration options for the I mailing list. The B<-C> option for B is just like the B<-C> option for B: it tells B to use an alternative configuration file for its behavior. The next piece of this alias is the name of our I outgoing alias, in this case 'vhost1~recipe-going-out'. Resend uses this list to determine who to send mail to. The trailing ', null' at the end is a B trick that hides the name of our real outgoing alias list. The reason it's important to hide this outgoing alias is so that spammers (and list members) don't bypass our B wrapper and mail directly to the list alias. In order for 'null' to work you'll need to add another alias in your aliases file like this: null: /dev/null which will simply put the message in the system bit bucket (oblivion). =item * Line 2: The next line is our mailing list. The portion beginning with ':include:/...' is the actual path to the mailing list. The next portion after the comma beginning with "|/usr/local/majordomo..." is B's archive program. This program will receive a copy of the message sent to the mailing list and append the message to a file called F in our F directory we created earlier. The B<-a> option indicates to B to simply append the message to the archive and the B<-m> option causes B to create a monthly rotating archive. You may view the first 20 lines of of the B program for other options (B is located in F<~/usr/local/majordomo>). If you don't want to archive your mailing list, I would omit the portion that calls B and would have this line instead for your outgoing alias: vhost1~recipe-going-out: :include:/www/vhosts/vhost1/Lists/recipe =item * Line 3: This line ('vhost1~recipe-request') is a "convenience" alias. Sending mail to this alias has the same effect as sending mail to the main B alias with the recipe mailing list already specified. Most B commands (instructions you wish B to carry out for you) are sent in the body of the email message. For example, to subscribe to a mailing list, you would send an email message to 'majordomo@vhost1.com' with the following line in the body: subscribe recipe With the 'vhost1~recipe-request' alias users can simply send a message to 'recipe-request@vhost1.com' with the following line: subscribe and B will understand the request as if it were sent with the 'recipe' mailing list information included. =item * Line 4: This is an historic alias that is not required but some older 'netizens' may send mail to it. Many people leave this alias out. =item * Line 5: This is the owner of this particular mailing list. In our example, we again use I which should be replaced by the local username or email address of the person who will be administering this particular list. B separates the main B administrator from each list administrator. You may specify a separate person for this role if you like. This person will be in charge of list bounces and other list-specific duties such as approving subscribers (if needed) or receiving notification of list actions. =back These five lines will handle all the recipe mailing list posts and administrative actions. =head2 4. Create the mailing list The last thing we need to do before we can start sending recipes to our friends is to create the actual list and list configuration file (and a few other little files). Change directories to the F directory we created in our first step: server:~/etc $ cd ~/www/vhosts/vhost1/Lists and create the I and an I so people who may wish to subscribe can get some information about the list before actually subscribing: server:~/www/vhosts/vhost1/Lists $ touch recipe server:~/www/vhosts/vhost1/Lists $ cat > recipe.info This is the recipe mailing list for vhost1.com. If you have a favorite recipe you would like to share or request, subscribe to this group by sending an email to: recipe-request@vhost1.com with the word 'subscribe' in the BODY of the message. ^D server:~/www/vhosts/vhost1/Lists $ (That is, type in the mailing list information, then hit a control-D to signify end-of-file.) Now let's create a new file with your password in it. The password adds a little extra security so that only those who know the password may make administrative changes (as we're about to do): server:~/www/vhosts/vhost1/Lists $ cat > recipe.passwd SEKRIT_PASSWERD ^D server:~/www/vhosts/vhost1/Lists $ B is now ready to accept your commands via email. First we need to create the recipe configuration file. This configuration file is distinct from the F file we created earlier and contains specific information about this list such as approval passwords, who may post to the email list, and who may view information about the list and so on. To create a new configuration file when none exists, simply send an email message to 'recipe-request@vhost1.com' with the following B command in the body of the message (B ignores subject lines when processing commands): writeconfig SEKRIT_PASSWERD Notice that we could have sent an email message to 'majordomo@vhost1.com' with the following body: writeconfig recipe SEKRIT_PASSWERD and the effect would have been the same; remember that sending mail to 'recipe-request' is the same as sending mail to the 'majordomo' alias but with the B<-l recipe> command-line option enabled (review your aliases file if you still don't understand this convenience alias). In a short while, you'll receive an email message with a copy of the newly created configuration file for the recipe mailing list: -- >>>> writeconfig SEKRIT_PASSWERD wrote new config for list recipe >>>> -- END OF COMMANDS That's all you have to do to create a new configuration file. If a configuration file already exists, the 'writeconfig PASSWORD' command will do nothing unless you've upgraded versions of B, in which case it will add in new configuration options (if any) and leave your existing settings alone. Now let's edit our configuration file to suit our needs. There are two ways to edit B list configuration files: =over 4 =item * B/B to the server and edit F<~/www/vhosts/vhost1/Lists/recipe.config> =item * request a copy to be sent via email to us so we can edit it in our email client and send it back =back If you (as the B administrator who will handle the rare B errors) are also going to be the recipe mailing list administrator (who handles list bounces and other list confirmation actions), then you may simply edit this file by hand. However, if your are going to let someone else administer the list, you'll want to learn how to edit the list configuration file over email. Read on. First we need to ask B for a copy of our newly created configuration file so we can edit it. Send an email message to 'recipe-request@vhost1.com' with the following B command in the body: config SEKRIT_PASSWERD Shortly you'll receive as a reply a copy of the configuration file, which should look something like this: -- >>>> config SEKRIT_PASSWERD # The configuration file for a majordomo mailing list. # Comments start with the first # on a line, and continue to the end # of the line. There is no way to escape the # character. The file # uses either a key = value for simple (i.e. a single) values, or uses # a here document # key << END # value 1 # value 2 # [ more values 1 per line] # END # for installing multiple values in array types. Note that the here ... We're going to change some values in this message and send it back to B for processing. Go ahead and 'reply' to the message in your email program, making sure to include the text from the original message, but I include the indenting marks ('> ' is a popular indenting mark) in your reply. Then make these changes: =over 4 =item * This is the administrative password for the list; if someone else besides you (the B administrator) will be managing this list, this will be their password. This password may be used to change the list configuration file and any other kinds of list administration commands that require a password. Line 61: old config file: admin_passwd = recipe.admin --- new config file: admin_passwd = SEKRIT_ADMIN_PASSWERD =item * B allows you to have a third person as the list moderator, if you wish, separate from the B administrator and list administrator. This password is for the list moderator (if any). Line 87: old config file: approve_passwd = recipe.pass --- new config file: approve_passwd = SEKRIT_APPROVE_PASSWERD =item * I tells B who is allowed to access the archive index and other file indices. By changing this to 'list' we tell B that only members of the list may have access to the index. Line 183: old config file: index_access = open --- new config file: index_access = list =item * I tells B to strip out 'Received' headers from messages that list members post to the list. This gives an added degree of privacy for your list members, but may make troubleshooting difficult when there are problems. Line 277: old config file: purge_received = no --- new config file: purge_received = yes =item * I tells B to add this string to the front of all subject lines posted to the mailing list. This is a good feature for people who subscribe to many mailing lists to be able to readily see where the message is coming from. You may set this to whatever value you like, though B provides a couple of useful variables (e.g, $LIST, $SENDER, etc.) Line 325: old config file: subject_prefix = --- new config file: subject_prefix = [$LIST] =item * I tells B who may send a 'which' command. The 'which' command is described in the B man page. Line 380: old config file: which_access = open --- new config file: which_access = list =item * I tells B who may send a 'who' command. The 'who' command is described in the B man page. 388c388,390 old config file: who_access = open --- new config file: who_access = list =back Once you have made these changes, add the string 'EOF' at the bottom of the configuration file to tell B not to try to process your email signature as a B command. Remember to strip out any email indenting marks as B will not do that for you automatically (and will not be able to read your new configuration file). The top of your message should look like this (with no lines above the line beginning with 'newconfig'): newconfig recipe SEKRIT_PASSWERD # The configuration file for a majordomo mailing list. # Comments start with the first # on a line, and continue to the end Make sure there are no '>>>>>' or stray comments that your email client may have inserted automatically. Send the message to B. If all went well, you should receive an email reply shortly confirming that your changes were accepted: -- >>>> newconfig recipe SEKRIT_PASSWERD New config for list recipe accepted. If you do not receive this message but another message indicating why B did not accept your new configuration file, make the appropriate changes and resend your message. =head2 Now what? Now you can check everything out by subscribing yourself to your new recipe mailing list. Send an email to 'recipe-request@vhost1.com' and put 'subscribe' in the body of the message. In a few moments you'll receive a confirmation notice asking you to authenticate yourself (the authentication prevents people subscribing other people without their knowledge). Once you've authenticated, B will let you send and receive messages at 'recipe@vhost1.com'. After subscribing, your email address will be found in the file <~/www/vhosts/vhost1/Lists/recipe>. If you want to quietly add many people to your list, just add their names to this file. Otherwise, encourage all your friends to send an email message to 'recipe-request@vhost1.com' just as you have done and subscribe themselves to the 'recipe@vhost1.com' mailing list. =head1 SEE ALSO majordomo(1), resend(1), I (included with your B distribution), I document (ditto), I document (ditto, ditto). =head1 AUTHOR Scott Wiersdorf =head1 COPYRIGHT Copyright (c) 2001 Scott Wiersdorf. This document may not be duplicated in any form without prior written consent of the author or his employer. =cut