Nastavení mail serveru: Porovnání verzí
Skočit na navigaci
Skočit na vyhledávání
Bez shrnutí editace |
Bez shrnutí editace |
||
Řádek 10: | Řádek 10: | ||
=Instalační skript= |
=Instalační skript= |
||
Většina návodů je |
Většina návodů je provedena jako dlouhý popis postupu s mnoha útržkovými částmi příkazů, které je potřeba provést. To je zdlouhavý proces kopírovat jednotlivé části povelů a po částech je provádět. Místo toho bychom rádi měli jednoduchou instalaci, kterou prostě spustíme, chvíli počkáme a máme hotovo. Zde je předložen skript, který se toto dle jednoho návodu snaží docílit. |
||
<source lang="php"> |
|||
<pre> |
|||
<?php |
|||
#!/bin/bash |
|||
$MysqlRootPassword = 'MysqlRootPassword'; |
|||
ROOT_PASSWORD=mysql_root_passwod |
|||
$MysqlUserPassword = 'MysqlUserPassword'; |
|||
PASSWORD=mail_admin_password |
|||
$PostfixAdminName = 'PostfixAdminName'; |
|||
$PostfixSetupPassword = 'PostfixSetupPassword'; |
|||
$DomainName = 'domain.com'; |
|||
$ServerDomain = 'mail.'.$DomainName; |
|||
function Execute($Command) |
|||
# LAMP web server |
|||
{ |
|||
apt-get update |
|||
echo('Executing: '.$Command."\n"); |
|||
apt-get upgrade --assume-yes |
|||
passthru($Command); |
|||
apt-get install --assume-yes lamp-server^ |
|||
} |
|||
function InstallPackages() |
|||
apt-get install --assume-yes \ |
|||
{ |
|||
// LAMP web server |
|||
Execute('apt-get update'); |
|||
Execute('apt-get upgrade --assume-yes'); |
|||
Execute('apt-get install --assume-yes lamp-server^'); |
|||
Execute('apt-get install --assume-yes \ |
|||
php-apc \ |
php-apc \ |
||
php5-mcrypt \ |
php5-mcrypt \ |
||
Řádek 29: | Řádek 41: | ||
php5-curl \ |
php5-curl \ |
||
php5-gd \ |
php5-gd \ |
||
php-xml-parser |
php-xml-parser'); |
||
ln -sf ../../mods-available/mcrypt.ini /etc/php5/apache2/conf.d/20-mcrypt.ini |
Execute('ln -sf ../../mods-available/mcrypt.ini /etc/php5/apache2/conf.d/20-mcrypt.ini'); |
||
// Configure apache |
|||
a2enmod rewrite ssl |
Execute('a2enmod rewrite ssl'); |
||
a2ensite default-ssl |
Execute('a2ensite default-ssl'); |
||
service apache2 restart |
Execute('service apache2 restart'); |
||
// Memcached |
|||
apt-get install --assume-yes memcached |
Execute('apt-get install --assume-yes memcached'); |
||
// Mail packages |
|||
Execute('apt-get install --assume-yes mail-server^'); |
|||
Execute('apt-get install --assume-yes \ |
|||
# Mail packages |
|||
apt-get install --assume-yes mail-server^ |
|||
apt-get install --assume-yes \ |
|||
postfix-mysql \ |
postfix-mysql \ |
||
dovecot-mysql \ |
dovecot-mysql \ |
||
Řádek 53: | Řádek 65: | ||
clamav-daemon \ |
clamav-daemon \ |
||
spamassassin \ |
spamassassin \ |
||
php5-imap |
php5-imap'); |
||
ln -sf ../../mods-available/imap.ini /etc/php5/apache2/conf.d/20-imap.ini |
Execute('ln -sf ../../mods-available/imap.ini /etc/php5/apache2/conf.d/20-imap.ini'); |
||
service apache2 restart |
Execute('service apache2 restart'); |
||
apt-get install --assume-yes \ |
Execute('apt-get install --assume-yes \ |
||
pyzor \ |
pyzor \ |
||
razor \ |
razor \ |
||
Řádek 73: | Řádek 85: | ||
unrar-free \ |
unrar-free \ |
||
zip \ |
zip \ |
||
zoo |
zoo'); |
||
} |
|||
function PrepareDatabase() |
|||
{ |
|||
global $MysqlUserPassword, $MysqlRootPassword; |
|||
// Mail database |
|||
Execute('mysql -uroot -p'.$MysqlRootPassword.' -Bse \ |
|||
"drop database mail; create database mail; |
|||
grant all on mail.* to \'mail\'@\'localhost\' identified by \''.$MysqlUserPassword.'\';"'); |
|||
} |
|||
function UpdatePHPConfigFile($FileName, $BaseVariable, $Parameters) |
|||
{ |
|||
if(!file_exists($FileName.'_backup')) |
|||
file_put_contents($FileName.'_backup', file_get_contents($FileName)); |
|||
$Content = explode("\n", file_get_contents($FileName.'_backup')); |
|||
foreach($Parameters as $Parameter) |
|||
{ |
|||
if(is_array($Parameter['name'])) { |
|||
foreach($Content as $Num => $Line) |
|||
{ |
|||
$Needle = '$'.$BaseVariable.'['."'".$Parameter['name'][0]."'] = array ("; |
|||
if(substr($Line, 0, strlen($Needle)) == $Needle) |
|||
{ |
|||
echo('Found group: '.$Parameter['name'][0]."\n"); |
|||
$Needle = " '".$Parameter['name'][1]."' => "; |
|||
$I = 1; |
|||
while((($Num + $I) < count($Content)) and ($Content[$Num + $I] != ');')) |
|||
{ |
|||
if(substr($Content[$Num + $I], 0, strlen($Needle)) == $Needle) { |
|||
echo('Found group: '.$Parameter['name'][1]."\n"); |
|||
$Content[$Num + $I] = $Needle.$Parameter['value'].','; |
|||
} |
|||
$I++; |
|||
} |
|||
} |
|||
} |
|||
} else { |
|||
foreach($Content as $Num => $Line) |
|||
{ |
|||
$Needle = '$'.$BaseVariable.'['."'".$Parameter['name']."'] = "; |
|||
if(substr($Line, 0, strlen($Needle)) == $Needle) |
|||
{ |
|||
echo('Found: '.$Parameter['name']."\n"); |
|||
$Content[$Num] = $Needle.$Parameter['value'].';'; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
file_put_contents($FileName, implode("\n", $Content)); |
|||
} |
|||
function generate_setup_password_salt() |
|||
{ |
|||
$salt = time().'*'.mt_rand(0,60000); |
|||
$salt = md5($salt); |
|||
return $salt; |
|||
} |
|||
function encrypt_setup_password($password, $salt) |
|||
{ |
|||
return $salt . ':' . sha1($salt . ':' . $password); |
|||
} |
|||
function InstallPostfixAdmin() |
|||
{ |
|||
global $ServerDomain, $PostfixAdminName, $MysqlUserPassword, $PostfixSetupPassword, $DomainName; |
|||
Execute('wget "http://downloads.sourceforge.net/project/postfixadmin/postfixadmin/'. |
|||
$PostfixAdminName.'/'.$PostfixAdminName.'.tar.gz?r=&ts=1417890779&use_mirror=netcologne" -O '. |
|||
$PostfixAdminName.'.tar.gz'); |
|||
Execute('tar -xf '.$PostfixAdminName.'.tar.gz'); |
|||
Execute('rm -f '.$PostfixAdminName.'.tar.gz'); |
|||
Execute('mv '.$PostfixAdminName.' /var/www/html/postfixadmin'); |
|||
Execute('chown -R www-data:www-data /var/www/html/postfixadmin'); |
|||
UpdatePHPConfigFile('/var/www/html/postfixadmin/config.inc.php', 'CONF', array( |
|||
array('name' => 'setup_password', 'value' => "'".encrypt_setup_password($PostfixSetupPassword, generate_setup_password_salt())."'"), |
|||
array('name' => 'configured', 'value' => 'true'), |
|||
array('name' => 'postfix_admin_url', 'value' => "'https://".$ServerDomain."/postfixadmin'"), |
|||
array('name' => 'database_type', 'value' => "'mysql'"), |
|||
array('name' => 'database_host', 'value' => "'localhost'"), |
|||
array('name' => 'database_user', 'value' => "'mail'"), |
|||
array('name' => 'database_password', 'value' => "'".$MysqlUserPassword."'"), |
|||
array('name' => 'database_name', 'value' => "'mail'"), |
|||
array('name' => 'admin_email', 'value' => "'admin@".$DomainName."'"), |
|||
array('name' => 'user_footer_link', 'value' => "'https://".$ServerDomain."/main.php'"), |
|||
array('name' => 'show_footer_text', 'value' => "'YES'"), |
|||
array('name' => 'footer_text', 'value' => "'Return to ".$ServerDomain."'"), |
|||
array('name' => 'footer_link', 'value' => "'https://".$ServerDomain."'"), |
|||
array('name' => array('default_aliases', 'abuse'), 'value' => "'abuse@".$DomainName."'"), |
|||
array('name' => array('default_aliases', 'hostmaster'), 'value' => "'hostmaster@".$DomainName."'"), |
|||
array('name' => array('default_aliases', 'postmaster'), 'value' => "'postmaster@".$DomainName."'"), |
|||
array('name' => array('default_aliases', 'webmaster'), 'value' => "'webmaster@".$DomainName."'"), |
|||
)); |
|||
} |
|||
function VirtualMailUser() |
|||
{ |
|||
Execute('useradd -r -u 150 -g mail -d /var/vmail -s /sbin/nologin -c "Virtual maildir handler" vmail'); |
|||
Execute('mkdir /var/vmail'); |
|||
Execute('chmod 770 /var/vmail'); |
|||
Execute('chown vmail:mail /var/vmail'); |
|||
} |
|||
function UpdateDovecotConfigFile($FileName, $Parameters) |
|||
{ |
|||
if(!file_exists($FileName.'_backup')) |
|||
file_put_contents($FileName.'_backup', file_get_contents($FileName)); |
|||
$Content = explode("\n", file_get_contents($FileName.'_backup')); |
|||
foreach($Parameters as $Parameter) |
|||
{ |
|||
if(!is_array($Parameter['name'])) |
|||
$Parameter['name'] = array($Parameter['name']); |
|||
// First find subgroup |
|||
$Num = 0; |
|||
$NestingLevel = 0; |
|||
while(count($Parameter['name']) > 1) |
|||
{ |
|||
$Found = false; |
|||
$Needle = '#'.array_values($Parameter['name'])[0].' {'; |
|||
$I = 0; |
|||
$StartNestingLevel = $NestingLevel; |
|||
while((($Num + $I) < count($Content)) and ($NestingLevel >= $StartNestingLevel)) |
|||
{ |
|||
if(substr(trim($Content[$Num + $I]), -1, 1) == '{') $NestingLevel++; |
|||
if(substr(trim($Content[$Num + $I]), -1, 1) == '}') $NestingLevel--; |
|||
if((trim(substr(trim($Content[$Num + $I]), 0, strlen($Needle))) == $Needle) |
|||
or (trim(substr(trim($Content[$Num + $I]), 0, strlen(substr($Needle, 1)))) == substr($Needle, 1))) |
|||
{ |
|||
$Content[$Num + $I] = array_values($Parameter['name'])[0].' {'; |
|||
$Num = $Num + $I + 1; |
|||
$Found = true; |
|||
echo('Found group: '.array_values($Parameter['name'])[0]."\n"); |
|||
array_shift($Parameter['name']); |
|||
break; |
|||
} |
|||
$I++; |
|||
} |
|||
if(!$Found) break; |
|||
} |
|||
// Find and replace value |
|||
if(count($Parameter['name']) == 1) |
|||
{ |
|||
if(!array_key_exists('value', $Parameter)) |
|||
{ |
|||
$Needle = array_values($Parameter['name'])[0]; |
|||
$Parameter['value'] = ''; |
|||
} else |
|||
$Needle = array_values($Parameter['name'])[0]." ="; |
|||
$I = 0; |
|||
$StartNestingLevel = $NestingLevel; |
|||
$Found = false; |
|||
while((($Num + $I) < count($Content)) and ($NestingLevel >= $StartNestingLevel)) |
|||
{ |
|||
if(substr(trim($Content[$Num + $I]), -1, 1) == '{') $NestingLevel++; |
|||
if(substr(trim($Content[$Num + $I]), -1, 1) == '}') |
|||
{ |
|||
if($NestingLevel == $StartNestingLevel) $Content[$Num + $I] = '}'; |
|||
$NestingLevel--; |
|||
} |
|||
if((trim(substr(trim($Content[$Num + $I]), 0, strlen($Needle))) == $Needle) |
|||
or ((substr(trim($Content[$Num + $I]), 0, 1) == '#') and (substr(trim(substr(trim($Content[$Num + $I]), 1)), 0, strlen($Needle)) == $Needle))) |
|||
{ |
|||
echo('Found: '.array_values($Parameter['name'])[0]."\n"); |
|||
$Content[$Num + $I] = $Needle.' '.$Parameter['value']; |
|||
$Found = true; |
|||
break; |
|||
} |
|||
$I++; |
|||
} |
|||
// If not found then add new value |
|||
if($Found == false) |
|||
{ |
|||
echo('Added new: '.array_values($Parameter['name'])[0]."\n"); |
|||
array_splice($Content, $Num + $I - 1, 0, $Needle.' '.$Parameter['value']); |
|||
} |
|||
} |
|||
} |
|||
file_put_contents($FileName, implode("\n", $Content)); |
|||
} |
|||
function ConfigureDovecot() |
|||
{ |
|||
global $MysqlUserPassword, $DomainName; |
|||
UpdateDovecotConfigFile('/etc/dovecot/dovecot-sql.conf.ext', array( |
|||
array('name' => 'driver', 'value' => 'mysql'), |
|||
array('name' => 'connect', 'value' => 'host=localhost dbname=mail user=mail password='.$MysqlUserPassword), |
|||
array('name' => 'default_pass_scheme', 'value' => 'MD5-CRYPT'), |
|||
array('name' => 'password_query', 'value' => "SELECT username as user, password, '/var/vmail/%d/%n' as userdb_home, \\ |
|||
'maildir:/var/vmail/%d/%n' as userdb_mail, 150 as userdb_uid, 8 as userdb_gid \\ |
|||
FROM mailbox WHERE username = '%u' AND active = '1'"), |
|||
array('name' => 'user_query', 'value' => "SELECT '/var/vmail/%d/%n' as home, 'maildir:/var/vmail/%d/%n' as mail, \\ |
|||
150 AS uid, 8 AS gid, concat('dirsize:storage=', quota) AS quota \\ |
|||
FROM mailbox WHERE username = '%u' AND active = '1'"), |
|||
)); |
|||
UpdateDovecotConfigFile('/etc/dovecot/conf.d/10-auth.conf', array( |
|||
array('name' => 'disable_plaintext_auth', 'value' => 'yes'), |
|||
array('name' => 'auth_mechanisms', 'value' => 'plain login'), |
|||
array('name' => '!include auth-sql.conf.ext'), |
|||
)); |
|||
UpdateDovecotConfigFile('/etc/dovecot/conf.d/10-mail.conf', array( |
|||
array('name' => 'mail_location', 'value' => 'maildir:/var/vmail/%d/%n'), |
|||
array('name' => 'mail_uid', 'value' => 'vmail'), |
|||
array('name' => 'mail_gid', 'value' => 'mail'), |
|||
array('name' => 'first_valid_uid', 'value' => '150'), |
|||
array('name' => 'last_valid_uid', 'value' => '150'), |
|||
)); |
|||
UpdateDovecotConfigFile('/etc/dovecot/conf.d/10-ssl.conf', array( |
|||
array('name' => 'ssl_cert', 'value' => '</etc/ssl/certs/'.$DomainName.'.crt'), |
|||
array('name' => 'ssl_key', 'value' => '</etc/ssl/private/'.$DomainName.'.key'), |
|||
array('name' => 'ssl_ca', 'value' => '</etc/ssl/certs/ca-bundle.crt'), |
|||
array('name' => 'ssl_cipher_list', 'value' => 'ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS'), |
|||
)); |
|||
UpdateDovecotConfigFile('/etc/dovecot/conf.d/10-master.conf', array( |
|||
array('name' => array('service auth', 'unix_listener auth-userdb', 'mode'), 'value' => '0666'), |
|||
array('name' => array('service auth', 'unix_listener auth-userdb', 'user'), 'value' => 'vmail'), |
|||
array('name' => array('service auth', 'unix_listener auth-userdb', 'group'), 'value' => 'mail'), |
|||
array('name' => array('service auth', 'unix_listener /var/spool/postfix/private/auth', 'mode'), 'value' => '0666'), |
|||
array('name' => array('service auth', 'unix_listener /var/spool/postfix/private/auth', 'user'), 'value' => 'postfix'), |
|||
array('name' => array('service auth', 'unix_listener /var/spool/postfix/private/auth', 'group'), 'value' => 'postfix'), |
|||
)); |
|||
UpdateDovecotConfigFile('/etc/dovecot/conf.d/15-lda.conf', array( |
|||
array('name' => 'postmaster_address', 'value' => 'postmaster@'.$DomainName), |
|||
)); |
|||
Execute('chown -R vmail:dovecot /etc/dovecot'); |
|||
Execute('chmod -R o-rwx /etc/dovecot'); |
|||
} |
|||
function UpdateAmavisConfigFile($FileName, $Parameters) |
|||
{ |
|||
if(!file_exists($FileName.'_backup')) |
|||
file_put_contents($FileName.'_backup', file_get_contents($FileName)); |
|||
$Content = explode("\n", file_get_contents($FileName.'_backup')); |
|||
if(count($Content) > 0) |
|||
{ |
|||
// Remove ending part |
|||
$I = count($Content) - 1; |
|||
while(($I >= 0)) |
|||
{ |
|||
if($Content[$I] != '#------------ Do not modify anything below this line -------------') |
|||
array_pop($Content); |
|||
else { |
|||
array_pop($Content); |
|||
break; |
|||
} |
|||
$I--; |
|||
} |
|||
} |
|||
foreach($Parameters as $Parameter) |
|||
{ |
|||
$Parameter['name'] = array($Parameter['name']); |
|||
$Num = 0; |
|||
if(!array_key_exists('value', $Parameter)) |
|||
{ |
|||
$Needle = array_values($Parameter['name'])[0]; |
|||
$Parameter['value'] = ''; |
|||
} else |
|||
$Needle = array_values($Parameter['name'])[0]." ="; |
|||
$I = 0; |
|||
$Found = false; |
|||
while((($Num + $I) < count($Content))) |
|||
{ |
|||
if((trim(substr(trim($Content[$Num + $I]), 0, strlen($Needle))) == $Needle) |
|||
or ((substr(trim($Content[$Num + $I]), 0, 1) == '#') and (substr(trim(substr(trim($Content[$Num + $I]), 1)), 0, strlen($Needle)) == $Needle))) |
|||
{ |
|||
echo('Found: '.array_values($Parameter['name'])[0]."\n"); |
|||
$Content[$Num + $I] = $Needle.' '.$Parameter['value']; |
|||
$Found = true; |
|||
break; |
|||
} |
|||
$I++; |
|||
} |
|||
// If not found then add new value |
|||
if($Found == false) |
|||
{ |
|||
echo('Added new: '.array_values($Parameter['name'])[0]."\n"); |
|||
array_splice($Content, $Num + $I - 1, 0, $Needle.' '.$Parameter['value']); |
|||
} |
|||
} |
|||
$Content[] = '#------------ Do not modify anything below this line -------------'; |
|||
$Content[] = '1; # ensure a defined return'; |
|||
file_put_contents($FileName, implode("\n", $Content)); |
|||
} |
|||
function UpdateDefaultConfigFile($FileName, $Parameters) |
|||
{ |
|||
if(!file_exists($FileName.'_backup')) |
|||
file_put_contents($FileName.'_backup', file_get_contents($FileName)); |
|||
$Content = explode("\n", file_get_contents($FileName.'_backup')); |
|||
foreach($Parameters as $Parameter) |
|||
{ |
|||
if(!is_array($Parameter['name'])) |
|||
$Parameter['name'] = array($Parameter['name']); |
|||
$Num = 0; |
|||
// Find and replace value |
|||
if(count($Parameter['name']) == 1) |
|||
{ |
|||
if(!array_key_exists('value', $Parameter)) |
|||
{ |
|||
$Needle = array_values($Parameter['name'])[0]; |
|||
$Parameter['value'] = ''; |
|||
} else |
|||
$Needle = array_values($Parameter['name'])[0]."="; |
|||
$I = 0; |
|||
$Found = false; |
|||
while((($Num + $I) < count($Content))) |
|||
{ |
|||
if((trim(substr(trim($Content[$Num + $I]), 0, strlen($Needle))) == $Needle) |
|||
or ((substr(trim($Content[$Num + $I]), 0, 1) == '#') and (substr(trim(substr(trim($Content[$Num + $I]), 1)), 0, strlen($Needle)) == $Needle))) |
|||
{ |
|||
echo('Found: '.array_values($Parameter['name'])[0]."\n"); |
|||
$Content[$Num + $I] = $Needle.$Parameter['value']; |
|||
$Found = true; |
|||
break; |
|||
} |
|||
$I++; |
|||
} |
|||
// If not found then add new value |
|||
if($Found == false) |
|||
{ |
|||
echo('Added new: '.array_values($Parameter['name'])[0]."\n"); |
|||
array_splice($Content, $Num + $I - 1, 0, $Needle.' '.$Parameter['value']); |
|||
} |
|||
} |
|||
} |
|||
file_put_contents($FileName, implode("\n", $Content)); |
|||
} |
|||
function SpamVirus() |
|||
{ |
|||
Execute('adduser clamav amavis'); |
|||
Execute('adduser amavis clamav'); |
|||
UpdateAmavisConfigFile('/etc/amavis/conf.d/15-content_filter_mode', array( |
|||
array('name' => '@bypass_virus_checks_maps', 'value' => '(\%bypass_virus_checks, \@bypass_virus_checks_acl, \$bypass_virus_checks_re);'), |
|||
array('name' => '@bypass_spam_checks_maps', 'value' => '(\%bypass_spam_checks, \@bypass_spam_checks_acl, \$bypass_spam_checks_re);'), |
|||
)); |
|||
UpdateDefaultConfigFile('/etc/default/spamassassin', array( |
|||
array('name' => 'ENABLED', 'value' => '1'), |
|||
array('name' => 'CRON', 'value' => '1'), |
|||
)); |
|||
UpdateAmavisConfigFile('/etc/amavis/conf.d/50-user', array( |
|||
array('name' => '$max_servers', 'value' => '3;'), |
|||
array('name' => '$sa_tag_level_deflt', 'value' => '-9999;'), |
|||
array('name' => '@lookup_sql_dsn', 'value' => "( |
|||
['DBI:mysql:database=mail;host=127.0.0.1;port=3306', |
|||
'mail', |
|||
'mailpassword']);"), |
|||
array('name' => '$sql_select_policy', 'value' => "'SELECT domain from domain WHERE CONCAT(\"@\",domain) IN (%k)';"), |
|||
)); |
|||
Execute('freshclam'); |
|||
Execute('service clamav-daemon restart'); |
|||
Execute('service amavis restart'); |
|||
Execute('service spamassassin restart'); |
|||
} |
|||
function ConfigurePostfix() |
|||
{ |
|||
file_put_contents('/etc/postfix/mysql_virtual_alias_domainaliases_maps.cf', |
|||
"user = mail |
|||
password = mailpassword |
|||
hosts = 127.0.0.1 |
|||
dbname = mail |
|||
query = SELECT goto FROM alias,alias_domain |
|||
WHERE alias_domain.alias_domain = '%d' |
|||
AND alias.address=concat('%u', '@', alias_domain.target_domain) |
|||
AND alias.active = 1"); |
|||
file_put_contents('/etc/postfix/mysql_virtual_alias_maps.cf', |
|||
"user = mail |
|||
password = mailpassword |
|||
hosts = 127.0.0.1 |
|||
dbname = mail |
|||
table = alias |
|||
select_field = goto |
|||
where_field = address |
|||
additional_conditions = and active = '1'"); |
|||
file_put_contents('/etc/postfix/mysql_virtual_domains_maps.cf', |
|||
"user = mail |
|||
password = mailpassword |
|||
hosts = 127.0.0.1 |
|||
dbname = mail |
|||
table = domain |
|||
select_field = domain |
|||
where_field = domain |
|||
additional_conditions = and backupmx = '0' and active = '1'"); |
|||
file_put_contents('/etc/postfix/mysql_virtual_mailbox_domainaliases_maps.cf', |
|||
"user = mail |
|||
password = mailpassword |
|||
hosts = 127.0.0.1 |
|||
dbname = mail |
|||
query = SELECT maildir FROM mailbox, alias_domain |
|||
WHERE alias_domain.alias_domain = '%d' |
|||
AND mailbox.username=concat('%u', '@', alias_domain.target_domain ) |
|||
AND mailbox.active = 1"); |
|||
file_put_contents('/etc/postfix/mysql_virtual_mailbox_maps.cf', |
|||
"user = mail |
|||
password = mailpassword |
|||
hosts = 127.0.0.1 |
|||
dbname = mail |
|||
table = mailbox |
|||
select_field = CONCAT(domain, '/', local_part) |
|||
where_field = username |
|||
additional_conditions = and active = '1'"); |
|||
file_put_contents('/etc/postfix/header_checks', |
|||
"/^Received:/ IGNORE |
|||
/^User-Agent:/ IGNORE |
|||
/^X-Mailer:/ IGNORE |
|||
/^X-Originating-IP:/ IGNORE |
|||
/^x-cr-[a-z]*:/ IGNORE |
|||
/^Thread-Index:/ |
|||
IGNORE"); |
|||
if(!file_exists('/etc/postfix/main.cf_backup')) |
|||
file_put_contents('/etc/postfix/main.cf_backup', file_get_contents('/etc/postfix/main.cf')); |
|||
file_put_contents('/etc/postfix/main.cf', |
|||
'# See /usr/share/postfix/main.cf.dist for a commented, more complete version |
|||
# The first text sent to a connecting process. |
|||
smtpd_banner = $myhostname ESMTP $mail_name |
|||
biff = no |
|||
# appending .domain is the MUA\'s job. |
|||
append_dot_mydomain = no |
|||
readme_directory = no |
|||
# SASL parameters |
|||
# --------------------------------- |
|||
# Use Dovecot to authenticate. |
|||
smtpd_sasl_type = dovecot |
|||
# Referring to /var/spool/postfix/private/auth |
|||
smtpd_sasl_path = private/auth |
|||
smtpd_sasl_auth_enable = yes |
|||
broken_sasl_auth_clients = yes |
|||
smtpd_sasl_security_options = noanonymous |
|||
smtpd_sasl_local_domain = |
|||
smtpd_sasl_authenticated_header = yes |
|||
# TLS parameters |
|||
# --------------------------------- |
|||
# The default snakeoil certificate. Comment if using a purchased |
|||
# SSL certificate. |
|||
smtpd_tls_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem |
|||
smtpd_tls_key_file=/etc/ssl/private/ssl-cert-snakeoil.key |
|||
# Uncomment if using a purchased SSL certificate. |
|||
# smtpd_tls_cert_file=/etc/ssl/certs/example.com.crt |
|||
# smtpd_tls_key_file=/etc/ssl/private/example.com.key |
|||
# The snakeoil self-signed certificate has no need for a CA file. But |
|||
# if you are using your own SSL certificate, then you probably have |
|||
# a CA certificate bundle from your provider. The path to that goes |
|||
# here. |
|||
# smtpd_tls_CAfile=/etc/ssl/certs/ca-bundle.crt |
|||
# Ensure we\'re not using no-longer-secure protocols. |
|||
smtpd_tls_mandatory_protocols=!SSLv2,!SSLv3 |
|||
smtp_tls_note_starttls_offer = yes |
|||
smtpd_tls_loglevel = 1 |
|||
smtpd_tls_received_header = yes |
|||
smtpd_tls_session_cache_timeout = 3600s |
|||
tls_random_source = dev:/dev/urandom |
|||
#smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache |
|||
#smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache |
|||
# Note that forcing use of TLS is going to cause breakage - most mail servers |
|||
# don\'t offer it and so delivery will fail, both incoming and outgoing. This is |
|||
# unfortunate given what various governmental agencies are up to these days. |
|||
# |
|||
# Enable (but don\'t force) all incoming smtp connections to use TLS. |
|||
smtpd_tls_security_level = may |
|||
# Enable (but don\'t force) all outgoing smtp connections to use TLS. |
|||
smtp_tls_security_level = may |
|||
# See /usr/share/doc/postfix/TLS_README.gz in the postfix-doc package for |
|||
# information on enabling SSL in the smtp client. |
|||
# SMTPD parameters |
|||
# --------------------------------- |
|||
# Uncomment the next line to generate \"delayed mail\" warnings |
|||
#delay_warning_time = 4h |
|||
# will it be a permanent error or temporary |
|||
unknown_local_recipient_reject_code = 450 |
|||
# how long to keep message on queue before return as failed. |
|||
# some have 3 days, I have 16 days as I am backup server for some people |
|||
# whom go on holiday with their server switched off. |
|||
maximal_queue_lifetime = 7d |
|||
# max and min time in seconds between retries if connection failed |
|||
minimal_backoff_time = 1000s |
|||
maximal_backoff_time = 8000s |
|||
# how long to wait when servers connect before receiving rest of data |
|||
smtp_helo_timeout = 60s |
|||
# how many address can be used in one message. |
|||
# effective stopper to mass spammers, accidental copy in whole address list |
|||
# but may restrict intentional mail shots. |
|||
smtpd_recipient_limit = 16 |
|||
# how many error before back off. |
|||
smtpd_soft_error_limit = 3 |
|||
# how many max errors before blocking it. |
|||
smtpd_hard_error_limit = 12 |
|||
# This next set are important for determining who can send mail and relay mail |
|||
# to other servers. It is very important to get this right - accidentally producing |
|||
# an open relay that allows unauthenticated sending of mail is a Very Bad Thing. |
|||
# |
|||
# You are encouraged to read up on what exactly each of these options accomplish. |
|||
# Requirements for the HELO statement |
|||
smtpd_helo_restrictions = permit_mynetworks, warn_if_reject reject_non_fqdn_hostname, reject_invalid_hostname, permit |
|||
# Requirements for the sender details |
|||
smtpd_sender_restrictions = permit_sasl_authenticated, permit_mynetworks, warn_if_reject reject_non_fqdn_sender, reject_unknown_sender_domain, reject_unauth_pipelining, permit |
|||
# Requirements for the connecting server |
|||
smtpd_client_restrictions = reject_rbl_client sbl.spamhaus.org, reject_rbl_client blackholes.easynet.nl, reject_rbl_client dnsbl.njabl.org |
|||
# Requirement for the recipient address. Note that the entry for |
|||
# \"check_policy_service inet:127.0.0.1:10023\" enables Postgrey. |
|||
smtpd_recipient_restrictions = reject_unauth_pipelining, permit_mynetworks, permit_sasl_authenticated, reject_non_fqdn_recipient, reject_unknown_recipient_domain, reject_unauth_destination, check_policy_service inet:127.0.0.1:10023, permit |
|||
smtpd_data_restrictions = reject_unauth_pipelining |
|||
# This is a new option as of Postfix 2.10, and is required in addition to |
|||
# smtpd_recipient_restrictions for things to work properly in this setup. |
|||
smtpd_relay_restrictions = reject_unauth_pipelining, permit_mynetworks, permit_sasl_authenticated, reject_non_fqdn_recipient, reject_unknown_recipient_domain, reject_unauth_destination, check_policy_service inet:127.0.0.1:10023, permit |
|||
# require proper helo at connections |
|||
smtpd_helo_required = yes |
|||
# waste spammers time before rejecting them |
|||
smtpd_delay_reject = yes |
|||
disable_vrfy_command = yes |
|||
# General host and delivery info |
|||
# ---------------------------------- |
|||
myhostname = mail.example.com |
|||
myorigin = /etc/hostname |
|||
# Some people see issues when setting mydestination explicitly to the server |
|||
# subdomain, while leaving it empty generally doesn\'t hurt. So it is left empty here. |
|||
# mydestination = mail.example.com, localhost |
|||
mydestination = |
|||
# If you have a separate web server that sends outgoing mail through this |
|||
# mailserver, you may want to add its IP address to the space-delimited list in |
|||
# mynetworks, e.g. as 10.10.10.10/32. |
|||
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128 |
|||
mailbox_size_limit = 0 |
|||
recipient_delimiter = + |
|||
inet_interfaces = all |
|||
mynetworks_style = host |
|||
# This specifies where the virtual mailbox folders will be located. |
|||
virtual_mailbox_base = /var/vmail |
|||
# This is for the mailbox location for each user. The domainaliases |
|||
# map allows us to make use of Postfix Admin\'s domain alias feature. |
|||
virtual_mailbox_maps = mysql:/etc/postfix/mysql_virtual_mailbox_maps.cf, mysql:/etc/postfix/mysql_virtual_mailbox_domainaliases_maps.cf |
|||
# and their user id |
|||
virtual_uid_maps = static:150 |
|||
# and group id |
|||
virtual_gid_maps = static:8 |
|||
# This is for aliases. The domainaliases map allows us to make |
|||
# use of Postfix Admin\'s domain alias feature. |
|||
virtual_alias_maps = mysql:/etc/postfix/mysql_virtual_alias_maps.cf, mysql:/etc/postfix/mysql_virtual_alias_domainaliases_maps.cf |
|||
# This is for domain lookups. |
|||
virtual_mailbox_domains = mysql:/etc/postfix/mysql_virtual_domains_maps.cf |
|||
# Integration with other packages |
|||
# --------------------------------------- |
|||
# Tell postfix to hand off mail to the definition for dovecot in master.cf |
|||
virtual_transport = dovecot |
|||
dovecot_destination_recipient_limit = 1 |
|||
# Use amavis for virus and spam scanning |
|||
content_filter = amavis:[127.0.0.1]:10024 |
|||
# Header manipulation |
|||
# -------------------------------------- |
|||
# Getting rid of unwanted headers. See: https://posluns.com/guides/header-removal/ |
|||
header_checks = regexp:/etc/postfix/header_checks |
|||
# getting rid of x-original-to |
|||
enable_original_recipient = no'); |
|||
if(!file_exists('/etc/postfix/master.cf_backup')) |
|||
file_put_contents('/etc/postfix/master.cf_backup', file_get_contents('/etc/postfix/master.cf')); |
|||
file_put_contents('/etc/postfix/master.cf', |
|||
'# |
|||
# Postfix master process configuration file. For details on the format |
|||
# of the file, see the master(5) manual page (command: \"man 5 master\"). |
|||
# |
|||
# Do not forget to execute \"postfix reload\" after editing this file. |
|||
# |
|||
# ========================================================================== |
|||
# service type private unpriv chroot wakeup maxproc command + args |
|||
# (yes) (yes) (yes) (never) (100) |
|||
# ========================================================================== |
|||
# SMTP on port 25, unencrypted. |
|||
smtp inet n - - - - smtpd |
|||
#smtp inet n - - - 1 postscreen |
|||
#smtpd pass - - - - - smtpd |
|||
#dnsblog unix - - - - 0 dnsblog |
|||
#tlsproxy unix - - - - 0 tlsproxy |
|||
# SMTP with TLS on port 587. Currently commented. |
|||
#submission inet n - - - - smtpd |
|||
# -o syslog_name=postfix/submission |
|||
# -o smtpd_tls_security_level=encrypt |
|||
# -o smtpd_sasl_auth_enable=yes |
|||
# -o smtpd_enforce_tls=yes |
|||
# -o smtpd_client_restrictions=permit_sasl_authenticated,reject_unauth_destination,reject |
|||
# -o smtpd_sasl_tls_security_options=noanonymous |
|||
# SMTP over SSL on port 465. |
|||
smtps inet n - - - - smtpd |
|||
-o syslog_name=postfix/smtps |
|||
-o smtpd_tls_wrappermode=yes |
|||
-o smtpd_sasl_auth_enable=yes |
|||
-o smtpd_tls_auth_only=yes |
|||
-o smtpd_client_restrictions=permit_sasl_authenticated,reject_unauth_destination,reject |
|||
-o smtpd_sasl_security_options=noanonymous,noplaintext |
|||
-o smtpd_sasl_tls_security_options=noanonymous |
|||
#628 inet n - - - - qmqpd |
|||
pickup fifo n - - 60 1 pickup |
|||
-o content_filter= |
|||
-o receive_override_options=no_header_body_checks |
|||
cleanup unix n - - - 0 cleanup |
|||
qmgr fifo n - n 300 1 qmgr |
|||
#qmgr fifo n - n 300 1 oqmgr |
|||
tlsmgr unix - - - 1000? 1 tlsmgr |
|||
rewrite unix - - - - - trivial-rewrite |
|||
bounce unix - - - - 0 bounce |
|||
defer unix - - - - 0 bounce |
|||
trace unix - - - - 0 bounce |
|||
verify unix - - - - 1 verify |
|||
flush unix n - - 1000? 0 flush |
|||
proxymap unix - - n - - proxymap |
|||
proxywrite unix - - n - 1 proxymap |
|||
smtp unix - - - - - smtp |
|||
relay unix - - - - - smtp |
|||
# -o smtp_helo_timeout=5 -o smtp_connect_timeout=5 |
|||
showq unix n - - - - showq |
|||
error unix - - - - - error |
|||
retry unix - - - - - error |
|||
discard unix - - - - - discard |
|||
local unix - n n - - local |
|||
virtual unix - n n - - virtual |
|||
lmtp unix - - - - - lmtp |
|||
anvil unix - - - - 1 anvil |
|||
scache unix - - - - 1 scache |
|||
# |
|||
# ==================================================================== |
|||
# Interfaces to non-Postfix software. Be sure to examine the manual |
|||
# pages of the non-Postfix software to find out what options it wants. |
|||
# |
|||
# Many of the following services use the Postfix pipe(8) delivery |
|||
# agent. See the pipe(8) man page for information about ${recipient} |
|||
# and other message envelope options. |
|||
# ==================================================================== |
|||
# |
|||
# maildrop. See the Postfix MAILDROP_README file for details. |
|||
# Also specify in main.cf: maildrop_destination_recipient_limit=1 |
|||
# |
|||
maildrop unix - n n - - pipe |
|||
flags=DRhu user=vmail argv=/usr/bin/maildrop -d ${recipient} |
|||
# |
|||
# ==================================================================== |
|||
# |
|||
# Recent Cyrus versions can use the existing \"lmtp\" master.cf entry. |
|||
# |
|||
# Specify in cyrus.conf: |
|||
# lmtp cmd=\"lmtpd -a\" listen=\"localhost:lmtp\" proto=tcp4 |
|||
# |
|||
# Specify in main.cf one or more of the following: |
|||
# mailbox_transport = lmtp:inet:localhost |
|||
# virtual_transport = lmtp:inet:localhost |
|||
# |
|||
# ==================================================================== |
|||
# |
|||
# Cyrus 2.1.5 (Amos Gouaux) |
|||
# Also specify in main.cf: cyrus_destination_recipient_limit=1 |
|||
# |
|||
#cyrus unix - n n - - pipe |
|||
# user=cyrus argv=/cyrus/bin/deliver -e -r ${sender} -m ${extension} ${user} |
|||
# |
|||
# ==================================================================== |
|||
# Old example of delivery via Cyrus. |
|||
# |
|||
#old-cyrus unix - n n - - pipe |
|||
# flags=R user=cyrus argv=/cyrus/bin/deliver -e -m ${extension} ${user} |
|||
# |
|||
# ==================================================================== |
|||
# |
|||
# See the Postfix UUCP_README file for configuration details. |
|||
# |
|||
uucp unix - n n - - pipe |
|||
flags=Fqhu user=uucp argv=uux -r -n -z -a$sender - $nexthop!rmail ($recipient) |
|||
# |
|||
# Other external delivery methods. |
|||
#/var/www/html/.htaccess |
|||
ifmail unix - n n - - pipe |
|||
flags=F user=ftn argv=/usr/lib/ifmail/ifmail -r $nexthop ($recipient) |
|||
bsmtp unix - n n - - pipe |
|||
flags=Fq. user=bsmtp argv=/usr/lib/bsmtp/bsmtp -t$nexthop -f$sender $recipient |
|||
scalemail-backend unix - n n - 2 pipe |
|||
flags=R user=scalemail argv=/usr/lib/scalemail/bin/scalemail-store ${nexthop} ${user} ${extension} |
|||
mailman unix - n n - - pipe |
|||
flags=FR user=list argv=/usr/lib/mailman/bin/postfix-to-mailman.py |
|||
${nexthop} ${user} |
|||
# The next two entries integrate with Amavis for anti-virus/spam checks. |
|||
amavis unix - - - - 3 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 |
|||
# Integration with Dovecot - hand mail over to it for local delivery, and |
|||
# run the process under the vmail user and mail group. |
|||
dovecot unix - n n - - pipe |
|||
flags=DRhu user=vmail:mail argv=/usr/lib/dovecot/dovecot-lda -d $(recipient)'); |
|||
} |
|||
function RestartAll() |
|||
# Mail database |
|||
{ |
|||
Execute('service postfix restart'); |
|||
Execute('service spamassassin restart'); |
|||
Execute('service clamav-daemon restart'); |
|||
Execute('service amavis restart'); |
|||
Execute('service dovecot restart'); |
|||
} |
|||
function InstallRoundCube() |
|||
mysql -uroot -p${ROOT_PASSWORD} -Bse \ |
|||
{ |
|||
"create database mail; |
|||
Execute('apt-get install --assume-yes \ |
|||
grant all on mail.* to 'mail'@'localhost' identified by 'mailpassword';" |
|||
roundcube \ |
|||
roundcube-plugins \ |
|||
roundcube-plugins-extra'); |
|||
UpdatePHPConfigFile('/etc/roundcube/main.inc.php', 'rcmail_config', array( |
|||
array('name' => 'default_host', 'value' => "'localhost'"), |
|||
array('name' => 'force_https', 'value' => 'true'), |
|||
array('name' => 'imap_cache', 'value' => "'memcache'"), |
|||
array('name' => 'session_storage', 'value' => "'memcache'"), |
|||
array('name' => 'memcache_hosts', 'value' => "array('localhost:11211')"), |
|||
)); |
|||
Execute('ln -s /var/lib/roundcube /var/www/html/roundcube'); |
|||
if(file_exists('/var/www/html/index.html')) |
|||
Execute('mv /var/www/html/index.html /var/www/html/index.bak.html'); |
|||
file_put_contents('/var/www/html/.htaccess', 'RewriteEngine On |
|||
# Redirect all HTTP traffic to HTTPS. |
|||
RewriteCond %{HTTPS} !=on |
|||
RewriteRule ^/?(.*) https://%{SERVER_NAME}/$1 [R,L] |
|||
# Send / to /roundcube. |
|||
RewriteRule ^/?$ /roundcube [L]'); |
|||
} |
|||
function InstallMonit() |
|||
# Postfix |
|||
{ |
|||
Execute('apt-get install --assume-yes monit'); |
|||
file_put_contents('/etc/monit/conf.d/amavis', |
|||
'check process amavisd with pidfile /var/run/amavis/amavisd.pid |
|||
every 5 cycles |
|||
group mail |
|||
start program = "/etc/init.d/amavis start" |
|||
stop program = "/etc/init.d/amavis stop" |
|||
if failed port 10024 protocol smtp then restart |
|||
if 5 restarts within 25 cycles then timeout'); |
|||
file_put_contents('/etc/monit/conf.d/apache2', |
|||
'check process apache2 with pidfile /var/run/apache2/apache2.pid |
|||
group www |
|||
start program = "/etc/init.d/apache2 start" |
|||
stop program = "/etc/init.d/apache2 stop" |
|||
if failed host localhost port 80 protocol http |
|||
with timeout 10 seconds |
|||
then restart |
|||
if 5 restarts within 5 cycles then timeout'); |
|||
file_put_contents('/etc/monit/conf.d/dovecot', |
|||
'check process dovecot with pidfile /var/run/dovecot/master.pid |
|||
group mail |
|||
start program = "/sbin/start dovecot" |
|||
stop program = "/sbin/stop dovecot" |
|||
group mail |
|||
# We\'d like to use this line, but see: |
|||
# http://serverfault.com/questions/610976/monit-failing-to-connect-to-dovecot-over-ssl-imap |
|||
#if failed port 993 type tcpssl sslauto protocol imap for 5 cycles then restart |
|||
if failed port 993 for 5 cycles then restart |
|||
if 5 restarts within 25 cycles then timeout'); |
|||
file_put_contents('/etc/monit/conf.d/mysql', |
|||
'check process mysqld with pidfile /var/run/mysqld/mysqld.pid |
|||
group database |
|||
start program = "/etc/init.d/mysql start" |
|||
stop program = "/etc/init.d/mysql stop" |
|||
if failed host localhost port 3306 protocol mysql then restart |
|||
if 5 restarts within 5 cycles then timeout'); |
|||
file_put_contents('/etc/monit/conf.d/memcached', |
|||
'check process memcached with pidfile /var/run/memcached.pid |
|||
group www |
|||
start program = "/etc/init.d/memcached start" |
|||
stop program = "/etc/init.d/memcached stop" |
|||
if failed host localhost port 11211 then restart |
|||
if 5 restarts within 5 cycles then timeout'); |
|||
file_put_contents('/etc/monit/conf.d/postfix', |
|||
'check process postfix with pidfile /var/spool/postfix/pid/master.pid |
|||
group mail |
|||
start program = "/etc/init.d/postfix start" |
|||
stop program = "/etc/init.d/postfix stop" |
|||
if failed port 25 protocol smtp then restart |
|||
if 5 restarts within 5 cycles then timeout'); |
|||
file_put_contents('/etc/monit/conf.d/spamassassin', |
|||
'check process spamassassin with pidfile /var/run/spamd.pid |
|||
group mail |
|||
start program = "/etc/init.d/spamassassin start" |
|||
stop program = "/etc/init.d/spamassassin stop" |
|||
if 5 restarts within 5 cycles then timeout'); |
|||
file_put_contents('/etc/monit/conf.d/sshd', |
|||
'check process sshd with pidfile /var/run/sshd.pid |
|||
start program "/etc/init.d/ssh start" |
|||
stop program "/etc/init.d/ssh stop" |
|||
if failed host 127.0.0.1 port 22 protocol ssh then restart |
|||
if 5 restarts within 5 cycles then timeout'); |
|||
Execute('service monit restart'); |
|||
} |
|||
InstallPackages(); |
|||
wget http://downloads.sourceforge.net/project/postfixadmin/postfixadmin/postfixadmin-2.3.7/postfixadmin-2.3.7.tar.gz |
|||
PrepareDatabase(); |
|||
tar -xf postfixadmin-2.3.7.tar.gz |
|||
InstallPostfixAdmin(); |
|||
rm -f postfixadmin-2.3.7.tar.gz |
|||
VirtualMailUser(); |
|||
mv postfixadmin-2.3.7 /var/www/html/postfixadmin |
|||
ConfigureDovecot(); |
|||
chown -R www-data:www-data /var/www/html/postfixadmin |
|||
SpamVirus(); |
|||
ConfigurePostfix(); |
|||
RestartAll(); |
|||
InstallMonit(); |
|||
InstallRoundCube(); |
|||
</ |
</source> |
||
Verze z 8. 12. 2014, 22:18
Návod popisuje instalace poštovního serveru s virtuálními účty v MySQL databázi.
- Budou použity následují komponenty:
- postfix - SMTP server
- dovecot - IMAP server
- roundcubemail - web mail klient
- postfixadmin - správa schránek
Instalační skript
Většina návodů je provedena jako dlouhý popis postupu s mnoha útržkovými částmi příkazů, které je potřeba provést. To je zdlouhavý proces kopírovat jednotlivé části povelů a po částech je provádět. Místo toho bychom rádi měli jednoduchou instalaci, kterou prostě spustíme, chvíli počkáme a máme hotovo. Zde je předložen skript, který se toto dle jednoho návodu snaží docílit.
<?php
$MysqlRootPassword = 'MysqlRootPassword';
$MysqlUserPassword = 'MysqlUserPassword';
$PostfixAdminName = 'PostfixAdminName';
$PostfixSetupPassword = 'PostfixSetupPassword';
$DomainName = 'domain.com';
$ServerDomain = 'mail.'.$DomainName;
function Execute($Command)
{
echo('Executing: '.$Command."\n");
passthru($Command);
}
function InstallPackages()
{
// LAMP web server
Execute('apt-get update');
Execute('apt-get upgrade --assume-yes');
Execute('apt-get install --assume-yes lamp-server^');
Execute('apt-get install --assume-yes \
php-apc \
php5-mcrypt \
php5-memcache \
php5-curl \
php5-gd \
php-xml-parser');
Execute('ln -sf ../../mods-available/mcrypt.ini /etc/php5/apache2/conf.d/20-mcrypt.ini');
// Configure apache
Execute('a2enmod rewrite ssl');
Execute('a2ensite default-ssl');
Execute('service apache2 restart');
// Memcached
Execute('apt-get install --assume-yes memcached');
// Mail packages
Execute('apt-get install --assume-yes mail-server^');
Execute('apt-get install --assume-yes \
postfix-mysql \
dovecot-mysql \
postgrey \
amavis \
clamav \
clamav-daemon \
spamassassin \
php5-imap');
Execute('ln -sf ../../mods-available/imap.ini /etc/php5/apache2/conf.d/20-imap.ini');
Execute('service apache2 restart');
Execute('apt-get install --assume-yes \
pyzor \
razor \
arj \
cabextract \
lzop \
nomarch \
p7zip-full \
ripole \
rpm2cpio \
tnef \
unzip \
unrar-free \
zip \
zoo');
}
function PrepareDatabase()
{
global $MysqlUserPassword, $MysqlRootPassword;
// Mail database
Execute('mysql -uroot -p'.$MysqlRootPassword.' -Bse \
"drop database mail; create database mail;
grant all on mail.* to \'mail\'@\'localhost\' identified by \''.$MysqlUserPassword.'\';"');
}
function UpdatePHPConfigFile($FileName, $BaseVariable, $Parameters)
{
if(!file_exists($FileName.'_backup'))
file_put_contents($FileName.'_backup', file_get_contents($FileName));
$Content = explode("\n", file_get_contents($FileName.'_backup'));
foreach($Parameters as $Parameter)
{
if(is_array($Parameter['name'])) {
foreach($Content as $Num => $Line)
{
$Needle = '$'.$BaseVariable.'['."'".$Parameter['name'][0]."'] = array (";
if(substr($Line, 0, strlen($Needle)) == $Needle)
{
echo('Found group: '.$Parameter['name'][0]."\n");
$Needle = " '".$Parameter['name'][1]."' => ";
$I = 1;
while((($Num + $I) < count($Content)) and ($Content[$Num + $I] != ');'))
{
if(substr($Content[$Num + $I], 0, strlen($Needle)) == $Needle) {
echo('Found group: '.$Parameter['name'][1]."\n");
$Content[$Num + $I] = $Needle.$Parameter['value'].',';
}
$I++;
}
}
}
} else {
foreach($Content as $Num => $Line)
{
$Needle = '$'.$BaseVariable.'['."'".$Parameter['name']."'] = ";
if(substr($Line, 0, strlen($Needle)) == $Needle)
{
echo('Found: '.$Parameter['name']."\n");
$Content[$Num] = $Needle.$Parameter['value'].';';
}
}
}
}
file_put_contents($FileName, implode("\n", $Content));
}
function generate_setup_password_salt()
{
$salt = time().'*'.mt_rand(0,60000);
$salt = md5($salt);
return $salt;
}
function encrypt_setup_password($password, $salt)
{
return $salt . ':' . sha1($salt . ':' . $password);
}
function InstallPostfixAdmin()
{
global $ServerDomain, $PostfixAdminName, $MysqlUserPassword, $PostfixSetupPassword, $DomainName;
Execute('wget "http://downloads.sourceforge.net/project/postfixadmin/postfixadmin/'.
$PostfixAdminName.'/'.$PostfixAdminName.'.tar.gz?r=&ts=1417890779&use_mirror=netcologne" -O '.
$PostfixAdminName.'.tar.gz');
Execute('tar -xf '.$PostfixAdminName.'.tar.gz');
Execute('rm -f '.$PostfixAdminName.'.tar.gz');
Execute('mv '.$PostfixAdminName.' /var/www/html/postfixadmin');
Execute('chown -R www-data:www-data /var/www/html/postfixadmin');
UpdatePHPConfigFile('/var/www/html/postfixadmin/config.inc.php', 'CONF', array(
array('name' => 'setup_password', 'value' => "'".encrypt_setup_password($PostfixSetupPassword, generate_setup_password_salt())."'"),
array('name' => 'configured', 'value' => 'true'),
array('name' => 'postfix_admin_url', 'value' => "'https://".$ServerDomain."/postfixadmin'"),
array('name' => 'database_type', 'value' => "'mysql'"),
array('name' => 'database_host', 'value' => "'localhost'"),
array('name' => 'database_user', 'value' => "'mail'"),
array('name' => 'database_password', 'value' => "'".$MysqlUserPassword."'"),
array('name' => 'database_name', 'value' => "'mail'"),
array('name' => 'admin_email', 'value' => "'admin@".$DomainName."'"),
array('name' => 'user_footer_link', 'value' => "'https://".$ServerDomain."/main.php'"),
array('name' => 'show_footer_text', 'value' => "'YES'"),
array('name' => 'footer_text', 'value' => "'Return to ".$ServerDomain."'"),
array('name' => 'footer_link', 'value' => "'https://".$ServerDomain."'"),
array('name' => array('default_aliases', 'abuse'), 'value' => "'abuse@".$DomainName."'"),
array('name' => array('default_aliases', 'hostmaster'), 'value' => "'hostmaster@".$DomainName."'"),
array('name' => array('default_aliases', 'postmaster'), 'value' => "'postmaster@".$DomainName."'"),
array('name' => array('default_aliases', 'webmaster'), 'value' => "'webmaster@".$DomainName."'"),
));
}
function VirtualMailUser()
{
Execute('useradd -r -u 150 -g mail -d /var/vmail -s /sbin/nologin -c "Virtual maildir handler" vmail');
Execute('mkdir /var/vmail');
Execute('chmod 770 /var/vmail');
Execute('chown vmail:mail /var/vmail');
}
function UpdateDovecotConfigFile($FileName, $Parameters)
{
if(!file_exists($FileName.'_backup'))
file_put_contents($FileName.'_backup', file_get_contents($FileName));
$Content = explode("\n", file_get_contents($FileName.'_backup'));
foreach($Parameters as $Parameter)
{
if(!is_array($Parameter['name']))
$Parameter['name'] = array($Parameter['name']);
// First find subgroup
$Num = 0;
$NestingLevel = 0;
while(count($Parameter['name']) > 1)
{
$Found = false;
$Needle = '#'.array_values($Parameter['name'])[0].' {';
$I = 0;
$StartNestingLevel = $NestingLevel;
while((($Num + $I) < count($Content)) and ($NestingLevel >= $StartNestingLevel))
{
if(substr(trim($Content[$Num + $I]), -1, 1) == '{') $NestingLevel++;
if(substr(trim($Content[$Num + $I]), -1, 1) == '}') $NestingLevel--;
if((trim(substr(trim($Content[$Num + $I]), 0, strlen($Needle))) == $Needle)
or (trim(substr(trim($Content[$Num + $I]), 0, strlen(substr($Needle, 1)))) == substr($Needle, 1)))
{
$Content[$Num + $I] = array_values($Parameter['name'])[0].' {';
$Num = $Num + $I + 1;
$Found = true;
echo('Found group: '.array_values($Parameter['name'])[0]."\n");
array_shift($Parameter['name']);
break;
}
$I++;
}
if(!$Found) break;
}
// Find and replace value
if(count($Parameter['name']) == 1)
{
if(!array_key_exists('value', $Parameter))
{
$Needle = array_values($Parameter['name'])[0];
$Parameter['value'] = '';
} else
$Needle = array_values($Parameter['name'])[0]." =";
$I = 0;
$StartNestingLevel = $NestingLevel;
$Found = false;
while((($Num + $I) < count($Content)) and ($NestingLevel >= $StartNestingLevel))
{
if(substr(trim($Content[$Num + $I]), -1, 1) == '{') $NestingLevel++;
if(substr(trim($Content[$Num + $I]), -1, 1) == '}')
{
if($NestingLevel == $StartNestingLevel) $Content[$Num + $I] = '}';
$NestingLevel--;
}
if((trim(substr(trim($Content[$Num + $I]), 0, strlen($Needle))) == $Needle)
or ((substr(trim($Content[$Num + $I]), 0, 1) == '#') and (substr(trim(substr(trim($Content[$Num + $I]), 1)), 0, strlen($Needle)) == $Needle)))
{
echo('Found: '.array_values($Parameter['name'])[0]."\n");
$Content[$Num + $I] = $Needle.' '.$Parameter['value'];
$Found = true;
break;
}
$I++;
}
// If not found then add new value
if($Found == false)
{
echo('Added new: '.array_values($Parameter['name'])[0]."\n");
array_splice($Content, $Num + $I - 1, 0, $Needle.' '.$Parameter['value']);
}
}
}
file_put_contents($FileName, implode("\n", $Content));
}
function ConfigureDovecot()
{
global $MysqlUserPassword, $DomainName;
UpdateDovecotConfigFile('/etc/dovecot/dovecot-sql.conf.ext', array(
array('name' => 'driver', 'value' => 'mysql'),
array('name' => 'connect', 'value' => 'host=localhost dbname=mail user=mail password='.$MysqlUserPassword),
array('name' => 'default_pass_scheme', 'value' => 'MD5-CRYPT'),
array('name' => 'password_query', 'value' => "SELECT username as user, password, '/var/vmail/%d/%n' as userdb_home, \\
'maildir:/var/vmail/%d/%n' as userdb_mail, 150 as userdb_uid, 8 as userdb_gid \\
FROM mailbox WHERE username = '%u' AND active = '1'"),
array('name' => 'user_query', 'value' => "SELECT '/var/vmail/%d/%n' as home, 'maildir:/var/vmail/%d/%n' as mail, \\
150 AS uid, 8 AS gid, concat('dirsize:storage=', quota) AS quota \\
FROM mailbox WHERE username = '%u' AND active = '1'"),
));
UpdateDovecotConfigFile('/etc/dovecot/conf.d/10-auth.conf', array(
array('name' => 'disable_plaintext_auth', 'value' => 'yes'),
array('name' => 'auth_mechanisms', 'value' => 'plain login'),
array('name' => '!include auth-sql.conf.ext'),
));
UpdateDovecotConfigFile('/etc/dovecot/conf.d/10-mail.conf', array(
array('name' => 'mail_location', 'value' => 'maildir:/var/vmail/%d/%n'),
array('name' => 'mail_uid', 'value' => 'vmail'),
array('name' => 'mail_gid', 'value' => 'mail'),
array('name' => 'first_valid_uid', 'value' => '150'),
array('name' => 'last_valid_uid', 'value' => '150'),
));
UpdateDovecotConfigFile('/etc/dovecot/conf.d/10-ssl.conf', array(
array('name' => 'ssl_cert', 'value' => '</etc/ssl/certs/'.$DomainName.'.crt'),
array('name' => 'ssl_key', 'value' => '</etc/ssl/private/'.$DomainName.'.key'),
array('name' => 'ssl_ca', 'value' => '</etc/ssl/certs/ca-bundle.crt'),
array('name' => 'ssl_cipher_list', 'value' => 'ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS'),
));
UpdateDovecotConfigFile('/etc/dovecot/conf.d/10-master.conf', array(
array('name' => array('service auth', 'unix_listener auth-userdb', 'mode'), 'value' => '0666'),
array('name' => array('service auth', 'unix_listener auth-userdb', 'user'), 'value' => 'vmail'),
array('name' => array('service auth', 'unix_listener auth-userdb', 'group'), 'value' => 'mail'),
array('name' => array('service auth', 'unix_listener /var/spool/postfix/private/auth', 'mode'), 'value' => '0666'),
array('name' => array('service auth', 'unix_listener /var/spool/postfix/private/auth', 'user'), 'value' => 'postfix'),
array('name' => array('service auth', 'unix_listener /var/spool/postfix/private/auth', 'group'), 'value' => 'postfix'),
));
UpdateDovecotConfigFile('/etc/dovecot/conf.d/15-lda.conf', array(
array('name' => 'postmaster_address', 'value' => 'postmaster@'.$DomainName),
));
Execute('chown -R vmail:dovecot /etc/dovecot');
Execute('chmod -R o-rwx /etc/dovecot');
}
function UpdateAmavisConfigFile($FileName, $Parameters)
{
if(!file_exists($FileName.'_backup'))
file_put_contents($FileName.'_backup', file_get_contents($FileName));
$Content = explode("\n", file_get_contents($FileName.'_backup'));
if(count($Content) > 0)
{
// Remove ending part
$I = count($Content) - 1;
while(($I >= 0))
{
if($Content[$I] != '#------------ Do not modify anything below this line -------------')
array_pop($Content);
else {
array_pop($Content);
break;
}
$I--;
}
}
foreach($Parameters as $Parameter)
{
$Parameter['name'] = array($Parameter['name']);
$Num = 0;
if(!array_key_exists('value', $Parameter))
{
$Needle = array_values($Parameter['name'])[0];
$Parameter['value'] = '';
} else
$Needle = array_values($Parameter['name'])[0]." =";
$I = 0;
$Found = false;
while((($Num + $I) < count($Content)))
{
if((trim(substr(trim($Content[$Num + $I]), 0, strlen($Needle))) == $Needle)
or ((substr(trim($Content[$Num + $I]), 0, 1) == '#') and (substr(trim(substr(trim($Content[$Num + $I]), 1)), 0, strlen($Needle)) == $Needle)))
{
echo('Found: '.array_values($Parameter['name'])[0]."\n");
$Content[$Num + $I] = $Needle.' '.$Parameter['value'];
$Found = true;
break;
}
$I++;
}
// If not found then add new value
if($Found == false)
{
echo('Added new: '.array_values($Parameter['name'])[0]."\n");
array_splice($Content, $Num + $I - 1, 0, $Needle.' '.$Parameter['value']);
}
}
$Content[] = '#------------ Do not modify anything below this line -------------';
$Content[] = '1; # ensure a defined return';
file_put_contents($FileName, implode("\n", $Content));
}
function UpdateDefaultConfigFile($FileName, $Parameters)
{
if(!file_exists($FileName.'_backup'))
file_put_contents($FileName.'_backup', file_get_contents($FileName));
$Content = explode("\n", file_get_contents($FileName.'_backup'));
foreach($Parameters as $Parameter)
{
if(!is_array($Parameter['name']))
$Parameter['name'] = array($Parameter['name']);
$Num = 0;
// Find and replace value
if(count($Parameter['name']) == 1)
{
if(!array_key_exists('value', $Parameter))
{
$Needle = array_values($Parameter['name'])[0];
$Parameter['value'] = '';
} else
$Needle = array_values($Parameter['name'])[0]."=";
$I = 0;
$Found = false;
while((($Num + $I) < count($Content)))
{
if((trim(substr(trim($Content[$Num + $I]), 0, strlen($Needle))) == $Needle)
or ((substr(trim($Content[$Num + $I]), 0, 1) == '#') and (substr(trim(substr(trim($Content[$Num + $I]), 1)), 0, strlen($Needle)) == $Needle)))
{
echo('Found: '.array_values($Parameter['name'])[0]."\n");
$Content[$Num + $I] = $Needle.$Parameter['value'];
$Found = true;
break;
}
$I++;
}
// If not found then add new value
if($Found == false)
{
echo('Added new: '.array_values($Parameter['name'])[0]."\n");
array_splice($Content, $Num + $I - 1, 0, $Needle.' '.$Parameter['value']);
}
}
}
file_put_contents($FileName, implode("\n", $Content));
}
function SpamVirus()
{
Execute('adduser clamav amavis');
Execute('adduser amavis clamav');
UpdateAmavisConfigFile('/etc/amavis/conf.d/15-content_filter_mode', array(
array('name' => '@bypass_virus_checks_maps', 'value' => '(\%bypass_virus_checks, \@bypass_virus_checks_acl, \$bypass_virus_checks_re);'),
array('name' => '@bypass_spam_checks_maps', 'value' => '(\%bypass_spam_checks, \@bypass_spam_checks_acl, \$bypass_spam_checks_re);'),
));
UpdateDefaultConfigFile('/etc/default/spamassassin', array(
array('name' => 'ENABLED', 'value' => '1'),
array('name' => 'CRON', 'value' => '1'),
));
UpdateAmavisConfigFile('/etc/amavis/conf.d/50-user', array(
array('name' => '$max_servers', 'value' => '3;'),
array('name' => '$sa_tag_level_deflt', 'value' => '-9999;'),
array('name' => '@lookup_sql_dsn', 'value' => "(
['DBI:mysql:database=mail;host=127.0.0.1;port=3306',
'mail',
'mailpassword']);"),
array('name' => '$sql_select_policy', 'value' => "'SELECT domain from domain WHERE CONCAT(\"@\",domain) IN (%k)';"),
));
Execute('freshclam');
Execute('service clamav-daemon restart');
Execute('service amavis restart');
Execute('service spamassassin restart');
}
function ConfigurePostfix()
{
file_put_contents('/etc/postfix/mysql_virtual_alias_domainaliases_maps.cf',
"user = mail
password = mailpassword
hosts = 127.0.0.1
dbname = mail
query = SELECT goto FROM alias,alias_domain
WHERE alias_domain.alias_domain = '%d'
AND alias.address=concat('%u', '@', alias_domain.target_domain)
AND alias.active = 1");
file_put_contents('/etc/postfix/mysql_virtual_alias_maps.cf',
"user = mail
password = mailpassword
hosts = 127.0.0.1
dbname = mail
table = alias
select_field = goto
where_field = address
additional_conditions = and active = '1'");
file_put_contents('/etc/postfix/mysql_virtual_domains_maps.cf',
"user = mail
password = mailpassword
hosts = 127.0.0.1
dbname = mail
table = domain
select_field = domain
where_field = domain
additional_conditions = and backupmx = '0' and active = '1'");
file_put_contents('/etc/postfix/mysql_virtual_mailbox_domainaliases_maps.cf',
"user = mail
password = mailpassword
hosts = 127.0.0.1
dbname = mail
query = SELECT maildir FROM mailbox, alias_domain
WHERE alias_domain.alias_domain = '%d'
AND mailbox.username=concat('%u', '@', alias_domain.target_domain )
AND mailbox.active = 1");
file_put_contents('/etc/postfix/mysql_virtual_mailbox_maps.cf',
"user = mail
password = mailpassword
hosts = 127.0.0.1
dbname = mail
table = mailbox
select_field = CONCAT(domain, '/', local_part)
where_field = username
additional_conditions = and active = '1'");
file_put_contents('/etc/postfix/header_checks',
"/^Received:/ IGNORE
/^User-Agent:/ IGNORE
/^X-Mailer:/ IGNORE
/^X-Originating-IP:/ IGNORE
/^x-cr-[a-z]*:/ IGNORE
/^Thread-Index:/
IGNORE");
if(!file_exists('/etc/postfix/main.cf_backup'))
file_put_contents('/etc/postfix/main.cf_backup', file_get_contents('/etc/postfix/main.cf'));
file_put_contents('/etc/postfix/main.cf',
'# See /usr/share/postfix/main.cf.dist for a commented, more complete version
# The first text sent to a connecting process.
smtpd_banner = $myhostname ESMTP $mail_name
biff = no
# appending .domain is the MUA\'s job.
append_dot_mydomain = no
readme_directory = no
# SASL parameters
# ---------------------------------
# Use Dovecot to authenticate.
smtpd_sasl_type = dovecot
# Referring to /var/spool/postfix/private/auth
smtpd_sasl_path = private/auth
smtpd_sasl_auth_enable = yes
broken_sasl_auth_clients = yes
smtpd_sasl_security_options = noanonymous
smtpd_sasl_local_domain =
smtpd_sasl_authenticated_header = yes
# TLS parameters
# ---------------------------------
# The default snakeoil certificate. Comment if using a purchased
# SSL certificate.
smtpd_tls_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
smtpd_tls_key_file=/etc/ssl/private/ssl-cert-snakeoil.key
# Uncomment if using a purchased SSL certificate.
# smtpd_tls_cert_file=/etc/ssl/certs/example.com.crt
# smtpd_tls_key_file=/etc/ssl/private/example.com.key
# The snakeoil self-signed certificate has no need for a CA file. But
# if you are using your own SSL certificate, then you probably have
# a CA certificate bundle from your provider. The path to that goes
# here.
# smtpd_tls_CAfile=/etc/ssl/certs/ca-bundle.crt
# Ensure we\'re not using no-longer-secure protocols.
smtpd_tls_mandatory_protocols=!SSLv2,!SSLv3
smtp_tls_note_starttls_offer = yes
smtpd_tls_loglevel = 1
smtpd_tls_received_header = yes
smtpd_tls_session_cache_timeout = 3600s
tls_random_source = dev:/dev/urandom
#smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
#smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
# Note that forcing use of TLS is going to cause breakage - most mail servers
# don\'t offer it and so delivery will fail, both incoming and outgoing. This is
# unfortunate given what various governmental agencies are up to these days.
#
# Enable (but don\'t force) all incoming smtp connections to use TLS.
smtpd_tls_security_level = may
# Enable (but don\'t force) all outgoing smtp connections to use TLS.
smtp_tls_security_level = may
# See /usr/share/doc/postfix/TLS_README.gz in the postfix-doc package for
# information on enabling SSL in the smtp client.
# SMTPD parameters
# ---------------------------------
# Uncomment the next line to generate \"delayed mail\" warnings
#delay_warning_time = 4h
# will it be a permanent error or temporary
unknown_local_recipient_reject_code = 450
# how long to keep message on queue before return as failed.
# some have 3 days, I have 16 days as I am backup server for some people
# whom go on holiday with their server switched off.
maximal_queue_lifetime = 7d
# max and min time in seconds between retries if connection failed
minimal_backoff_time = 1000s
maximal_backoff_time = 8000s
# how long to wait when servers connect before receiving rest of data
smtp_helo_timeout = 60s
# how many address can be used in one message.
# effective stopper to mass spammers, accidental copy in whole address list
# but may restrict intentional mail shots.
smtpd_recipient_limit = 16
# how many error before back off.
smtpd_soft_error_limit = 3
# how many max errors before blocking it.
smtpd_hard_error_limit = 12
# This next set are important for determining who can send mail and relay mail
# to other servers. It is very important to get this right - accidentally producing
# an open relay that allows unauthenticated sending of mail is a Very Bad Thing.
#
# You are encouraged to read up on what exactly each of these options accomplish.
# Requirements for the HELO statement
smtpd_helo_restrictions = permit_mynetworks, warn_if_reject reject_non_fqdn_hostname, reject_invalid_hostname, permit
# Requirements for the sender details
smtpd_sender_restrictions = permit_sasl_authenticated, permit_mynetworks, warn_if_reject reject_non_fqdn_sender, reject_unknown_sender_domain, reject_unauth_pipelining, permit
# Requirements for the connecting server
smtpd_client_restrictions = reject_rbl_client sbl.spamhaus.org, reject_rbl_client blackholes.easynet.nl, reject_rbl_client dnsbl.njabl.org
# Requirement for the recipient address. Note that the entry for
# \"check_policy_service inet:127.0.0.1:10023\" enables Postgrey.
smtpd_recipient_restrictions = reject_unauth_pipelining, permit_mynetworks, permit_sasl_authenticated, reject_non_fqdn_recipient, reject_unknown_recipient_domain, reject_unauth_destination, check_policy_service inet:127.0.0.1:10023, permit
smtpd_data_restrictions = reject_unauth_pipelining
# This is a new option as of Postfix 2.10, and is required in addition to
# smtpd_recipient_restrictions for things to work properly in this setup.
smtpd_relay_restrictions = reject_unauth_pipelining, permit_mynetworks, permit_sasl_authenticated, reject_non_fqdn_recipient, reject_unknown_recipient_domain, reject_unauth_destination, check_policy_service inet:127.0.0.1:10023, permit
# require proper helo at connections
smtpd_helo_required = yes
# waste spammers time before rejecting them
smtpd_delay_reject = yes
disable_vrfy_command = yes
# General host and delivery info
# ----------------------------------
myhostname = mail.example.com
myorigin = /etc/hostname
# Some people see issues when setting mydestination explicitly to the server
# subdomain, while leaving it empty generally doesn\'t hurt. So it is left empty here.
# mydestination = mail.example.com, localhost
mydestination =
# If you have a separate web server that sends outgoing mail through this
# mailserver, you may want to add its IP address to the space-delimited list in
# mynetworks, e.g. as 10.10.10.10/32.
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
mailbox_size_limit = 0
recipient_delimiter = +
inet_interfaces = all
mynetworks_style = host
# This specifies where the virtual mailbox folders will be located.
virtual_mailbox_base = /var/vmail
# This is for the mailbox location for each user. The domainaliases
# map allows us to make use of Postfix Admin\'s domain alias feature.
virtual_mailbox_maps = mysql:/etc/postfix/mysql_virtual_mailbox_maps.cf, mysql:/etc/postfix/mysql_virtual_mailbox_domainaliases_maps.cf
# and their user id
virtual_uid_maps = static:150
# and group id
virtual_gid_maps = static:8
# This is for aliases. The domainaliases map allows us to make
# use of Postfix Admin\'s domain alias feature.
virtual_alias_maps = mysql:/etc/postfix/mysql_virtual_alias_maps.cf, mysql:/etc/postfix/mysql_virtual_alias_domainaliases_maps.cf
# This is for domain lookups.
virtual_mailbox_domains = mysql:/etc/postfix/mysql_virtual_domains_maps.cf
# Integration with other packages
# ---------------------------------------
# Tell postfix to hand off mail to the definition for dovecot in master.cf
virtual_transport = dovecot
dovecot_destination_recipient_limit = 1
# Use amavis for virus and spam scanning
content_filter = amavis:[127.0.0.1]:10024
# Header manipulation
# --------------------------------------
# Getting rid of unwanted headers. See: https://posluns.com/guides/header-removal/
header_checks = regexp:/etc/postfix/header_checks
# getting rid of x-original-to
enable_original_recipient = no');
if(!file_exists('/etc/postfix/master.cf_backup'))
file_put_contents('/etc/postfix/master.cf_backup', file_get_contents('/etc/postfix/master.cf'));
file_put_contents('/etc/postfix/master.cf',
'#
# Postfix master process configuration file. For details on the format
# of the file, see the master(5) manual page (command: \"man 5 master\").
#
# Do not forget to execute \"postfix reload\" after editing this file.
#
# ==========================================================================
# service type private unpriv chroot wakeup maxproc command + args
# (yes) (yes) (yes) (never) (100)
# ==========================================================================
# SMTP on port 25, unencrypted.
smtp inet n - - - - smtpd
#smtp inet n - - - 1 postscreen
#smtpd pass - - - - - smtpd
#dnsblog unix - - - - 0 dnsblog
#tlsproxy unix - - - - 0 tlsproxy
# SMTP with TLS on port 587. Currently commented.
#submission inet n - - - - smtpd
# -o syslog_name=postfix/submission
# -o smtpd_tls_security_level=encrypt
# -o smtpd_sasl_auth_enable=yes
# -o smtpd_enforce_tls=yes
# -o smtpd_client_restrictions=permit_sasl_authenticated,reject_unauth_destination,reject
# -o smtpd_sasl_tls_security_options=noanonymous
# SMTP over SSL on port 465.
smtps inet n - - - - smtpd
-o syslog_name=postfix/smtps
-o smtpd_tls_wrappermode=yes
-o smtpd_sasl_auth_enable=yes
-o smtpd_tls_auth_only=yes
-o smtpd_client_restrictions=permit_sasl_authenticated,reject_unauth_destination,reject
-o smtpd_sasl_security_options=noanonymous,noplaintext
-o smtpd_sasl_tls_security_options=noanonymous
#628 inet n - - - - qmqpd
pickup fifo n - - 60 1 pickup
-o content_filter=
-o receive_override_options=no_header_body_checks
cleanup unix n - - - 0 cleanup
qmgr fifo n - n 300 1 qmgr
#qmgr fifo n - n 300 1 oqmgr
tlsmgr unix - - - 1000? 1 tlsmgr
rewrite unix - - - - - trivial-rewrite
bounce unix - - - - 0 bounce
defer unix - - - - 0 bounce
trace unix - - - - 0 bounce
verify unix - - - - 1 verify
flush unix n - - 1000? 0 flush
proxymap unix - - n - - proxymap
proxywrite unix - - n - 1 proxymap
smtp unix - - - - - smtp
relay unix - - - - - smtp
# -o smtp_helo_timeout=5 -o smtp_connect_timeout=5
showq unix n - - - - showq
error unix - - - - - error
retry unix - - - - - error
discard unix - - - - - discard
local unix - n n - - local
virtual unix - n n - - virtual
lmtp unix - - - - - lmtp
anvil unix - - - - 1 anvil
scache unix - - - - 1 scache
#
# ====================================================================
# Interfaces to non-Postfix software. Be sure to examine the manual
# pages of the non-Postfix software to find out what options it wants.
#
# Many of the following services use the Postfix pipe(8) delivery
# agent. See the pipe(8) man page for information about ${recipient}
# and other message envelope options.
# ====================================================================
#
# maildrop. See the Postfix MAILDROP_README file for details.
# Also specify in main.cf: maildrop_destination_recipient_limit=1
#
maildrop unix - n n - - pipe
flags=DRhu user=vmail argv=/usr/bin/maildrop -d ${recipient}
#
# ====================================================================
#
# Recent Cyrus versions can use the existing \"lmtp\" master.cf entry.
#
# Specify in cyrus.conf:
# lmtp cmd=\"lmtpd -a\" listen=\"localhost:lmtp\" proto=tcp4
#
# Specify in main.cf one or more of the following:
# mailbox_transport = lmtp:inet:localhost
# virtual_transport = lmtp:inet:localhost
#
# ====================================================================
#
# Cyrus 2.1.5 (Amos Gouaux)
# Also specify in main.cf: cyrus_destination_recipient_limit=1
#
#cyrus unix - n n - - pipe
# user=cyrus argv=/cyrus/bin/deliver -e -r ${sender} -m ${extension} ${user}
#
# ====================================================================
# Old example of delivery via Cyrus.
#
#old-cyrus unix - n n - - pipe
# flags=R user=cyrus argv=/cyrus/bin/deliver -e -m ${extension} ${user}
#
# ====================================================================
#
# See the Postfix UUCP_README file for configuration details.
#
uucp unix - n n - - pipe
flags=Fqhu user=uucp argv=uux -r -n -z -a$sender - $nexthop!rmail ($recipient)
#
# Other external delivery methods.
#/var/www/html/.htaccess
ifmail unix - n n - - pipe
flags=F user=ftn argv=/usr/lib/ifmail/ifmail -r $nexthop ($recipient)
bsmtp unix - n n - - pipe
flags=Fq. user=bsmtp argv=/usr/lib/bsmtp/bsmtp -t$nexthop -f$sender $recipient
scalemail-backend unix - n n - 2 pipe
flags=R user=scalemail argv=/usr/lib/scalemail/bin/scalemail-store ${nexthop} ${user} ${extension}
mailman unix - n n - - pipe
flags=FR user=list argv=/usr/lib/mailman/bin/postfix-to-mailman.py
${nexthop} ${user}
# The next two entries integrate with Amavis for anti-virus/spam checks.
amavis unix - - - - 3 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
# Integration with Dovecot - hand mail over to it for local delivery, and
# run the process under the vmail user and mail group.
dovecot unix - n n - - pipe
flags=DRhu user=vmail:mail argv=/usr/lib/dovecot/dovecot-lda -d $(recipient)');
}
function RestartAll()
{
Execute('service postfix restart');
Execute('service spamassassin restart');
Execute('service clamav-daemon restart');
Execute('service amavis restart');
Execute('service dovecot restart');
}
function InstallRoundCube()
{
Execute('apt-get install --assume-yes \
roundcube \
roundcube-plugins \
roundcube-plugins-extra');
UpdatePHPConfigFile('/etc/roundcube/main.inc.php', 'rcmail_config', array(
array('name' => 'default_host', 'value' => "'localhost'"),
array('name' => 'force_https', 'value' => 'true'),
array('name' => 'imap_cache', 'value' => "'memcache'"),
array('name' => 'session_storage', 'value' => "'memcache'"),
array('name' => 'memcache_hosts', 'value' => "array('localhost:11211')"),
));
Execute('ln -s /var/lib/roundcube /var/www/html/roundcube');
if(file_exists('/var/www/html/index.html'))
Execute('mv /var/www/html/index.html /var/www/html/index.bak.html');
file_put_contents('/var/www/html/.htaccess', 'RewriteEngine On
# Redirect all HTTP traffic to HTTPS.
RewriteCond %{HTTPS} !=on
RewriteRule ^/?(.*) https://%{SERVER_NAME}/$1 [R,L]
# Send / to /roundcube.
RewriteRule ^/?$ /roundcube [L]');
}
function InstallMonit()
{
Execute('apt-get install --assume-yes monit');
file_put_contents('/etc/monit/conf.d/amavis',
'check process amavisd with pidfile /var/run/amavis/amavisd.pid
every 5 cycles
group mail
start program = "/etc/init.d/amavis start"
stop program = "/etc/init.d/amavis stop"
if failed port 10024 protocol smtp then restart
if 5 restarts within 25 cycles then timeout');
file_put_contents('/etc/monit/conf.d/apache2',
'check process apache2 with pidfile /var/run/apache2/apache2.pid
group www
start program = "/etc/init.d/apache2 start"
stop program = "/etc/init.d/apache2 stop"
if failed host localhost port 80 protocol http
with timeout 10 seconds
then restart
if 5 restarts within 5 cycles then timeout');
file_put_contents('/etc/monit/conf.d/dovecot',
'check process dovecot with pidfile /var/run/dovecot/master.pid
group mail
start program = "/sbin/start dovecot"
stop program = "/sbin/stop dovecot"
group mail
# We\'d like to use this line, but see:
# http://serverfault.com/questions/610976/monit-failing-to-connect-to-dovecot-over-ssl-imap
#if failed port 993 type tcpssl sslauto protocol imap for 5 cycles then restart
if failed port 993 for 5 cycles then restart
if 5 restarts within 25 cycles then timeout');
file_put_contents('/etc/monit/conf.d/mysql',
'check process mysqld with pidfile /var/run/mysqld/mysqld.pid
group database
start program = "/etc/init.d/mysql start"
stop program = "/etc/init.d/mysql stop"
if failed host localhost port 3306 protocol mysql then restart
if 5 restarts within 5 cycles then timeout');
file_put_contents('/etc/monit/conf.d/memcached',
'check process memcached with pidfile /var/run/memcached.pid
group www
start program = "/etc/init.d/memcached start"
stop program = "/etc/init.d/memcached stop"
if failed host localhost port 11211 then restart
if 5 restarts within 5 cycles then timeout');
file_put_contents('/etc/monit/conf.d/postfix',
'check process postfix with pidfile /var/spool/postfix/pid/master.pid
group mail
start program = "/etc/init.d/postfix start"
stop program = "/etc/init.d/postfix stop"
if failed port 25 protocol smtp then restart
if 5 restarts within 5 cycles then timeout');
file_put_contents('/etc/monit/conf.d/spamassassin',
'check process spamassassin with pidfile /var/run/spamd.pid
group mail
start program = "/etc/init.d/spamassassin start"
stop program = "/etc/init.d/spamassassin stop"
if 5 restarts within 5 cycles then timeout');
file_put_contents('/etc/monit/conf.d/sshd',
'check process sshd with pidfile /var/run/sshd.pid
start program "/etc/init.d/ssh start"
stop program "/etc/init.d/ssh stop"
if failed host 127.0.0.1 port 22 protocol ssh then restart
if 5 restarts within 5 cycles then timeout');
Execute('service monit restart');
}
InstallPackages();
PrepareDatabase();
InstallPostfixAdmin();
VirtualMailUser();
ConfigureDovecot();
SpamVirus();
ConfigurePostfix();
RestartAll();
InstallMonit();
InstallRoundCube();