My Perfect Ubuntu Server v7.10

From FactotumNW Wiki

Jump to: navigation, search

My perfect Gutsy Gibbon Ubuntu Server v7.10

Note: Throughout this document the use of "servername" is used as the name of the server but you should replace this with your server's name. Also, the domain name used here is simply "domain" and again, you should replace this word with the actual name of your domain.

The following is an accumulation of information from several sites and a lot of trial and error. It reads a little clunky in some spots but I tried to clean it up as best I could (and I'll keep trying to fix issues as time goes on), so don't beat me up too bad, I mainly have this here for my help and not you.

The initial install and setup of Ubuntu was from: http://www.howtoforge.com/perfect_server_ubuntu7.10. The Postfix section was mainly from this site: http://workaround.org/articles/ispmail-etch/ which worked just fine for Gutsy Gibbon even though it was written for Debian-Etch. After that as I added features and modified configurations to the server I kept documenting what I learned, which is below.


  • Install from Ubuntu CD
    • Install to Hard Drive
    • Select English
    • Select United States
    • Say No to detect keyboard then select English – US English
    • Type in hostname – servername
    • Select guided, use entire drive
      • 2 partitions ext3 and swap
    • Select Pacific time zone
    • Say No to UTC
    • Type in full name of user – username
    • Type in username – username
    • Type in password 2 times
    • Install DNS – LAMP – Mail – OpenSSH – Samba
      • Or at least just OpenSSH Server (do Pink items if so)
    • Type in SQL root password
    • Select “Internet Site” for email server
    • System mail name = servername.domain.com
    • Remove CD and reboot
  • After login run “sudo passwd root” to enable su
  • Login as su
  • Apt-get install ssh openssh-server vim-full
  • “mkdir /mnt/floppy” or “mkdir /mnt/usb”
  • “mount –t vfat /dev/fd0 /mnt/floppy” or “mount –t auto /dev/sdb1 /mnt/usb”
    • “cp /mnt/floppy/apps_2_install.txt /home/username/” and anything else I have handy (file contains the following)
      • apt-get install binutils cpp fetchmail flex gcc libarchive-zip-perl libc6-dev libcompress-zlib-perl libdb4.3-dev libpopt-dev lynx m4 make ncftp nmap unzip zip zlib1g-dev autoconf automake1.9 libtool bison autotools-dev g++ build-essential mysql-client libmysqlclient15-dev sasl2-bin libdb3-util apache2-doc php5 php5-curl php5-dev php5-gd php5-idn php-pear php5-imagick php5-imap php5-mcrypt php5-memcache php5-mhash php5-ming php5-ps php5-pspell php5-recode php5-snmp php5-sqlite php5-tidy php5-xmlrpc php5-xsl proftpd webalizer ntp ntpdate libhtml-parser-perl libdb-file-lock-perl libnet-dns-perl
    • “chmod 666 /home/username/apps_2_install_1.txt”
    • “vim /etc/network/interfaces”
      • Change line to read
      • iface eth0 inet static
        • address 192.168.2.15
        • netmask 255.255.255.0
        • network 192.168.2.0
        • broadcast 192.168.2.255
        • gateway 192.168.2.1
        • pre-up iptables-restore < /etc/iptables.rules
        • post-down iptables-save > /etc/iptables.rules
    • “/etc/init.d/networking restart”
    • If copied an iptables.rules file to /etc/ then restore to keep from clobbering it if you have to reboot and the above post-down command over-writes it.
      • iptables-restore < /etc/iptables.rules
    • “vim /etc/hosts”
      • First 2 lines:
        • 127.0.0.1 localhost.localdomain localhost
        • 192.168.2.15 servername.domain.com servername
    • “echo servername.domain.com > /etc/hostname”
    • “/etc/init.d/hostname.sh start”
    • Check if hostname is right with these 2 commands “hostname” and “hostname –f”
      • Both should come back servername.domain.com
    • “vim /etc/apt/sources.list”
      • Remark out the CDROM line “deb cdrom:[Ubuntu-Server…]”
    • “apt-get update”
    • “apt-get upgrade”
      • Upgrade Dovecot – use new conf and not already installed
    • “apt-get dist-upgrade”
      • Once done do:
      • ssh-keygen –l –f /etc/ssh/ssh_host_rsa_key
      • ssh-keygen –l –f /etc/ssh/ssh_host_dsa_key
      • ssh-vulnkey – to check for vulnerabilities
    • “apt-get install ssh openssh-server”
    • Fix Vim problem – “apt-get install vim-full”
    • “ln –sf /bin/bash /bin/sh” to change default shell to Bash
    • “bash /home/username/apps_2_install_1.txt” - Installs 118 apps
      • “Yes” to install libc-client without Maildir support
      • “Standalone” for proftp
    • Or install the following:
      • apt-get install binutils cpp fetchmail flex gcc libarchive-zip-perl libc6-dev libcompress-zlib-perl libdb4.3-dev libpopt-dev lynx m4 make ncftp nmap unzip zip zlib1g-dev autoconf automake1.9 libtool bison autotools-dev g++ build-essential
    • Log in using PuTTY
    • If you want quota on
      • “apt-get install quota”
    • “vim /etc/fstab”
      • If you want quota on:
        • Add to hda1 line to use quota “,usrquota,grpquota” for quota:
        • Ext3 defaults,errors=remount-ro,usrquota,grpquota 0
        • Change the cdrom and floppy lines to “auto” vs “noauto”
    • To enable quota:
      • “touch /quota.user /quota.group”
      • “chmod 600 /quota.*”
      • “mount –o remount /”
      • “quotacheck –avugm”
      • “quotaon –avug”
  • DNS Setup – not chrooted
    • Apt-get install bind9
    • If you want to chroot:
      • /etc/init.d/bind9 stop
      • Vim /etc/default/bind9
        • Edit this make the daemon run as an unprivileged user ‘bind’, chrooted to /var/lib/named:
        • OPTIONS=”-u bind –t /var/lib/named”
          1. set RESOLVCONF=no to not run resolvconf
        • RESOLVCONF=yes
      • mkdir –p /var/lib/named/etc
      • mkdir /var/lib/named/dev
      • mkdir –p /var/lib/named/var/cache/bind
      • mkdir –p /var/lib/named/var/run/bind/run
      • mv /etc/bind /var/lib/named/etc
      • ln –s /var/lib/named/etc/bind /etc/bind
      • mknod /var/lib/named/dev/null c 1 3
      • mknod /var/lib/named/dev/random c 1 8
      • chmod 666 /var/lib/named/dev/null /var/lib/named/dev/random
      • chown –R bind:bind /var/lib/named/var/*
      • chown –R bind:bind /var/lib/named/etc/bind
      • Modify /etc/default/syslogd to make logfiles work properly
        • SYSLOGD=”-a /var/lib/named/dev/log”
      • /etc/init.d/sysklogd restart
      • /etc/init.d/bind9 start
    • “vim /etc/bind/named.conf.options”
      • Un-remark “forwarders” and add 2 lines for the ISP’s DNS
        • forwarders {
        • 216.227.100.60;
        • 137.118.1.32;
        • };
    • “vim /etc/resolv.conf”
    • “search domain.com”
    • “nameserver 192.168.2.15”
    • “vim /etc/bind/named.conf.local”
      • Add the new zone for domain and Reverse DNS for network
        • zone “domain.com” {
        • type master;
        • file “/etc/bind/db.domain”;
        • };
        • zone “2.168.192.in-addr.arpa” {
        • type master;
        • file “/etc/bind/db.192”;
        • };
    • “cp /etc/bind/db.local /etc/bind/db.domain”
    • “cp /etc/bind/db.127 /etc/bind/db.192”
    • “vim /etc/bind/db.domain”
      • Change the “BIND” line at top to describe the file
      • “@ IN SOA servername.domain.com. root.domain.com. (“
        • Notice dot at end of both names in line above
      • “1  ;Serial” (this needs to be incremented each time file is changed)
      • “604800  ; Refresh”
      • “86400  ;Retry”
      • “2419200  ;Expire”
      • “604800 )  ;Negative Cache TTL”
      • “@ IN NS servername.domain.com.” (dot at end)
      • “@ IN A 192.168.2.15”
      • “ IN MX 10 mail.domain.com.” (dot at end)
      • “mail IN A 192.168.2.15”
      • “servername IN A 192.168.2.15”
      • “www IN A 192.168.2.15”
      • “ftp IN A 192.168.2.15”
      • “webmail IN A 192.168.2.15”
    • “vim /etc/bind/db.192”
      • Change the BIND line to describe what file is for
      • “@ IN SOA servername.domain.com. root.domain.com. (“
        • Keep the 5 Refresh, etc lines as is and edit next:
      • “@ IN NS servername.domain.com.” (dot at end)
      • “@ IN A 192.168.2.15”
      • “mail IN A 192.168.2.15”
      • “servername IN A 192.168.2.15”
      • “www IN A 192.168.2.15”
      • “ftp IN A 192.168.2.15”
      • “webmail IN A 192.168.2.15”
    • “/etc/init.d/bind9 restart”
    • Test with ping www.domain.com and google
    • “dig –x 2.168.192.in-addr.arpa” should show servername as the server
    • “dig –x 127.0.0.1” should show servername as the server


Go to top


  • MySQL – root password set at initial install
    • Apt-get install mysql-server mysql-client libmysqlclient15-dev
      • Provide root password
    • “vim /etc/mysql/my.cnf”
      • Remark out “bind-address 127.0.0.1” to allow listening all interfaces
    • “/etc/init.s/mysql restart”
    • “netstat –tap | grep mysql”
      • Should say “tcp 0 0 *.mysql *:* LISTEN 5286/mysql
  • Apache2
    • Apt-get install apache2 apache2-doc apache2-mpm-prefork apache2-utils libexpat1 ssl-cert libapache2-mod-php5 php5 php5-common php5-curl php5-dev php5-gd php5-idn php-pear php5-imagick php5-imap php5-mcrypt php5-memcache php5-mhash php5-ming php5-mysql php5-ps php5-pspell php5-recode php5-snmp php5-sqlite php5-tidy php5-xmlrpc php5-xsl
      • Answer questions asked
    • “vim /etc/apache2/mods-available/dir.conf”
      • “DirectoryIndex index.html index.htm index.shtml index.cgi index.php index.php3 index.pl index.xhtml”
    • Enable these modules
      • “a2enmod ssl”
      • “a2enmod rewrite”
      • “a2enmod suexec”
      • “a2enmod include”
    • “/etc/init.d/apache2 force-reload”
    • “vim /etc/apache2/apache2.conf”
      • Edit “Timeout 45”
      • Edit “MaxKeepAliveRequests 200”
      • Edit “KeepAliveTimeout 3”
      • Edit “ServerSignature Off”
      • Edit “ServerTokens Prod”
      • Add the following at bottom of file:
        • NameVirtualHost *:80
        • <IfModule mod_ssl.c>
          • NameVirtualHost *:443
        • </IfModule>
    • “vim /etc/apache2/sites-available/default”
      • Remark out NameVirtualHost * at top of file
      • Change the 2nd line to “<VirtualHost *:80>”
      • Change the DocumentRoot line to say:
        • DocumentRoot /var/www/apache2-default
    • “vim /var/www/apache2-default/index.html”
      • <html><body>It works!</body></html>
      • Note: browser default will fall into “It Works” when trying a site not on the server
    • Make a new site on Apache2
      • “mkdir /var/www/website”
      • “chown username:username /var/www/website”
        • Or to the web designer name uploading to the server
      • Copies files to the folder via FileZilla
      • “cp /etc/apache2/sites-available/default /etc/apache2/sites-available/website”
      • Edit the website file:
        • #NameVirtualHost *
        • <VirtualHost *:80>
          • ServerAdmin webmaster@localhost
          • ServerName website.com
          • ServerAlias www.website.com
          • DocumentRoot /var/www/website
          • #DirectoryIndex index.html
          • ErrorLog /var/log/apache2/website.error.log
          • LogLevel warn
          • CustomLog /var/log/apache2/website.access.log
        • </VirtualHost>
      • a2ensite website
      • “/etc/init.d/apache2 force-reload”
      • If error “httpd (no pid file) not running” when Apache2 Restart
        • “cp /var/run/apache2.pid /var/run/apache2/apache2.pid
      • Edit /etc/bind/named.conf.local to add zone
      • Add a new db.file for new zone in /etc/bind/db.<file>
      • Check access and error logs
    • Multiple Sites with SSL
      • You need multiple OUTSIDE IP’s!!!
      • Each site with its own SSL Certificate must have its own IP. You only need a NameVirtualHost directive for sites that are doing named-virtual hosting. <VirtualHost 192.168.2.14:443>
      • Add another IP to Ethernet by editing /etc/network/interfaces
        • Auto eth0:1
        • Iface eth0:1 inet static
          • Address 192.168.2.16
          • Subnet 255.255.255.0 (etc)
          • Include the 2 iptable lines to load and save
      • /etc/init.d/networking restart
      • ??
      • Router port forward 443 request for second IP to destination 10443
      • listen 80
      • Listen 443
      • NameVirtualHost 192.168.2.15:80
      • <VirtualHost 192.168.2.16:80>
      • ServerName www.firstdomain.com
      • </VirtualHost>
      • <VirtualHost 192.168.2.15:443>
      • ServerName www.firstdomain.com
      • </VirtualHost>
      • NameVirtualHost 192.168.2.15:80
      • <VirtualHost 192.168.2.16:80>
      • ServerName www.Seconddomain.com
      • </VirtualHost>
      • <VirtualHost 192.168.2.15:10443>
      • ServerName www.Seconddomain.com
      • </VirtualHost>


  • ProFTP – not locked down
    • Apt-get install proftp ucf
    • Answer “Standalone”
    • “vim /etc/proftpd/proftpd.conf”
      • Change UseIPv6 to “off”
    • For security reasons – vim /etc/proftpd/proftpd.conf – and add:
      • DefaultRoot ~
      • IdentLookups off
      • ServerIdent on “FTP Server ready.”
    • “/etc/init.d/proftpd restart”
    • Test FTP access with FileZilla
  • Secure shared memory
    • “vim /etc/fstab” and add following lines:
      • tmpfs /dev/shm tmpfs defaults,ro 0 0
        1. to make writeable use this line:
        2. tmpfs /dev/shm tmpfs defaults,noexec,nosuid 0 0
        3. add to mount usbfs at bootup and see devices on usb
      • none /proc/bus/usb usbfs defaults 0 0
    • “mount –o remount /dev/shm” to remount the shared memory
  • Install Webalizer
    • Apt-get install webalizer
  • Synchronize System Clock
    • Apt-get install ntp ntpdate
  • Other Perl modules needed
    • Apt-get install libhtml-parser-perl libdb-file-lock-perl libnet-dns-perl
  • Secure SSH
    • “vim /etc/ssh/sshd_config”
      • Edit line to say NO – “PermitRootLogin no”
      • Edit line to 20 seconds – “LoginGraceTime 20”
      • Can add a banner by un-commenting “Banner /etc/issue.net”
        • Edit /etc/issue.net file as you’d like:
      • Add line at bottom “AllowUsers rodney”
        • This only allows me to use SSH
    • “/etc/init.d/ssh restart”
  • To disallow ‘su’ access by non-admin persons:
    • “chown root:admin /bin/su”
    • “chmod 04750 /bin/su”
  • Automatic Security Updates
    • Create “vim /etc/cron.weekly/apt-security-updates”
    • Edit file to include the following:
      • #! /bin/sh
      • echo "**************" >> /var/log/apt-security-updates
      • date >> /var/log/apt-security-updates
      • aptitude update >> /var/log/apt-security-updates
      • aptitude safe-upgrade -o Aptitude::Delete-Unused=false --assume-yes --target-release `lsb_release -cs`-security >> /var/log/apt-security-updates
      • echo "Security updates (if any) installed"
    • Make the file executable – “chmod +x /etc/ cron.weekly/apt-security-updates”
    • Create file “vim /var/log/apt-security-updates”
    • Errors will be logged in /var/log/apt-security-updates
    • To prevent log from getting to big create the following:
      • “vim /etc/logrotate.d/apt-security-updates” with the following:
        • /var/log/apt-security-updates {
        • rotate 2
        • weekly
        • size 250k
        • compress
        • notifempty
        • }
  • Rootkit checker
    • “apt-get install chkrootkit”
    • Execute “chkrootkit” to check for any backdoors, worms, or Trojans
  • IPTables firewall
    • “iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT”
    • “iptables -A OUTPUT -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT”
    • “iptables -A INPUT -p tcp -m tcp --dport 22 -j ACCEPT”
    • “iptables -A INPUT -p tcp -m tcp --dport 80 -j ACCEPT”
    • “iptables -A INPUT -p tcp -m tcp --dport 443 -j ACCEPT”
    • “iptables -A INPUT -p tcp -m tcp --dport 21 -j ACCEPT”
    • “iptables -A INPUT -p tcp -m tcp --dport 20 -j ACCEPT”
    • “iptables -A INPUT -p tcp -m tcp --dport 110 -j ACCEPT”
    • “iptables -A INPUT -p tcp -m tcp --dport 25 -j ACCEPT”
    • “iptables -A INPUT -p tcp -m tcp --dport 23 -j ACCEPT”
      • May want to delete this after testing is all done – (Telnet)
    • “iptables -A INPUT -p tcp -m tcp --dport 143 -j ACCEPT”
    • “iptables -A INPUT -p udp -i eth0 --dport 53 --sport 1024:65535 -j ACCEPT”
    • “iptables -A INPUT -s 127.0.0.1 -j ACCEPT”
    • “iptables -A OUTPUT -p udp -o eth0 --dport 53 --sport 1024:65535 -j ACCEPT”
    • “iptables -A OUTPUT -p tcp -m tcp --dport 22 -j DROP”
    • “iptables -A INPUT -j DROP”
    • “iptables -A FORWARD -j DROP”
    • Save iptables to a file:
      • “iptables-save > /etc/iptables.rules”
    • Re-edit iptables.rules file and make sure the first OUTPUT entry is the NEW,RELATED,ESTABLISHED line and all other OUTPUT statements follow it.
      • ALSO, make sure at the top of the file all 3 lines say [0:0].
    • “vim /etc/network/interfaces” to add reload of iptables at bootup for eth0
      • “pre-up iptables-restore < /etc/iptables.rules”
      • “post-down iptables-save > /etc/iptables.rules”
    • Restart /etc/init.d/networking restart
    • Note – FTP clients should use Active mode, not Passive
  • Backup server - complete
    • Plug in external USB drive
    • “mkdir /mnt/usb”
    • “mount –t auto /dev/sda1 /mnt/usb” (may be sdb1)
    • “cd /mnt/usb”
    • “tar cvpzfP backup.tgz –exclude=/proc/* --exclude=/lost+found/* --exclude=/dev/* --exclude=/mnt/* --exclude=/media/* --exclude=/sys/* --exclude=/tmp/* --exclude=/var/cache/apt/* /”
  • Recover
    • Install new OS with basic install & no updates
    • From the external drive
      • “tar xvpfz backup.tgz –C /”
    • Folders excluded
      • /proc
      • /lost+found
      • /mnt
      • /sys
      • /dev
      • /media
      • /tmp
      • /var/cache/apt
    • Reboot
  • Backup selective use rsync –arvu /what to get/ /where to put it
    • The trailing “/” after the source is important so a real command might look like this:
      • rsync –arvu /var/www/nevelspas/ /mnt/usb/nevelspas
        • -a = archive
        • -r = recursive
        • -v = verbose
        • -u = update, skip files that are newer on destination


Go to top


  • Postfix
    • “vim /etc/hostname”
      • Edit to only say “maya” (contradicts earlier ??)
    • Check “/etc/mailname” = “servername.domain.com” (won’t be there until installed)
    • Run “hostname --fqdn” and make sure “servername.domain.com” comes back, otherwise “vim /etc/hosts” and make sure the fqdn is listed first
    • “aptitude install postfix-mysql” (will install postfix if not already too).
      • Choose “Internet Site”
      • Choose fqdn
    • “aptitude install amavisd-new libclass-dbi-mysql-perl” - 41 programs will installed
    • “aptitude install spamassassin clamav-daemon cpio arj zoo nomarch lzop cabextract pax” - 32 new packages will install
    • May not have to do the following:
    • “aptitude install lha unrar”
    • “aptitude install squirrelmail” 6 programs installed
    • “aptitude install phpmyadmin libapache2-mod-php5 php5-mysql”
        • Select “apache2” from list
    • “mysqladmin password <password>” to reset admin password if needed
    • “mysqladmin –p create mailserver” to create new mail database
    • “mysql –p” to log into mysql
    • “GRANT SELECT ON mailserver.* TO mailuser@localhost IDENTIFIED BY '<password>';” creates a new unprivileged user
    • “exit”
    • “mysql –p mailserver” to log into mysql using new database
    • “CREATE TABLE virtual_domains (
    • id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
    • name VARCHAR(50) NOT NULL
    • ) ENGINE = InnoDB;”
    • CREATE TABLE virtual_users (
    • id int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
    • domain_id INT(11) NOT NULL,
    • user VARCHAR(40) NOT NULL,
    • password VARCHAR(32) NOT NULL,
    • CONSTRAINT UNIQUE_EMAIL UNIQUE (domain_id,user),
    • FOREIGN KEY (domain_id) REFERENCES virtual_domains(id) ON DELETE CASCADE
    • ) ENGINE = InnoDB;
    • CREATE TABLE virtual_aliases (
    • id int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
    • domain_id INT(11) NOT NULL,
    • source VARCHAR(20) NOT NULL,
    • destination VARCHAR(80) NOT NULL,
    • FOREIGN KEY (domain_id) REFERENCES virtual_domains(id) ON DELETE CASCADE
    • ) ENGINE = InnoDB;
    • Note: You wonder about the foreign keys? They express that entries in the virtual_aliases and virtual_users tables are connected to entries in the virtual_domains table. This will keep the data in your database consistent because you cannot create virtual aliases or virtual users that are not connected to a virtual domain. And you avoid redundancy because you just store the domain name once - in the virtual_domains table - and nowhere else. The suffix 'ON DELETE CASCADE' means that if you delete a row from the referenced table that the deletion will also be done on the current table automatically. So you do not leave orphaned entries accidentally. Imagine that you do not host a certain domain any longer. You can remove the domain entry from the virtual_domains table and all dependent/referenced entries in the other tables will also be removed. This approach is also called a normalized database.
    • Insert data into virtual_domains and virtual_users tables using http://<server>/phpmyadmin/
    • Create file “/etc/postfix/mysql-virtual-mailbox-domains.cf” and add the following:
      • user = mailuser
      • password = <password>
      • hosts = 127.0.0.1
      • dbname = mailserver
      • query = SELECT 1 FROM virtual_domains WHERE name=’%s’
    • “postconf –e virtual_mailbox_domains=mysql:/etc/postfix/ mysql-virtual-mailbox-domains.cf”
      • This adds the line to /etc/postfix/main.cf file
    • To manually populate virtual_domains with a domain:
      • mysql –p mailserver
      • INSERT INTO virtual_domains (id, name) VALUES (1, ‘domain.com’);
      • exit
    • Check to see if this will work:
      • postmap –q domain.com mysql:/etc/postfix/mysql-virtual-mailbox-domains.cf
      • Should get a ‘1’ back saying it’s true.
      • If error “postmap: warning: connect to mysql server 127.0.0.1: Access denied…” then there’s a problem with the mailuser account and to check mysql privileges again.
      • If error “postmap: warning: connect to mysql server 127.0.0.1: Can’t connect to mysql server on 127.0.0.1” then mysql is not running or not listening; check /etc/mysql/my.cnf settings.
  • Create a new user to own all virtual mailboxes:
      • Use “find / -gid 5000” to see if it’s in use, same command for UID.
      • “groupadd –g 5000 vmail” to add the group and assign it GID 5000.
      • “useradd –g vmail –u 5000 vmail –d /home/vmail –m”
    • Tell postfix to use them:
      • “postconf –e virtual_uid_maps=static:5000”
      • “postconf –e virtual_gid_maps=static:5000”
    • Add users in mysql virtual_users table through phpmyadmin or:
      • INSERT INTO virtual_users (id, domain_id, user, password) VALUES (1, 1, ‘username’, MD5(‘password’));
    • Create sql query cf file for this table, go into mysql:
      • mysql –p mailserver
      • SELECT CONCAT(virtual_users.user, ‘@’, virtual_domains.name) AS email FROM virtual_users LEFT JOIN virtual_domains ON virtual_users.domain_id=virtual_domains.id;
    • Should print “email” and then “username@domain.com”
    • Mailbox structure will be “/home/vmail/$domain/$user
    • Create sql query to get user password in sql
      • mysql –p mailserver
      • SELECT CONCAT(virtual_users.user, '@', virtual_domains.name) AS email, virtual_users.password FROM virtual_users LEFT JOIN virtual_domains ON virtual_users.domain_id=virtual_domains.id;
    • The result should show user email address and passwords.
    • Create a view in mysql for the password query:
      • Mysql –p mailserver
      • CREATE VIEW view_users AS SELECT CONCAT(virtual_users.user, '@', virtual_domains.name) AS email, virtual_users.password FROM virtual_users LEFT JOIN virtual_domains ON virtual_users.domain_id=virtual_domains.id;
      • While still in mysql try new view:
        • SELECT * FROM view_users;
      • Should get the same result, name and passwords
    • Create query cf file and use the view query:
      • “vim /etc/postfix/mysql-virtual-mailbox-maps.cf”
        • user = mailuser
        • password = <password>
        • hosts = 127.0.0.1
        • dbname = mailserver
        • query = SELECT 1 FROM view_users WHERE email='%s'
    • Tell postfix to use this:
      • postconf -e virtual_mailbox_maps=mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf
    • Test this out from the command prompt:
      • postmap -q john@example.com mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf
    • Should get a “1” back.
    • Add 2 alias forwards in the virtual-aliases table using phpmyadmin or:
      • INSERT INTO virtual_aliases (id, domain_id, source, destination) VALUES (1, 1, 'john', 'john@example.com'), (2, 1, 'john', 'jmiller@gmail.com');
      • The first numbers are sequence numbers and the second are the domain_id
    • Create a view for the aliases in mysql:
      • CREATE VIEW view_aliases AS SELECT CONCAT(virtual_aliases.source, '@', virtual_domains.name) AS email, destination FROM virtual_aliases LEFT JOIN virtual_domains ON virtual_aliases.domain_id=virtual_domains.id;
    • Do this command in mysql to test it:
      • SELECT * FROM view_aliases;
    • Should get 2 lines that show the email to email and email to new email
    • Create a cf file for this view for aliases: /etc/postfix/mysql-virtual-alias-maps.cf:
      • user = mailuser
      • password = <password>
      • hosts = 127.0.0.1
      • dbname = mailserver
      • query = SELECT destination FROM view_aliases WHERE email='%s'
    • Test the new cf file: “postmap -q john@example.com mysql:/etc/postfix/mysql-virtual-alias-maps.cf”
      • Should get the first email and the forward to email
    • If you want a catch-all account to get all emails for accounts not on the domain then do the following:
      • Create a cf file /etc/postfix/mysql-email2email.cf to fix the catch-all issue with all emails going to the catch-all email account and to no one else:
        • user = mailuser
        • password = <password>
        • hosts = 127.0.0.1
        • dbname = mailserver
        • query = SELECT email FROM view_users WHERE email='%s'
      • Add 2 records in the aliases table in mysql,
        • One that says that @domain2.com (all email prefix not on file) and james@domain3.com as the forward to account (the catch-all).
        • Second that says don@domain2.com to don@domain2.com.
      • Test to see if it works:
        • postmap -q john@example.com mysql:/etc/postfix/mysql-email2email.cf”
        • The result should be don@domain2.com.
      • Now add this line to postfix main.cf:
        • postconf -e virtual_alias_maps=mysql:/etc/postfix/mysql-virtual-alias-maps.cf,mysql:/etc/postfix/mysql-email2email.cf
      • The order of the previous line is important for it to work properly.
    • After all database passwords are stored then make it so only the root and postfix users can access them:
      • chgrp postfix /etc/postfix/mysql-*.cf
      • chmod u=rw,g=r,o= /etc/postfix/mysql-*.cf
  • To enable Dovecot LDA edit /etc/postfix/master.cf with these 3 lines:
  • dovecot unix - n n - - pipe
  • flags=DRhu user=vmail:vmail argv=/usr/lib/dovecot/deliver -d
  • ${recipient}
  • Edit /etc/postfix/main.cf with these 2 lines from the command prompt:
  • postconf -e virtual_transport=dovecot
  • postconf -e dovecot_destination_recipient_limit=1
  • Configure Dovecot in /etc/dovecot/dovecot.conf:
  • protocols = imap imaps pop3 pop3s
  • This should already be done
  • If users complain about not getting email:
  • disable_plaintext_auth = no
  • The default is ‘yes’ and hopefully won’t require changing
  • Had to do this to make it work with Outlook
  • mail_location = maildir:/home/vmail/%d/%n
  • If you already have virtual mailboxes on the system prior to doing this install then do the following edit:
  • namespace private {
  • separator = .
  • prefix = INBOX.
  • inbox = yes
  • }
  • In the section called “auth default” edit the following:
  • mechanisms = plain login
  • Should just need to add “login” to line
  • passdb sql {
  • args = /etc/dovecot/dovecot-sql.conf
  • }
  • userdb static {
  • args = uid=5000 gid=5000 home=/home/vmail/%d/%n allow_all_users=yes
  • }
  • Comment out the section on “passdb pam”.
  • In section called “socket listen” un-comment and edit to say:
  • socket listen {
  • master {
  • path = /var/run/dovecot/auth-master
  • mode = 0600
  • user = vmail
  • }
  • client {
  • path = /var/spool/postfix/private/auth
  • mode = 0660
  • user = postfix
  • group = postfix
  • }
  • }
  • Edit protocol lda section to say this:
  • protocol lda {
  • log_path = /home/vmail/dovecot-deliver.log
  • auth_socket_path = /var/run/dovecot/auth-master
  • postmaster_address = username@domain.com
  • mail_plugins = cmusieve
  • global_script_path = /home/vmail/globalsieverc
  • }
  • Edit /etc/dovecot/dovecot-sql.conf and change these settings:
  • driver = mysql
  • connect = host=127.0.0.1 dbname=mailserver user=mailuser password=<password>
  • default_pass_scheme = PLAIN-MD5
  • password_query = SELECT email as user, password FROM view_users WHERE email='%u';
  • Restart Dovecot:
  • /etc/init.d/dovecot restart
  • Restart postfix
  • /etc/init.d/postfix restart
  • Check /var/log/mail.log logfile to see the following is there:
  • dovecot: Dovecot v1.0.rc15 starting up
  • dovecot: auth-worker(default): mysql: Connected to 127.0.0.1 (mymailserver)
  • Need to fix file system permissions for the /etc/dovecot/dovecot.conf file so that the vmail user can access the Dovecot configuration:
  • chgrp vmail /etc/dovecot/dovecot.conf
  • chmod g+r /etc/dovecot/dovecot.conf
  • Dovecot Logfile Rotate
  • Create /etc/logrotate.d/dovecot and add the following:
  • /home/vmail/dovecot-deliver.log {
  • missingok
  • rotate 2
  • weekly
  • size 250k
  • delaycompress
  • compress
  • notifempty
  • }
  • Test the server with:
  • telnet localhost smtp
  • If it won’t connect restart postfix and try again
  • ehlo factotumnw.com
  • mail from: rodney@domain.com
  • rcpt to: john@domain.com
  • data
  • subject: test
  • test <CR> . <CR>
  • Check log /var/log/mail.log for delivery of mail
  • If “file not found error, then create /home/vmail/globalsieverc
  • require [“fileinto”];
  • # move spam into spam folder
  • if exists “X-Spam-Flag” {
  • fileinto “spam”;
  • stop;
  • }
  • There should be an email in /home/vmail/domain.com/john/cur
  • cd to john folder
  • Use “mutt –f .” to access the email and q twice to exit
  • Test pop3 connection
  • telnet localhost pop3
  • user john@domain.com
  • pass <password>
  • list
  • retr 1
  • quit
  • Test Imap using Mutt
  • mutt -f imaps://john@example.com@localhost
  • To enable relay for authenticated user:
  • 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
  • Make a Base64 encryption of your login credentials:
  • perl -MMIME::Base64 –e 'print encode_base64("rodney\@domain.com\0rodney\@domain.com\0<password>")';
“telnet localhost smtp”
  • ehlo local host
  • auth plain <long encrypted code from above>
  • quit
  • Should get “Authentication successful”
  • I can’t make this work…
  • If I have issues with built-in Dovecot certificate:
  • openssl req -new -x509 -days 3650 -nodes -out /etc/ssl/certs/dovecot.pem -keyout /etc/ssl/private/dovecot.pem
  • The certificate and key will be created while you get asked a few questions:
  • Generating a 1024 bit RSA private key
  • .........++++++............................++++++
  • writing new private key to '/etc/ssl/certs/dovecot.pem'-----
  • You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank.
  • -----
  • Country Name (2 letter code) [AU]:DE
  • State or Province Name (full name) [Some-State]:Hamburg
  • Locality Name (eg, city) []:Hamburg
  • Organization Name (eg, company) [Internet Widgits Pty Ltd]:workaround.org
  • Organizational Unit Name (eg, section) []:
  • Common Name (eg, YOUR name) []:mailtest.workaround.org
  • Email Address []:postmaster@workaround.org
  • Of course you should fill in your own information here. The most important setting is the Common Name which must contain the fully-qualified name of your mail server. Oh, and this certificate will be valid for 10 years (3650 days) - adjust that period as you want.
  • Do not forget to set the permissions on the private key so that no unauthorized people can read it:
  • chmod o= /etc/ssl/private/dovecot.pem
  • To make a new certificate for Postfix:
  • Your email program may have warned you that the mail server uses an untrusted SSL certificate. The default certificate that comes with Postfix is made out to the funny nonexisting "Office for Complication of Otherwise Simple Affairs" organization. This is sufficient for testing but just like you did for Dovecot it is advised you create a proper SSL certificate that at least has the correct host name included. The default certificate is stored at /etc/ssl/certs/ssl-cert-snakeoil.pem and the default private key is stored at /etc/ssl/private/ssl-cert-snakeoil.key. Consider creating a new certificate/key pair and store it as postfix.pem:
  • openssl req -new -x509 -days 3650 -nodes -out /etc/ssl/certs/postfix.pem -keyout /etc/ssl/private/postfix.pem
  • Same procedure as above when you created a certificate for Dovecot. Just remember to set the "Common Name" to the fully-qualified hostname. You could as well use the same certificate you created for Dovecot if the server name is the same. In that case just use the files /etc/ssl/certs/dovecot.pem and /etc/ssl/private/dovecot.pem below.
  • Do not forget to set the permissions on the private key so that no unauthorized people can read it:
  • chmod o= /etc/ssl/private/postfix.pem
  • You will just have to tell Postfix where to find your certificate and private key:
  • postconf -e smtpd_tls_cert_file=/etc/ssl/certs/postfix.pem
  • postconf -e smtpd_tls_key_file=/etc/ssl/private/postfix.pem
  • When you relay through Postfix again you should not get that certificate warning any longer.
  • Edit /etc/postfix/main.cf:
  • smtpd_use_tls=yes
  • postconf -e smtpd_tls_auth_only=yes
  • This was set to no in Maya server???
  • If you truly do want to forbid unencrypted SMTP connections (I do this on ports 587 and 465), you'd want to use either "smtpd_tls_security_level = encrypt" (for STARTTLS, generally on port 587) or "smtpd_tls_wrappermode = yes" (for SSL encryption from the initial connection on, generally on port 465).
  • See Postgrey section to install and configure GreyListing
  • Another suggestion for spam management:
  • If you're not using it - postgrey is super effective for grey listing. apt-get install postgrey and mod /etc/postfix/main.cf like this:
  • =====
  • # -=CAH=-
  • # smtp server restrictions
  • smtpd_recipient_restrictions =
  • permit_mynetworks,
  • permit_sasl_authenticated,
  • reject_unauth_destination,
  • check_policy_service inet:127.0.0.1:60000,
  • # -=CAH=- next 8 variables problematic for some environments
  • reject_invalid_hostname,
  • reject_non_fqdn_hostname,
  • reject_non_fqdn_sender,
  • reject_non_fqdn_recipient,
  • reject_unknown_sender_domain,
  • reject_unknown_recipient_domain,
  • reject_unauth_pipelining,
  • # -=CAH=- following line zaps mail with no ptr record
  • # reject_unknown_client, (requires sender server have PTR record)
  • reject_rbl_client zombie.dnsbl.sorbs.net,
  • reject_rbl_client relays.ordb.org,
  • reject_rbl_client opm.blitzed.org,
  • reject_rbl_client list.dsbl.org,
  • reject_rbl_client zen.spamhaus.org,
  • reject_rbl_client blackholes.mail-abuse.org,
  • reject_rbl_client cbl.abuseat.org,
  • reject_rbl_client relays.mail-abuse.org,
  • reject_rbl_client bl.spamcop.net,
  • reject_rbl_client or.orbl.org,
  • reject_rhsbl_sender dsn.rfc-ignorant.org,
  • =====
  • Restart postfix and you'll be in good shape. I have mail servers that reject ~100k messages per day, but only deliver ~2000 messages to user inboxes, out of which less than 50 are tagged as spam by SA and amavis.
  • The combination of the rules, rbls and grey listing noted above is pretty good for reducing cpu loads, but eliminating most spam.
  • Performance issues with Postfix
  • The 2 changes in the master.cf file below with cause 2 warnings in the /var/log/mail.log file:
warning: unexpected attribute W in input from smtp socket
warning: deliver_request_get: error receiving common attributes
  • edit /etc/postfix/master.cf to reset the process limit from the default of 100 to 10 with the following line:
  • smtp inet n - - - 10 smtpd
  • Limit the number of concurrent outbound connections by editing the following line to look like this:
  • smtp unix - - n 4 - smtp
  • Finally, add the following to /etc/postfix/main.cf:
  • default_process_limit = 10


  • Limit user’s mailbox and message sizes in to /etc/postfix/main.cf
  • These will set it to unlimited
  • mailbox_size_limit = 0
  • message_size_limit = 0
  • virtual_mailbox_limit = 0
  • Do a postconf -d | grep size and check the values:
  • mailbox_size_limit = 51200000
  • message_size_limit = 10240000
  • virtual_mailbox_limit = 51200000
  • Set the limits in 1 Meg increments if you want:
  • 1 meg = 1048576
  • Manually set sizes:
  • postconf –e mailbox_size_limit=0
  • postconf –e message_size_limit=0
  • Restart with /etc/init.d/postfix restart


Go to top


  • Force PHPMyAdmin to SSL
  • Assuming you already have SSL installed and configured
  • Edit /etc/phpmyadmin/config.inc.php – and add:
  • $cfg[‘ForceSSL’] = true;
  • Restart apache2
  • Anti-Spam and Anti-Virus
  • Edit /etc/amavis/conf.d/20-debian_defaults:
  • Change $sa_tag_level_deflt to undef for debugging – which will place a X-Spam Status header on all emails not just certain emails.
  • Change $final_spam_destiny to D_PASS
  • Edit /etc/amavis/conf.d/15-content_filter_mode:
  • Uncomment both @bypass… lines (4 total #’s)
  • Edit /etc/amavis/conf.d/50-user (this fixed later problem no header spam scores)
  • Add "@local_domains_acl = ( "." );"
  • Edit /etc/spamassassin/local.cf:
  • Add “bayes_auto_expire 0"
  • /etc/init.d/amavis restart
  • Test to see if Amavis is listening:
  • netstat -nap | grep 10024
  • should get “tcp 0 0 127.0.0.1:10024 0.0.0.0:* LISTEN 12345/amavisd” or something close
  • Check /var/log/mail.log for errors if not
  • Edit /etc/postfix/main.cf
  • Add “content_filter=smtp-amavis:[127.0.0.1]:10024”
  • Add “receive_override_options=no_address_mappings”
  • Edit /etc/postfix/master.cf and add the following:
  • smtp-amavis unix - - n - 2 smtp
  • -o smtp_data_done_timeout=1200
  • -o smtp_send_xforward_command=yes
  • -o disable_dns_lookups=yes
  • -o max_use=20
  • 127.0.0.1:10025 inet n - - - - smtpd
  • -o content_filter=
  • -o local_recipient_maps=
  • -o relay_recipient_maps=
  • -o smtpd_restriction_classes=
  • -o smtpd_delay_reject=no
  • -o smtpd_client_restrictions=permit_mynetworks,reject
  • -o smtpd_helo_restrictions=
  • -o smtpd_sender_restrictions=
  • -o smtpd_recipient_restrictions=permit_mynetworks,reject
  • -o smtpd_data_restrictions=reject_unauth_pipelining
  • -o smtpd_end_of_data_restrictions=
  • -o mynetworks=127.0.0.0/8
  • -o smtpd_error_sleep_time=0
  • -o smtpd_soft_error_limit=1001
  • -o smtpd_hard_error_limit=1000
  • -o smtpd_client_connection_count_limit=0
  • -o smtpd_client_connection_rate_limit=0
  • -o receive_override_options=no_header_body_checks,no_unknown_recipient_checks
  • -o local_header_rewrite_clients=
  • Restart Postfix first:
  • postfix reload
  • Setting receive_override_options=no_address_mappings makes Postfix not consider aliases any more. So if you wish to disable AMaViS as a content filter then you must not set this parameter either.
  • Another tiny caveat is that the user "clamav" must be a member of the system group "amavis" so that the two services are allowed to talk to each other:
  • adduser clamav amavis
  • /etc/init.d/clamav-daemon restart
  • Edit /etc/amavis/conf.d/50-user and add the following above the “1”
  • @lookup_sql_dsn = (
  • ['DBI:mysql:database=mailserver;host=127.0.0.1;port=3306',
  • 'mailuser',
  • 'mailuser2007']);
  • $sql_select_policy = 'SELECT name FROM virtual_domains WHERE CONCAT("@",name) IN (%k)';
  • /etc/init.d/amavis restart
  • Test send an email and look at header, should have something:
  • X-Virus-Scanned: Debian amavisd-new at mymailserver
  • X-Spam-Score: 0
  • X-Spam-Level:
  • X-Spam-Status: No, score=0 tagged_above=-9999 required=6.31 tests=[none]
  • Test with a sudo-real virus email by sending a sample to a user:
  • sendmail john@example.com < /usr/share/doc/spamassassin/examples/sample-spam.txt
  • Should come back as spam and look at header and log for more info
  • Fix permissions on this file:
  • chmod o= /etc/amavis/conf.d/50-user
  • Create script to teach bayes filter daily and place it in cron.daily
  • Create a “MissedSpam” and “NotSpam” folder for each user or create the same 2 folders as public IMAP folders (which I do not know how to do yet).
  • Best to do Install Squirrelmail below and squirrelmail-configure
  • Make sure owner is vmail:vmail and chmod 700 if you create folders manually at prompt
  • Create a file to have cron execute each day and call it something like “spam_teach_script” and place it in /etc/cron.daily/ folder and make the file executable.
  • n the spam_teach_script file have the following:
  • #!/bin/bash –e
  • SADIR=/var/lib/amavis/.spamassassin
  • DBPATH=/var/lib/amavis/.spamassassin/bayes
  • SPAMFOLDERS=”\
  • /home/vmail/spamfolder \
  • /home/vmail/domain.com/rodney/.MissedSpam/new \
  • /home/vmail/domain.com/jane/.MissedSpam/new \
  • /home/vmail/domain.com/rodney/.MissedSpam/cur \
  • /home/vmail/domain.com/jane/.MissedSpam/cur \
  • HAMFOLDER=”\
  • /home/vmail/hamfolder \
  • /home/vmail/domain.com/rodney/.NotSpam/new \
  • /home/vmail/domain.com/jane/.NotSpam/new \
  • /home/vmail/domain.com/rodney/.NotSpam/cur \
  • /home/vmail/domain.com/jane/.NotSpam/cur \
  • for spamfolder in $SPAMFOLDERS ; do \
  • echo Learning spam from $spamfolder ; \
  • nice sa-learn --spam --showdots --dbpath $DBPATH $spamfolder
  • done
  • for hamfolder in $HAMFOLDERS ; do \
  • echo Learning ham from $hamfolder ; \
  • nice sa-learn --ham --showdots --dbpath $DBPATH $hamfolder
  • done
  • chown –R amavis:amavis $SADIR
  • rm –f /home/vmail/spamfolder/*
  • rm –f /home/vmail/domain.com/rodney/.MissedSpam/new/*
  • rm –f /home/vmail/domain.com/jane/.MissedSpam/new/*
  • rm –f /home/vmail/domain.com/rodney/.MissedSpam/cur/*
  • rm –f /home/vmail/domain.com/jane/.MissedSpam/cur/*
  • rm –f /home/vmail/hamfolder/*
  • rm –f /home/vmail/domain.com/rodney/.NotSpam/new/*
  • rm –f /home/vmail/domain.com/jane/.NotSpam/new/*
  • rm –f /home/vmail/domain.com/rodney/.NotSpam/cur/*
  • rm –f /home/vmail/domain.com/jane/.NotSpam/cur/*
  • Then somehow I made it send me a copy of the learning in an email each day???


  • Do this command to see teaching progress:
  • sa-learn --dbpath /var/lib/amavis/.spamassassin/bayes --dump magic
  • To make the daily cron.daily’s work:
  • apt-get install anacron
  • execute ‘anacron” to get it started
  • Squirrelmail
  • ln -s /etc/squirrelmail/apache.conf /etc/apache2/conf.d/squirrelmail.conf
  • apache2ctl restart
  • Execute “squirrelmail-configure”
  • select option 3 (Folder Defaults) and set option 1 (Default Folder Prefix) to 'none'
  • Change other setting as needed.
  • Save and exit
  • Sign in with full email address and password
  • Create a /home/vmail/globalsieverc file containing these lines:
  • require ["fileinto"];
  • # Move spam to spam folder
  • if exists "X-Spam-Flag" {
  • fileinto "spam";
  • stop;
  • }
  • Send spam email again:
  • sendmail rodney@domain.com < /usr/share/doc/spamassassin/examples/sample-spam.txt
  • Look at “/home/vmail/dovecot-deliver.log” and see that the email was moved to spam folder.
  • Use squirrelmail or Outlook to see the new spam folder and the email in it.
  • Add the spam folder by going to “Folders” and select “Subscribe” button on the bottom where the spam folder is at. Log out and back in and it will be on the left column.
  • Postgrey
  • If I want to enable Greylisting then do the following:
  • apt-get install postgrey
  • Edit /etc/postfix/main.cf, add this to the end of smtpd_recipient_restrictions
  • ,check_policy_service inet:127.0.0.1:60000
  • Reload Postfix
  • /etc/init.d/postfix reload
  • Edit /etc/postgrey/whitelist_clients
    1. My listing
  • domain.com
  • user@domain.com
  • edit /etc/default/postgrey to set durations and add to end of POSTGREY_OPTS line:
  • --delay=300 --max-age=20 --auto-whitelist-clients=10”
  • This will delay 300 seconds (5 min), if seen within 20 days, whitelist once been here at least 10 times.
  • /etc/init.d/postfix reload
  • The 5-minute delay of receiving email can be seen in mail.log
  • To get a report indexed by IP do the following command:
  • #cat /var/log/mail.log | postgreyreport \
--nosingle_line --check_sender=mx,a --show_tries \
--separate_by_subnet=":====================\n”
  • Emails marked for deletion from clients remain on the server. To delete emails marked for deletion from the server use crontab with the following command:
  • find /home/vmail/ -name '*,ST' -ctime +7 | xargs rm -f
  • This will add “.ST” to the end of all marked emails and with the –ctime of +7 means older than 7 days.


  • DHCP Server
  • Uses dhcpd for the DHCP server
  • “apt-get install dhcp”
  • /etc/init.d/dhcp stop and then edit /etc/dhcpd.conf file and then start the server again
  • Log messages go to the syslog so go there to check for errors
  • Sample:
  • Default-lease-time 600;
  • Max-lease-time 7200;
  • Option subnet-mask 255.255.255.0;
  • Option broadcast-address 192.168.2.255;
  • Option routers 192.168.2.1;
  • Options domain-name-servers 192.168.2.15, 192.168.2.10;
  • Option domain-name “domain.com”;
  • Subnet 192.168.2.0 netmask 255.255.255.0 {
  • Range 192.168.2.10 192.168.2.100;
  • Range 192.168.2.150 192.168.2.200;
  • }
  • For WINS add a line:
  • Option netbios-name-servers 192.168.2.25


  • APC UPS Installation and configuration
  • Plug USB cable from the UPS to the server
  • Execute lsusb -v to see it on the bus – see if HID section is there
  • Execute – cat /proc/bus/usb/devices
  • Look down the list to find on an “S” line Manufacturer = APC
  • In the APC section look at the “I” line for Driver=usbhid. If it is there then it will communicate well with the server. If not and Driver=none then the HID driver needs to be loaded or the Linux kernel is pre-2.4.x and needs to be upgraded.
  • Check for /dev/usb/hiddev(#) device node is there using the “ls” command
  • Install the program “aptitude install apcupsd”
  • Edit /etc/apcupsd/apcupsd.conf and make the lines look like this
  • UPSCABLE usb
  • UPSTYPE usb
  • Comment out DEVICE
  • Edit /etc/default/apcupsd and change ISCONFIGURED=no to yes
  • Execute /sbin/apcupsd to start up the apsusbd program
  • Then execute apcaccess to show status of UPS
  • Execute ls –l /etc/rc?.d/*apcupsd to show all the links in the startup and shutdown level folders for apcupsd. Preceeded with a “K” means Kill, preceeded with an “S” means start. Runlevel 0 is Halt, Runlevel 1 is Single User Mode, Runlevel 2 is Multi-User Mode, Runlevel 3 is Multi-User Mode with Network, Runlevel 4 is Unused, Runlevel 5 is X11 ( as runlevel 3 + display), Runlevel 6 is reboot, Runlevel S is Single User Mode does not configure network or start daemons. It should startup automatically upon bootup.
  • The event file is in /var/log/apcupsd.events
  • Probably no need to rotate the log because it won’t get that big (hope anyway).
  • Execute ps fax and look for /sbin/apcupsd as running. There will be 1 or 3 lines with this in it (main and 2 threads).


  • Adding SSL Certificate
  • To add a self-signed certificate
  • cd (and make) a folder you want the files in /etc/ssl/temp
  • Openssl genrsa –des3 –out server.key 1024
  • Enter in a passphrase for the key
  • Leave out the “-des3” above so no passphrase is needed
  • Create Certificate request based on server private/public key
  • Openssl req –new –key server.key –out server.csr
  • Country = US
  • State = Washington
  • City = Kent
  • Org. Name = My Company
  • Org. Unit = Web
  • Common Name = www.mycompany.com
  • Email = gerald@mycompany.com
  • openssl x509 -req -days 3650 -in server.csr -signkey server.key -out server.crt
  • Copy certificate file (crt) and any intermediate files to /etc/ssl/certs
  • Copy server key file (key) to /etc/ssl/private
  • Request a certificate from SSL provider.
  • Navigate to a folder you want files such as cd /etc/ssl/temp
  • Create server key file from server:
  • Openssl genrsa –des3 –out server.key 1024
  • Enter in a passphrase for the key
  • Leave out the “-des3” above so no passphrase is needed
  • Create Certificate request based on server private/public key
  • Openssl req –new –key server.key –out server.csr
  • Country = US
  • State = Washington
  • City = Kent
  • Org. Name = Nevels Stoves
  • Org. Unit = Web
  • Common Name = www.nevelsparts.com
  • Email = gerald@nevels4home.com
  • Copy the server.csr file to the CA you are requesting the cert from
  • This will generate a .KEY file that must be copied to the server. (/etc/ssl/private).
  • Make sure ServerName and ServerAlias match “common name”
  • This was accomplished by adding the following lines inside my <VirtualHost *:80> block (I did it at the top, but that almost certainly doesn’t matter):
  • ServerName www.bonanzle.com
ServerAlias www.bonanzle.com
  • Copy certificate file (crt) and any intermediate files to /etc/ssl/certs
  • Copy server key file (key) to /etc/ssl/private
  • Enabled mods with a2enmod ssl and a2enmod headers
  • Edit and include following in /etc/apache2/sites-available/default
  • <VirtualHost *:443>
# SSL requests should proxy just like normal ones... this is the same
# code I use in my "VirtualHost *:80" block to forward http requests
# to my mongrel cluster... If you have different proxying code,
# you'd paste that here.
RewriteEngine On
RewriteCond %{DOCUMENT_ROOT}/system/maintenance.html -f
RewriteCond %{SCRIPT_FILENAME} !maintenance.html
RewriteRule ^.*$ /system/maintenance.html [L]
RewriteRule ^/$ /index.html [QSA]
RewriteRule ^([^.]+)$ $1.html [QSA]
RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f
RewriteRule ^/(.*)$ balancer://railsapp%{REQUEST_URI} [P,QSA,L]
# The actual SSL stuff, make sure the engine is on, enable some options that the Gutsy page said I should,
# and tell Apache where my key+CSR files are
  • All that’s needed:
  • ServerAdmin webmaster@localhost
  • Servername nevelspas.com
  • DocumentRoot /var/www/nevelspas
  • SSLEngine on
SSLOptions +FakeBasicAuth +ExportCertData +StrictRequire
SSLCertificateFile /etc/ssl/certs/bonanzle.crt
SSLCertificateKeyFile /etc/ssl/private/bonanzle.key
  • ErrorLog /var/log/apache2/nevelspas.error.log
  • LogLevel warn
  • CustomLog /var/log/apache2/nevelspas.access.log combined
  • # Used by Rails. Mentioned in all the Rails SSL tutorials.
RequestHeader set X_FORWARDED_PROTO "https"
</VirtualHost>
  • Restart apache
  • Installing SquirrelCart
  • Download and copy files to its own folder in /var/www/????
  • apt-get install expat
  • fsockopen is required but installed by default
  • login to mysql –p with root password and do the following:
  • create database partsdb;
  • GRANT ALL PRIVILEGES ON *.* TO ‘partsuser’@’localhost’ IDENTIFIED BY ‘<password>’
  • put in FTP info of server and the root folder for the website ie, /var/www/website
  • fill in all info to set all permissions and fix any errors it finds
  • make sure in the file location folders to have the first 2 lines say http://www.website.com and https://www.website.com
  • After install is done delete the sc_install folder or rename it
  • mv /var/www/website/squirrelcart/sc_data /var/www/website/sc_data
  • edit /var/www/website/squirrelcart-v2.6.1/squirrelcart/config.php and change line to read $sc_data_path = ‘../sc_data’;
  • Should be good to go.
  • Upgrading OpenSSL
  • Do the following commands to test openssl vulnerability:
  • If see “weak keys” then need to update OpenSSL
  • Do apt-get update
  • apt-get upgrade
  • apt-get dist-upgrade
  • Should see openssl upgrade
  • Should get warnings about key files needing updated after upgrade of OpenSSL, do the following commands to do the upgrades:
  • ssh-keygen –l –f /etc/ssh/ssh_host_rsa_key
  • ssh-keygen –l –f /etc/ssh/ssh_host_dsa_key
  • Do “./dowkd.pl host servername.domain.com” to recheck keys
  • Should be no weak keys now


Go to top


  • Installing MediaWiki
  • Need to install apt-get install libgd2-xpm-dev
  • Edit /etc/php5/apache2/php.ini
  • upload_max_filesize = 8M (or more, less)
  • memory_limit = 12M (or more)
  • add - extension=mysql.so
  • if use GD graphics vs. ImageMagick add – extension=gd.so
  • add – wiki record and index the count
  • /etc/init.d/bind9 restart
  • cp /etc/apache2/sites-available/domain /etc/apache2/sites-available/wiki
  • vim /etc/apache2/sites-available/wiki and alter to point to folders and alias to wiki.domain.com and log file names
  • a2ensite wiki
  • apache2ctl restart
  • browse to http://wiki.domain.com and click “set up the wiki”
  • name – DomainWiki
  • contact email
  • admin name – wikiSysop with <password> as password
  • no caching – improves performance but need memcache install/configured first
  • keep email configs the same
  • MySQL database name = wikidb
  • MySQL db username = wikiuser
  • Db username password = <password>
  • Checked to use root w/ mysql password <password>
  • No db prefix, keep InnoDB, and keep character set
  • Press Install MediaWiki
  • mv config/LocalSettings.php . (moves it to wiki folder)
  • rm –rf config (to remove the config folder)
  • It should work now
  • To change allow upload of files (pictures) change LocalSettings.php $wgEnableUploads to true
  • Specify upload file types $wgFileExtensions
  • The image upload folder needs chmod a+w /var/www/wiki/images
  • To enable thumbnails
  • aptitude install imagemagick
  • in LocalSettings.php
  • $wgUseImageResize = true;
  • $wgUseImageMagick = true;
  • $wgImageMagickConvertCommand = “/usr/bin/convert”;
  • Change logo with a 135x135 pixel jpg file in wiki folder
  • $wgLogo = “$wgScriptPath/wiki.jpg”;
  • Make it so users have to confirm email before editing
  • $wgEmailConfirmToEdit = true; (this is a default setting and may not be needed)
  • To restrict anonymous editing of pages
  • $wgGroupPermissions[‘*’][‘edit’] = false;
  • Favicon
  • $wgFavicon = “$wgScriptPath/favicon.ico”;
  • Let sysop edit left side bar
  • $wgGroupPermissions[‘sysop’][‘editinterfaces’] = true;
  • Remove Toolbox from left nav unless logged in:
  • Note: The following has the syntax "div" and "h5" spaced out to be seen here but should not have the spaces in actual practice. I spaced them out here to keep the wiki from actually executing the html code.
  • Edit the file: /skins/MonoBook.php. Find the section that looks like this (by searching for p-tb):
  • < d i v class="portlet" id="p-tb">
  • < h 5 ><?php $this->msg('toolbox') ?>< / h 5 >
  • Replace with this:
  • < d i v class="portlet" id="p-tb">
  • <?php if($this->data['loggedin']) { ?>
  • < h 5 ><?php $this->msg('toolbox') ?>< / h 5 >
  • Go down to the bottom of the div block that you are editing and find the section that looks like this:
  • wfRunHooks( 'MonoBookTemplateToolboxEnd', array( &$this ) );
  • ?>
  • </ul>
  • </div>
  • </div>
  • and add the line (between the two /div's) that closes off your new "if" statement:
  • wfRunHooks( 'MonoBookTemplateToolboxEnd', array( &$this ) );
  • ?>
  • </ul>
  • </div>
  • <?php } ?>
  • </div>
  • To enable and restrict file upload access
  • /var/www/wiki/LocalSettings.php
  • $wgEnableUploads = true; # Enable uploads
  • Upload permissions
  • Per default, all registered users can upload files. To restrict this, you have to change Manual:$wgGroupPermissions:
  • To prevent normal users from uploading files:

$wgGroupPermissions['user']['upload'] = false;

  • To create a special group called "uploadaccess", and allow members of that group to upload files:

$wgGroupPermissions['uploadaccess']['upload'] = true;

  • To allow "autoconfirmed" (non-newbie) users to upload files:

$wgGroupPermissions['autoconfirmed']['upload'] = true;

  • The right to replace existing files is handled by an extra permission, called reupload:
  • To prevent normal users from overriding existing files:

$wgGroupPermissions['user']['reupload'] = false;

  • To allow "autoconfirmed" (non-newbie) users to replace existing files:

$wgGroupPermissions['autoconfirmed']['reupload'] = true;

  • Configuring file types
  • You can add to $wgFileExtensions to allow uploads of any type of file you like. If not included then the $wgFileExtensions line would look something like
  • $wgFileExtensions = array('png', 'gif', 'jpg', 'jpeg', 'doc', 'xls', 'mpp', 'pdf', 'zip');
  • Or
  • $wgFileExtensions = array_merge($wgFileExtensions, array('doc', 'xls', 'mpp', 'pdf', 'zip'));
  • Or
  • # Add new types to the existing list from DefaultSettings.php
  • $wgFileExtensions[] = 'doc';
  • $wgFileExtensions[] = 'xls';
  • $wgFileExtensions[] = 'pdf';
  • $wgFileExtensions[] = 'mpp';


  • Installing AwStats
  • apt-get install awstats
  • apt-get install libnet-ip-perl (probably already installed)
  • apt-get install libgeo-ipfree-perl (for geoipfree plugin to work)
  • cp /etc/awstats/awstats.conf /etc/awstats.www.domain1.com.conf
  • cp /etc/awstats/awstats.conf /etc/awstats.www.domain2.com.conf
  • vim /etc/awstats.www.domain1.com.conf
  • LogFile=”/var/log/apache2/domain1.access.log.1”
  • LogType=W (W for web, M for mail, F for FTP)
  • LogFormat=1 (for combined)
  • SiteDomain=www.domain1.com
  • Uncomment LoadPlugin=”geoipfree”
  • perl /usr/lib/cgi-bin/awstats.pl –config=www.domain1.com –update
  • depending on the size of the log file this could be a while
  • Make an executable file with the following for cron.daily:
  • #! /bin/sh
  • perl /usr/lib/cgi-bin/awstats.pl -config=www.domain1.com -output -staticlinks > /var/www/domain1/awstats.html
  • perl /usr/lib/cgi-bin/awstats.pl -config=www.domain1.com -output=alldomains -staticlinks > /var/www/domain1/awstats.www.domain1.com.alldomains.html
  • perl /usr/lib/cgi-bin/awstats.pl -config=www.domain1.com -output=allhosts -staticlinks > /var/www/domain1/awstats.www.domain1.com.allhosts.html
  • perl /usr/lib/cgi-bin/awstats.pl -config=www.domain1.com -output=lasthosts -staticlinks > /var/www/domain1/awstats.www.domain1.com.lasthosts.html
  • perl /usr/lib/cgi-bin/awstats.pl -config=www.domain1.com -output=unknownip -staticlinks > /var/www/domain1/awstats.www.domain1.com.unknownip.html
  • perl /usr/lib/cgi-bin/awstats.pl -config=www.domain1.com -output=alllogins -staticlinks > /var/www/domain1/awstats.www.domain1.com.alllogins.html
  • perl /usr/lib/cgi-bin/awstats.pl -config=www.domain1.com -output=lastlogins -staticlinks > /var/www/domain1/awstats.www.domain1.com.lastlogins.html
  • perl /usr/lib/cgi-bin/awstats.pl -config=www.domain1.com -output=allrobots -staticlinks > /var/www/domain1/awstats.www.domain1.com.allrobots.html
  • perl /usr/lib/cgi-bin/awstats.pl -config=www.domain1.com -output=lastrobots -staticlinks > /var/www/domain1/awstats.www.domain1.com.lastrobots.html
  • perl /usr/lib/cgi-bin/awstats.pl -config=www.domain1.com -output=urldetail -staticlinks > /var/www/domain1/awstats.www.domain1.com.urldetail.html
  • perl /usr/lib/cgi-bin/awstats.pl -config=www.domain1.com -output=urlentry -staticlinks > /var/www/domain1/awstats.www.domain1.com.urlentry.html
  • perl /usr/lib/cgi-bin/awstats.pl -config=www.domain1.com -output=urlexit -staticlinks > /var/www/domain1/awstats.www.domain1.com.urlexit.html
  • perl /usr/lib/cgi-bin/awstats.pl -config=www.domain1.com -output=browserdetail -staticlinks > /var/www/domain1/awstats.www.domain1.com.browserdetail.html
  • perl /usr/lib/cgi-bin/awstats.pl -config=www.domain1.com -output=osdetail -staticlinks > /var/www/domain1/awstats.www.domain1.com.osdetail.html
  • perl /usr/lib/cgi-bin/awstats.pl -config=www.domain1.com -output=unknownbrowser -staticlinks > /var/www/domain1/awstats.www.domain1.com.unknownbrowser.html
  • perl /usr/lib/cgi-bin/awstats.pl -config=www.domain1.com -output=unknownos -staticlinks > /var/www/domain1/awstats.www.domain1.com.unknownos.html
  • perl /usr/lib/cgi-bin/awstats.pl -config=www.domain1.com -output=refererse -staticlinks > /var/www/domain1/awstats.www.domain1.com.refererse.html
  • perl /usr/lib/cgi-bin/awstats.pl -config=www.domain1.com -output=refererpages -staticlinks > /var/www/domain1/awstats.www.domain1.com.refererpages.html
  • perl /usr/lib/cgi-bin/awstats.pl -config=www.domain1.com -output=keyphrases -staticlinks > /var/www/domain1/awstats.www.domain1.com.keyphrases.html
  • perl /usr/lib/cgi-bin/awstats.pl -config=www.domain1.com -output=keywords -staticlinks > /var/www/domain1/awstats.www.domain1.com.keywords.html
  • perl /usr/lib/cgi-bin/awstats.pl -config=www.domain1.com -output=errors404 -staticlinks > /var/www/domain1/awstats.www.domain1.com.errors404.html
  • can execute this file to initiate the html pages.
  • Apt-get install iftop
  • Apt-get install htop
  • LogWatch
  • apt-get install logwatch
  • vim /usr/share/logwatch/default.conf/logwatch.conf
  • MailTo=Rodney@domain.com
  • Print = No
  • Detail = High (Low, Med, High)
  • logwatch (to execute – will get an email daily via cron)


  • Troubleshooting
  • Check /var/log/mail.log where 93.7% of all problems cause a more or less clear error message there.
  • Run postfix check. No output means everything is well.
  • Ask on the #postfix IRC channel on irc.freenode.net. I usually attend there as Signum but please just ask and wait for people to help you. Especially read the hints in the channel's topic.
  • This tutorial is meant for Debian "Etch". If you are trying this setup on any other distribution you are completely on your own. No, Ubuntu does not count as Debian because the package versions differ.
  • Notes
  • Check /var/lib/amavis/virusmails/ for any emails in there. This is the quarantine area for emails.
  • Versions:
  • Ubuntu 7.10 (Gutsy Gibbon)
  • Linux Kernal 2.6.22-14-38 - server (old)
2.6.22-15.39 – server (new)
  • Perl 5.8.8
  • Apache2 2.2.4.3
  • Postfix 2.4.5-3
  • Webmin 1.4.10 (died)
  • Amavis 2.4.2
  • Squirrelmail 1.4.10a
  • APCupsd 3.14.1
  • MySQL 5.0.45
  • ClamAV 0.92.1
  • Dovecot 1.0.5
  • Spamassassin 3.2.3
  • OpenSSL-Blacklist 0.1-0ubuntu0.7.10.4 (new)
0.9.8e 23 Feb 2007 (old)
  • Bind 1:9.4.1-P1-3
  • DHCP 2.0pl5dfsg1-20
  • Mutt 1.5.15
  • PHP5 5.2.3
  • Python 2.5.1-1
  • Samba 3.0.26a
Personal tools