August 2013 - A boring and outdated list of steps I followed in to setup the smida.it server
In this HowTo I would like to collect all the series of operations I did to bring up the Smida.it server.
Here you can go through all the single commands and steps that I followed to have a fully functional server, from the domain and server purchase to the mail server set up.
Next: Users and accounts, Previous: Top, [Index]
Recently (August 2013, why always on August?), due to a bike accident, I broke my left wrist, so that I had to stay for a long period at home. As a software engineer, my efficiency drops drastically with only one hand, so that, with a cast on my left hand and the keyboard on my right hand, I decided to spend my time for doing some easy work, the kind of work that gets always postponed because there is never time to actually do it.
One of the work I always wanted to do was setting up a personal server with many services I may need for my personal life, store files, communicate with people, share ideas and experience. With this excuse I could also learn how to do better things that I never had (and probably I will never have) the opportunity to learn, like writing web code (HTML, CSS, PHP), administrating a server, managing a database.
The service I decided to use was offered by OVH.DE.
In past I had some bad experiences with virtual servers, due to slowness and bandwidth limitation, so that this time I preferred having a physical one. The hardware I chose is the so called KS 4G:
not a supercomputer, but enough for my needs.
As to start, from my new machine I wanted the following services:
Considering that I am very far from being a system administrator rather than a web developer, I wouldn't exclude that on all the steps I followed I could have made some mistakes, I'm open to receive from the possible reader of this howto advices for improvements.
Next: SSH server, Previous: Introduction, [Index]
After a couple of days I requested the server, I got an e-mail with a public IP (94.23.22.176) and a root password. Time to connect and start.
The first connection goes through ssh:
# ssh root@94.23.22.176
and as a first thing it's always good to change the predefined root password.
The root password should be secure enough to avoid brutal forcing. The following command is a way generate 16 characters random passwords which are a mixture of low and capital letters and numbers:
$ tr -dc A-Za-z0-9 < /dev/urandom | head -c 64 | xargs
I can now set the new generated password as a root password:
# passwd
A lower privileged user is a must to have on every Linux based system, so that let's create, for example, the user 'andi' in the group 'andi'.
Create first the group:
# groupadd andi
and then the user that belongs to the newly created group:
# useradd -d /home/andi -g andi -m -k /etc/skel/ -s /bin/bash andi
At the same way as we did with the root user, let's assign a random password to the user 'andi':
# passwd andi
Although 'andi' is a lower privileged user, it's always good to set an equally secure password, because, as we will see, 'andi' will be the first entry point to this server.
Next: DNS record, Previous: Users and accounts, [Index]
I consider ssh to be a very secure and reliable service, nevertheless, some peculiarities more, wouldn't harm.
Let's edit the ssh configuration file
# vim /etc/ssh/sshd_config
ssh is a protocol that moves on TCP/IP through the port 22. Moving the default port number to a non default one makes port scanning programs to not find immediately the service they are looking for. Let's set for example 76543 to be the default port:
Port 76543
Assuming that password brutal forcing can work, I prefer to deny the possibility to login as root user
PermitRootLogin no
I would also prefer only some specific users to be allowed to login via ssh, in my case only the user 'andi'
AllowUsers andi
Next: DNS records, Previous: SSH server, [Index]
Password login is always the weakest point for a secure connection. ssh gives the possibility to use keys instead. For doing this you need to generate and upload your key on the server.
In case you don't have one, with the following command you generate an ssh key
$ ssh-keygen
The new key will be stored under /home/<user>/.ssh/id_rsa. To upload the key on the server, copy the the public side of the key in the file .ssh/id_rsa.pub using scp.
$ scp ~/.ssh/id_rsa.pub andi@94.23.22.176:/home/andi
On the server side let's create the directory .ssh first in the home directory, since the server is new and doesn't have anything configured yet.
$ cd $ mkdir ~/.ssh
Applying the new key is a matter of copy paste on a file called authorized_keys under .ssh
$ cat id_rsa.pub > .ssh/authorized_keys
To upload other keys, for example to bee able to access from more than one PC, either I use the same key for all my PCs or I can enqueue on authorized_keys as many keys as my computers. Next time I would use '>>' instead of '>':
$ cat id_rsa-2.pub >> .ssh/authorized_keys
Then I delete the id_rsa.pub file from my home directory on the server:
$ rm id_rsa.pub
If all this sounds complicated or long, ssh provides a shortcut to all these laborious operations, just hit from your PC:
$ ssh-copy-id andi@94.23.22.176
and all what we did before will be automatically done.
At this point I can set ssh daemon to deny all the accesses through username and password and use only authentication via ssh key. On the sshd_config file I set:
PasswordAuthentication no
Let's restart ssh daemon:
# /etc/init.d/ssh restart
From now on, on every connection to the server should not ask anymore for the password, bu ssh should pull me directly on the server, while it will deny all the accesses to every kind of connection attempts on other computers and to all the users other than 'andi'.
If I get the following error while restarting ssh:
[....] Restarting OpenBSD Secure Shell server: sshdCould not load host key: /etc/ssh/ssh_host_ecdsa_key
it's because the latest versions of ssh expect also a key authentication from the sever side, apparently to avoid cases of DNS spoofing.
To mute this error, just create a key on the server side:
ssh-keygen -t ecdsa -b 521 -C "$(whoami)@$(hostname)-$(date -I)" -f /etc/ssh/ssh_host_ecdsa_key
Next: Git server, Previous: SSH server, [Index]
Smida.it is an old domain I bought time ago from aruba.it which was quite disappointing as a service. I decided to keep it and transfer it to ovh.
OVH.DE gives the possibility to modify the DNS entry related to your domain manually directly from the control manager in your personal page. If you, then, are familiar with BIND9 , the configuration file will look familiar and it will not be hard to configure.
Of course, please keep in mind, that the Bind9 configuration file we are going to personalize, is not on our server but on a different machine that works specifically as a DNS server (in ovh is dns200.anycast.me and ns200.anycast.me).
The file we are going to change on those servers is loaded somewhere by bind9 and in some named.conf files there should be an entry like this:
zone "smida.it" { type master; file "/etc/bind/db.smida.it"; };
where db.smida.it should indeed be our file. I guess that the inverted translation file is automatically generated by some tools.
First of all let's set the association between IP address and smida.it domain:
IN A 94.23.22.176
This tells to the DNS server that the IPv4 (A) address 94.23.22.176 has to be associated to the logical domain name of 'smida.it'.
Next: DNS record, Previous: Mail and MX record, [Index]
Let's list what exactly I want to have from my new server, and whitch subdomains I need:
I want all the addresses I listed to point to my smida.it machine. For doing this BIND9 gives the possibility to create aliases and I'm going to create an alias for each subdomain I want.
The alias section of the bind db file, will look something like:
andi IN CNAME smida.it. blog IN CNAME smida.it. git IN CNAME smida.it. lists IN CNAME smida.it. mail IN CNAME smida.it. webmail IN CNAME smida.it. www IN CNAME smida.it.
I intentionally omitted the mail services. Let's have a look to them in the following section.
Next: Git server, Previous: Subdomains, [Index]
The MX record is that record that a DNS server looks for when it has to translate the domain for e-mails. If we omit to set this record, our e-mails wouldn't be translated by any DNS and therefore rejected.
Here is how the MX record looks like in BIND9:
IN MX 10 imap.smida.it. imap IN A 94.23.22.176
The number '10' is a priority number in case we have more than one mail server, it's not my case, so that it doesn't really matter what its value is.
At the end I set the smtp subdomain as an alias of imap.
smtp IN CNAME imap.smida.it.
Before considering my DNS configuration file ready to go, I also want to set the SPF (Sender Policy Framework) record, so that my email won't be considered as spam by mail servers:
600 IN TXT "v=spf1 include:smida.it ~all"
And finally my DNS configuration file will look like:
$TTL 86400 @ IN SOA dns200.anycast.me. andi.smida.it. (2013082501 86400 3600 3600000 300) IN NS dns200.anycast.me. IN NS ns200.anycast.me. IN MX 10 imap.smida.it. IN A 94.23.22.176 imap IN A 94.23.22.176 600 IN TXT "v=spf1 include:smida.it ~all" andi IN CNAME smida.it. blog IN CNAME smida.it. git IN CNAME smida.it. lists IN CNAME smida.it. mail IN CNAME smida.it. smtp IN CNAME imap.smida.it. webmail IN CNAME smida.it. www IN CNAME smida.it.
For the other parameters, refer to the BIND 9 Administrator Reference Manual
Next: Web server: Apache, Previous: DNS record, [Index]
I am a big fan of git and I cosider it one of the most important features my server should have. Let's start by installing it.
# apt-get install git
As first I create a 'git' user and group. The new user has to handle all the git repositories and they have be shared within all the other users.
# groupadd git # useradd -d /home/git -g git -m -k /etc/skel/ -s /bin/bash git # passwd git
Let's assign a secure password to 'git' as we did for 'andi' and 'root':
$ tr -dc A-Za-z0-9 < /dev/urandom | head -c 64 | xargs
Since the git user is a kind of "shared user", I pretend other users belonging to the same group to be able to freely access and modify files and directories created by 'git'. For doing this I add in the git's .bashrc the following:
# vim ~git/.bashrc umask 002
So that every file created by 'git' will have permission '664' while directories '775'. In this way all the users in the group 'git' are able to modify git's files.
I add, then, 'andi' to the group 'git'
# usermod -a -G git andi
Now it's time to create a directory 'git' in '/' that will conatain all my repositories:
# cd / # mkdir git
This directory has to belong to 'git':
# chown git:git git
Now we can start populating our repositories:
# su git $ git clone --mirror git://git.etezian.org/ktest.git
The '--mirror' options generate a new repostory and adds all the git objects in it. Ktest is a software that I started long time ago for Linux Kernel testing but never had time to proceed any further.
It's now time to test our git server. Git is able to work over ssh and indeed this will be the tunnel that git will estabilish to clone the repository. As descriped previously , on the host machine which ssh public key I uploaded on the server and as user 'andi', I run:
$ git clone ssh://andi@smida.it:76543/git/ktest.git
In case I want to allow other users to be able to clone and push, I just need to add their ssh keys as described here and enable them in /etc/ssh/sshd_config:
$ cat id_rsa.pub >> ~git/.ssh/authorized_keys
Next: Web git, Previous: Git server, [Index]
Of course, I don't want to add on my ssh list everyone who wants to get my git repositories. For this, git has a server application that enables a git protocol that doesn't need any autentication in reading.
This application is called git-daemon and in order to start it, just hit:
# git daemon --base-path=/git/ --reuseaddr --user=git --group=git /git/
I want this sevice to start already at the PC boot, so that I need to enable it on the debian init system.
I will create an script that starts my daemon and put it in the Debian init directoriea. Debian gives ready in /etc/init.d a script skeleton for handling daemons, it needs just to be modified and adapted:
# cd /etc/init.d # cp skeleton git-daemon # vim git-daemon
This is what I got at the end:
#! /bin/sh set -e PATH=/sbin:/usr/sbin:/bin:/usr/bin DESC="a really simple server for Git repositories" NAME=git-daemon PIDFILE=/var/run/git.pid DAEMON=/usr/bin/git DAEMON_ARGS="daemon --base-path=/git/ --reuseaddr --pid-file=$PIDFILE --user=git --group=git /git/" SCRIPTNAME=/etc/init.d/git-daemon [ -x "$DAEMON" ] || exit 0 . /lib/init/vars.sh . /lib/lsb/init-functions do_start() { start-stop-daemon --start -b --quiet --pidfile $PIDFILE --exec $DAEMON --test >gt; /dev/null \ || return 1 start-stop-daemon --start -b --quiet --pidfile $PIDFILE --exec $DAEMON -- \ $DAEMON_ARGS \ || return 2 } do_stop() { start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME RETVAL="$?" [ "$RETVAL" = 2 ] && return 2 start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON [ "$?" = 2 ] && return 2 rm -f $PIDFILE return "$RETVAL" } case "$1" in start) [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME" do_start case "$?" in 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; esac ;; stop) [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME" do_stop case "$?" in 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; esac ;; status) status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $? ;; restart) log_daemon_msg "Restarting $DESC" "$NAME" do_stop case "$?" in 0|1) do_start case "$?" in 0) log_end_msg 0 ;; 1) log_end_msg 1 ;; # Old process is still running *) log_end_msg 1 ;; # Failed to start esac ;; *) log_end_msg 1 ;; esac ;; *) echo "Usage: $SCRIPTNAME {start|stop|status|restart}" >&2 exit 3 ;; esac
Let's give to the new file executable permissions:
# chmod a+x git-daemon
I also need it to execute the script during boot everytime I have to restart the server:
# cd /etc/rc2.d # ln -s ../init.d/git-daemon S06git-daemon # cd /etc/rc3.d # ln -s ../init.d/git-daemon S06git-daemon # cd /etc/rc4.d # ln -s ../init.d/git-daemon S06git-daemon # cd /etc/rc5.d # ln -s ../init.d/git-daemon S06git-daemon
In order to keep things clean, at the same way I would like to stop the script correctly when shutting down the server:
# cd /etc/rc0.d # ln -s ../init.d/git-daemon K01git-daemon # cd /etc/rc6.d # ln -s ../init.d/git-daemon K01git-daemon
How I set the script, git daemon exposes all the repositories under the '/git' directory, but first it checks on each of them for the existence of an empty file called 'git-daemon-export-ok', so that I need to create it on the repositories I want to expose:
# su git $ cd /git/ktest.git $ touch git-daemon-export-ok
Now I'm ready to start the server:
# /etc/init.d/git-daemon start
Let's make a test on a PC and, if everything is done properly, it should work
$ git clone git://git.smida.it/ktest.git
Next: Web server: Apache, Previous: Git daemon, [Index]
I could now think to install a web front end for for my repositories and in the git book I found some good tips. I decided anyway to not follow any of those advices but to take as example the Linux Kernel way and using cgit . But for doing this I first need to set up a web server which we will se in the next chapter.
Chapter 7 of this howto goes through the cgit configuration.
Next: Web git, Previous: Git server, [Index]
Apache HTTP server will give me the opportunity to publish my personal web pages (the ones you are reading) and my blog. Let's start by installing it:
# apt-get install apache2 # apt-get install libapache2-mod-php5
PHP will be useful for the blog.
I create a new configuration file for smida.it:
# vim /etc/apache2/sites-available/smida.it
<VirtualHost *:80> ServerAdmin andi@smida.it ServerName git.smida.it DirectoryIndex cgit.cgi Alias /cgit.png /var/www/cgit/cgit.png Alias /cgit.css /var/www/cgit/cgit.css Alias /cgit/ /var/www/cgit/cgit.cgi/ DocumentRoot /var/www/cgit/ <Directory /> AllowOverride None Options FollowSymlinks ExecCGI Order allow,deny Allow from all <Files cgit.cgi> SetHandler cgi-script </Files> </Directory> ErrorLog ${APACHE_LOG_DIR}/error.log # Possible values include: debug, info, notice, warn, error, crit, # alert, emerg. LogLevel warn CustomLog ${APACHE_LOG_DIR}/access.log combined </VirtualHost>
I enable the new site:
# a2ensite smida.it
and populate the directory /var/www/smida.it with the xhtml files. Then I can restart apache
# /etc/init.d/apache2 restart
That's it!
Next: Smida.it on git, Previous: Web server: Apache, [Index]
Userdir is an Apache mode that allows to access to the files in ~/public_html via web, following the link http://<site_url>/~<user_name>.
I want to have this feature for the user 'andi', so that first I login as 'andi' and I create the directory 'public_html':
$ mkdir ~/public_html
As 'root' I enable the new apache mode:
# a2enmod userdir
and restart Apache:
# /etc/init.d/apache2 restart
Now by writing in my browser
http://www.smida.it/~andi
I will see in a file system structure the content of the directory ~/public_html.
On Apache I can set a redirect to the public_html if someone tries to access through http://andi.smida.it.
I creat and edit the Apache file 'andi.smida.it':
# vim /etc/apache2/sites-available/andi.smida.it
<VirtualHost *:80> ServerAdmin andi@smida.it ServerName andi.smida.it DocumentRoot /home/andi/public_html Redirect / http://www.smida.it/~andi </VirtualHost>
enable it:
# a2ensite andi.smida.it
and restart Apache:
# /etc/init.d/apache2 restart
Next: Web git: cgit, Previous: Userdir, [Index]
As I said earlier, I am a big fan of git, therefore I would also like to maintain my web pages with git.
Log in first as 'git' user:
# su git
and create the repository directory:
$ cd /git $ mkdir smida.it.git
In the end initalize a bare git repository:
$ cd smida.it.git $ git --bare init
On the host side I go on the directory that contains all the web files:
$ cd /.../smida.it
and initialize a new git repository:
$ git init
I add the remote corresponding to the smida server:
$ git remote add origin ssh://andi@smida.it:76543/git/smida.it.git $ git fetch origin
and I make the first commit:
$ git add . $ git commit -s $ git push origin master
If you are not familiar with git, I suggest to fix this as soon as possible, starting reading the Git book .
I have now all the contents of my web pages on the git server, I need, now, to update them on /var/www/smida.it. First I clone the repository locally on the server, for example in the /root directory:
$ su # cd # git clone /git/smida.it
I update, then what is on /var/www/smida.it:
# cd .. # rsync -av smida.it/ /var/www/smida.it/ --exclude=.git*
Everytime that I push something new to smida.it from my personal PC, I have to update the web content more or less as follows:
# cd /root/smida.it # git pull # cd .. # rsync -av smida.it/ /var/www/smida.it/ --exclude=.git*
Next: Mail server, Previous: Web server: Apache, [Index]
For this section of the howto, Max's post on his blog was useful.
There are many web interfaces for git, but the one I like more is cgit . Cgit is developed in C, has the most modern UI and is the one used by the Kernel community . Today (August 2013) the latest version is 0.9.2.
For compiling and installing cgit, we need some preliminary packages:
# apt-get install gcc make libssl-dev curl
Purists administrators can say that a server shouldn't have building capabilities because it's just a server and should work only as such; but in principle is my personal server and I'm not a purist :)
I get the latest version:
$ wget http://git.zx2c4.com/cgit/snapshot/cgit-0.9.2.tar.xz
I untar it:
$ tar -xf cgit-0.9.2.tar.xz
build it:
$ cd cgit-0.9.2 $ make
and, as root user, install it:
# make install
By default the web part of cgit is installed under /var/www/htdocs/cgit, there's nothing wrong on that, but I want it to be under /var/www/cgit:
# mv /var/www/htdocs/cgit /var/www/ # rmdir /var/www/htdocs/
Now let's tell Apache about the new web pages by creating a new apache configuration file:
# vim /etc/apache2/sites-available/git.smida.it
<VirtualHost *:80> ServerAdmin andi@smida.it ServerName git.smida.it DirectoryIndex cgit.cgi Alias /cgit.png /var/www/cgit/cgit.png Alias /cgit.css /var/www/cgit/cgit.css Alias /cgit/ /var/www/cgit/cgit.cgi/ DocumentRoot /var/www/cgit/ <Directory /> AllowOverride None Options FollowSymlinks ExecCGI Order allow,deny Allow from all <Files cgit.cgi> SetHandler cgi-script </Files> </Directory> ErrorLog ${APACHE_LOG_DIR}/error.log # Possible values include: debug, info, notice, warn, error, crit, # alert, emerg. LogLevel warn CustomLog ${APACHE_LOG_DIR}/access.log combined </VirtualHost>
Save, enable and then, as usual, let's restart Apache:
# a2ensite git.smida.it # /etc/init.d/apache2 restart
Now my git web page is ready and reachable by typing on a browser: http://git.smida.it. In a first place you wouldn't see anything, just a blank page with some junk on it because we haven't still personalized cgit.
Cgit has a configuration file that allows to customize the frontend and the behavior, mine looks like this:
# vim /etc/cgitrc
# Enable caching of up to 1000 output entriess cache-size=1000 # Specify some default clone prefixes clone-prefix=git://git.smida.it # Specify the css url css=/cgit.css # Specify the logo url logo=/cgit.png favicon=/cgit.png # Show extra links for each repository on the index page enable-index-links=1 # Show number of affected files per commit on the log pages enable-log-filecount=1 # Show number of added/removed lines per commit on the log pages enable-log-linecount=1 # Set the title and heading of the repository index page root-title=Smida.it git repositories root-desc=All repositories # Allow download of tar.gz, tar.bz2 and zip-files snapshots=tar.gz source-filter=/usr/lib/cgit/filters/syntax-highlighting.sh remove-suffix=1 ## ## List of common mimetypes ## mimetype.git=image/git mimetype.html=text/html mimetype.jpg=image/jpeg mimetype.jpeg=image/jpeg mimetype.pdf=application/pdf mimetype.png=image/png mimetype.svg=image/svg+xml
At the bottom of the gitrc file, we can list our git repositories we want to expose to the world, in my case I want to expose my awful ktest, so that I add:
# List of repositories repo.url=ktest.git repo.path=/git/ktest.git repo.desc=Kernel testing suite repo.owner=Andi Shyti
Next: Mail server, Previous: Web git: cgit, [Index]
Periodically search engines unleash their bots (or robots) to index all the web pages. What they do is to poll every single web page and go though all the possible links. There's nothing wrong with that because we all want our websites to be reached by search engines. But git pages, usually, don't contain something that people may search and mostly the web pages may get huge and full of links where every link means a git operation (if for example it goes through the git history). Moreover robots work in multithreading, so that they start multi instances of indexing on our web git pages.
It's good, then, to politely ask to robots to avoid indexing our git pages. Indeed bots before starting their job on a specific website they look for a file called robots.txt where the owner of the website expresses his will to index or not portions of his pages. In my case I don't want any of my git web pages to be indexed. So that I create the file robots.txt:
# vim /var/www/cgit/robots.txt
The syntax is fairly simple and you can choose whitch parts of your website you don't want to be indexed:
User-agent: * Disallow: /
In my case I disallow robots to scan starting from the root directory, which is git.smida.it.
Next: Web mail, Previous: Web git: cgit, [Index]
Workaround.org from Cristoph Haas is very useful to me setting up a persona mail server and I followed his instructions almost step by step. For more accurate explanations please refer to it.
Essentially we need for four components for building up a working mail client: DNS, postfix, mysql and dovecot.
The DNS MX record will forward all the mails to my machine. But we did already the DNS registration so that we don't need to care anymore.
Pstfix plays different roles in the mail gaming. First establishes smtp connections with the clients, reads the e-mail to understand the content and evaluate if the mail is spam or a valid mail and then makes a connection with MySQL to see if the mail domain belongs to that server and if the 'To:' address is recognized as well. At the end, delivers the mail to dovecot.
Dovecot takes over the mails from postfix and stores them somewhere in the file system. It's also able to set an imap(s) or pop3(s) connection for clients who want to download the e-mails locally on their machines.
Next: Postfix, Previous: Mail server, [Index]
MySQL will be the pool where I will store all the informations regarding the mail server. Indeed I'm going to store in a database mail accounts, domains and aliases.
Let's start by installing MySQL:
# apt-get install mysql-server
During the installation it will ask for the MySQL root password (which is not the system root password) and, as we are used, let's insert a random generated password:
$ tr -dc A-Za-z0-9 < /dev/urandom | head -c 32 | xargs
MySQL now is installed and ready to use. I create the database "mailserver":
# mysqladmin -p create mailserver
Now I can login and start working directly on the database:
# mysql -p -u root mailserver
As in all the systems, I create a less privileged user called "mailuser" which will have only selection power on each table of the database:
mysql> grant select on mailserver.* -> to 'mailuser'@'127.0.0.1' -> identified by 'veKI8vDcd4ebIhNwz5FrJvKxqW67L0Sx'; Query OK, 0 rows affected (0.00 sec)
With "identified by 'password'"
I specify
the password of the 'mailuser' user, if you are following these
instructions, care to place your own password, of course the one
I wrote is not the one I set on my server.
Now I start creating the tables. On the 'virtual_domains' table I will keep informations about the domains supported by my mail server:
mysql> create table `virtual_domains` ( -> `id` int(11) not null auto_increment, -> `name` varchar(50) not null, -> primary key (`id`) -> ) engine=InnoDB default charset=utf8; Query OK, 0 rows affected (0.07 sec)
On 'virtual_users' I store the informations about the mail accounts for each domain:
mysql> create table `virtual_users` ( -> `id` int(11) not null auto_increment, -> `domain_id` int(11) not null, -> `password` varchar(100) not null, -> `email` varchar(100) not null, -> primary key (`id`), -> unique key `email` (`email`), -> foreign key (domain_id) references virtual_domains(id) on delete cascade -> ) engine=InnoDB default charset=utf8; Query OK, 0 rows affected (0.08 sec)
And at the end I want each user to have the possibility to have more than one alias (this step is not necessary):
mysql> create table `virtual_aliases` ( -> `id` int(11) not null auto_increment, -> `domain_id` int(11) not null, -> `source` varchar(100) not null, -> `destination` varchar(100) not null, -> primary key (`id`), -> foreign key (domain_id) references virtual_domains(id) on delete cascade -> ) engine=InnoDB default charset=utf8; Query OK, 0 rows affected (0.08 sec)
The database is set now let's start insterting the data we need.
In the virtual domains I insert the domain 'smida.it':
mysql> insert into `mailserver`.`virtual_domains` ( -> `id`, -> `name` -> ) values ( -> '1', 'smida.it' -> ); Query OK, 1 row affected (0.02 sec)
id | name |
---|---|
1 | smida.it |
The first mail address inserted will be the mine in the table virtual_users:
mysql> insert into `mailserver`.`virtual_users` ( -> `id`, -> `domain_id`, -> `password`, -> `email` -> ) values ( -> '1', '1', -> '{SSHA256}...', -> 'andi@smida.it' -> ); Query OK, 1 row affected (0.02 sec)
id | domain id | password | |
---|---|---|---|
1 | 1 | {SSHA256}... | andi@smida.it |
I decided to ecrypt passwords in SHA256, it's always better to not store plain passwords. At the end I create an alias for my account which will be of the type name.surname@smida.it.
mysql> insert into `mailserver`.`virtual_aliases` ( -> `id`, -> `domain_id`, -> `source`, -> `destination` -> ) values ( -> '1', '1', 'andi.shyti@smida.it', 'andi@smida.it' -> ); Query OK, 1 row affected (0.03 sec)
id | domain_id | source | destination |
---|---|---|---|
1 | 1 | andi.shyti@smida.it | andi@smida.it |
My database now is all set and ready to be connected to postfix.
mysql> quit Bye
Next: Dovecot, Previous: MySQL setup, [Index]
Postfix receives incoming e-mails through smtp and performs a first check on them.
Let's start installing it first:
# apt-get install postfix postfix-mysql
During the postfix installation it will ask about the mail server configuration type and I choose Internet site and then it will ask to enter the domain, I type smida.it.
During the mail server setup, through each step we have to add bits and pieces to the postfix configuration, for now we will see just how to make postfix to interact with mysql and the tables we already created .
Let's start making postfix to know which are the domains stored in the database. We do that by creating a file which will keep all the instructions for selecting a specific domain:
# vim /etc/postfix/mysql-virtual-mailbox-domains.cf
user = mailuser password = veKI8vDcd4ebIhNwz5FrJvKxqW67L0Sx hosts = 127.0.0.1 dbname = mailserver query = select 1 from virtual_domains where name='%s'
As you can see in this file we provide instructions on how to connect to the database: username, host, password (of course is the fake password I generated in the previous chapter) and database name. We also provide the query string that postfix has to execute when looking for a domain.
Now we need to tell postfix that everytime it has to look for a specific domain it has to refer to the file just created:
# postconf -e virtual_mailbox_domains=mysql:/etc/postfix/mysql-virtual-mailbox-domains.cf
We could try a first preliminary test to see if the connection works and the query is performed:
# postmap -q smida.it mysql:/etc/postfix/mysql-virtual-mailbox-domains.cf 1
If the result is 1 it means that we didn't do any mistake.
At the same way we create a configuration file for the mail accounts:
# vim /etc/postfix/mysql-virtual-mailbox-maps.cf
user = mailuser password = veKI8vDcd4ebIhNwz5FrJvKxqW67L0Sx hosts = 127.0.0.1 dbname = mailserver query = select 1 from virtual_users where email='%s'
I inform postfix about the file:
# postconf -e virtual_mailbox_maps=mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf
And I test it:
# postmap -q andi@smida.it mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf 1
As before, if I get 1, it means that the connection works.
And, finally, I do the exact same operations for the aliases:
# vim /etc/postfix/mysql-virtual-alias-maps.cf
user = mailuser password = veKI8vDcd4ebIhNwz5FrJvKxqW67L0Sx hosts = 127.0.0.1 dbname = mailserver query = select destination from virtual_aliases where source='%s'
# postconf -e virtual_alias_maps=mysql:/etc/postfix/mysql-virtual-alias-maps.cf
A final test:
# postmap -q andi.shyti@smida.it mysql:/etc/postfix/mysql-virtual-alias-maps.cf andi@smida.it
In this last case I expect to get the destination for the specific source.
Next: SSL, Previous: Postfix, [Index]
Dovecot will take care of handing over from postfix all the received mails and store them somewhere in the file system. Moreover, dovecot is able to set smtp(s) or pop3(s) connections to allow users to download the mails locally on their PC through their favourite mail client.
We need first to create the user that dovecot will use to store the mails. In my case I want the mails to be stored in the path:
/var/vmail/<domain>/<user>/
all the mails will be saved in maildir format. Let's create now the user and the group vmail:
# groupadd -g 5000 vmail # useradd -g vmail -u 5000 -d /var/vmail -m vmail
Let's edit and configure dovecot:
# vim /etc/dovecot/dovecot.conf
This an example on how dovecot.conf should look like:
auth_mechanisms = plain login log_timestamp = "%Y-%m-%d %H:%M:%S " mail_location = maildir:/var/vmail/%d/%n/Maildir:LAYOUT=fs mail_privileged_group = mail passdb { args = /etc/dovecot/dovecot-sql.conf.ext driver = sql } protocols = imap service auth { unix_listener /var/spool/postfix/private/auth { group = postfix mode = 0660 user = postfix } unix_listener auth-master { mode = 0600 user = vmail } user = root } service imap-login { inet_listener imap { port = 0 } } ssl_cert = </etc/ssl/certs/dovecot.pem ssl_key = </etc/ssl/private/dovecot.pem userdb { driver = passwd } userdb { args = uid=5000 gid=5000 home=/var/vmail/%d/%n allow_all_users=yes driver = static } verbose_ssl = yes protocol pop3 { pop3_uidl_format = %08Xu%08Xv } protocol lda { auth_socket_path = /var/run/dovecot/auth-master log_path = mail_plugins = sieve postmaster_address = andi@smida.it }
This configuration file enables only imaps connections, indeed it uses the public certificate /etc/ssl/certs/dovecot.pem and the private key in /etc/ssl/private/dovecot.pem. For more detailed explanations of the parameters refer to workaround.org. Keep in mind that there are some differences because dovecot I'm using is version 2.1.7 while on workaround.org is used an older version and they are quite different.
Dovecot connects to mysql to fetch the user informations and the passwords since it's going to estabilish smtp connections. The database details are stored in the file /etc/dovecot/dovecot-sql.conf.ext:
# vim /etc/dovecot/dovecot-sql.conf.ext
driver = mysql connect = host=127.0.0.1 dbname=mailserver user=mailuser password=veKI8vDcd4ebIhNwz5FrJvKxqW67L0Sx default_pass_scheme = SSHA256 password_query = select email as user,password from virtual_users where email = '%u'
I specify as encryption method SSHA256, the same as the one used during the database insertion. Remember to put your own password, the one written is the fake password I generated before. It's better to make this file unaccessible to other users:
# chown root:root /etc/dovecot/dovecot-sql.conf.ext # chmod go= /etc/dovecot/dovecot-sql.conf.ext
While we need the user vmail to be able to read from the dovecot.conf since postfix delivers through the user vmail:
# chgrp vmail /etc/dovecot/dovecot.conf # chmod g+r /etc/dovecot/dovecot.conf
Now we need to tell postfix to use dovecot as delivery agent in his master configuration file:
# vim /etc/postfix/master.cf
We need to add the following two lines, the indentation must be done only with spaces:
dovecot unix - n n - - pipe flags=DRhu user=vmail:vmail argv=/usr/lib/dovecot/deliver -f ${sender} -d ${recipient}
At the end we tell postfix to use dovecot for the virtual delivery:
# postconf -e virtual_transport=dovecot # postconf -e dovecot_destination_recipient_limit=1
Now we can reload the postfix configuration:
# postfix reload
Next: SMTP restriction, Previous: Dovecot, [Index]
The use of the SSL protocol will allow us to have encrypted connection with the smida mail server from both the sides, smtp and imap. SSL is based on a public certificate and a private key which are stored in files, usually under /etc/ssl/certs/ are the public certificates and under /etc/ssl/private/ are the private keys.
I create first the certificates for dovecot therefore for the imap protocol
# openssl req -new -x509 -days 3650 -nodes -out /etc/ssl/certs/dovecot.pem -keyout /etc/ssl/private/dovecot.pem
Users belonging to the 'others' type shouldn't be able to read the private key:
# chmod o= /etc/ssl/private/dovecot.pem
I restart dovecot in order to load the two keys:
# /etc/init.d/dovecot restart
I do the same for postfix and the smtp protocol; first I generate the certificates:
# openssl req -new -x509 -days 3650 -nodes -out /etc/ssl/certs/postfix.pem -keyout /etc/ssl/private/postfix.pem
I limit the access to the private key:
# chmod o= /etc/ssl/private/postfix.pem
At the end I enable them in postfix:
# postconf -e smtpd_tls_cert_file=/etc/ssl/certs/postfix.pem # postconf -e smtpd_tls_key_file=/etc/ssl/private/postfix.pem
For enabling the authenticated smtp in posftix I need some more configuration:
# postconf -e smtpd_sasl_type=dovecot # postconf -e smtpd_sasl_path=private/auth # postconf -e smtpd_sasl_auth_enable=yes # postconf -e smtpd_recipient_restrictions="permit_mynetworks \ permit_sasl_authenticated \ reject_unauth_destination \ reject_unknown_client_hostname \ reject_unknown_sender_domain \ reject_unauth_pipelining"
in this case postfix will not reject mails coming from the smida network and that are authenticated through SASL, while will reject all the unauthenticated connections, unkown hostnames, unknown senders and mails sent ahead in the time.
Reload postfix:
# postfix reload
Now finally I should be able to send and receive mails using my new smida.it server.
Next: Accman, Previous: SSL, [Index]
One of the most annoying thing to deal with mails is spam, so that having in place a minimum of anti-spam security may benefit our mail system.
Next: HELO restriction, Previous: SMTP restriction, [Index]
The blacklisting is done based on the IP address of the sender.
Fortunately there are some websites that keep track of IPs that
use to send spam. To use those services I need to inform postfix
where to check for the incoming e-mail, so that I add the
following url:
bl.spamcop.net zen.spamhaus.org dnsbl-1.uceprotect.net to the
smtpd_recipient_restrictions
variable in main.cf:
# vim /etc/postfix/main.cf
smtpd_recipient_restrictions = permit_mynetworks permit_sasl_authenticated reject_unknown_client_hostname reject_unknown_sender_domain reject_unauth_pipelining reject_rbl_client bl.spamcop.net reject_rbl_client zen.spamhaus.org reject_rbl_client dnsbl-1.uceprotect.net reject_unauth_destination
Reload postfix:
# postfix reload
Next: Grey list, Previous: Black list, [Index]
When a client connects to a mail server, the first command sent
is a HELO greeting followed by the hostname. Postfix has a
special variable smtpd_helo_restrictions
to
perform a further restriction. Let's set this variable in
main.cf:
# vim /etc/postfix/main.cf
smtpd_helo_restrictions = reject_invalid_helo_hostname, reject_non_fqdn_helo_hostname, reject_unknown_helo_hostname
In this case we will reject hosts that are using as HELO hostname invalid or unknown hostnames or not fully qualified domain names.
Then let's reload again postfix:
# postfix reload
Next: Accman, Previous: HELO restriction, [Index]
The greylisting mechanism doesn't make any mail filtering, i.e. is not allowed to reject mails rather than delaying the mail reception. Infact it rejects in a first place the mail taking advantage of the fact that mail servers have an outgoing queue and in case of error they retry to send the mail again. The second attempt is not rejected.
First I install tumgreyspf which is the program that performs the greylisting:
# apt-get install tumgreyspf
And then I add to the postfix
smtpd_recipient_restrictions
variable the tumgrey
policy:
smtpd_recipient_restrictions = permit_mynetworks permit_sasl_authenticated reject_unknown_client_hostname reject_unknown_sender_domain reject_unauth_pipelining reject_rbl_client bl.spamcop.net reject_rbl_client zen.spamhaus.org reject_rbl_client dnsbl-1.uceprotect.net check_policy_service unix:private/tumgreyspf reject_unauth_destination
And reload postfix:
# postfix reload
Next: Web mail, Previous: SMTP restriction, [Index]
Accman (ACCountMANager) is a little stupid program that I wrote to help me to insert other users in the virtual_users database. It's very far from being complete, but it's handy and doesn't ask to other possible users to connect to the database.
For building accman I need to install the mysql client libraries:
# apt-get install libmysqlclient-dev
Then it's better to create a user which will have only insertion rights on the virtual_users table:
# mysql -p mailserver mysql> grant insert on mailserver.virtual_users -> to 'officer'@'127.0.0.1' -> identified by 'veKI8vDcd4ebIhNwz5FrJvKxqW67L0Sx'; Query OK, 0 rows affected (0.00 sec)
We can get accman directly from git:
$ git clone git://git.etezian.org/accman.it
As I said, the program is far from being complete and it needs some customization directly in the code:
I need to set my domain:
$ vim include/accman.h - #define DOMAIN "etezian.org" + #define DOMAIN "smida.it"
and my mysql credentials:
$ vim src/db_user.c - if (!mysql_real_connect(conn, "localhost", "user", "password", + if (!mysql_real_connect(conn, "127.0.0.1", "officer", "veKI8vDcd4ebIhNwz5FrJvKxqW67L0Sx",
now I can build it and install it:
$ make # make install
The usage is fairly simple, just hit accman and it starts. Let's assume we want to create the user donald.duck@smida.it:
$ accman Insert user name (user@smida.it): donald.duck Password: Re-type password: Do you want to insert new user 'donald.duck@smida.it'? [Y/n] User donald.duck@smida.it inserted correctly
when accman asks for the user care to not insert the full e-mail, but just the name without the domain.
Next: Mailing lists, Previous: SMTP restriction, [Index]
For this part of the tutorial I've been helped by Chris post Roundcube for your Debian Squeeze Mail Server on his blog
Could be useful to also have a webmail application to be able to read the mails when I don't have my mail client under my hands. There are two webmail frontends, SquirrelMail and Roundcube. The first is one of the most used, a bit old fashion, though, while Roundcube has a bit more modern interface and a few features more.
Let's start installing it:
# apt-get install roundcube roundcube-mysql
I configure Apache for the new website:
# vim /etc/apache2/sites-available/mail.smida.it
<VirtualHost *:80> ServerAdmin andi@smida.it ServerName mail.smida.it ServerAlias mail.* webmail.* DocumentRoot /var/lib/roundcube Alias /program/js/tiny_mce/ /usr/share/tinymce/www/ <Directory /var/lib/roundcube/> Options +FollowSymLinks AllowOverride All Order allow,deny Allow from all </Directory> <Directory /var/lib/roundcube/config> Options -FollowSymLinks AllowOverride None </Directory> <Directory /var/lib/roundcube/temp> Options -FollowSymLinks AllowOverride None Order allow,deny Deny from all </Directory> <Directory /var/lib/roundcube/logs> Options -FollowSymLinks AllowOverride None Order allow,deny Deny from all </Directory> <Directory /usr/share/tinymce/www/> Options Indexes MultiViews FollowSymLinks AllowOverride None Order allow,deny Allow from all </Directory> </VirtualHost>
I enable the website:
# a2ensite mail.smida.it
And I restart Apache:
# /etc/init.d/apache2 restart
To make roundcube working I need also to make some customisations to the roundcube configuration file. It's written in PHP and dynamically loaded to the web pages, so that I don't need to restart any services for reloading my changes:
# vim /etc/roundcube/main.inc.php
These are the lines I changed for my webmail pages:
$rcmail_config['default_host'] = 'ssl://localhost'; $rcmail_config['default_port'] = 993; $rcmail_config['smtp_server'] = 'localhost'; $rcmail_config['smtp_user'] = '%u'; $rcmail_config['smtp_pass'] = '%p'; $rcmail_config['create_default_folders'] = TRUE; $rcmail_config['product_name'] = 'Smida.it';
As suggested in Chris's blog, I also change the label in the mainpage to be "Email" instead of "username", since the user logs in using his e-mail and not username:
# vim /usr/share/roundcube/program/localization/en_US/labels.inc
$labels['username'] = 'Email';
I can also modify the logo by replacing the existing one in /usr/share/roundcube/skins/default/images/roundcube_logo.png, the image has to be 178x47px.
Next: Mailing lists, Previous: Web mail, [Index]
Would be better to encrypt the HTTP session for my web mail reading. Therefore I would like Apache to establish a secure http connection with the browsers. Apache supports https protocol over the port 443 by using certificates as we did for the mail server. As well we need to create a public and a private key:
# openssl req -new -x509 -days 365 -nodes -out /etc/ssl/certs/apache.pem -keyout /etc/ssl/private/apache.key
Now we tell apache to connect through https for the domain mail.smida.it and use the certificates I created:
# vim /etc/apache2/sites-available/mail.smida.it
I replace the default 80 port:
<VirtualHost *:443> ... </VirtualHost>
and I ask to enable SSL providing the path to the certificates:
<VirtualHost *:443> SSLEngine On SSLCertificateFile /etc/ssl/certs/apache.pem SSLCertificateKeyFile /etc/ssl/private/apache.key ... </VirtualHost>
The problem now is that apache will not respond anymore to the port 80 for mail.smida.it and it will open one of the domains I registered (blog or www). Moreover everytime I want to connect to my mail web page, I would always need to write manually 'https://' which on the long term could be annoying.
One way how to fix this is to tell apache to redirect all the
connections to mail.smida.it through https 443 port. I do this
by adding on the top of the file sites-available/mail.smida.it a
VirtualHost
section which will just respond to
the http requests and will direct those to https://mail.smida.it:
<VirtualHost *:80> ServerAdmin andi@smida.it ServerName mail.smida.it ServerAlias mail.* webmail.* DocumentRoot /var/lib/roundcube Redirect permanent / https://mail.smida.it </VirtualHost> <VirtualHost *:443> ... </VirtualHost>
I restart Apache and my webmail pages are ready to be used:
# /etc/init.d/apache2 restart
Next: Bottom, Previous: Web mail, [Index]
The web page here was my reference for this section.
Perhaps having a mailing list on an own server is a bit of asking to much to a private server, but it could be fun to share it as a social network with friends, family or for private projects. The mailing list engine I chose is Mailman.
I install mailman first:
# apt-get install mailman
And I create a configuration file in Apache to respond to the domain lists.smida.it. Mailman provides already an apache configuration, I just need to copy it to the sites-available directory and personalize it:
# cp /etc/mailman/apache.conf /etc/apache2/sites-available/mailman.conf # vim /etc/apache2/sites-available/mailman.conf
<Directory /usr/lib/cgi-bin/mailman/> AllowOverride None Options ExecCGI AddHandler cgi-script .cgi Order allow,deny Allow from all </Directory> <Directory /var/lib/mailman/archives/public/> Options FollowSymlinks AllowOverride None Order allow,deny Allow from all </Directory> <Directory /usr/share/images/mailman/> AllowOverride None Order allow,deny Allow from all </Directory> <VirtualHost *:80> ServerName lists.smida.it DocumentRoot /var/www/lists ErrorLog /var/log/apache2/lists-error.log CustomLog /var/log/apache2/lists-access.log combined <Directory /var/lib/mailman/archives/> Options FollowSymLinks AllowOverride None </Directory> Alias /pipermail/ /var/lib/mailman/archives/public/ Alias /images/mailman/ /usr/share/images/mailman/ ScriptAlias /admin /usr/lib/cgi-bin/mailman/admin ScriptAlias /admindb /usr/lib/cgi-bin/mailman/admindb ScriptAlias /confirm /usr/lib/cgi-bin/mailman/confirm ScriptAlias /create /usr/lib/cgi-bin/mailman/create ScriptAlias /edithtml /usr/lib/cgi-bin/mailman/edithtml ScriptAlias /listinfo /usr/lib/cgi-bin/mailman/listinfo ScriptAlias /options /usr/lib/cgi-bin/mailman/options ScriptAlias /private /usr/lib/cgi-bin/mailman/private ScriptAlias /rmlist /usr/lib/cgi-bin/mailman/rmlist ScriptAlias /roster /usr/lib/cgi-bin/mailman/roster ScriptAlias /subscribe /usr/lib/cgi-bin/mailman/subscribe ScriptAlias /mailman/ /usr/lib/cgi-bin/mailman/ </VirtualHost>
I create a directory 'lists' in /var/www:
# mkdir /var/www/lists
And I enable the new site:
# a2ensite mailman.conf # /etc/init.d/apache2 restart
Some configurations are needed for mailman to get to know the new lists.smida.it as a domain:
# vim /etc/mailman/mm_cfg.py
DEFAULT_EMAIL_HOST = 'lists.smida.it' DEFAULT_URL_HOST = 'lists.smida.it' DEFAULT_URL_PATTERN = 'http://%s/' MTA='Postfix'
In the last line I tell mailman that the mail transfer agent to use is postfix.
Now we need to inform postfix about the new domain:
# postconf -e 'relay_domains = lists.smida.it' # postconf -e 'mailman_destination_recipient_limit = 1'
And we need to make sure that in master.cf there are the following two lines for the mail delivery:
# vim /etc/postfix/master.cf
mailman unix - n n - - pipe flags=FR user=list argv=/usr/lib/mailman/bin/postfix-to-mailman.py ${nexthop} ${user}
I need, then, to insert in the database more details about the new domain:
# mysql -p mailserver
I create a new table which will contain informations about the transport domains:
mysql> create table virtual_transport ( -> `id` int(11) not null auto_increment, -> `domain_id` int(11) not null, -> `domain` varchar(50) not null, -> `transport` varchar(50) not null, -> primary key(`id`), -> unique key `domain`(`domain`), -> foreign key (domain_id) references virtual_domains(id) on delete cascade -> ) engine=InnoDB charset=utf8; Query OK, 0 rows affected (0.07 sec)
I insert the informations related to lists.smida.it:
mysql> insert into `virtual_transport` (`domain_id`, `domain`, `transport`) -> values ( -> '1', 'lists.smida.it', 'mailman:'); Query OK, 1 row affected (0.03 sec)
id | domain_id | domain | transport |
---|---|---|---|
1 | 1 | lists.smida.it | mailman: |
Once the database is ready, I need to create a file with the database account details and the query string for postfix, as I did for the other tables :
# vim /etc/postfix/mysql-virtual_transports.cf
user = mailuser password = 0XTDoEpvvzIZ8pyG hosts = 127.0.0.1 dbname = mailserver query = SELECT transport FROM virtual_transport WHERE domain='%s'
Remember that the password is fake and to put your own. I set the file permissions:
# chmod o= /etc/postfix/mysql-virtual_transports.cf
And tell postfix to use this file for the transport domain mapping:
# postconf -e 'transport_maps = proxy:mysql:/etc/postfix/mysql-virtual_transports.cf'
To make the changes effective I restart postfix:
# /etc/init.d/postfix restart
Now I'm ready to use the mailing list, but first I need to create one. I'll start with the list that mailman likes, i.e. "mailman":
# newlist --urlhost=lists.smida.it --emailhost=lists.smida.it mailman
The list creation is interactive and it will ask first for the administrator mail, in my case andi@smida.it:
Enter the email of the person running the list: andi@smida.it
Then it will ask the password for the administrative interface. As usual you can use this command to generate one:
$ tr -dc A-Za-z0-9 < /dev/urandom | head -c 64 | xargs
At the end it will provide a list of standard mail accounts used for the list management and it will send an e-mail to notify the creation of the "mailman" mailing list. We need to copy paste that list in the aliases file:
# vim /etc/aliases
## mailman mailing list mailman: "|/var/lib/mailman/mail/mailman post mailman" mailman-admin: "|/var/lib/mailman/mail/mailman admin mailman" mailman-bounces: "|/var/lib/mailman/mail/mailman bounces mailman" mailman-confirm: "|/var/lib/mailman/mail/mailman confirm mailman" mailman-join: "|/var/lib/mailman/mail/mailman join mailman" mailman-leave: "|/var/lib/mailman/mail/mailman leave mailman" mailman-owner: "|/var/lib/mailman/mail/mailman owner mailman" mailman-request: "|/var/lib/mailman/mail/mailman request mailman" mailman-subscribe: "|/var/lib/mailman/mail/mailman subscribe mailman" mailman-unsubscribe: "|/var/lib/mailman/mail/mailman unsubscribe mailman"
Everytime I create new aliases I make them effective by running:
# newaliases
I restart postix:
# /etc/init.d/postfix restart
And I finally give life to mailman:
# /etc/init.d/mailman start
Home / Index / Top / Last: Mailing lists
Andi Shyti