diff --git a/Makefile.in b/Makefile.in index a9769bc..58e767e 100644 --- a/Makefile.in +++ b/Makefile.in @@ -109,3 +109,8 @@ key: dd if=/dev/urandom bs=56 count=1 of=piler.key +postinstall: + @sh util/postinstall.sh $(RUNNING_USER) $(RUNNING_GROUP) $(sysconfdir) $(localstatedir) + + + diff --git a/etc/sphinx.conf b/etc/sphinx.conf deleted file mode 100644 index 734a5c9..0000000 --- a/etc/sphinx.conf +++ /dev/null @@ -1,144 +0,0 @@ -# -# Minimal Sphinx configuration sample (clean, simple, functional) -# - -source base -{ - type = mysql - sql_host = localhost - sql_db = piler - sql_user = piler - sql_pass = piler -} - -source main : base -{ - sql_query_pre = SET NAMES utf8 - sql_query = SELECT id, `from`, `to`, `fromdomain`, `todomain`, `subject`, `arrived`, `sent`, `body`, `size`, `direction`, `folder`, `attachments`, `attachment_types` FROM sph_index \ - WHERE id<=( SELECT max_doc_id FROM sph_counter WHERE counter_id=1 ) - - sql_attr_uint = size - sql_attr_uint = arrived - sql_attr_uint = sent - sql_attr_uint = direction - sql_attr_uint = folder - sql_attr_uint = attachments - -} - - -source delta : base -{ - sql_query_pre = SET NAMES utf8 - sql_query_pre = REPLACE INTO sph_counter SELECT 1, MAX(id) FROM sph_index - sql_query_post_index = DELETE FROM sph_index WHERE id<=(SELECT max_doc_id FROM sph_counter WHERE counter_id=1) - sql_query = SELECT id, `from`, `to`, `fromdomain`, `todomain`, `subject`, `arrived`, `sent`, `body`, `size`, `direction`, `folder`, `attachments`, `attachment_types` FROM sph_index \ - WHERE id <= (SELECT max_doc_id FROM sph_counter WHERE counter_id=1) - - sql_attr_uint = size - sql_attr_uint = arrived - sql_attr_uint = sent - sql_attr_uint = direction - sql_attr_uint = folder - sql_attr_uint = attachments - - sql_query_killlist = SELECT `id` FROM `metadata` WHERE `deleted`=1 - -} - - -source tag : base -{ - sql_query_pre = SET NAMES utf8 - sql_query = SELECT `_id`, `id`, `uid`, `tag` FROM `tag` - - sql_attr_uint = id - sql_attr_uint = uid - -} - - -source note : base -{ - sql_query_pre = SET NAMES utf8 - sql_query = SELECT `_id`, `id`, `uid`, `note` FROM `note` - - sql_attr_uint = id - sql_attr_uint = uid - -} - - -index main1 -{ - source = main - path = /var/piler/sphinx/main1 - docinfo = extern - charset_type = utf-8 - enable_star = 1 - min_prefix_len = 6 - min_word_len = 1 - -} - - -index delta1 -{ - source = delta - path = /var/piler/sphinx/delta1 - docinfo = extern - charset_type = utf-8 - enable_star = 1 - min_prefix_len = 6 - min_word_len = 1 - -} - - -index tag1 -{ - source = tag - path = /var/piler/sphinx/tag1 - docinfo = extern - charset_type = utf-8 - enable_star = 1 - min_prefix_len = 6 - min_word_len = 1 -} - - -index note1 -{ - source = note - path = /var/piler/sphinx/note1 - docinfo = extern - charset_type = utf-8 - enable_star = 1 - min_prefix_len = 6 - min_word_len = 1 -} - - -indexer -{ - mem_limit = 64M -} - - -searchd -{ - listen = 127.0.0.1:9312 - listen = 127.0.0.1:9306:mysql41 - log = /dev/null - binlog_path = - ##query_log = - read_timeout = 5 - max_children = 30 - pid_file = /var/run/piler/searchd.pid - max_matches = 1000 - seamless_rotate = 1 - preopen_indexes = 1 - unlink_old = 1 - workers = threads # for RT to work - compat_sphinxql_magics = 0 -} diff --git a/etc/sphinx.conf.in b/etc/sphinx.conf.in new file mode 100644 index 0000000..c20248e --- /dev/null +++ b/etc/sphinx.conf.in @@ -0,0 +1,144 @@ +# +# Minimal Sphinx configuration sample (clean, simple, functional) +# + +source base +{ + type = mysql + sql_host = MYSQL_HOSTNAME + sql_db = MYSQL_DATABASE + sql_user = MYSQL_USERNAME + sql_pass = MYSQL_PASSWORD +} + +source main : base +{ + sql_query_pre = SET NAMES utf8 + sql_query = SELECT id, `from`, `to`, `fromdomain`, `todomain`, `subject`, `arrived`, `sent`, `body`, `size`, `direction`, `folder`, `attachments`, `attachment_types` FROM sph_index \ + WHERE id<=( SELECT max_doc_id FROM sph_counter WHERE counter_id=1 ) + + sql_attr_uint = size + sql_attr_uint = arrived + sql_attr_uint = sent + sql_attr_uint = direction + sql_attr_uint = folder + sql_attr_uint = attachments + +} + + +source delta : base +{ + sql_query_pre = SET NAMES utf8 + sql_query_pre = REPLACE INTO sph_counter SELECT 1, MAX(id) FROM sph_index + sql_query_post_index = DELETE FROM sph_index WHERE id<=(SELECT max_doc_id FROM sph_counter WHERE counter_id=1) + sql_query = SELECT id, `from`, `to`, `fromdomain`, `todomain`, `subject`, `arrived`, `sent`, `body`, `size`, `direction`, `folder`, `attachments`, `attachment_types` FROM sph_index \ + WHERE id <= (SELECT max_doc_id FROM sph_counter WHERE counter_id=1) + + sql_attr_uint = size + sql_attr_uint = arrived + sql_attr_uint = sent + sql_attr_uint = direction + sql_attr_uint = folder + sql_attr_uint = attachments + + sql_query_killlist = SELECT `id` FROM `metadata` WHERE `deleted`=1 + +} + + +source tag : base +{ + sql_query_pre = SET NAMES utf8 + sql_query = SELECT `_id`, `id`, `uid`, `tag` FROM `tag` + + sql_attr_uint = id + sql_attr_uint = uid + +} + + +source note : base +{ + sql_query_pre = SET NAMES utf8 + sql_query = SELECT `_id`, `id`, `uid`, `note` FROM `note` + + sql_attr_uint = id + sql_attr_uint = uid + +} + + +index main1 +{ + source = main + path = /var/piler/sphinx/main1 + docinfo = extern + charset_type = utf-8 + enable_star = 1 + min_prefix_len = 6 + min_word_len = 1 + +} + + +index delta1 +{ + source = delta + path = /var/piler/sphinx/delta1 + docinfo = extern + charset_type = utf-8 + enable_star = 1 + min_prefix_len = 6 + min_word_len = 1 + +} + + +index tag1 +{ + source = tag + path = /var/piler/sphinx/tag1 + docinfo = extern + charset_type = utf-8 + enable_star = 1 + min_prefix_len = 6 + min_word_len = 1 +} + + +index note1 +{ + source = note + path = /var/piler/sphinx/note1 + docinfo = extern + charset_type = utf-8 + enable_star = 1 + min_prefix_len = 6 + min_word_len = 1 +} + + +indexer +{ + mem_limit = 64M +} + + +searchd +{ + listen = 127.0.0.1:9312 + listen = 127.0.0.1:9306:mysql41 + log = /dev/null + binlog_path = + ##query_log = + read_timeout = 5 + max_children = 30 + pid_file = /var/run/piler/searchd.pid + max_matches = 1000 + seamless_rotate = 1 + preopen_indexes = 1 + unlink_old = 1 + workers = threads # for RT to work + compat_sphinxql_magics = 0 +} diff --git a/src/config.h b/src/config.h index 9f0c3f7..fd53513 100644 --- a/src/config.h +++ b/src/config.h @@ -13,7 +13,7 @@ #define VERSION "0.1.23-master-branch" -#define BUILD 782 +#define BUILD 783 #define HOSTID "mailarchiver" diff --git a/util/db-mysql-root.sql.in b/util/db-mysql-root.sql.in new file mode 100644 index 0000000..be73e14 --- /dev/null +++ b/util/db-mysql-root.sql.in @@ -0,0 +1,5 @@ +create database MYSQL_DATABASE character set 'utf8'; +grant all privileges on MYSQL_DATABASE.* to MYSQL_USERNAME@localhost identified by 'MYSQL_PASSWORD'; +flush privileges; + + diff --git a/util/db-mysql.sql b/util/db-mysql.sql index 70c45f2..7b4ad7b 100644 --- a/util/db-mysql.sql +++ b/util/db-mysql.sql @@ -1,6 +1,3 @@ -create database if not exists `piler` character set 'utf8'; -use `piler`; - drop table if exists `sph_counter`; create table if not exists `sph_counter` ( diff --git a/util/postinstall.sh b/util/postinstall.sh new file mode 100755 index 0000000..43a4071 --- /dev/null +++ b/util/postinstall.sh @@ -0,0 +1,283 @@ +#!/bin/sh + + +INDEXER=`which indexer 2>/dev/null` +SEARCHD=`which searchd 2>/dev/null` +CRON_ORIG="/tmp/crontab.piler.orig" +CRON_TMP="/tmp/crontab.piler" + + +. ./util/utilfunc.sh + + +preinstall_check() { + check_user root + + if [ "x$INDEXER" = "x" ]; then "ERROR: cannot find sphinx indexer"; echo ""; exit ; fi + + if [ "x$SEARCHD" = "x" ]; then "ERROR: cannot find sphinx searchd"; echo ""; exit 0; fi + + if [ -f $KEYFILE ]; then echo "ERROR: found existing keyfile ($KEYFILE), aborting install"; echo ""; exit 0; fi +} + + +gather_webserver_data() { + askNonBlank "Please enter the path of your documentroot" "$DOCROOT" + DOCROOT=$response + + if [ -d $DOCROOT ]; then echo "ERROR: vhost docroot should NOT exist, abroting install"; echo ""; exit 0; fi + + askNonBlank "Please enter the webserver groupname" "$WWWGROUP" + WWWGROUP=$response +} + + +gather_mysql_account() { + + askNonBlank "Please enter mysql hostname" "$MYSQL_HOSTNAME" + MYSQL_HOSTNAME=$response + + askNonBlank "Please enter mysql database" "$MYSQL_DATABASE" + MYSQL_DATABASE=$response + + askNonBlank "Please enter mysql user name" "$MYSQL_USERNAME" + MYSQL_USERNAME=$response + + askNonBlankNoEcho "Please enter mysql password for $MYSQL_USERNAME" "" + MYSQL_PASSWORD=$response + + askNonBlankNoEcho "Please enter mysql root password" "" + MYSQL_ROOT_PASSWORD=$response + + s=`echo "use information_schema; select TABLE_NAME from TABLES where TABLE_SCHEMA='$MYSQL_DATABASE'" | mysql -h $MYSQL_HOSTNAME -u root --password=$MYSQL_ROOT_PASSWORD` + if [ $? -eq 0 ]; + then + echo "mysql connection successful"; echo; + if [ `echo $s | grep -c metadata` -eq 1 ]; then echo "ERROR: Detected metadata table in $MYSQL_DATABASE. Aborting"; exit 0; fi + else + echo "ERROR: failed to connect to mysql"; + gather_mysql_account + fi + +} + + +gather_sphinx_data() { + + if [ $INDEXER = "/usr/bin/indexer" ]; then SPHINXCFG="/etc/sphinx.conf"; fi + + askNonBlank "Please enter the path of sphinx.conf" "$SPHINXCFG" + SPHINXCFG=$response +} + + +gather_smtp_relay_data() { + ask "Please enter smtp relay" "$SMARTHOST" + SMARTHOST=$response + + askNonBlankNoEcho "Please enter smtp relay port" "$SMARTHOST_PORT" + SMARTHOST_PORT=$response +} + + +make_cron_entries() { + + crontab -u $PILERUSER -l > $CRON_ORIG + + grep PILERSTART $CRON_ORIG > /dev/null 2>&1 + if [ $? != 0 ]; then + cat /dev/null > $CRON_ORIG + fi + + grep PILEREND $CRON_ORIG > /dev/null 2>&1 + if [ $? != 0 ]; then + cat /dev/null > $CRON_ORIG + fi + + + rm -f $CRON_TMP + + echo "" + echo "### PILERSTART" >> $CRON_TMP + echo "*/5 * * * * LC_ALL=C mpstat | tail -1 | awk '{print $11}' > $LOCALSTATEDIR/piler/stat/cpu.stat" >> $CRON_TMP + echo "5,35 * * * * $INDEXER --quiet delta1 --rotate && sleep 2 && $INDEXER --quiet --merge main1 delta1 --merge-dst-range deleted 0 0 --rotate" >> $CRON_TMP + echo "*/15 * * * * $INDEXER --quiet tag1 --rotate" >> $CRON_TMP + echo "*/15 * * * * $INDEXER --quiet note1 --rotate" >> $CRON_TMP + echo "### PILEREND" >> $CRON_TMP +} + + +make_new_key() { + dd if=/dev/urandom bs=56 count=1 of=$KEYTMPFILE 2>/dev/null + + if [ `stat -c '%s' $KEYTMPFILE` -ne 56 ]; then echo "could not read 56 bytes from /dev/urandom to $KEYTMPFILE"; exit 1; fi +} + + +show_summary() { + echo + echo + echo "INSTALLATION SUMMARY:" + echo + + echo "piler user: $PILERUSER" + echo "keyfile: $KEYFILE" + echo + + echo "mysql host: $MYSQL_HOSTNAME" + echo "mysql database: $MYSQL_DATABASE" + echo "mysql username: $MYSQL_USERNAME" + echo "mysql password: *******" + echo + + echo "sphinx indexer: $INDEXER" + echo "sphinx config file: $SPHINXCFG" + echo + + echo "vhost docroot: $DOCROOT" + echo "www group: $WWWGROUP" + echo + + echo "smtp relay host: $SMARTHOST" + echo "smtp relay port: $SMARTHOST_PORT" + echo + + echo "piler crontab:" + cat $CRON_TMP + echo; echo; + + askYN "Correct? [Y/N]" "N" + if [ $response != "yes" ]; then + echo "Aborted." + exit + fi + +} + + +execute_post_install_tasks() { + + askYN "Continue and modify system? [Y/N]" "N" + if [ $response != "yes" ]; then + echo "Aborted." + exit + fi + + echo; + echo -n "Creating mysql database... "; + sed -e "s%MYSQL_HOSTNAME%$MYSQL_HOSTNAMEg%" -e "s%MYSQL_DATABASE%$MYSQL_DATABASE%g" -e "s%MYSQL_USERNAME%$MYSQL_USERNAME%g" -e "s%MYSQL_PASSWORD%$MYSQL_PASSWORD%g" util/db-mysql-root.sql.in | mysql -h $MYSQL_HOSTNAME -u root --password=$MYSQL_ROOT_PASSWORD + mysql -h $MYSQL_HOSTNAME -u $MYSQL_USERNAME --password=$MYSQL_PASSWORD $MYSQL_DATABASE < util/db-mysql.sql + echo "Done." + + echo -n "Overwriting sphinx configuration... "; + sed -e "s%MYSQL_HOSTNAME%$MYSQL_HOSTNAME%" -e "s%MYSQL_DATABASE%$MYSQL_DATABASE%" -e "s%MYSQL_USERNAME%$MYSQL_USERNAME%" -e "s%MYSQL_PASSWORD%$MYSQL_PASSWORD%" etc/sphinx.conf.in > etc/sphinx.conf + cp etc/sphinx.conf $SPHINXCFG + echo "Done." + + echo -n "Initializing sphinx indices... "; + su $PILERUSER -c "indexer --all" + echo "Done." + + + echo -n "installing cron entries for $PILERUSER... " + crontab -u $PILERUSER $CRON_TMP + echo "Done." + + + echo -n "installing keyfile ($KEYTMPFILE) to $KEYFILE... " + cp $KEYTMPFILE $KEYFILE + chgrp $PILERUSER $KEYFILE + chmod 640 $KEYFILE + rm -f $KEYTMPFILE + echo "Done." + + echo -n "Copying www files to $DOCROOT... " + mkdir -p $DOCROOT || exit 1 + + cp -R webui/* $DOCROOT + cp -R webui/.htaccess $DOCROOT + chmod 770 $DOCROOT/tmp + chgrp $WWWGROUP $DOCROOT/tmp + + echo " $DOCROOT/config-site.php + echo >> $DOCROOT/config-site.php + + echo "\$config['SITE_NAME'] = '$HOSTNAME';" >> $DOCROOT/config-site.php + echo "\$config['SITE_URL'] = 'http://$HOSTNAME/';" >> $DOCROOT/config-site.php + echo "\$config['DIR_BASE'] = '$DOCROOT/';" >> $DOCROOT/config-site.php + + echo >> $DOCROOT/config-site.php + + echo "\$config['ENABLE_SYSLOG'] = 1;" >> $DOCROOT/config-site.php + + echo >> $DOCROOT/config-site.php + + echo "\$config['SMTP_DOMAIN'] = '$HOSTNAME';" >> $DOCROOT/config-site.php + echo "\$config['SMTP_FROMADDR'] = 'no-reply@$HOSTNAME';" >> $DOCROOT/config-site.php + echo "\$config['ADMIN_EMAIL'] = 'admin@$HOSTNAME';" >> $DOCROOT/config-site.php + + echo >> $DOCROOT/config-site.php + + echo "\$config['DB_DRIVER'] = 'mysql';" >> $DOCROOT/config-site.php + echo "\$config['DB_PREFIX'] = '';" >> $DOCROOT/config-site.php + echo "\$config['DB_HOSTNAME'] = '$MYSQL_HOSTNAME';" >> $DOCROOT/config-site.php + echo "\$config['DB_USERNAME'] = '$MYSQL_USERNAME';" >> $DOCROOT/config-site.php + echo "\$config['DB_PASSWORD'] = '$MYSQL_PASSWORD';" >> $DOCROOT/config-site.php + echo "\$config['DB_DATABASE'] = '$MYSQL_DATABASE';" >> $DOCROOT/config-site.php + + echo >> $DOCROOT/config-site.php + + echo "\$config['SMARTHOST'] = '$SMARTHOST';" >> $DOCROOT/config-site.php + echo "\$config['SMARTHOST_PORT'] = $SMARTHOST_PORT;" >> $DOCROOT/config-site.php + + echo >> $DOCROOT/config-site.php + + echo "?>" >> $DOCROOT/config-site.php + + echo "Done." + +} + + +clean_up_temp_stuff() { + rm -f $CRON_TMP + + echo; echo "Done post installation tasks."; echo +} + + +load_default_values + + +if [ $# -ne 4 ]; then usage; fi + +PILERUSER=$1 +PILERGROUP=$2 +SYSCONFDIR=$3 +LOCALSTATEDIR=$4 + + +#LOGFILE="/tmp/piler-install.log.$$" +#touch $LOGFILE +#chmod 600 $LOGFILE + +preinstall_check + +display_install_intro + +gather_webserver_data +gather_mysql_account +gather_sphinx_data +gather_smtp_relay_data + + +make_cron_entries +make_new_key + +show_summary + +execute_post_install_tasks + +clean_up_temp_stuff + + diff --git a/util/utilfunc.sh b/util/utilfunc.sh new file mode 100644 index 0000000..7236ffd --- /dev/null +++ b/util/utilfunc.sh @@ -0,0 +1,154 @@ +#!/bin/sh + + +usage() { + echo "usage: $0 "; + exit 1; +} + + +load_default_values() { + PILERUSER="piler" + SYSCONFDIR="/usr/local/etc" + LOCALSTATEDIR="/var" + + KEYTMPFILE="piler.key" + KEYFILE="$SYSCONFDIR/piler.key" + + HOSTNAME=`hostname --fqdn` + + MYSQL_HOSTNAME="localhost" + MYSQL_DATABASE="piler" + MYSQL_USERNAME="piler" + MYSQL_PASSWORD="" + MYSQL_ROOT_PASSWORD="" + + SPHINXCFG="/usr/local/etc/sphinx.conf" + + WWWGROUP="apache" + DOCROOT="/var/www/$HOSTNAME" + + SMARTHOST="" + SMARTHOST_PORT=25 +} + + +display_install_intro() { + echo "" + echo "" + echo "This is the postinstall utility for piler" + echo "It should be run only at the first install. DO NOT run on an existing piler installation!" + echo "" + + askYN "Continue? [Y/N]" "N" + if [ $response != "yes" ]; then + echo "Aborted." + exit + fi + + echo "" +} + + +check_user() { + user=$1 + + if [ x`whoami` != x$user ]; then echo "ERROR: postinstaller must be run as $user user"; exit 1; fi +} + + +isFQDN() { + # we need min. 2 dots + if [ x"$1" = "xdogfood" ]; then + echo 1 + return + fi + + if [ x"$1" = "x" ]; then + echo 0 + return + fi + + NF=`echo $1 | awk -F. '{print NF}'` + if [ $NF -ge 2 ]; then + echo 1 + else + echo 0 + fi +} + + +ask() { + PROMPT=$1 + DEFAULT=$2 + + echo "" + echo -n "$PROMPT [$DEFAULT] " + read response + + if [ -z $response ]; then + response=$DEFAULT + fi +} + + +askNonBlankNoEcho() { + PROMPT=$1 + DEFAULT=$2 + + while [ 1 ]; do + stty -echo + ask "$PROMPT" "$DEFAULT" + stty echo + echo "" + if [ ! -z $response ]; then + break + fi + echo "A non-blank answer is required" + done +} + +askNonBlank() { + PROMPT=$1 + DEFAULT=$2 + + while [ 1 ]; do + ask "$PROMPT" "$DEFAULT" + if [ ! -z $response ]; then + break + fi + echo "A non-blank answer is required" + done +} + +askYN() { + PROMPT=$1 + DEFAULT=$2 + + if [ "x$DEFAULT" = "xyes" -o "x$DEFAULT" = "xYes" -o "x$DEFAULT" = "xy" -o "x$DEFAULT" = "xY" ]; then + DEFAULT="Y" + else + DEFAULT="N" + fi + + while [ 1 ]; do + ask "$PROMPT" "$DEFAULT" + response=$(perl -e "print lc(\"$response\");") + if [ -z $response ]; then + : + else + if [ $response = "yes" -o $response = "y" ]; then + response="yes" + break + else + if [ $response = "no" -o $response = "n" ]; then + response="no" + break + fi + fi + fi + echo "A Yes/No answer is required" + done +} + +