Newer
Older
<?php
/**
* Description of class
*
* @author croydon
*/
class ISPConfigDebianOS extends ISPConfigBaseOS {
public function getPackageVersion($package) {
$cmd = 'dpkg --list ' . $package . ' 2>&1';
$result = $this->exec($cmd);
$version = false;
$matches = array();
if(preg_match_all('/^ii\s+\S+\s+(\S+)(?:\s|$)/m', $result, $matches, PREG_SET_ORDER)) {
for($i = 0; $i < count($matches); $i++) {
$tmp_version = $matches[$i][1];
if(!$version || ISPProtectFunctions::version_compare($version, $tmp_version, '<')) {
$version = $tmp_version;
}
}
}
public function getPackageAlias($package) {
switch($package) {
case 'libssl':
$package = 'libssl[0-9]*';
break;
case 'kernel':
$package = 'linux-image-[0-9]*';
break;
}
public function getUpdateCommand($mode = 'update') {
if($mode == 'prepare') {
$cmd = 'DEBIAN_FRONTEND="noninteractive" apt-get update -qq -y';
} elseif($mode == 'update') {
// for updating all updateable packages
$cmd = 'DEBIAN_FRONTEND="noninteractive" apt-get dist-upgrade -o Dpkg::Options::="--force-overwrite" -qq -y';
} elseif($mode == 'install' || $mode == 'partly_update') {
// for installing / updating specific packages
$cmd = 'DEBIAN_FRONTEND="noninteractive" apt-get install -o Dpkg::Options::="--force-overwrite" -qq -y';
$cmd .= ' <PACKAGES>';
}
$cmd = 'while fuser /var/lib/dpkg/lock >/dev/null 2>&1 || fuser /var/lib/apt/lists/lock >/dev/null 2>&1 ; do sleep 2; done; ' . $cmd . ' 2>&1';
public function getUpdatePackageRegex() {
$regex = '^\w+\s+(?P<package>\S+)\s+(?:\[(?P<oldversion>\S+)\]\s*)?(?:\((?P<newversion>\S+))?(?:\s|$)';
public function getInstallPackageRegex($mode = '') {
if($mode == 'oldversion') {
$regex = '(?P<package>\S+)\s+(?:(?P<oldversion>\d\S+)\s+)?\(.*\.deb';
} elseif($mode == 'newversion') {
$regex = '(?:^|\s+)(?P<package>\S+)\s+\((?P<newversion>\d\S*)\)\s+';
} else {
$regex = ''; // not on debian!
}
public function getRestartServiceCommand($service, $command = 'restart') {
if($command != 'start' && $command != 'stop' && $command != 'status') {
$command = 'restart';
}
switch($service) {
case 'apache':
$service = 'apache2';
break;
case 'pureftpd':
$service = 'pure-ftpd-mysql';
break;
}
return 'service ' . escapeshellarg($service) . ' ' . $command . ' 2>&1';
}
protected function updateMySQLConfig($mysql_root_pw) {
ISPConfigLog::info('Writing MySQL config files.', true);
$this->replaceContents('/etc/mysql/debian.cnf', array('/^password\s*=.*$/m' => 'password = ' . $mysql_root_pw));
$this->replaceContents('/etc/mysql/mariadb.conf.d/50-server.cnf', array('/^bind-address/m' => '#bind-address', '/^sql-mode\s*=.*?$/m' => 'sql-mode = "NO_ENGINE_SUBSTITUTION"'), true, 'mysqld');
protected function getPackagesToInstall($section) {
if($section === 'mail') {
$packages = array(
'dnsutils',
'resolvconf',
'clamav',
'clamav-daemon',
'arj',
'nomarch',
'lzop',
'cabextract',
'apt-listchanges',
'libnet-ldap-perl',
'libauthen-sasl-perl',
'daemon',
'libio-string-perl',
'libio-socket-ssl-perl',
'libnet-ident-perl',
'libnet-dns-perl',
if(ISPConfig::wantsUnbound()) {
$packages[] = 'unbound';
} else {
$packages[] = 'bind9';
}
Marius Burkard
committed
}
if(ISPConfig::shallInstall('mail')) {
$packages[] = 'spamassassin';
if(ISPConfig::wantsAmavis()) {
$packages[] = 'amavisd-new';
} else {
$packages[] = 'rspamd';
$packages[] = 'redis-server';
}
$packages[] = 'postgrey';
}
} elseif($section === 'base') {
$packages = array(
'php-pear',
'php-memcache',
'php-imagick',
'php-gettext',
'mcrypt',
'imagemagick',
'libruby',
'memcached',
'php-apcu'
);
protected function getApacheModulesToDisable() {
$modules = array(
'mpm_prefork'
);
return $modules;
}
$modules = array('suexec', 'rewrite', 'ssl', 'actions', 'include', 'dav_fs', 'dav', 'auth_digest', 'cgi', 'headers', 'proxy_fcgi', 'alias', 'http2', 'mpm_event');
ISPConfigLog::info('Setting default system php version.', true);
$cmd = 'update-alternatives --set php /usr/bin/php7.0';
$result = $this->exec($cmd);
if($result === false) {
throw new ISPConfigOSException('Command ' . $cmd . ' failed.');
if(ISPConfig::shallInstall('web')) {
Thom Pol
committed
// When --use-php-system is used, there is no alternative for php-fpm.sock.
if(ISPConfig::wantsPHP() === 'system') {
$cmd = 'update-alternatives --set php-cgi /usr/bin/php-cgi7.0';
} else {
$cmd = 'update-alternatives --set php-cgi /usr/bin/php-cgi7.0 ; update-alternatives --set php-fpm.sock /run/php/php7.0-fpm.sock';
}
$result = $this->exec($cmd);
if($result === false) {
throw new ISPConfigOSException('Command ' . $cmd . ' failed.');
}
}
protected function installPHPMyAdmin($mysql_root_pw) {
if(!ISPConfig::shallInstall('web') || !ISPConfig::shallInstall('pma')) {
return;
}
$cmd = 'APP_PASS="' . ISPConfigFunctions::generatePassword(15) . '"' . "\n";
$cmd .= 'ROOT_PASS="' . $mysql_root_pw . '"' . "\n";
$cmd .= 'APP_DB_PASS="' . ISPConfigFunctions::generatePassword(15) . '"' . "\n";
$cmd .= 'echo "phpmyadmin phpmyadmin/dbconfig-install boolean true" | debconf-set-selections 2>&1' . "\n";
$cmd .= 'echo "phpmyadmin phpmyadmin/app-password-confirm password $APP_PASS" | debconf-set-selections 2>&1' . "\n";
$cmd .= 'echo "phpmyadmin phpmyadmin/mysql/admin-user string root" | debconf-set-selections 2>&1' . "\n";
$cmd .= 'echo "phpmyadmin phpmyadmin/mysql/admin-pass password $ROOT_PASS" | debconf-set-selections 2>&1' . "\n";
$cmd .= 'echo "phpmyadmin phpmyadmin/mysql/app-pass password $APP_DB_PASS" | debconf-set-selections 2>&1' . "\n";
$cmd .= 'echo "phpmyadmin phpmyadmin/reconfigure-webserver multiselect apache2" | debconf-set-selections 2>&1' . "\n";
$result = $this->exec($cmd);
if($result === false) {
throw new ISPConfigOSException('Command ' . $cmd . ' failed.');
$this->installPackages('phpmyadmin');
protected function fixDbconfigCommon() {
ISPConfigLog::info('Fixing dbconfig-common if neccessary');
$replacements = array(
'/_dbc_nodb="yes" dbc_mysql_exec/' => '_dbc_nodb="yes"; dbc_mysql_exec'
);
$this->replaceContents('/usr/share/dbconfig-common/internal/mysql', $replacements, false);
}
protected function setPHPTimezone() {
if(!is_file('/etc/timezone')) {
return;
}
$tz = trim(file_get_contents('/etc/timezone'));
if(!in_array($tz, timezone_identifiers_list())) {
return;
}
// set in all php inis
$ini_files = array(
'/etc/php/5.6/cgi/php.ini',
'/etc/php/5.6/cli/php.ini',
'/etc/php/5.6/fpm/php.ini',
'/etc/php/5.6/apache2/php.ini',
'/etc/php/7.0/cgi/php.ini',
'/etc/php/7.0/cli/php.ini',
'/etc/php/7.0/fpm/php.ini',
'/etc/php/7.0/apache2/php.ini',
'/etc/php/7.1/cgi/php.ini',
'/etc/php/7.1/cli/php.ini',
'/etc/php/7.1/fpm/php.ini',
'/etc/php/7.1/apache2/php.ini',
'/etc/php/7.2/cgi/php.ini',
'/etc/php/7.2/cli/php.ini',
'/etc/php/7.2/fpm/php.ini',
'/etc/php/7.2/apache2/php.ini',
'/etc/php/7.3/cgi/php.ini',
'/etc/php/7.3/cli/php.ini',
'/etc/php/7.3/fpm/php.ini',
'/etc/php/7.3/apache2/php.ini',
'/etc/php/7.4/cgi/php.ini',
'/etc/php/7.4/cli/php.ini',
'/etc/php/7.4/fpm/php.ini',
'/etc/php/7.4/apache2/php.ini',
'/etc/php/8.0/cgi/php.ini',
'/etc/php/8.0/cli/php.ini',
'/etc/php/8.0/fpm/php.ini',
'/etc/php/8.0/apache2/php.ini'
$replace = array(
'/^;?\s*date\.timezone\s+=.*$/' => 'date.timezone = ' . $tz
);
foreach($ini_files as $ini) {
if(is_file($ini)) {
$this->replaceContents($ini, $replace);
}
}
}
protected function configureApt() {
// enable contrib and non-free
ISPConfigLog::info('Enabling contrib and non-free repositories.', true);
$replacements = array(
'/^(deb.*\s+main)\s*$/' => '$1 contrib non-free'
);
$this->replaceContents('/etc/apt/sources.list', $replacements);
}
protected function addSuryRepo() {
ISPConfigLog::info('Activating sury php repository.', true);
$cmd = 'wget -O /etc/apt/trusted.gpg.d/php.gpg https://packages.sury.org/php/apt.gpg >/dev/null 2>&1 ; echo "deb https://packages.sury.org/php/ $(lsb_release -c -s) main" > /etc/apt/sources.list.d/php.list';
$result = $this->exec($cmd);
if($result === false) {
throw new ISPConfigOSException('Command ' . $cmd . ' failed.');
protected function addGoAccessRepo() {
ISPConfigLog::info('Activating GoAccess repository.', true);
$cmd = 'echo "deb https://deb.goaccess.io/ $(lsb_release -cs) main" | sudo tee -a /etc/apt/sources.list.d/goaccess.list >/dev/null 2>&1 ; wget -O - https://deb.goaccess.io/gnugpg.key 2>&1 | sudo apt-key --keyring /etc/apt/trusted.gpg.d/goaccess.gpg add - 2>&1';
$result = $this->exec($cmd);
if($result === false) {
throw new ISPConfigOSException('Command ' . $cmd . ' failed.');
}
}
protected function shallCompileJailkit() {
return true;
}
protected function getFail2BanJail() {
$jk_jail = '[pure-ftpd]
enabled = true
port = ftp
filter = pure-ftpd
logpath = /var/log/syslog
maxretry = 3
[dovecot]
enabled = true
filter = dovecot
logpath = /var/log/mail.log
maxretry = 5
[postfix-sasl]
enabled = true
port = smtp
filter = postfix-sasl
logpath = /var/log/mail.log
maxretry = 3';
return $jk_jail;
}
protected function installMailman($host_name) {
if(!ISPConfig::shallInstall('mail') || !ISPConfig::shallInstall('mailman')) {
return;
}
ISPConfigLog::info('Installing Mailman', true);
$cmd = 'echo "mailman mailman/site_languages multiselect de (German), en (English)" | debconf-set-selections 2>&1' . "\n";
if(isset($_GET['lang']) && $_GET['lang'] === 'de') {
$cmd .= 'echo "mailman mailman/default_server_language select de (German)" | debconf-set-selections 2>&1';
} else {
$cmd .= 'echo "mailman mailman/default_server_language select en (English)" | debconf-set-selections 2>&1';
}
$result = $this->exec($cmd);
if($result === false) {
throw new ISPConfigOSException('Command ' . $cmd . ' failed.');
}
$package = 'mailman';
$this->installPackages($package);
$listpw = '';
if(!is_dir('/var/lib/mailman/lists/mailman')) {
$listpw = ISPConfigFunctions::generatePassword(12);
$cmd = 'newlist -q -e ' . escapeshellarg($host_name) . ' mailman ' . escapeshellarg('root@' . $host_name) . ' ' . escapeshellarg($listpw);
$result = $this->exec($cmd);
if($result === false) {
throw new ISPConfigOSException('Command ' . $cmd . ' failed.');
}
$add_content = '## mailman mailing list
mailman: "|/var/lib/mailman/mail/mailman post mailman"
mailman-admin: "|/var/lib/mailman/mail/mailman admin mailman"
mailman-bounces: "|/var/lib/mailman/mail/mailman bounces mailman"
mailman-confirm: "|/var/lib/mailman/mail/mailman confirm mailman"
mailman-join: "|/var/lib/mailman/mail/mailman join mailman"
mailman-leave: "|/var/lib/mailman/mail/mailman leave mailman"
mailman-owner: "|/var/lib/mailman/mail/mailman owner mailman"
mailman-request: "|/var/lib/mailman/mail/mailman request mailman"
mailman-subscribe: "|/var/lib/mailman/mail/mailman subscribe mailman"
mailman-unsubscribe: "|/var/lib/mailman/mail/mailman unsubscribe mailman"';
$fp = fopen('/etc/aliases', 'r+');
if(!$fp) {
throw new ISPConfigOSException('Opening /etc/aliases failed.');
}
$found = false;
while(!feof($fp)) {
$line = trim(fgets($fp));
if($line === '## mailman mailing list') {
$found = true;
break;
}
}
if($found === false) {
fseek($fp, SEEK_END);
fwrite($fp, "\n\n" . $add_content);
}
$cmd = 'newaliases';
$result = $this->exec($cmd);
if($result === false) {
throw new ISPConfigOSException('Command ' . $cmd . ' failed.');
}
if(ISPConfig::$WEBSERVER === ISPC_WEBSERVER_APACHE) {
if(!is_link('/etc/apache2/conf-enabled/mailman.conf') && !is_file('/etc/apache2/conf-enabled/mailman.conf')) {
symlink('/etc/mailman/apache.conf', '/etc/apache2/conf-enabled/mailman.conf');
}
$this->restartService('postfix');
$this->restartService('mailman');
if(ISPConfig::$WEBSERVER === ISPC_WEBSERVER_APACHE) {
$this->restartService('apache2');
}
protected function installPackages($packages) {
if(is_string($packages)) {
$packages = array($packages);
}
ISPConfigLog::info('Installing packages ' . implode(', ', $packages), true);
$result = parent::installPackages($packages);
if($result !== false) {
ISPConfigLog::info('Installed packages ' . implode(', ', $packages), true);
} else {
throw new ISPConfigOSException('Installing packages failed.');
}
$log_filename = 'setup-' . strftime('%Y%m%d%H%M%S', time()) . '.log';
ISPConfigLog::setLogFile($log_filename);
if(is_file('/usr/local/ispconfig/server/lib/config.inc.php')) {
ISPConfigLog::error('The server already has ISPConfig installed. Aborting.', true);
return false;
}
if(ISPConfig::wantsUnbound() && ISPConfig::shallInstall('dns')) {
ISPConfigLog::error('You can only use --use-unbound together with --no-dns as ISPConfig requires Bind when dns is enabled.');
return false;
}
$this->configureApt();
$this->updatePackageList();
ISPConfigLog::info('Updating packages', true);
$cmd = $this->getUpdateCommand('update');
$result = $this->exec($cmd);
if($result !== false) {
ISPConfigLog::info('Updated packages', true);
} else {
throw new ISPConfigOSException('Command ' . $cmd . ' failed.');
}
try {
$this->beforePackageInstall();
} catch (Exception $ex) {
throw $ex;
$packages = array(
'ssh',
'openssh-server',
'nano',
'vim-nox',
'lsb-release',
'apt-transport-https',
'ca-certificates',
'wget',
'git'
);
if(ISPConfig::shallInstall('ntp')) {
$packages[] = 'ntp';
}
$this->installPackages($packages);
if(ISPConfig::shallInstall('mail') && !ISPConfig::wantsAmavis()) {
ISPConfigLog::info('Activating rspamd repository.', true);
$cmd = 'wget -O - "https://rspamd.com/apt-stable/gpg.key" 2>/dev/null | apt-key add - 2>/dev/null ; echo "deb http://rspamd.com/apt-stable/ $(lsb_release -c -s) main" > /etc/apt/sources.list.d/rspamd.list';
$result = $this->exec($cmd);
if($result === false) {
throw new ISPConfigOSException('Command ' . $cmd . ' failed.');
}
if(ISPConfig::wantsPHP() !== 'system') {
$this->addSuryRepo();
}
if(ISPConfig::shallInstall('web')) {
$this->addGoAccessRepo();
}
ISPConfigLog::info('Updating packages (after enabling 3rd party repos).', true);
$cmd = $this->getUpdateCommand('update');
$result = $this->exec($cmd);
if($result !== false) {
ISPConfigLog::info('Updated packages', true);
} else {
throw new ISPConfigOSException('Command ' . $cmd . ' failed.');
/*$hostname_changed = false;
ISPConfigLog::info('Setting hostname to ' . $host_name, true);
$dotpos = strpos($host_name, '.');
if($dotpos !== false) {
$short_hostname = substr($host_name, 0, $dotpos);
} else {
$short_hostname = '';
}
$hosts_entry = $this->ip_address . "\t" . $host_name . ($short_hostname ? ' ' . $short_hostname : '');
$use_hosts_file = '/etc/cloud/templates/hosts.tmpl';
} else {
$use_hosts_file = '/etc/hosts';
}
if(preg_match('/^\s*' . preg_quote($this->ip_address, '/') . ' (.*?)$/m', $content, $matches)) {
ISPConfigLog::info('Hostname is currently set to ' . $matches[1]);
$content = str_replace($matches[0], $hosts_entry, $content);
if($matches[0] != $hosts_entry) {
$hostname_changed = true;
}
} else {
ISPConfigLog::info('Hostname not found in hosts file.');
$content .= "\n" . $hosts_entry;
$hostname_changed = true;
}
$content = trim(file_get_contents('/etc/hostname'));
if($content != $short_hostname) {
ISPConfigLog::info('/etc/hostname is currently set to ' . $content, true);
$hostname_changed = true;
file_put_contents('/etc/hostname', $short_hostname);
ISPConfigLog::info('Hostname saved.', true);
if($hostname_changed) {
ISPConfigLog::info('Rebooting server.', true);
$ok = $this->exec('shutdown -r now >/dev/null 2>&1', array(0, 255));
if($ok === false) {
throw new ISPConfigOSException('Command for server reboot failed.');
}
$ok = $this->waitForReboot(30, 1200);
if(!$ok) {
throw new ISPConfigOSException('Timeout waiting for server to come up.');
ISPConfigLog::info('Server online again.', true);
}*/
ISPConfigLog::info('Checking hostname.', true);
$host_name = false;
$cmd = 'hostname -f 2>&1';
$check = $this->exec($cmd);
if($check === false) {
throw new ISPConfigOSException('Command ' . $cmd . ' failed.');
} else {
$host_name = $check;
}/* elseif(trim($check) !== $host_name) {
ISPConfigLog::warn('Hostname mismatch: ' . $check . ' != ' . $host_name);
}*/
$cmd = 'hostname 2>&1';
$check = $this->exec($cmd);
if($check === false) {
throw new ISPConfigOSException('Command ' . $cmd . ' failed.');
}/* elseif(trim($check) !== $short_hostname) {
ISPConfigLog::warn('Short hostname mismatch: ' . $check . ' != ' . $short_hostname);
}*/
if($host_name == '') {
ISPConfigLog::error('Could not read the host name of your server. Please check it is correctly set.', true);
throw new ISPConfigOSException('Invalid host name or host name not found.');
} elseif(substr_count($host_name, '.') < 2) {
ISPConfigLog::error('The host name ' . $host_name . ' of your server is no fully qualified domain name (xyz.domain.com). Please check it is correctly set.', true);
throw new ISPConfigOSException('Host name is no FQDN.');
}
$cmd = 'readlink /bin/sh 2>&1';
$check = trim($this->exec($cmd));
if($check === false) {
throw new ISPConfigOSException('Command ' . $cmd . ' failed.');
} elseif($check !== 'bash') {
//debconf-show dash
ISPConfigLog::info('Default shell is currently ' . $check . '.', true);
ISPConfigLog::info('Setting bash as default shell.', true);
$cmd = 'echo "dash dash/sh boolean false" | debconf-set-selections && DEBIAN_FRONTEND=noninteractive dpkg-reconfigure dash 2>&1';
$result = $this->exec($cmd);
if($result === false) {
throw new ISPConfigOSException('Command ' . $cmd . ' failed.');
}
$cmd = 'readlink /bin/sh 2>&1';
$check = trim($this->exec($cmd));
ISPConfigLog::info('Default shell is now ' . $check . '.', true);
}
$cmd = 'echo "postfix postfix/mailname string ' . $host_name . '" | debconf-set-selections 2>&1' . "\n";
$cmd .= 'echo "postfix postfix/main_mailer_type select Internet Site" | debconf-set-selections 2>&1';
$result = $this->exec($cmd);
if($result === false) {
throw new ISPConfigOSException('Command ' . $cmd . ' failed.');
'postfix',
'postfix-mysql',
'postfix-doc',
'mariadb-client',
'mariadb-server',
'openssl',
'getmail4',
'rkhunter',
'binutils',
'sudo'
);
$this->installPackages($packages);
if(ISPConfig::shallInstall('mail')) {
$packages = array(
'dovecot-imapd',
'dovecot-pop3d',
'dovecot-mysql',
'dovecot-sieve',
'dovecot-managesieved',
'dovecot-lmtpd'
);
$this->installPackages($packages);
} else {
$cmd = 'postconf -e "inet_interfaces = loopback-only"';
$result = $this->exec($cmd);
if($result === false) {
ISPConfigLog::warn('Command ' . $cmd . ' failed.', true);
}
ISPConfigLog::info('Generating mySQL password.', true);
// generate random password
$mysql_root_pw = ISPConfigFunctions::generatePassword(20);
$escaped_pw = preg_replace('/[\'\\\\]/', '\\$1', $mysql_root_pw);
$queries = array(
'DELETE FROM mysql.user WHERE User=\'\';',
'DELETE FROM mysql.user WHERE User=\'root\' AND Host NOT IN (\'localhost\', \'127.0.0.1\', \'::1\');',
'DROP DATABASE IF EXISTS test;',
'DELETE FROM mysql.db WHERE Db=\'test\' OR Db=\'test\\_%\';',
'UPDATE mysql.user SET Password=PASSWORD(\'' . $escaped_pw . '\') WHERE User=\'root\';',
'UPDATE mysql.user SET plugin = \'mysql_native_password\' WHERE User=\'root\';',
'FLUSH PRIVILEGES;'
);
foreach($queries as $query) {
$cmd = 'mysql --defaults-file=/etc/mysql/debian.cnf -e ' . escapeshellarg($query) . ' 2>&1';
$result = $this->exec($cmd);
if($result === false) {
ISPConfigLog::warn('Query ' . $query . ' failed.', true);
if(ISPConfig::shallInstall('mail')) {
ISPConfigLog::info('Configuring postfix.', true);
$entries = array(
array(
'first_line' => '/^submission\s+inet/',
'last_line' => '/^[a-z]/',
'skip_last_line' => true,
'search' => '/^\s+-o/'
),
array(
'first_line' => '/^smtps\s+inet/',
'last_line' => '/^[a-z]/',
'skip_last_line' => true,
'search' => '/^\s+-o/'
)
);
$this->commentLines('/etc/postfix/master.cf', $entries);
$entries = array(
array(
'first_line' => '/^#?submission\s+inet/',
'last_line' => null,
'search' => null,
'add_lines' => array(
' -o syslog_name=postfix/submission',
' -o smtpd_tls_security_level=encrypt',
' -o smtpd_sasl_auth_enable=yes',
' -o smtpd_client_restrictions=permit_sasl_authenticated,reject'
)
),
array(
'first_line' => '/^#?smtps\s+inet/',
'last_line' => null,
'search' => null,
'add_lines' => array(
' -o syslog_name=postfix/smtps',
' -o smtpd_tls_wrappermode=yes',
' -o smtpd_sasl_auth_enable=yes',
' -o smtpd_client_restrictions=permit_sasl_authenticated,reject'
)
);
$this->uncommentLines('/etc/postfix/master.cf', $entries);
}
ISPConfigLog::info('Restarting postfix', true);
$replacements = array(
'/^mysql\s+soft\s+nofile\s+.*/' => 'mysql soft nofile 65535',
'/^mysql\s+hard\s+nofile\s+.*/' => 'mysql hard nofile 65535'
);
$this->replaceContents('/etc/security/limits.conf', $replacements, true);
if(!is_dir('/etc/systemd/system/mysql.service.d/')) {
mkdir('/etc/systemd/system/mysql.service.d/', 0777, true);
$replacements = array(
'/^\s*LimitNOFILE\s*=.*?$/m' => 'LimitNOFILE=infinity'
);
$this->replaceContents('/etc/systemd/system/mysql.service.d/limits.conf', $replacements, true, 'Service');
$this->exec('systemctl daemon-reload 2>&1');
$this->restartService('mysql');
$this->installPackages($packages);
if(ISPConfig::shallInstall('mail') && !ISPConfig::wantsAmavis()) {
ISPConfigLog::info('Stopping Rspamd.', true);
$this->stopService('rspamd');
if(ISPConfig::wantsUnbound()) {
ISPConfigLog::info('(Re)starting unbound.', true);
$this->restartService('unbound');
} else {
ISPConfigLog::info('(Re)starting Bind.', true);
$this->restartService('bind9');
}
ISPConfigLog::info('Disabling spamassassin daemon.', true);
$this->stopService('spamassassin');
$this->exec('systemctl disable spamassassin 2>&1');
//$cmd = 'sudo -u unbound unbound-anchor -a /var/lib/unbound/root.key';
/*$result = $this->exec($cmd);
if($result === false) {
throw new ISPConfigOSException('Command ' . $cmd . ' failed.');
}
$this->restartService('unbound');
*/
Marius Burkard
committed
if(!is_dir('/etc/resolvconf/resolv.conf.d')) {
mkdir('/etc/resolvconf/resolv.conf.d', 0755);
}
$this->addLines('/etc/resolvconf/resolv.conf.d/head', 'nameserver 127.0.0.1', false);
$cmd = 'resolvconf -u 2>&1';
$result = $this->exec($cmd);
if($result === false) {
throw new ISPConfigOSException('Command ' . $cmd . ' failed.');
}
ISPConfigLog::info('Checking local dns resolver.', true);
$cmd = 'nslookup denic.de | grep Server';
$result = $this->exec($cmd);
if($result === false) {
throw new ISPConfigOSException('Command ' . $cmd . ' failed.');
} elseif(strpos($result, '127.0.0.1') === false) {
ISPConfigLog::warn('Unexpected resolver response: ' . $result, true);
}
if(ISPConfig::shallInstall('web')) {
$this->stopService('apache2');
$this->stopService('nginx');
if(ISPConfig::$WEBSERVER === ISPC_WEBSERVER_APACHE) {
$packages = array(
'apache2',
'apache2-doc',
'apache2-utils',
'libapache2-mod-fcgid',
'apache2-suexec-pristine',
'libapache2-mod-python',
'libapache2-mod-passenger'
);
} elseif(ISPConfig::$WEBSERVER === ISPC_WEBSERVER_NGINX) {
$packages = array(
'nginx-full',
'fcgiwrap'
);
}
$this->installPackages($packages);
if(ISPConfig::$WEBSERVER === ISPC_WEBSERVER_NGINX) {
$this->stopService('apache2');
$cmd = 'systemctl disable apache2';
$this->exec($cmd); // ignore if this fails
$this->startService('nginx');
}
$packages = $this->getPackagesToInstall('base');
if(ISPConfig::wantsPHP() === 'system') {
$php_versions = array($this->getSystemPHPVersion());
} else {
//ISPConfig::run() validations prevent sending here null values
$php_versions = ISPConfig::wantsPHP();
$php_modules = array(
'common',
'gd',
'mysql',
'imap',
'cli',
'mcrypt',
'curl',
'intl',
'pspell',
'recode',
'sqlite3',
'tidy',
'xmlrpc',
'xsl',
'zip',
'mbstring',
'soap',
'opcache'
);
if(ISPConfig::shallInstall('web')) {
$php_modules[] = 'cgi';
$php_modules[] = 'fpm';
}
foreach($php_versions as $curver) {
$packages[] = 'php' . $curver;
reset($php_modules);
foreach($php_modules as $curmod) {
if(version_compare($curver, '7.2', '>=') && in_array($curmod, array('mcrypt'), true)) {
continue;
} elseif(version_compare($curver, '7.4', '>=') && in_array($curmod, array('mcrypt', 'recode'), true)) {
continue;
} elseif(version_compare($curver, '8.0', '>=') && in_array($curmod, array('mcrypt', 'recode', 'json', 'xmlrpc'), true)) {
$packages[] = 'php' . $curver . '-' . $curmod;
}
}
$this->installPackages($packages);
if(ISPConfig::shallInstall('web') && ISPConfig::$WEBSERVER === ISPC_WEBSERVER_APACHE) {
// Disable conflicting modules so mpm_event can be used with http2
ISPConfigLog::info('Disabling conflicting apache modules.', true);
$modules = $this->getApacheModulesToDisable();
$cmd = 'a2dismod ' . implode(' ', $modules) . ' 2>&1';
$result = $this->exec($cmd);
if($result === false) {
throw new ISPConfigOSException('Command ' . $cmd . ' failed.');
}
ISPConfigLog::info('Enabling apache modules.', true);
$modules = $this->getApacheModulesToEnable();
$cmd = 'a2enmod ' . implode(' ', $modules) . ' 2>&1';
$result = $this->exec($cmd);
if($result === false) {
throw new ISPConfigOSException('Command ' . $cmd . ' failed.');
}
ISPConfigLog::info('Enabling default PHP-FPM config.', true);
$conf = 'php' . $this->getSystemPHPVersion() . '-fpm';
$cmd = 'a2enconf ' . $conf . ' 2>&1';
$result = $this->exec($cmd);
if($result === false) {
throw new ISPConfigOSException('Command ' . $cmd . ' failed.');
}
$this->restartService('apache2');
$this->setPHPTimezone();
$this->setDefaultPHP();
foreach($php_versions as $curver) {
$this->restartService('php' . $curver . '-fpm');
if(ISPConfig::shallInstall('web') && ISPConfig::$WEBSERVER === ISPC_WEBSERVER_APACHE) {
ISPConfigLog::info('HTTPoxy config.', true);
$httpoxy = '<IfModule mod_headers.c>' . "\n" . ' RequestHeader unset Proxy early' . "\n" . '</IfModule>';
file_put_contents('/etc/apache2/conf-available/httpoxy.conf', $httpoxy);
$cmd = 'a2enconf httpoxy 2>&1';
$result = $this->exec($cmd);
if($result === false) {
throw new ISPConfigOSException('Command ' . $cmd . ' failed.');
}
$this->restartService('apache2');
ISPConfigLog::info('Installing letsencrypt (acme.sh).', true);
$cmd = 'cd /tmp ; wget -O - https://get.acme.sh 2>/dev/null | sh 2>/dev/null';
$result = $this->exec($cmd);
if($result === false) {
ISPConfigLog::warn('Installing letsencrypt failed.', true);
} else {
ISPConfigLog::info('Letsencrypt installed.', true);
$mailman_password = '';
if(ISPConfig::shallInstall('mailman')) {
$mailman_password = $this->installMailman($host_name);
$packages = array(
'quota',
'quotatool',
'haveged',
'libclass-dbi-mysql-perl',
'libtimedate-perl',
'build-essential',
'autoconf',
'automake',
'libtool',
'flex',
'bison',
'debhelper',
'binutils'
$this->installPackages($packages);
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
if(ISPConfig::shallInstall('quota')) {
// check kernel if it is virtual
$check = $this->getPackageVersion('linux-image-virtual');
if($check) {
ISPConfigLog::info('Installing extra quota package for virtual kernel.', true);
$this->installPackages('linux-image-extra-virtual');
// check kernel version from dpkg vs version running
$check = $this->getPackageVersion('linux-image-extra-virtual');
$running_version = php_uname('r');
if(!is_dir('/lib/modules/' . $running_version . '/kernel/fs/quota/') || !is_file('/lib/modules/' . $running_version . '/kernel/fs/quota/quota_v2.ko')) {
$running_version = preg_replace('/^([0-9\.]+(?:-\d+)?)(?:-.*?)?$/', '$1', $running_version);
try {
$this->installPackages('linux-image-extra-virtual=' . $running_version . '*');
} catch (Exception $ex) {
// ignore it
}
// check if quota module is available
if(!$this->exec('modinfo quota_v1 quota_v2 2>&1')) {
ISPConfigLog::error('The running kernel version (' . $running_version . ') does not match your installed kernel modules (' . $check . '). Currently there is no quota available! Please reboot your server to load the new kernel and run the autoinstaller again or start it with --no-quota to disable quota completely.', true);
throw new ISPConfigOSException('Installation aborted due to missing dependencies.');
}
}
ISPConfigLog::info('Enabling quota modules for virtual kernel.', true);
$cmd = 'modprobe quota_v2 quota_v1 2>&1';
$result = $this->exec($cmd);
if($result === false) {
throw new ISPConfigOSException('Enabling quota modules failed.');
}
}
ISPConfigLog::info('Adding quota to fstab.', true);
$replacements = array(
'/^(\S+\s+\/\s+ext\d)\s+(\S+)\s+(\d\s+\d)\s*$/m' => array(