This commit is contained in:
Alexey Berezhok
2024-03-19 22:05:27 +03:00
commit 346a50856b
1572 changed files with 182163 additions and 0 deletions

579
func/backup.sh Normal file
View File

@@ -0,0 +1,579 @@
#!/bin/bash
#===========================================================================#
# #
# Hestia Control Panel - Backup Function Library #
# #
#===========================================================================#
# Local storage
# Defining local storage function
local_backup() {
rm -f $BACKUP/$user.$backup_new_date.tar
# Checking retention
backup_list=$(ls -lrt $BACKUP/ | awk '{print $9}' | grep "^$user\." | grep ".tar")
backups_count=$(echo "$backup_list" | wc -l)
if [ "$BACKUPS" -le "$backups_count" ]; then
backups_rm_number=$((backups_count - BACKUPS + 1))
# Removing old backup
for backup in $(echo "$backup_list" | head -n $backups_rm_number); do
backup_date=$(echo $backup | sed -e "s/$user.//" -e "s/.tar$//")
echo -e "$(date "+%F %T") Rotated: $backup_date" \
| tee -a $BACKUP/$user.log
rm -f $BACKUP/$backup
done
fi
# Checking disk space
disk_usage=$(df $BACKUP | tail -n1 | tr ' ' '\n' | grep % | cut -f 1 -d %)
if [ "$disk_usage" -ge "$BACKUP_DISK_LIMIT" ]; then
rm -rf $tmpdir
rm -f $BACKUP/$user.log
sed -i "/ $user /d" $HESTIA/data/queue/backup.pipe
echo "Not enough disk space" | $SENDMAIL -s "$subj" "$email" "yes"
check_result "$E_DISK" "Not enough dsk space"
fi
# Creating final tarball
cd $tmpdir
tar -cf $BACKUP/$user.$backup_new_date.tar .
chmod 640 $BACKUP/$user.$backup_new_date.tar
chown admin:$user $BACKUP/$user.$backup_new_date.tar
localbackup='yes'
echo -e "$(date "+%F %T") Local: $BACKUP/$user.$backup_new_date.tar" \
| tee -a $BACKUP/$user.log
}
# FTP Functions
# Defining ftp command function
ftpc() {
/usr/bin/ftp -np $HOST $PORT << EOF
quote USER $USERNAME
quote PASS $PASSWORD
binary
$1
$2
$3
quit
EOF
}
# Defining ftp storage function
ftp_backup() {
# Checking config
if [ ! -e "$HESTIA/conf/ftp.backup.conf" ]; then
error="ftp.backup.conf doesn't exist"
echo "$error" | $SENDMAIL -s "$subj" $email "yes"
sed -i "/ $user /d" $HESTIA/data/queue/backup.pipe
echo "$error"
errorcode="$E_NOTEXIST"
return "$E_NOTEXIST"
fi
# Parse config
source_conf "$HESTIA/conf/ftp.backup.conf"
# Set default port
if [ -z "$(grep 'PORT=' $HESTIA/conf/ftp.backup.conf)" ]; then
PORT='21'
fi
# Checking variables
if [ -z "$HOST" ] || [ -z "$USERNAME" ] || [ -z "$PASSWORD" ]; then
error="Can't parse ftp backup configuration"
echo "$error" | $SENDMAIL -s "$subj" $email "yes"
sed -i "/ $user /d" $HESTIA/data/queue/backup.pipe
echo "$error"
errorcode="$E_PARSING"
return "$E_PARSING"
fi
# Debug info
echo -e "$(date "+%F %T") Remote: ftp://$HOST$BPATH/$user.$backup_new_date.tar"
# Checking ftp connection
fconn=$(ftpc)
ferror=$(echo $fconn | grep -i -e failed -e error -e "Can't" -e "not conn")
if [ -n "$ferror" ]; then
error="Error: can't login to ftp ftp://$USERNAME@$HOST"
echo "$error" | $SENDMAIL -s "$subj" $email $notify
sed -i "/ $user /d" $HESTIA/data/queue/backup.pipe
echo "$error"
errorcode="$E_CONNECT"
return "$E_CONNECT"
fi
# Check ftp permissions
if [ -z $BPATH ]; then
ftmpdir="vst.bK76A9SUkt"
else
ftpc "mkdir $BPATH" > /dev/null 2>&1
ftmpdir="$BPATH/vst.bK76A9SUkt"
fi
ftpc "mkdir $ftmpdir" "rm $ftmpdir"
ftp_result=$(ftpc "mkdir $ftmpdir" "rm $ftmpdir" | grep -v Trying)
if [ -n "$ftp_result" ]; then
error="Can't create ftp backup folder ftp://$HOST$BPATH"
echo "$error" | $SENDMAIL -s "$subj" $email $notify
sed -i "/ $user /d" $HESTIA/data/queue/backup.pipe
echo "$error"
errorcode="$E_FTP"
return "$E_FTP"
fi
# Checking retention (Only include .tar files)
if [ -z $BPATH ]; then
backup_list=$(ftpc "ls" | awk '{print $9}' | grep "^$user\." | grep ".tar")
else
backup_list=$(ftpc "cd $BPATH" "ls" | awk '{print $9}' | grep "^$user\." | grep ".tar")
fi
backups_count=$(echo "$backup_list" | wc -l)
if [ "$backups_count" -ge "$BACKUPS" ]; then
backups_rm_number=$((backups_count - BACKUPS + 1))
for backup in $(echo "$backup_list" | head -n $backups_rm_number); do
backup_date=$(echo $backup | sed -e "s/$user.//" -e "s/.tar$//")
echo -e "$(date "+%F %T") Rotated ftp backup: $backup_date" \
| tee -a $BACKUP/$user.log
if [ -z $BPATH ]; then
ftpc "delete $backup"
else
ftpc "cd $BPATH" "delete $backup"
fi
done
fi
# Uploading backup archive
if [ "$localbackup" = 'yes' ]; then
cd $BACKUP
if [ -z $BPATH ]; then
ftpc "put $user.$backup_new_date.tar"
else
ftpc "cd $BPATH" "put $user.$backup_new_date.tar"
fi
else
cd $tmpdir
tar -cf $BACKUP/$user.$backup_new_date.tar .
cd $BACKUP/
if [ -z $BPATH ]; then
ftpc "put $user.$backup_new_date.tar"
else
ftpc "cd $BPATH" "put $user.$backup_new_date.tar"
fi
rm -f $user.$backup_new_date.tar
fi
}
# FTP backup download function
ftp_download() {
source_conf "$HESTIA/conf/ftp.backup.conf"
if [ -z "$PORT" ]; then
PORT='21'
fi
cd $BACKUP
if [ -z $BPATH ]; then
ftpc "get $1"
else
ftpc "cd $BPATH" "get $1"
fi
}
#FTP Delete function
ftp_delete() {
source_conf "$HESTIA/conf/ftp.backup.conf"
if [ -z "$PORT" ]; then
PORT='21'
fi
if [ -z $BPATH ]; then
ftpc "delete $1"
else
ftpc "cd $BPATH" "delete $1"
fi
}
# SFTP Functions
# sftp command function
sftpc() {
if [ "$PRIVATEKEY" != "yes" ]; then
expect -f "-" "$@" << EOF
set timeout 60
set count 0
spawn /usr/bin/sftp -o StrictHostKeyChecking=no \
-o Port=$PORT $USERNAME@$HOST
expect {
-nocase "password:" {
send "$PASSWORD\r"
exp_continue
}
-re "Password for (.*)@(.*)" {
send "$PASSWORD\r"
exp_continue
}
-re "Couldn't|(.*)disconnect|(.*)stalled|(.*)not found" {
set count \$argc
set output "Disconnected."
set rc $E_FTP
exp_continue
}
-re ".*denied.*(publickey|password)." {
set output "Permission denied, wrong publickey or password."
set rc $E_CONNECT
}
-re "\[0-9]*%" {
exp_continue
}
"sftp>" {
if {\$count < \$argc} {
set arg [lindex \$argv \$count]
send "\$arg\r"
incr count
} else {
send "exit\r"
set output "Disconnected."
if {[info exists rc] != 1} {
set rc $OK
}
}
exp_continue
}
timeout {
set output "Connection timeout."
set rc $E_CONNECT
}
}
if {[info exists output] == 1} {
puts "\$output"
}
exit \$rc
EOF
else
expect -f "-" "$@" << EOF
set timeout 60
set count 0
spawn /usr/bin/sftp -o StrictHostKeyChecking=no \
-o Port=$PORT -i $PASSWORD $USERNAME@$HOST
expect {
-nocase "password:" {
send "$PASSWORD\r"
exp_continue
}
-re "Couldn't|(.*)disconnect|(.*)stalled|(.*)not found" {
set count \$argc
set output "Disconnected."
set rc $E_FTP
exp_continue
}
-re ".*denied.*(publickey|password)." {
set output "Permission denied, wrong publickey or password."
set rc $E_CONNECT
}
-re "\[0-9]*%" {
exp_continue
}
"sftp>" {
if {\$count < \$argc} {
set arg [lindex \$argv \$count]
send "\$arg\r"
incr count
} else {
send "exit\r"
set output "Disconnected."
if {[info exists rc] != 1} {
set rc $OK
}
}
exp_continue
}
timeout {
set output "Connection timeout."
set rc $E_CONNECT
}
}
if {[info exists output] == 1} {
puts "\$output"
}
exit \$rc
EOF
fi
}
# SFTP backup download function
sftp_download() {
source_conf "$HESTIA/conf/sftp.backup.conf"
if [ -z "$PORT" ]; then
PORT='22'
fi
cd $BACKUP
if [ -z $BPATH ]; then
sftpc "get $1" > /dev/null 2>&1
else
sftpc "cd $BPATH" "get $1" > /dev/null 2>&1
fi
}
sftp_delete() {
echo "$1"
source_conf "$HESTIA/conf/sftp.backup.conf"
if [ -z "$PORT" ]; then
PORT='22'
fi
echo $BPATH
if [ -z $BPATH ]; then
sftpc "rm $1" > /dev/null 2>&1
else
sftpc "cd $BPATH" "rm $1" > /dev/null 2>&1
fi
}
sftp_backup() {
# Checking config
if [ ! -e "$HESTIA/conf/sftp.backup.conf" ]; then
error="Can't open sftp.backup.conf"
echo "$error" | $SENDMAIL -s "$subj" $email "yes"
sed -i "/ $user /d" $HESTIA/data/queue/backup.pipe
echo "$error"
errorcode="$E_NOTEXIST"
return "$E_NOTEXIST"
fi
# Parse config
source_conf "$HESTIA/conf/sftp.backup.conf"
# Set default port
if [ -z "$(grep 'PORT=' $HESTIA/conf/sftp.backup.conf)" ]; then
PORT='22'
fi
# Checking variables
if [ -z "$HOST" ] || [ -z "$USERNAME" ] || [ -z "$PASSWORD" ]; then
error="Can't parse sftp backup configuration"
echo "$error" | $SENDMAIL -s "$subj" $email "yes"
sed -i "/ $user /d" $HESTIA/data/queue/backup.pipe
echo "$error"
errorcode="$E_PARSING"
return "$E_PARSING"
fi
# Debug info
echo -e "$(date "+%F %T") Remote: sftp://$HOST/$BPATH/$user.$backup_new_date.tar" \
| tee -a $BACKUP/$user.log
# Checking network connection and write permissions
if [ -z $BPATH ]; then
sftmpdir="vst.bK76A9SUkt"
else
sftmpdir="$BPATH/vst.bK76A9SUkt"
fi
sftpc "mkdir $BPATH" > /dev/null 2>&1
sftpc "mkdir $sftmpdir" "rmdir $sftmpdir" > /dev/null 2>&1
rc=$?
if [[ "$rc" != 0 ]]; then
case $rc in
$E_CONNECT) error="Can't login to sftp host $HOST" ;;
$E_FTP) error="Can't create temp folder on sftp $HOST" ;;
esac
echo "$error" | $SENDMAIL -s "$subj" $email "yes"
sed -i "/ $user /d" $HESTIA/data/queue/backup.pipe
echo "$error"
errorcode="$rc"
return "$rc"
fi
# Checking retention (Only include .tar files)
if [ -z $BPATH ]; then
backup_list=$(sftpc "ls -l" | awk '{print $9}' | grep "^$user\." | grep ".tar")
else
backup_list=$(sftpc "cd $BPATH" "ls -l" | awk '{print $9}' | grep "^$user\." | grep ".tar")
fi
backups_count=$(echo "$backup_list" | wc -l)
if [ "$backups_count" -ge "$BACKUPS" ]; then
backups_rm_number=$((backups_count - BACKUPS + 1))
for backup in $(echo "$backup_list" | head -n $backups_rm_number); do
backup_date=$(echo $backup | sed -e "s/$user.//" -e "s/.tar.*$//")
echo -e "$(date "+%F %T") Rotated sftp backup: $backup_date" \
| tee -a $BACKUP/$user.log
if [ -z $BPATH ]; then
sftpc "rm $backup" > /dev/null 2>&1
else
sftpc "cd $BPATH" "rm $backup" > /dev/null 2>&1
fi
done
fi
# Uploading backup archive
echo "$(date "+%F %T") Uploading $user.$backup_new_date.tar" | tee -a $BACKUP/$user.log
if [ "$localbackup" = 'yes' ]; then
cd $BACKUP
if [ -z $BPATH ]; then
sftpc "put $user.$backup_new_date.tar" "chmod 0600 $user.$backup_new_date.tar" > /dev/null 2>&1
else
sftpc "cd $BPATH" "put $user.$backup_new_date.tar" "chmod 0600 $user.$backup_new_date.tar" > /dev/null 2>&1
fi
else
cd $tmpdir
tar -cf $BACKUP/$user.$backup_new_date.tar .
cd $BACKUP/
if [ -z $BPATH ]; then
sftpc "put $user.$backup_new_date.tar" "chmod 0600 $user.$backup_new_date.tar" > /dev/null 2>&1
else
sftpc "cd $BPATH" "put $user.$backup_new_date.tar" "chmod 0600 $user.$backup_new_date.tar" > /dev/null 2>&1
fi
rm -f $user.$backup_new_date.tar
fi
}
# BackBlaze B2 backup function
b2_backup() {
# Defining backblaze b2 settings
source_conf "$HESTIA/conf/b2.backup.conf"
# Recreate backblaze auth file ~/.b2_account_info (for situation when key was changed in b2.backup.conf)
b2 clear-account > /dev/null 2>&1
b2 authorize-account $B2_KEYID $B2_KEY > /dev/null 2>&1
# Uploading backup archive
echo -e "$(date "+%F %T") Upload to B2: $user/$user.$backup_new_date.tar"
if [ "$localbackup" = 'yes' ]; then
cd $BACKUP
b2 upload-file $BUCKET $user.$backup_new_date.tar $user/$user.$backup_new_date.tar > /dev/null 2>&1
else
cd $tmpdir
tar -cf $BACKUP/$user.$backup_new_date.tar .
cd $BACKUP/
b2 upload-file $BUCKET $user.$backup_new_date.tar $user/$user.$backup_new_date.tar > /dev/null 2>&1
rc=$?
rm -f $user.$backup_new_date.tar
if [ "$rc" -ne 0 ]; then
check_result "$E_CONNECT" "b2 failed to upload $user.$backup_new_date.tar"
fi
fi
# Checking retention
backup_list=$(b2 ls --long $BUCKET $user | cut -f 1 -d ' ' 2> /dev/null)
backups_count=$(echo "$backup_list" | wc -l)
if [ "$backups_count" -ge "$BACKUPS" ]; then
backups_rm_number=$(($backups_count - $BACKUPS))
for backup in $(echo "$backup_list" | head -n $backups_rm_number); do
backup_file_name=$(b2 get-file-info $backup | grep fileName | cut -f 4 -d '"' 2> /dev/null)
echo -e "$(date "+%F %T") Rotated b2 backup: $backup_file_name"
b2 delete-file-version $backup > /dev/null 2>&1
done
fi
}
b2_download() {
# Defining backblaze b2 settings
source_conf "$HESTIA/conf/b2.backup.conf"
# Recreate backblaze auth file ~/.b2_account_info (for situation when key was changed in b2.backup.conf)
b2 clear-account > /dev/null 2>&1
b2 authorize-account $B2_KEYID $B2_KEY > /dev/null 2>&1
cd $BACKUP
b2 download-file-by-name $BUCKET $user/$1 $1 > /dev/null 2>&1
if [ "$?" -ne 0 ]; then
check_result "$E_CONNECT" "b2 failed to download $user.$1"
fi
}
b2_delete() {
# Defining backblaze b2 settings
source_conf "$HESTIA/conf/b2.backup.conf"
# Recreate backblaze auth file ~/.b2_account_info (for situation when key was changed in b2.backup.conf)
b2 clear-account > /dev/null 2>&1
b2 authorize-account $B2_KEYID $B2_KEY > /dev/null 2>&1
b2 delete-file-version $1/$2 > /dev/null 2>&1
}
rclone_backup() {
# Define rclone config
source_conf "$HESTIA/conf/rclone.backup.conf"
echo -e "$(date "+%F %T") Upload With Rclone to $HOST: $user.$backup_new_date.tar"
if [ "$localbackup" != 'yes' ]; then
cd $tmpdir
tar -cf $BACKUP/$user.$backup_new_date.tar .
fi
cd $BACKUP/
if [ -z "$BPATH" ]; then
rclone copy -v $user.$backup_new_date.tar $HOST:$backup
if [ "$?" -ne 0 ]; then
check_result "$E_CONNECT" "Unable to upload backup"
fi
# Only include *.tar files
backup_list=$(rclone lsf $HOST: | cut -d' ' -f1 | grep "^$user\." | grep ".tar")
backups_count=$(echo "$backup_list" | wc -l)
backups_rm_number=$((backups_count - BACKUPS))
if [ "$backups_count" -ge "$BACKUPS" ]; then
for backup in $(echo "$backup_list" | head -n $backups_rm_number); do
echo "Delete file: $backup"
rclone deletefile $HOST:/$backup
done
fi
else
rclone copy -v $user.$backup_new_date.tar $HOST:$BPATH
if [ "$?" -ne 0 ]; then
check_result "$E_CONNECT" "Unable to upload backup"
fi
# Only include *.tar files
backup_list=$(rclone lsf $HOST:$BPATH | cut -d' ' -f1 | grep "^$user\." | grep ".tar")
backups_count=$(echo "$backup_list" | wc -l)
backups_rm_number=$(($backups_count - $BACKUPS))
if [ "$backups_count" -ge "$BACKUPS" ]; then
for backup in $(echo "$backup_list" | head -n $backups_rm_number); do
echo "Delete file: $backup"
rclone deletefile $HOST:$BPATH/$backup
done
fi
fi
if [ "$localbackup" != 'yes' ]; then
rm -f $user.$backup_new_date.tar
fi
}
rclone_delete() {
# Defining rclone settings
source_conf "$HESTIA/conf/rclone.backup.conf"
if [ -z "$BPATH" ]; then
rclone deletefile $HOST:/$1
else
rclone deletefile $HOST:$BPATH/$1
fi
}
rclone_download() {
# Defining rclone b2 settings
source_conf "$HESTIA/conf/rclone.backup.conf"
cd $BACKUP
if [ -z "$BPATH" ]; then
rclone copy -v $HOST:/$1 ./
else
rclone copy -v $HOST:$BPATH/$1 ./
fi
}

653
func/db.sh Normal file
View File

@@ -0,0 +1,653 @@
#!/bin/bash
#===========================================================================#
# #
# Hestia Control Panel - Domain Function Library #
# #
#===========================================================================#
# Global
database_set_default_ports() {
# Set default ports for MySQL and PostgreSQL
mysql_default="3306"
pgsql_default="5432"
# Handle missing values for both $PORT and $port
# however don't override both at once or custom ports will be overridden.
if [ -z "$PORT" ]; then
if [ "$type" = 'mysql' ]; then
PORT="$mysql_default"
fi
if [ "$type" = 'pgsql' ]; then
PORT="$pgsql_default"
fi
fi
if [ -z "$port" ]; then
if [ "$type" = 'mysql' ]; then
port="$mysql_default"
fi
if [ "$type" = 'pgsql' ]; then
port="$pgsql_default"
fi
fi
}
# MySQL
mysql_connect() {
unset PORT
host_str=$(grep "HOST='$1'" $HESTIA/conf/mysql.conf)
parse_object_kv_list "$host_str"
if [ -z $PORT ]; then PORT=3306; fi
if [ -z $HOST ] || [ -z $USER ] || [ -z $PASSWORD ]; then
echo "Error: mysql config parsing failed"
log_event "$E_PARSING" "$ARGUMENTS"
exit $E_PARSING
fi
mycnf="$HESTIA/conf/.mysql.$HOST"
if [ ! -e "$mycnf" ]; then
echo "[client]" > $mycnf
echo "host='$HOST'" >> $mycnf
echo "user='$USER'" >> $mycnf
echo "password='$PASSWORD'" >> $mycnf
echo "port='$PORT'" >> $mycnf
chmod 600 $mycnf
else
mypw=$(grep password $mycnf | cut -f 2 -d \')
if [ "$mypw" != "$PASSWORD" ]; then
echo "[client]" > $mycnf
echo "host='$HOST'" >> $mycnf
echo "user='$USER'" >> $mycnf
echo "password='$PASSWORD'" >> $mycnf
echo "port='$PORT'" >> $mycnf
chmod 660 $mycnf
fi
fi
mysql_out=$(mktemp)
if [ -f '/usr/bin/mariadb' ]; then
mariadb --defaults-file=$mycnf -e 'SELECT VERSION()' > $mysql_out 2>&1
else
mysql --defaults-file=$mycnf -e 'SELECT VERSION()' > $mysql_out 2>&1
fi
if [ '0' -ne "$?" ]; then
if [ "$notify" != 'no' ]; then
email=$(grep CONTACT $HESTIA/data/users/admin/user.conf | cut -f 2 -d \')
subj="MySQL connection error on $(hostname)"
echo -e "Can't connect to MySQL $HOST\n$(cat $mysql_out)" \
| $SENDMAIL -s "$subj" $email
fi
rm -f $mysql_out
echo "Error: Connection to $HOST failed"
log_event "$E_CONNECT" "$ARGUMENTS"
exit $E_CONNECT
fi
mysql_ver=$(cat $mysql_out | tail -n1 | cut -f 1 -d -)
mysql_fork="mysql"
check_mysql_fork=$(grep "MariaDB" $mysql_out)
if [ "$check_mysql_fork" ]; then
mysql_fork="mariadb"
fi
rm -f $mysql_out
}
mysql_query() {
sql_tmp=$(mktemp)
echo "$1" > $sql_tmp
if [ -f '/usr/bin/mariadb' ]; then
mariadb --defaults-file=$mycnf < "$sql_tmp" 2> /dev/null
return_code=$?
else
mysql --defaults-file=$mycnf < "$sql_tmp" 2> /dev/null
return_code=$?
fi
rm -f "$sql_tmp"
return $return_code
}
mysql_dump() {
err="/tmp/e.mysql"
mysqldmp="mysqldump"
if [ -f '/usr/bin/mariadb-dump' ]; then
mysqldmp="/usr/bin/mariadb-dump"
fi
$mysqldmp --defaults-file=$mycnf --single-transaction --routines -r $1 $2 2> $err
if [ '0' -ne "$?" ]; then
$mysqldmp --defaults-extra-file=$mycnf --single-transaction --routines -r $1 $2 2> $err
if [ '0' -ne "$?" ]; then
rm -rf $tmpdir
if [ "$notify" != 'no' ]; then
email=$(grep CONTACT $HESTIA/data/users/admin/user.conf | cut -f 2 -d \')
subj="MySQL error on $(hostname)"
echo -e "Can't dump database $database\n$(cat $err)" \
| $SENDMAIL -s "$subj" $email
fi
echo "Error: dump $database failed"
log_event "$E_DB" "$ARGUMENTS"
exit "$E_DB"
fi
fi
}
# PostgreSQL
psql_connect() {
unset PORT
host_str=$(grep "HOST='$1'" $HESTIA/conf/pgsql.conf)
parse_object_kv_list "$host_str"
export PGPASSWORD="$PASSWORD"
if [ -z $PORT ]; then PORT=5432; fi
if [ -z $HOST ] || [ -z $USER ] || [ -z $PASSWORD ] || [ -z $TPL ]; then
echo "Error: postgresql config parsing failed"
log_event "$E_PARSING" "$ARGUMENTS"
exit $E_PARSING
fi
psql -h $HOST -U $USER -p $PORT -c "SELECT VERSION()" > /dev/null 2> /tmp/e.psql
if [ '0' -ne "$?" ]; then
if [ "$notify" != 'no' ]; then
email=$(grep CONTACT $HESTIA/data/users/admin/user.conf | cut -f 2 -d \')
subj="PostgreSQL connection error on $(hostname)"
echo -e "Can't connect to PostgreSQL $HOST\n$(cat /tmp/e.psql)" \
| $SENDMAIL -s "$subj" $email
fi
echo "Error: Connection to $HOST failed"
log_event "$E_CONNECT" "$ARGUMENTS"
exit "$E_CONNECT"
fi
}
psql_query() {
sql_tmp=$(mktemp)
echo "$1" > $sql_tmp
psql -h $HOST -U $USER -f "$sql_tmp" 2> /dev/null
rm -f $sql_tmp
}
psql_dump() {
pg_dump -h $HOST -U $USER -c --inserts -O -x -f $1 $2 2> /tmp/e.psql
if [ '0' -ne "$?" ]; then
rm -rf $tmpdir
if [ "$notify" != 'no' ]; then
email=$(grep CONTACT $HESTIA/data/users/admin/user.conf | cut -f 2 -d \')
subj="PostgreSQL error on $(hostname)"
echo -e "Can't dump database $database\n$(cat /tmp/e.psql)" \
| $SENDMAIL -s "$subj" $email
fi
echo "Error: dump $database failed"
log_event "$E_DB" "$ARGUMENTS"
exit "$E_DB"
fi
}
# Get database host
get_next_dbhost() {
if [ -z "$host" ] || [ "$host" == 'default' ]; then
IFS=$'\n'
host='EMPTY_DB_HOST'
config="$HESTIA/conf/$type.conf"
host_str=$(grep "SUSPENDED='no'" $config)
check_row=$(echo "$host_str" | wc -l)
if [ 0 -lt "$check_row" ]; then
if [ 1 -eq "$check_row" ]; then
for db in $host_str; do
parse_object_kv_list "$db"
if [ "$MAX_DB" -gt "$U_DB_BASES" ]; then
host=$HOST
fi
done
else
old_weight='100'
for db in $host_str; do
parse_object_kv_list "$db"
let weight="$U_DB_BASES * 100 / $MAX_DB" > /dev/null 2>&1
if [ "$old_weight" -gt "$weight" ]; then
host="$HOST"
old_weight="$weight"
fi
done
fi
fi
fi
}
# Database charset validation
is_charset_valid() {
host_str=$(grep "HOST='$host'" $HESTIA/conf/$type.conf)
parse_object_kv_list "$host_str"
if [ -z "$(echo $CHARSETS | grep -wi $charset)" ]; then
echo "Error: charset $charset not exist"
log_event "$E_NOTEXIST" "$ARGUMENTS"
exit $E_NOTEXIST
fi
}
# Increase database host value
increase_dbhost_values() {
host_str=$(grep "HOST='$host'" $HESTIA/conf/$type.conf)
parse_object_kv_list "$host_str"
old_dbbases="U_DB_BASES='$U_DB_BASES'"
new_dbbases="U_DB_BASES='$((U_DB_BASES + 1))'"
if [ -z "$U_SYS_USERS" ]; then
old_users="U_SYS_USERS=''"
new_users="U_SYS_USERS='$user'"
else
old_users="U_SYS_USERS='$U_SYS_USERS'"
new_users="U_SYS_USERS='$U_SYS_USERS'"
if [ -z "$(echo $U_SYS_USERS | sed "s/,/\n/g" | grep -w $user)" ]; then
old_users="U_SYS_USERS='$U_SYS_USERS'"
new_users="U_SYS_USERS='$U_SYS_USERS,$user'"
fi
fi
sed -i "s/$old_dbbases/$new_dbbases/g" $HESTIA/conf/$type.conf
sed -i "s/$old_users/$new_users/g" $HESTIA/conf/$type.conf
}
# Decrease database host value
decrease_dbhost_values() {
host_str=$(grep "HOST='$HOST'" $HESTIA/conf/$TYPE.conf)
parse_object_kv_list "$host_str"
old_dbbases="U_DB_BASES='$U_DB_BASES'"
new_dbbases="U_DB_BASES='$((U_DB_BASES - 1))'"
old_users="U_SYS_USERS='$U_SYS_USERS'"
U_SYS_USERS=$(echo "$U_SYS_USERS" \
| sed "s/,/\n/g" \
| sed "s/^$user$//g" \
| sed "/^$/d" \
| sed ':a;N;$!ba;s/\n/,/g')
new_users="U_SYS_USERS='$U_SYS_USERS'"
sed -i "s/$old_dbbases/$new_dbbases/g" $HESTIA/conf/$TYPE.conf
sed -i "s/$old_users/$new_users/g" $HESTIA/conf/$TYPE.conf
}
# Create MySQL database
add_mysql_database() {
mysql_connect $host
mysql_ver_sub=$(echo $mysql_ver | cut -d '.' -f1)
mysql_ver_sub_sub=$(echo $mysql_ver | cut -d '.' -f2)
query="CREATE DATABASE \`$database\` CHARACTER SET $charset"
mysql_query "$query"
check_result $? "Unable to create database $database"
if [ "$mysql_fork" = "mysql" ] && [ "$mysql_ver_sub" -ge 8 ]; then
query="CREATE USER \`$dbuser\`@\`%\`
IDENTIFIED BY '$dbpass'"
mysql_query "$query" > /dev/null
query="CREATE USER \`$dbuser\`@localhost
IDENTIFIED BY '$dbpass'"
mysql_query "$query" > /dev/null
query="GRANT ALL ON \`$database\`.* TO \`$dbuser\`@\`%\`"
mysql_query "$query" > /dev/null
query="GRANT ALL ON \`$database\`.* TO \`$dbuser\`@localhost"
mysql_query "$query" > /dev/null
else
query="GRANT ALL ON \`$database\`.* TO \`$dbuser\`@\`%\`
IDENTIFIED BY '$dbpass'"
mysql_query "$query" > /dev/null
query="GRANT ALL ON \`$database\`.* TO \`$dbuser\`@localhost
IDENTIFIED BY '$dbpass'"
mysql_query "$query" > /dev/null
fi
if [ "$mysql_fork" = "mysql" ]; then
# mysql
if [ "$mysql_ver_sub" -ge 8 ] || { [ "$mysql_ver_sub" -eq 5 ] && [ "$mysql_ver_sub_sub" -ge 7 ]; }; then
if [ "$mysql_ver_sub" -ge 8 ]; then
# mysql >= 8
# This query will be proceeding with the usage of Print identified with as hex feature
md5=$(mysql_query "SET print_identified_with_as_hex=ON; SHOW CREATE USER \`$dbuser\`" 2> /dev/null)
# echo $md5
if [[ "$md5" =~ 0x([^ ]+) ]]; then
md5=$(echo "$md5" | grep password | grep -E -o '0x([^ ]+)')
else
md5=$(echo "$md5" | grep password | cut -f4 -d \')
fi
# echo $md5
else
# mysql < 8
md5=$(mysql_query "SHOW CREATE USER \`$dbuser\`" 2> /dev/null)
md5=$(echo "$md5" | grep password | cut -f8 -d \')
fi
else
# mysql < 5.7
md5=$(mysql_query "SHOW GRANTS FOR \`$dbuser\`" 2> /dev/null)
md5=$(echo "$md5" | grep PASSW | tr ' ' '\n' | tail -n1 | cut -f 2 -d \')
fi
else
# mariadb
md5=$(mysql_query "SHOW GRANTS FOR \`$dbuser\`" 2> /dev/null)
md5=$(echo "$md5" | grep PASSW | tr ' ' '\n' | tail -n1 | cut -f 2 -d \')
fi
}
# Create PostgreSQL database
add_pgsql_database() {
psql_connect $host
query="CREATE ROLE $dbuser WITH LOGIN PASSWORD '$dbpass'"
psql_query "$query" > /dev/null
query="CREATE DATABASE $database OWNER $dbuser"
if [ "$TPL" = 'template0' ]; then
query="$query ENCODING '$charset' TEMPLATE $TPL"
else
query="$query TEMPLATE $TPL"
fi
psql_query "$query" > /dev/null
query="GRANT ALL PRIVILEGES ON DATABASE $database TO $dbuser"
psql_query "$query" > /dev/null
query="GRANT CONNECT ON DATABASE template1 to $dbuser"
psql_query "$query" > /dev/null
query="SELECT rolpassword FROM pg_authid WHERE rolname='$dbuser'"
md5=$(psql_query "$query" | grep md5 | cut -f 2 -d \ )
}
add_mysql_database_temp_user() {
mysql_connect $host
mysql_ver_sub=$(echo $mysql_ver | cut -d '.' -f1)
mysql_ver_sub_sub=$(echo $mysql_ver | cut -d '.' -f2)
if [ "$mysql_fork" = "mysql" ] && [ "$mysql_ver_sub" -ge 8 ]; then
query="CREATE USER \`$dbuser\`@localhost
IDENTIFIED BY '$dbpass'"
mysql_query "$query" > /dev/null
query="GRANT ALL ON \`$database\`.* TO \`$dbuser\`@localhost"
mysql_query "$query" > /dev/null
else
query="GRANT ALL ON \`$database\`.* TO \`$dbuser\`@localhost
IDENTIFIED BY '$dbpass'"
mysql_query "$query" > /dev/null
fi
}
delete_mysql_database_temp_user() {
mysql_connect $host
query="REVOKE ALL ON \`$database\`.* FROM \`$dbuser\`@localhost"
mysql_query "$query" > /dev/null
query="DROP USER '$dbuser'@'localhost'"
mysql_query "$query" > /dev/null
}
# Check if database host do not exist in config
is_dbhost_new() {
if [ -e "$HESTIA/conf/$type.conf" ]; then
check_host=$(grep "HOST='$host'" $HESTIA/conf/$type.conf)
if [ "$check_host" ]; then
echo "Error: db host exist"
log_event "$E_EXISTS" "$ARGUMENTS"
exit $E_EXISTS
fi
fi
}
# Get database values
get_database_values() {
parse_object_kv_list $(grep "DB='$database'" $USER_DATA/db.conf)
}
# Change MySQL database password
change_mysql_password() {
mysql_connect $HOST
mysql_ver_sub=$(echo $mysql_ver | cut -d '.' -f1)
mysql_ver_sub_sub=$(echo $mysql_ver | cut -d '.' -f2)
if [ "$mysql_fork" = "mysql" ]; then
# mysql
if [ "$mysql_ver_sub" -ge 8 ]; then
# mysql >= 8
query="SET PASSWORD FOR \`$DBUSER\`@\`%\` = '$dbpass'"
mysql_query "$query" > /dev/null
query="SET PASSWORD FOR \`$DBUSER\`@localhost = '$dbpass'"
mysql_query "$query" > /dev/null
else
# mysql < 8
query="GRANT ALL ON \`$database\`.* TO \`$DBUSER\`@\`%\`
IDENTIFIED BY '$dbpass'"
mysql_query "$query" > /dev/null
query="GRANT ALL ON \`$database\`.* TO \`$DBUSER\`@localhost
IDENTIFIED BY '$dbpass'"
mysql_query "$query" > /dev/null
fi
else
# mariadb
query="GRANT ALL ON \`$database\`.* TO \`$DBUSER\`@\`%\`
IDENTIFIED BY '$dbpass'"
mysql_query "$query" > /dev/null
query="GRANT ALL ON \`$database\`.* TO \`$DBUSER\`@localhost
IDENTIFIED BY '$dbpass'"
mysql_query "$query" > /dev/null
fi
if [ "$mysql_fork" = "mysql" ]; then
# mysql
if [ "$mysql_ver_sub" -ge 8 ] || { [ "$mysql_ver_sub" -eq 5 ] && [ "$mysql_ver_sub_sub" -ge 7 ]; }; then
if [ "$mysql_ver_sub" -ge 8 ]; then
# mysql >= 8
# This query will be proceeding with the usage of Print identified with as hex feature
md5=$(mysql_query "SET print_identified_with_as_hex=ON; SHOW CREATE USER \`$DBUSER\`" 2> /dev/null)
# echo $md5
if [[ "$md5" =~ 0x([^ ]+) ]]; then
md5=$(echo "$md5" | grep password | grep -E -o '0x([^ ]+)')
else
md5=$(echo "$md5" | grep password | cut -f4 -d \')
fi
# echo $md5
else
# mysql < 8
md5=$(mysql_query "SHOW CREATE USER \`$DBUSER\`" 2> /dev/null)
md5=$(echo "$md5" | grep password | cut -f8 -d \')
fi
else
# mysql < 5.7
md5=$(mysql_query "SHOW GRANTS FOR \`$DBUSER\`" 2> /dev/null)
md5=$(echo "$md5" | grep PASSW | tr ' ' '\n' | tail -n1 | cut -f 2 -d \')
fi
else
# mariadb
md5=$(mysql_query "SHOW GRANTS FOR \`$DBUSER\`" 2> /dev/null)
md5=$(echo "$md5" | grep PASSW | tr ' ' '\n' | tail -n1 | cut -f 2 -d \')
fi
}
# Change PostgreSQL database password
change_pgsql_password() {
psql_connect $HOST
query="ALTER ROLE $DBUSER WITH LOGIN PASSWORD '$dbpass'"
psql_query "$query" > /dev/null
query="SELECT rolpassword FROM pg_authid WHERE rolname='$DBUSER'"
md5=$(psql_query "$query" | grep md5 | cut -f 2 -d \ )
}
# Delete MySQL database
delete_mysql_database() {
mysql_connect $HOST
query="DROP DATABASE \`$database\`"
mysql_query "$query"
query="REVOKE ALL ON \`$database\`.* FROM \`$DBUSER\`@\`%\`"
mysql_query "$query" > /dev/null
query="REVOKE ALL ON \`$database\`.* FROM \`$DBUSER\`@localhost"
mysql_query "$query" > /dev/null
if [ "$(grep "DBUSER='$DBUSER'" $USER_DATA/db.conf | wc -l)" -lt 2 ]; then
query="DROP USER '$DBUSER'@'%'"
mysql_query "$query" > /dev/null
query="DROP USER '$DBUSER'@'localhost'"
mysql_query "$query" > /dev/null
fi
}
# Delete PostgreSQL database
delete_pgsql_database() {
psql_connect $HOST
query="REVOKE ALL PRIVILEGES ON DATABASE $database FROM $DBUSER"
psql_query "$query" > /dev/null
query="DROP DATABASE $database"
psql_query "$query" > /dev/null
if [ "$(grep "DBUSER='$DBUSER'" $USER_DATA/db.conf | wc -l)" -lt 2 ]; then
query="REVOKE CONNECT ON DATABASE template1 FROM $DBUSER"
psql_query "$query" > /dev/null
query="DROP ROLE $DBUSER"
psql_query "$query" > /dev/null
fi
}
# Dump MySQL database
dump_mysql_database() {
mysql_connect $HOST
mysql_dump $dump $database
query="SHOW GRANTS FOR '$DBUSER'@'localhost'"
mysql_query "$query" | grep -v "Grants for" > $grants
query="SHOW GRANTS FOR '$DBUSER'@'%'"
mysql_query "$query" | grep -v "Grants for" > $grants
}
# Dump PostgreSQL database
dump_pgsql_database() {
psql_connect $HOST
psql_dump $dump $database
query="SELECT rolpassword FROM pg_authid WHERE rolname='$DBUSER'"
md5=$(psql_query "$query" | head -n1 | cut -f 2 -d \ )
pw_str="UPDATE pg_authid SET rolpassword='$md5' WHERE rolname='$DBUSER'"
gr_str="GRANT ALL PRIVILEGES ON DATABASE $database to '$DBUSER'"
echo -e "$pw_str\n$gr_str" >> $grants
}
# Check if database server is in use
is_dbhost_free() {
host_str=$(grep "HOST='$host'" $HESTIA/conf/$type.conf)
parse_object_kv_list "$host_str"
if [ 0 -ne "$U_DB_BASES" ]; then
echo "Error: host $HOST is used"
log_event "$E_INUSE" "$ARGUMENTS"
exit $E_INUSE
fi
}
# Suspend MySQL database
suspend_mysql_database() {
mysql_connect $HOST
query="REVOKE ALL ON \`$database\`.* FROM \`$DBUSER\`@\`%\`"
mysql_query "$query" > /dev/null
query="REVOKE ALL ON \`$database\`.* FROM \`$DBUSER\`@localhost"
mysql_query "$query" > /dev/null
}
# Suspend PostgreSQL database
suspend_pgsql_database() {
psql_connect $HOST
query="REVOKE ALL PRIVILEGES ON $database FROM $DBUSER"
psql_query "$query" > /dev/null
}
# Unsuspend MySQL database
unsuspend_mysql_database() {
mysql_connect $HOST
query="GRANT ALL ON \`$database\`.* TO \`$DBUSER\`@\`%\`"
mysql_query "$query" > /dev/null
query="GRANT ALL ON \`$database\`.* TO \`$DBUSER\`@localhost"
mysql_query "$query" > /dev/null
}
# Unsuspend PostgreSQL database
unsuspend_pgsql_database() {
psql_connect $HOST
query="GRANT ALL PRIVILEGES ON DATABASE $database TO $DBUSER"
psql_query "$query" > /dev/null
}
# Get MySQL disk usage
get_mysql_disk_usage() {
mysql_connect $HOST
query="SELECT SUM( data_length + index_length ) / 1024 / 1024 'Size'
FROM information_schema.TABLES WHERE table_schema='$database'"
usage=$(mysql_query "$query" | tail -n1)
if [ "$usage" == '' ] || [ "$usage" == 'NULL' ] || [ "${usage:0:1}" -eq '0' ]; then
usage=1
fi
export LC_ALL=C
usage=$(printf "%0.f\n" $usage)
}
# Get PostgreSQL disk usage
get_pgsql_disk_usage() {
psql_connect $HOST
query="SELECT pg_database_size('$database');"
usage=$(psql_query "$query")
usage=$(echo "$usage" | grep -v "-" | grep -v 'row' | sed "/^$/d")
usage=$(echo "$usage" | grep -v "pg_database_size" | awk '{print $1}')
if [ -z "$usage" ]; then
usage=0
fi
usage=$(($usage / 1048576))
if [ "$usage" -eq '0' ]; then
usage=1
fi
}
# Delete MySQL user
delete_mysql_user() {
mysql_connect $HOST
query="REVOKE ALL ON \`$database\`.* FROM \`$old_dbuser\`@\`%\`"
mysql_query "$query" > /dev/null
query="REVOKE ALL ON \`$database\`.* FROM \`$old_dbuser\`@localhost"
mysql_query "$query" > /dev/null
query="DROP USER '$old_dbuser'@'%'"
mysql_query "$query" > /dev/null
query="DROP USER '$old_dbuser'@'localhost'"
mysql_query "$query" > /dev/null
}
# Delete PostgreSQL user
delete_pgsql_user() {
psql_connect $HOST
query="REVOKE ALL PRIVILEGES ON DATABASE $database FROM $old_dbuser"
psql_query "$query" > /dev/null
query="REVOKE CONNECT ON DATABASE template1 FROM $old_dbuser"
psql_query "$query" > /dev/null
query="DROP ROLE $old_dbuser"
psql_query "$query" > /dev/null
}

1071
func/domain.sh Normal file

File diff suppressed because it is too large Load Diff

25
func/firewall.sh Normal file
View File

@@ -0,0 +1,25 @@
#!/bin/bash
#===========================================================================#
# #
# Hestia Control Panel - Firewall Function Library #
# #
#===========================================================================#
heal_iptables_links() {
packages="iptables iptables-save iptables-restore"
for package in $packages; do
if [ ! -e "/sbin/${package}" ]; then
if which ${package}; then
ln -s "$(which ${package})" /sbin/${package}
elif [ -e "/usr/sbin/${package}" ]; then
ln -s /usr/sbin/${package} /sbin/${package}
elif whereis -B /bin /sbin /usr/bin /usr/sbin -f -b ${package}; then
autoiptables=$(whereis -B /bin /sbin /usr/bin /usr/sbin -f -b ${package} | cut -d '' -f 2)
if [ -x "$autoiptables" ]; then
ln -s "$autoiptables" /sbin/${package}
fi
fi
fi
done
}

280
func/ip.sh Normal file
View File

@@ -0,0 +1,280 @@
#!/bin/bash
#===========================================================================#
# #
# Hestia Control Panel - IP/Network Function Library #
# #
#===========================================================================#
# Global definitions
REGEX_IPV4="^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.|$)){4}$"
# Check ip ownership
is_ip_owner() {
owner=$(grep 'OWNER=' $HESTIA/data/ips/$ip | cut -f 2 -d \')
if [ "$owner" != "$user" ]; then
check_result "$E_FORBIDEN" "$ip is not owned by $user"
fi
}
# Check if ip address is free
is_ip_free() {
if [ -e "$HESTIA/data/ips/$ip" ]; then
check_result "$E_EXISTS" "$ip is already exists"
fi
}
# Check ip address specific value
is_ip_key_empty() {
key="$1"
string=$(cat $HESTIA/data/ips/$ip)
eval $string
eval value="$key"
if [ -n "$value" ] && [ "$value" != '0' ]; then
key="$(echo $key | sed -e "s/\$U_//")"
check_result "$E_EXISTS" "IP is in use / $key = $value"
fi
}
is_ip_rdns_valid() {
local ip="$1"
local network_ip=$(echo $ip | cut -d"." -f1-3)
local awk_ip=$(echo $network_ip | sed 's|\.|/\&\&/|g')
local rev_awk_ip=$(echo $awk_ip | rev)
if [ -z "$rdns" ]; then
local rdns=$(dig +short -x "$ip" | head -n 1 | sed 's/.$//') || unset rdns
fi
if [ -n "$rdns" ] && [ ! $(echo $rdns | awk "/$awk_ip/ || /$rev_awk_ip/") ]; then
echo $rdns
return 0 # True
fi
return 1 # False
}
# Update ip address value
update_ip_value() {
key="$1"
value="$2"
conf="$HESTIA/data/ips/$ip"
str=$(cat $conf)
eval $str
c_key=$(echo "${key//$/}")
eval old="${key}"
old=$(echo "$old" | sed -e 's/\\/\\\\/g' -e 's/&/\\&/g' -e 's/\//\\\//g')
new=$(echo "$value" | sed -e 's/\\/\\\\/g' -e 's/&/\\&/g' -e 's/\//\\\//g')
sed -i "$str_number s/$c_key='${old//\*/\\*}'/$c_key='${new//\*/\\*}'/g" \
$conf
}
# New method that is improved on a later date we need to check if we can improve it for other locations
update_ip_value_new() {
key="$1"
value="$2"
conf="$HESTIA/data/ips/$ip"
check_ckey=$(grep "^$key='" $conf)
if [ -z "$check_ckey" ]; then
echo "$key='$value'" >> $conf
else
sed -i "s|^$key=.*|$key='$value'|g" $conf
fi
}
# Get ip name
get_ip_alias() {
ip_name=$(grep "NAME=" $HESTIA/data/ips/$local_ip | cut -f 2 -d \')
if [ -n "$ip_name" ]; then
echo "${1//./-}.$ip_name"
fi
}
# Increase ip value
increase_ip_value() {
sip=${1-ip}
USER=${2-$user}
web_key='U_WEB_DOMAINS'
usr_key='U_SYS_USERS'
current_web=$(grep "$web_key=" $HESTIA/data/ips/$sip | cut -f 2 -d \')
current_usr=$(grep "$usr_key=" $HESTIA/data/ips/$sip | cut -f 2 -d \')
if [ -z "$current_web" ]; then
echo "Error: Parsing error"
log_event "$E_PARSING" "$ARGUMENTS"
exit "$E_PARSING"
fi
new_web=$((current_web + 1))
if [ -z "$current_usr" ]; then
new_usr="$USER"
else
check_usr=$(echo -e "${current_usr//,/\\n}" | grep -x "$USER")
if [ -z "$check_usr" ]; then
new_usr="$current_usr,$USER"
else
new_usr="$current_usr"
fi
fi
# Make sure users list does not contain duplicates
new_usr=$(echo "$new_usr" \
| sed "s/,/\n/g" \
| sort -u \
| sed ':a;N;$!ba;s/\n/,/g')
sed -i "s/$web_key='$current_web'/$web_key='$new_web'/g" \
$HESTIA/data/ips/$sip
sed -i "s/$usr_key='$current_usr'/$usr_key='$new_usr'/g" \
$HESTIA/data/ips/$sip
}
# Decrease ip value
decrease_ip_value() {
sip=${1-ip}
local user=${2-$user}
web_key='U_WEB_DOMAINS'
usr_key='U_SYS_USERS'
current_web=$(grep "$web_key=" $HESTIA/data/ips/$sip | cut -f 2 -d \')
current_usr=$(grep "$usr_key=" $HESTIA/data/ips/$sip | cut -f 2 -d \')
if [ -z "$current_web" ]; then
check_result $E_PARSING "Parsing error"
fi
new_web=$((current_web - 1))
check_ip=$(grep $sip $USER_DATA/web.conf | wc -l)
if [[ $check_ip = 0 ]]; then
new_usr=$(echo "$current_usr" \
| sed "s/,/\n/g" \
| sed "s/^$user$//g" \
| sed "/^$/d" \
| sort -u \
| sed ':a;N;$!ba;s/\n/,/g')
else
new_usr="$current_usr"
fi
sed -i "s/$web_key='$current_web'/$web_key='$new_web'/g" \
$HESTIA/data/ips/$sip
sed -i "s/$usr_key='$current_usr'/$usr_key='$new_usr'/g" \
$HESTIA/data/ips/$sip
}
# Get ip address value
get_ip_value() {
key="$1"
string=$(cat $HESTIA/data/ips/$ip)
eval $string
eval value="$key"
echo "$value"
}
# Get real ip address
get_real_ip() {
if [ -e "$HESTIA/data/ips/$1" ]; then
echo "$1"
else
nat=$(grep -H "^NAT='$1'" $HESTIA/data/ips/* | head -n1)
if [ -n "$nat" ]; then
echo "$nat" | cut -f 1 -d : | cut -f 7 -d /
fi
fi
}
# Convert CIDR to netmask
convert_cidr() {
set -- $((5 - ($1 / 8))) 255 255 255 255 \
$(((255 << (8 - ($1 % 8))) & 255)) 0 0 0
if [[ $1 -gt 1 ]]; then
shift $1
else
shift
fi
echo ${1-0}.${2-0}.${3-0}.${4-0}
}
# Convert netmask to CIDR
convert_netmask() {
nbits=0
IFS=.
for dec in $1; do
case $dec in
255) let nbits+=8 ;;
254) let nbits+=7 ;;
252) let nbits+=6 ;;
248) let nbits+=5 ;;
240) let nbits+=4 ;;
224) let nbits+=3 ;;
192) let nbits+=2 ;;
128) let nbits+=1 ;;
0) ;;
esac
done
echo "$nbits"
}
# Calculate broadcast address
get_broadcast() {
OLD_IFS=$IFS
IFS=.
typeset -a I=($1)
typeset -a N=($2)
IFS=$OLD_IFS
echo "$((${I[0]} | (255 ^ ${N[0]}))).$((${I[1]} | (255 ^ ${N[1]}))).$((${I[2]} | (255 ^ ${N[2]}))).$((${I[3]} | (255 ^ ${N[3]})))"
}
# Get user ips
get_user_ips() {
dedicated=$(grep -H "OWNER='$user'" $HESTIA/data/ips/*)
dedicated=$(echo "$dedicated" | cut -f 1 -d : | sed 's=.*/==' | grep -E ${REGEX_IPV4})
shared=$(grep -H -A1 "OWNER='admin'" $HESTIA/data/ips/* | grep shared)
shared=$(echo "$shared" | cut -f 1 -d : | sed 's=.*/==' | cut -f 1 -d \- | grep -E ${REGEX_IPV4})
for dedicated_ip in $dedicated; do
shared=$(echo "$shared" | grep -v $dedicated_ip)
done
echo -e "$dedicated\n$shared" | sed "/^$/d"
}
# Get user ip
get_user_ip() {
ip=$(get_user_ips | head -n1)
if [ -z "$ip" ]; then
check_result $E_NOTEXIST "no IP is available"
fi
local_ip=$ip
nat=$(grep "^NAT" $HESTIA/data/ips/$ip | cut -f 2 -d \')
if [ -n "$nat" ]; then
ip=$nat
fi
}
# Validate ip address
is_ip_valid() {
local_ip="$1"
if [ ! -e "$HESTIA/data/ips/$1" ]; then
nat=$(grep -H "^NAT='$1'" $HESTIA/data/ips/*)
if [ -z "$nat" ]; then
check_result "$E_NOTEXIST" "IP $1 doesn't exist"
else
nat=$(echo "$nat" | cut -f1 -d: | cut -f7 -d/)
local_ip=$nat
fi
fi
if [ -n "$2" ]; then
if [ -z "$nat" ]; then
ip_data=$(cat $HESTIA/data/ips/$1)
else
ip_data=$(cat $HESTIA/data/ips/$nat)
fi
ip_owner=$(echo "$ip_data" | grep OWNER= | cut -f2 -d \')
ip_status=$(echo "$ip_data" | grep STATUS= | cut -f2 -d \')
if [ "$ip_owner" != "$user" ] && [ "$ip_status" = 'dedicated' ]; then
check_result "$E_FORBIDEN" "$user user can't use IP $1"
fi
get_user_owner
if [ "$ip_owner" != "$user" ] && [ "$ip_owner" != "$owner" ]; then
check_result "$E_FORBIDEN" "$user user can't use IP $1"
fi
fi
}

1714
func/main.sh Normal file

File diff suppressed because it is too large Load Diff

918
func/rebuild.sh Normal file
View File

@@ -0,0 +1,918 @@
#!/bin/bash
#===========================================================================#
# #
# Hestia Control Panel - Rebuild Function Library #
# #
#===========================================================================#
# User account rebuild
rebuild_user_conf() {
sanitize_config_file "user"
# Get user variables
source_conf "$USER_DATA/user.conf"
# Creating user data files
chmod 770 $USER_DATA
chmod 660 $USER_DATA/user.conf
touch $USER_DATA/backup.conf
chmod 660 $USER_DATA/backup.conf
touch $USER_DATA/history.log
chmod 660 $USER_DATA/history.log
touch $USER_DATA/stats.log
chmod 660 $USER_DATA/stats.log
# Update FNAME LNAME to NAME
if [ -z "$NAME" ]; then
NAME="$FNAME $LNAME"
if [ -z $FNAME ]; then NAME=""; fi
sed -i "s/FNAME='$FNAME'/NAME='$NAME'/g" $USER_DATA/user.conf
sed -i "/LNAME='$LNAME'/d" $USER_DATA/user.conf
fi
if [ -z "${TWOFA+x}" ]; then
sed -i "/RKEY/a TWOFA=''" $USER_DATA/user.conf
fi
if [ -z "${QRCODE+x}" ]; then
sed -i "/TWOFA/a QRCODE=''" $USER_DATA/user.conf
fi
if [ -z "${PHPCLI+x}" ]; then
sed -i "/QRCODE/a PHPCLI=''" $USER_DATA/user.conf
fi
if [ -z "${ROLE+x}" ]; then
sed -i "/PHPCLI/a ROLE='user'" $USER_DATA/user.conf
fi
if [ -z "${THEME+x}" ]; then
sed -i "/LANGUAGE/a THEME=''" $USER_DATA/user.conf
fi
if [ -z "${PREF_UI_SORT+x}" ]; then
sed -i "/NOTIFICATIONS/a PREF_UI_SORT='name'" $USER_DATA/user.conf
fi
if [ -z "${LOGIN_DISABLED+x}" ]; then
sed -i "/PREF_UI_SORT/a LOGIN_DISABLED=''" $USER_DATA/user.conf
fi
if [ -z "${LOGIN_USE_IPLIST+x}" ]; then
sed -i "/LOGIN_DISABLED/a LOGIN_USE_IPLIST=''" $USER_DATA/user.conf
fi
if [ -z "${LOGIN_ALLOW_IPS+x}" ]; then
sed -i "/LOGIN_USE_IPLIST/a LOGIN_ALLOW_IPS=''" $USER_DATA/user.conf
fi
if [ -z "${RATE_LIMIT+x}" ]; then
sed -i "/MAIL_ACCOUNTS/a RATE_LIMIT='200'" $USER_DATA/user.conf
fi
# Run template trigger
if [ -x "$HESTIA/data/packages/$PACKAGE.sh" ]; then
$HESTIA/data/packages/$PACKAGE.sh "$user" "$CONTACT" "$NAME"
fi
# Rebuild user
shell=$(grep -w "$SHELL" /etc/shells | head -n1)
/usr/sbin/useradd "$user" -s "$shell" -c "$CONTACT" \
-m -d "$HOMEDIR/$user" > /dev/null 2>&1
# Add a general group for normal users created by Hestia
if [ -z "$(grep "^hestia-users:" /etc/group)" ]; then
groupadd --system "hestia-users"
fi
# Add membership to hestia-users group to non-admin users
if [ "$user" = "admin" ]; then
setfacl -m "g:admin:r-x" "$HOMEDIR/$user"
else
usermod -a -G "hestia-users" "$user"
setfacl -m "u:$user:r-x" "$HOMEDIR/$user"
fi
setfacl -m "g:hestia-users:---" "$HOMEDIR/$user"
# Update user shell
/usr/bin/chsh -s "$shell" "$user" &> /dev/null
# Update password
chmod u+w /etc/shadow
sed -i "s|^$user:[^:]*:|$user:$MD5:|" /etc/shadow
chmod u-w /etc/shadow
# Building directory tree
if [ -e "$HOMEDIR/$user/conf" ]; then
chattr -i $HOMEDIR/$user/conf > /dev/null 2>&1
fi
# Create default writeable folders
mkdir -p \
$HOMEDIR/$user/conf \
$HOMEDIR/$user/.config \
$HOMEDIR/$user/.cache \
$HOMEDIR/$user/.local \
$HOMEDIR/$user/.composer \
$HOMEDIR/$user/.vscode-server \
$HOMEDIR/$user/.ssh \
$HOMEDIR/$user/.npm
chmod a+x $HOMEDIR/$user
chmod a+x $HOMEDIR/$user/conf
chown --no-dereference $user:$user \
$HOMEDIR/$user \
$HOMEDIR/$user/.config \
$HOMEDIR/$user/.cache \
$HOMEDIR/$user/.local \
$HOMEDIR/$user/.composer \
$HOMEDIR/$user/.vscode-server \
$HOMEDIR/$user/.ssh \
$HOMEDIR/$user/.npm
chown root:root $HOMEDIR/$user/conf
$BIN/v-add-user-sftp-jail "$user"
# Update disk pipe
sed -i "/ $user$/d" $HESTIA/data/queue/disk.pipe
echo "$BIN/v-update-user-disk $user" >> $HESTIA/data/queue/disk.pipe
# WEB
if [ -n "$WEB_SYSTEM" ] && [ "$WEB_SYSTEM" != 'no' ]; then
mkdir -p $USER_DATA/ssl
chmod 770 $USER_DATA/ssl
touch $USER_DATA/web.conf
chmod 660 $USER_DATA/web.conf
if [ "$(grep -w $user $HESTIA/data/queue/traffic.pipe)" ]; then
echo "$BIN/v-update-web-domains-traff $user" \
>> $HESTIA/data/queue/traffic.pipe
fi
echo "$BIN/v-update-web-domains-disk $user" \
>> $HESTIA/data/queue/disk.pipe
if [[ -L "$HOMEDIR/$user/web" ]]; then
rm $HOMEDIR/$user/web
fi
mkdir -p $HOMEDIR/$user/conf/web/$domain
mkdir -p $HOMEDIR/$user/web
mkdir -p $HOMEDIR/$user/tmp
chmod 751 $HOMEDIR/$user/conf/web
chmod 751 $HOMEDIR/$user/web
chmod 771 $HOMEDIR/$user/tmp
chown --no-dereference $root:$user $HOMEDIR/$user/web
if [ "$create_user" = "yes" ]; then
$BIN/v-rebuild-web-domains $user $restart
fi
fi
# DNS
if [ -n "$DNS_SYSTEM" ] && [ "$DNS_SYSTEM" != 'no' ]; then
mkdir -p $USER_DATA/dns
chmod 770 $USER_DATA/dns
touch $USER_DATA/dns.conf
chmod 660 $USER_DATA/dns.conf
mkdir -p $HOMEDIR/$user/conf/dns
chmod 771 $HOMEDIR/$user/conf/dns
if [ "$DNS_SYSTEM" = 'named' ]; then
dns_group='named'
else
dns_group='bind'
fi
chown $dns_group:$dns_group $HOMEDIR/$user/conf/dns
if [ "$create_user" = "yes" ]; then
$BIN/v-rebuild-dns-domains $user $restart
fi
fi
if [ -n "$MAIL_SYSTEM" ] && [ "$MAIL_SYSTEM" != 'no' ]; then
mkdir -p $USER_DATA/mail
chmod 770 $USER_DATA/mail
touch $USER_DATA/mail.conf
chmod 660 $USER_DATA/mail.conf
echo "$BIN/v-update-mail-domains-disk $user" \
>> $HESTIA/data/queue/disk.pipe
if [[ -L "$HOMEDIR/$user/mail" ]]; then
rm $HOMEDIR/$user/mail
fi
mkdir -p $HOMEDIR/$user/conf/mail/$domain
mkdir -p $HOMEDIR/$user/mail
chmod 751 $HOMEDIR/$user/mail
chmod 751 $HOMEDIR/$user/conf/mail
if [ "$create_user" = "yes" ]; then
$BIN/v-rebuild-mail-domains $user
fi
fi
if [ -n "$DB_SYSTEM" ] && [ "$DB_SYSTEM" != 'no' ]; then
touch $USER_DATA/db.conf
chmod 660 $USER_DATA/db.conf
echo "$BIN/v-update-databases-disk $user" >> $HESTIA/data/queue/disk.pipe
if [ "$create_user" = "yes" ]; then
$BIN/v-rebuild-databases $user
fi
fi
if [ -n "$CRON_SYSTEM" ] && [ "$CRON_SYSTEM" != 'no' ]; then
touch $USER_DATA/cron.conf
chmod 660 $USER_DATA/cron.conf
if [ "$create_user" = "yes" ]; then
$BIN/v-rebuild-cron-jobs $user $restart
fi
fi
# Set immutable flag
chattr +i $HOMEDIR/$user/conf > /dev/null 2>&1
}
# WEB domain rebuild
rebuild_web_domain_conf() {
# Ensure that global domain folders are available
if [ ! -d /etc/$WEB_SYSTEM/conf.d/domains ]; then
mkdir -p /etc/$WEB_SYSTEM/conf.d/domains
fi
if [ ! -d /etc/$PROXY_SYSTEM/conf.d/domains ]; then
mkdir -p /etc/$PROXY_SYSTEM/conf.d/domains
fi
syshealth_repair_web_config
get_domain_values 'web'
is_ip_valid $IP
prepare_web_domain_values
# Remove old web configuration files
if [ -f /etc/$WEB_SYSTEM/conf.d/$domain.conf ]; then
rm -f /etc/$WEB_SYSTEM/conf.d/$domain*.conf
fi
if [ -f /etc/$PROXY_SYSTEM/conf.d/$domain.conf ]; then
rm -f /etc/$PROXY_SYSTEM/conf.d/$domain*.conf
fi
# Temporary allow write permissions to owner
[ -d "$HOMEDIR/$user/web/$domain" ] && chmod 751 "$HOMEDIR/$user/web/$domain"
# Rebuilding domain directories
if [ -d "$HOMEDIR/$user/web/$domain/document_errors" ]; then
if [ "$POLICY_SYNC_ERROR_DOCUMENTS" != "no" ]; then
$BIN/v-delete-fs-directory "$user" "$HOMEDIR/$user/web/$domain/document_errors"
fi
fi
if [ ! -d $HOMEDIR/$user/web/$domain ]; then
mkdir $HOMEDIR/$user/web/$domain
fi
chown --no-dereference $user:$user $HOMEDIR/$user/web/$domain
$BIN/v-add-fs-directory "$user" "$HOMEDIR/$user/web/$domain/public_html"
if [ ! -d "$HOMEDIR/$user/web/$domain/document_errors" ]; then
$BIN/v-add-fs-directory "$user" "$HOMEDIR/$user/web/$domain/document_errors"
# Propagating html skeleton
user_exec cp -r "$WEBTPL/skel/document_errors/" "$HOMEDIR/$user/web/$domain/"
fi
$BIN/v-add-fs-directory "$user" "$HOMEDIR/$user/web/$domain/cgi-bin"
$BIN/v-add-fs-directory "$user" "$HOMEDIR/$user/web/$domain/private"
$BIN/v-add-fs-directory "$user" "$HOMEDIR/$user/web/$domain/stats"
$BIN/v-add-fs-directory "$user" "$HOMEDIR/$user/web/$domain/logs"
# Creating domain logs
if [ ! -e "/var/log/$WEB_SYSTEM/domains" ]; then
mkdir -p /var/log/$WEB_SYSTEM/domains
chmod 771 /var/log/$WEB_SYSTEM/domains
fi
touch /var/log/$WEB_SYSTEM/domains/$domain.bytes \
/var/log/$WEB_SYSTEM/domains/$domain.log \
/var/log/$WEB_SYSTEM/domains/$domain.error.log
# Creating symlinks
cd $HOMEDIR/$user/web/$domain/logs/
ln -f -s /var/log/$WEB_SYSTEM/domains/$domain.log .
ln -f -s /var/log/$WEB_SYSTEM/domains/$domain.error.log .
cd /
# Set ownership
chown --no-dereference $user:$user \
$HOMEDIR/$user/web/$domain \
$HOMEDIR/$user/web/$domain/private \
$HOMEDIR/$user/web/$domain/cgi-bin \
$HOMEDIR/$user/web/$domain/public_*html
chown -R $user:$user $HOMEDIR/$user/web/$domain/document_errors
chown root:$user /var/log/$WEB_SYSTEM/domains/$domain.*
# Adding vhost configuration
conf="$HOMEDIR/$user/conf/web/$domain/$WEB_SYSTEM.conf"
add_web_config "$WEB_SYSTEM" "$TPL.tpl"
# Adding SSL vhost configuration
if [ "$SSL" = 'yes' ]; then
ssl_file_dir="$HOMEDIR/$user/conf/web/$domain/ssl"
conf="$HOMEDIR/$user/conf/web/$domain/$WEB_SYSTEM.ssl.conf"
if [ ! -d "$ssl_file_dir" ]; then
mkdir -p $ssl_file_dir
fi
add_web_config "$WEB_SYSTEM" "$TPL.stpl"
cp -f $USER_DATA/ssl/$domain.crt \
$HOMEDIR/$user/conf/web/$domain/ssl/$domain.crt
cp -f $USER_DATA/ssl/$domain.key \
$HOMEDIR/$user/conf/web/$domain/ssl/$domain.key
cp -f $USER_DATA/ssl/$domain.pem \
$HOMEDIR/$user/conf/web/$domain/ssl/$domain.pem
if [ -e "$USER_DATA/ssl/$domain.ca" ]; then
cp -f $USER_DATA/ssl/$domain.ca \
$HOMEDIR/$user/conf/web/$domain/ssl/$domain.ca
fi
fi
# Refresh HTTPS redirection if previously enabled
if [ "$SSL_FORCE" = 'yes' ]; then
$BIN/v-delete-web-domain-ssl-force $user $domain no yes
$BIN/v-add-web-domain-ssl-force $user $domain no yes
fi
if [ "$SSL_HSTS" = 'yes' ]; then
$BIN/v-delete-web-domain-ssl-hsts $user $domain no yes
$BIN/v-add-web-domain-ssl-hsts $user $domain no yes
fi
if [ "$FASTCGI_CACHE" = 'yes' ]; then
$BIN/v-delete-fastcgi-cache $user $domain
$BIN/v-add-fastcgi-cache $user $domain "$FASTCGI_DURATION"
fi
# Adding proxy configuration
if [ -n "$PROXY_SYSTEM" ] && [ -n "$PROXY" ]; then
conf="$HOMEDIR/$user/conf/web/$domain/$PROXY_SYSTEM.conf"
add_web_config "$PROXY_SYSTEM" "$PROXY.tpl"
if [ "$SSL" = 'yes' ]; then
conf="$HOMEDIR/$user/conf/web/$domain/$PROXY_SYSTEM.ssl.conf"
add_web_config "$PROXY_SYSTEM" "$PROXY.stpl"
fi
fi
# Adding web stats parser
if [ -n "$STATS" ]; then
domain_idn=$domain
format_domain_idn
cat $WEBTPL/$STATS/$STATS.tpl \
| sed -e "s|%ip%|$local_ip|g" \
-e "s|%web_system%|$WEB_SYSTEM|g" \
-e "s|%domain_idn%|$domain_idn|g" \
-e "s|%domain%|$domain|g" \
-e "s|%user%|$user|g" \
-e "s|%home%|$HOMEDIR|g" \
-e "s|%alias%|${aliases//,/ }|g" \
-e "s|%alias_idn%|${aliases_idn//,/ }|g" \
> $HOMEDIR/$user/conf/web/$domain/$STATS.conf
if [ "$STATS" == 'awstats' ]; then
if [ -e "/etc/awstats/$STATS.$domain_idn.conf" ]; then
rm -f "/etc/awstats/$STATS.$domain_idn.conf"
fi
ln -f -s $HOMEDIR/$user/conf/web/$domain/$STATS.conf \
/etc/awstats/$STATS.$domain_idn.conf
fi
webstats="$BIN/v-update-web-domain-stat $user $domain"
check_webstats=$(grep "$webstats" $HESTIA/data/queue/webstats.pipe)
if [ -z "$check_webstats" ]; then
echo "$webstats" >> $HESTIA/data/queue/webstats.pipe
fi
if [ -n "$STATS_USER" ]; then
stats_dir="$HOMEDIR/$user/web/$domain/stats"
if [ "$WEB_SYSTEM" = 'nginx' ]; then
echo "auth_basic \"Web Statistics\";" | user_exec tee $stats_dir/auth.conf > /dev/null
echo "auth_basic_user_file $stats_dir/.htpasswd;" | user_exec tee -a $stats_dir/auth.conf > /dev/null
else
echo "AuthUserFile $stats_dir/.htpasswd" | user_exec tee $stats_dir/.htaccess > /dev/null
echo "AuthName \"Web Statistics\"" | user_exec tee -a $stats_dir/.htaccess > /dev/null
echo "AuthType Basic" | user_exec tee -a $stats_dir/.htaccess > /dev/null
echo "Require valid-user" | user_exec tee -a $stats_dir/.htaccess > /dev/null
fi
echo "$STATS_USER:$STATS_CRYPT" | user_exec tee $stats_dir/.htpasswd > /dev/null
fi
fi
# Adding ftp users
if [ -z "$FTP_SHELL" ]; then
shell=$(which nologin)
if [ -e "/usr/bin/rssh" ]; then
shell='/usr/bin/rssh'
fi
else
shell=$FTP_SHELL
fi
for ftp_user in ${FTP_USER//:/ }; do
if [ -z "$(grep ^$ftp_user: /etc/passwd)" ]; then
position=$(echo $FTP_USER | tr ':' '\n' | grep -n '' \
| grep ":$ftp_user$" | cut -f 1 -d:)
ftp_path=$(echo $FTP_PATH | tr ':' '\n' | grep -n '' \
| grep "^$position:" | cut -f 2 -d :)
ftp_md5=$(echo $FTP_MD5 | tr ':' '\n' | grep -n '' \
| grep "^$position:" | cut -f 2 -d :)
# rebuild S/FTP users
$BIN/v-delete-web-domain-ftp "$user" "$domain" "$ftp_user"
# Generate temporary password to add user but update afterwards
temp_password=$(generate_password)
$BIN/v-add-web-domain-ftp "$user" "$domain" "${ftp_user#*_}" "$temp_password" "$ftp_path"
# Updating ftp user password
chmod u+w /etc/shadow
sed -i "s|^$ftp_user:[^:]*:|$ftp_user:$ftp_md5:|" /etc/shadow
chmod u-w /etc/shadow
#Update web.conf for next rebuild or move
update_object_value 'web' 'DOMAIN' "$domain" '$FTP_MD5' "$ftp_md5"
fi
done
# Adding http auth protection
htaccess="$HOMEDIR/$user/conf/web/$domain/htaccess"
htpasswd="$HOMEDIR/$user/conf/web/$domain/htpasswd"
docroot="$HOMEDIR/$user/web/$domain/public_html"
for auth_user in ${AUTH_USER//:/ }; do
# Parsing auth user variables
position=$(echo $AUTH_USER | tr ':' '\n' | grep -n '' \
| grep ":$auth_user$" | cut -f 1 -d:)
auth_hash=$(echo $AUTH_HASH | tr ':' '\n' | grep -n '' \
| grep "^$position:" | cut -f 2 -d :)
# Adding http auth user
touch $htpasswd
sed -i "/^$auth_user:/d" $htpasswd
echo "$auth_user:$auth_hash" >> $htpasswd
# Adding htaccess password protection
if [ "$WEB_SYSTEM" = "nginx" ] || [ "$PROXY_SYSTEM" = "nginx" ]; then
htaccess="$HOMEDIR/$user/conf/web/$domain/nginx.conf_htaccess"
shtaccess="$HOMEDIR/$user/conf/web/$domain/nginx.ssl.conf_htaccess"
if [ ! -f "$htaccess" ]; then
echo "auth_basic \"$domain password access\";" > $htaccess
echo "auth_basic_user_file $htpasswd;" >> $htaccess
ln -s $htaccess $shtaccess
restart_required='yes'
fi
else
htaccess="$HOMEDIR/$user/conf/web/$domain/apache2.conf_htaccess"
shtaccess="$HOMEDIR/$user/conf/web/$domain/apache2.ssl.conf_htaccess"
if [ ! -f "$htaccess" ]; then
echo "<Directory $docroot>" > $htaccess
echo " AuthUserFile $htpasswd" >> $htaccess
echo " AuthName \"$domain access\"" >> $htaccess
echo " AuthType Basic" >> $htaccess
echo " Require valid-user" >> $htaccess
echo "</Directory>" >> $htaccess
ln -s $htaccess $shtaccess
restart_required='yes'
fi
fi
chmod 644 $htpasswd $htaccess
chgrp $user $htpasswd $htaccess
done
# Set folder permissions
no_symlink_chmod 551 $HOMEDIR/$user/web/$domain \
$HOMEDIR/$user/web/$domain/stats \
$HOMEDIR/$user/web/$domain/logs
no_symlink_chmod 751 $HOMEDIR/$user/web/$domain/private \
$HOMEDIR/$user/web/$domain/cgi-bin \
$HOMEDIR/$user/web/$domain/public_*html \
$HOMEDIR/$user/web/$domain/document_errors
chmod 640 /var/log/$WEB_SYSTEM/domains/$domain.*
chown --no-dereference $user:www-data $HOMEDIR/$user/web/$domain/public_*html
}
# DNS domain rebuild
rebuild_dns_domain_conf() {
# Get domain values
get_domain_values 'dns'
domain_idn=$(idn2 --quiet "$domain")
if [ "$SLAVE" != "yes" ]; then
# Checking zone file
if [ ! -e "$USER_DATA/dns/$domain.conf" ]; then
cat $DNSTPL/$TPL.tpl \
| sed -e "s/%ip%/$IP/g" \
-e "s/%domain_idn%/$domain_idn/g" \
-e "s/%domain%/$domain/g" \
-e "s/%ns1%/$ns1/g" \
-e "s/%ns2%/$ns2/g" \
-e "s/%ns3%/$ns3/g" \
-e "s/%ns4%/$ns4/g" \
-e "s/%time%/$TIME/g" \
-e "s/%date%/$DATE/g" > $USER_DATA/dns/$domain.conf
fi
# Sorting records
sort_dns_records
#Remove old sign files
rm -fr $HOMEDIR/$user/conf/dns/$domain.db.*
# Updating zone
update_domain_zone
# Set permissions
if [ "$DNS_SYSTEM" = 'named' ]; then
dns_group='named'
else
dns_group='bind'
fi
# Set file permissions
chmod 640 $HOMEDIR/$user/conf/dns/$domain.db
chown $root:$dns_group $HOMEDIR/$user/conf/dns/$domain.db
else
rm -fr $HOMEDIR/$user/conf/dns/$domain.db.*
chown $dns_group:$dns_group $HOMEDIR/$user/conf/dns/$domain.db
fi
# Get dns config path
if [ -e '/etc/named.conf' ]; then
dns_conf='/etc/named.conf'
fi
if [ -e '/etc/bind/named.conf' ]; then
dns_conf='/etc/bind/named.conf'
fi
# Bind config check
if [ "$SUSPENDED" = 'yes' ]; then
rm_string=$(grep -n /etc/namedb/$domain.db $dns_conf | cut -d : -f 1)
if [ -n "$rm_string" ]; then
sed -i "$rm_string d" $dns_conf
fi
suspended_dns=$((suspended_dns + 1))
else
sed -i "/dns\/$domain.db/d" $dns_conf
if [ "$SLAVE" = "yes" ]; then
named="zone \"$domain_idn\" in {type slave; masters { $MASTER; }; file"
named="$named \"$HOMEDIR/$user/conf/dns/$domain.db\";};"
echo "$named" >> $dns_conf
else
if [ "$DNSSEC" = "yes" ]; then
named="zone \"$domain_idn\" in {type master; dnssec-policy default; inline-signing yes; file"
named="$named \"$HOMEDIR/$user/conf/dns/$domain.db\";};"
echo "$named" >> $dns_conf
else
named="zone \"$domain_idn\" {type master; file"
named="$named \"$HOMEDIR/$user/conf/dns/$domain.db\";};"
echo "$named" >> $dns_conf
fi
fi
fi
user_domains=$((user_domains + 1))
records=$(wc -l $USER_DATA/dns/$domain.conf | cut -f 1 -d ' ')
user_records=$((user_records + records))
update_object_value 'dns' 'DOMAIN' "$domain" '$RECORDS' "$records"
# Load new config
/usr/sbin/rndc reconfig > /dev/null 2>&1
# Reload config
/usr/sbin/rndc reload $domain > /dev/null 2>&1
if [ "$DNSSEC" = "yes" ]; then
# Key consists always out of 5 digits when less is used they are "lost"
key=$(/usr/sbin/rndc dnssec -status $domain_idn | grep ^key: | cut -f2 -d' ' | numfmt --format='%05.0f' --invalid=ignore)
if [ ! -d "$USER_DATA/keys/" ]; then
mkdir -p $USER_DATA/keys/
fi
cp /var/cache/bind/K$domain_idn.+013+$key.* $USER_DATA/keys/
update_object_value 'dns' 'DOMAIN' "$domain" '$KEY' "$key"
fi
rndc notify $domain_idn > /dev/null 2>&1
}
# MAIL domain rebuild
rebuild_mail_domain_conf() {
syshealth_repair_mail_config
get_domain_values 'mail'
if [[ "$domain" = *[![:ascii:]]* ]]; then
domain_idn=$(idn2 --quiet $domain)
else
domain_idn=$domain
fi
# Inherit web domain local ip address
unset -v nat ip local_ip domain_ip
local domain_ip=$(get_object_value 'web' 'DOMAIN' "$domain" '$IP')
if [ -n "$domain_ip" ]; then
local local_ip=$(get_real_ip "$domain_ip")
is_ip_valid "$local_ip" "$user"
else
get_user_ip
fi
if [ "$SUSPENDED" = 'yes' ]; then
SUSPENDED_MAIL=$((SUSPENDED_MAIL + 1))
fi
if [ ! -d "$USER_DATA/mail" ]; then
rm -f $USER_DATA/mail
mkdir $USER_DATA/mail
fi
# Rebuilding exim config structure
if [[ "$MAIL_SYSTEM" =~ exim ]]; then
rm -f /etc/$MAIL_SYSTEM/domains/$domain_idn
mkdir -p $HOMEDIR/$user/conf/mail/$domain
ln -s $HOMEDIR/$user/conf/mail/$domain \
/etc/$MAIL_SYSTEM/domains/$domain_idn
rm -f $HOMEDIR/$user/conf/mail/$domain/accounts
rm -f $HOMEDIR/$user/conf/mail/$domain/aliases
rm -f $HOMEDIR/$user/conf/mail/$domain/antispam
rm -f $HOMEDIR/$user/conf/mail/$domain/reject_spam
rm -f $HOMEDIR/$user/conf/mail/$domain/antivirus
rm -f $HOMEDIR/$user/conf/mail/$domain/protection
rm -f $HOMEDIR/$user/conf/mail/$domain/passwd
rm -f $HOMEDIR/$user/conf/mail/$domain/fwd_only
rm -f $HOMEDIR/$user/conf/mail/$domain/ip
rm -fr $HOMEDIR/$user/conf/mail/$domain/limits
touch $HOMEDIR/$user/conf/mail/$domain/accounts
touch $HOMEDIR/$user/conf/mail/$domain/aliases
touch $HOMEDIR/$user/conf/mail/$domain/passwd
touch $HOMEDIR/$user/conf/mail/$domain/fwd_only
touch $HOMEDIR/$user/conf/mail/$domain/limits
# Setting outgoing ip address
if [ -n "$local_ip" ]; then
echo "$local_ip" > $HOMEDIR/$user/conf/mail/$domain/ip
fi
# Adding antispam protection
if [ "$ANTISPAM" = 'yes' ]; then
touch $HOMEDIR/$user/conf/mail/$domain/antispam
fi
# Adding antivirus protection
if [ "$ANTIVIRUS" = 'yes' ]; then
touch $HOMEDIR/$user/conf/mail/$domain/antivirus
fi
# Adding reject spam protection
if [ "$REJECT" = 'yes' ]; then
touch $HOMEDIR/$user/conf/mail/$domain/reject_spam
fi
# Adding dkim
if [ "$DKIM" = 'yes' ]; then
cp $USER_DATA/mail/$domain.pem \
$HOMEDIR/$user/conf/mail/$domain/dkim.pem
fi
# Rebuild SMTP Relay configuration
if [ "$U_SMTP_RELAY" = 'true' ]; then
$BIN/v-add-mail-domain-smtp-relay $user $domain "$U_SMTP_RELAY_HOST" "$U_SMTP_RELAY_USERNAME" "$U_SMTP_RELAY_PASSWORD" "$U_SMTP_RELAY_PORT"
fi
# Removing configuration files if domain is suspended
if [ "$SUSPENDED" = 'yes' ]; then
rm -f /etc/$MAIL_SYSTEM/domains/$domain_idn
rm -f /etc/dovecot/conf.d/domains/$domain_idn.conf
fi
# Adding mail directory
if [ ! -e $HOMEDIR/$user/mail/$domain_idn ]; then
mkdir "$HOMEDIR/$user/mail/$domain_idn"
fi
# Webamil client
if [ "$WEBMAIL" = '' ]; then
$BIN/v-add-mail-domain-webmail $user $domain 'roundcube' 'no'
fi
# Adding catchall email
dom_aliases=$HOMEDIR/$user/conf/mail/$domain/aliases
if [ -n "$CATCHALL" ]; then
echo "*@$domain_idn:$CATCHALL" >> $dom_aliases
fi
fi
# Rebuild domain accounts
accs=0
dom_disk=0
if [ -e "$USER_DATA/mail/$domain.conf" ]; then
accounts=$(search_objects "mail/$domain" 'SUSPENDED' "no" 'ACCOUNT')
else
accounts=''
fi
for account in $accounts; do
((++accs))
object=$(grep "ACCOUNT='$account'" $USER_DATA/mail/$domain.conf)
FWD_ONLY='no'
parse_object_kv_list "$object"
if [ "$SUSPENDED" = 'yes' ]; then
MD5='SUSPENDED'
fi
if [[ "$MAIL_SYSTEM" =~ exim ]]; then
if [ "$QUOTA" = 'unlimited' ]; then
QUOTA=0
fi
str="$account:$MD5:$user:mail::$HOMEDIR/$user:${QUOTA}:userdb_quota_rule=*:storage=${QUOTA}M"
echo $str >> $HOMEDIR/$user/conf/mail/$domain/passwd
userstr="$account:$account:$user:mail:$HOMEDIR/$user"
echo $userstr >> $HOMEDIR/$user/conf/mail/$domain/accounts
for malias in ${ALIAS//,/ }; do
echo "$malias@$domain_idn:$account@$domain_idn" >> $dom_aliases
done
if [ -n "$FWD" ]; then
echo "$account@$domain_idn:$FWD" >> $dom_aliases
fi
if [ "$FWD_ONLY" = 'yes' ]; then
echo "$account" >> $HOMEDIR/$user/conf/mail/$domain/fwd_only
fi
user_rate_limit=$(get_object_value 'mail' 'DOMAIN' "$domain" '$RATE_LIMIT')
if [ -n "$RATE_LIMIT" ]; then
#user value
sed -i "/^$account@$domain_idn:/ d" $HOMEDIR/$user/conf/mail/$domain/limits
echo "$account@$domain_idn:$RATE_LIMIT" >> $HOMEDIR/$user/conf/mail/$domain/limits
elif [ -n "$user_rate_limit" ]; then
#revert to account value
sed -i "/^$account@$domain_idn:/ d" $HOMEDIR/$user/conf/mail/$domain/limits
echo "$account@$domain_idn:$user_rate_limit" >> $HOMEDIR/$user/conf/mail/$domain/limits
else
#revert to system value
system=$(cat /etc/exim4/limit.conf)
sed -i "/^$account@$domain_idn:/ d" $HOMEDIR/$user/conf/mail/$domain/limits
echo "$account@$domain_idn:$system" >> $HOMEDIR/$user/conf/mail/$domain/limits
fi
fi
done
# Set permissions and ownership
if [[ "$MAIL_SYSTEM" =~ exim ]]; then
chmod 660 $USER_DATA/mail/$domain.*
chmod 771 $HOMEDIR/$user/conf/mail/$domain
chmod 660 $HOMEDIR/$user/conf/mail/$domain/*
chmod 771 /etc/$MAIL_SYSTEM/domains/$domain_idn
chmod 770 $HOMEDIR/$user/mail/$domain_idn
chown -R $MAIL_USER:mail $HOMEDIR/$user/conf/mail/$domain
if [ "$IMAP_SYSTEM" = "dovecot" ]; then
chown -R dovecot:mail $HOMEDIR/$user/conf/mail/$domain/passwd
fi
chown $MAIL_USER:mail $HOMEDIR/$user/conf/mail/$domain/accounts
chown $user:mail $HOMEDIR/$user/mail/$domain_idn
fi
# Add missing SSL configuration flags to existing domains
# for per-domain SSL migration
sslcheck=$(grep "DOMAIN='$domain'" $USER_DATA/mail.conf | grep SSL)
if [ -z "$sslcheck" ]; then
sed -i "s|$domain'|$domain' SSL='no' LETSENCRYPT='no'|g" $USER_DATA/mail.conf
fi
# Remove and recreate SSL configuration
if [ -f "$HOMEDIR/$user/conf/mail/$domain/ssl/$domain.crt" ]; then
del_mail_ssl_config
add_mail_ssl_config
update_object_value 'mail' 'DOMAIN' "$domain" '$SSL' "yes"
else
update_object_value 'mail' 'DOMAIN' "$domain" '$SSL' "no"
fi
dom_disk=0
for account in $(search_objects "mail/$domain" 'SUSPENDED' "no" 'ACCOUNT'); do
home_dir=$HOMEDIR/$user/mail/$domain/$account
if [ -e "$home_dir" ]; then
udisk=$(nice -n 19 du -shm $home_dir | cut -f 1)
else
udisk=0
fi
update_object_value "mail/$domain" 'ACCOUNT' "$account" '$U_DISK' "$udisk"
dom_disk=$((dom_disk + udisk))
done
update_object_value 'mail' 'DOMAIN' "$domain" '$ACCOUNTS' "$accs"
update_object_value 'mail' 'DOMAIN' "$domain" '$U_DISK' "$dom_disk"
# Update usage counters
U_MAIL_ACCOUNTS=$((U_MAIL_ACCOUNTS + accs))
U_MAIL_DOMAINS=$((U_MAIL_DOMAINS + 1))
recalc_user_disk_usage
}
# Rebuild MySQL
rebuild_mysql_database() {
mysql_connect $HOST
mysql_query "CREATE DATABASE \`$DB\` CHARACTER SET $CHARSET" > /dev/null
if [ "$mysql_fork" = "mysql" ]; then
# mysql
mysql_ver_sub=$(echo $mysql_ver | cut -d '.' -f1)
mysql_ver_sub_sub=$(echo $mysql_ver | cut -d '.' -f2)
if [ "$mysql_ver_sub" -ge 8 ] || { [ "$mysql_ver_sub" -eq 5 ] && [ "$mysql_ver_sub_sub" -ge 7 ]; }; then
# mysql >= 5.7
mysql_query "CREATE USER IF NOT EXISTS \`$DBUSER\`" > /dev/null
mysql_query "CREATE USER IF NOT EXISTS \`$DBUSER\`@localhost" > /dev/null
# mysql >= 8, with enabled Print identified with as hex feature
if [[ "$mysql_ver_sub" -ge 8 && "$MD5" =~ ^0x.* ]]; then
query="UPDATE mysql.user SET authentication_string=UNHEX('${MD5:2}')"
else
query="UPDATE mysql.user SET authentication_string='$MD5'"
fi
query="$query WHERE User='$DBUSER'"
else
# mysql < 5.7
query="UPDATE mysql.user SET Password='$MD5' WHERE User='$DBUSER'"
fi
else
# mariadb
mysql_ver_sub=$(echo $mysql_ver | cut -d '.' -f1)
mysql_ver_sub_sub=$(echo $mysql_ver | cut -d '.' -f2)
if [ "$mysql_ver_sub" -eq 5 ]; then
# mariadb = 5
mysql_query "CREATE USER \`$DBUSER\`" > /dev/null
mysql_query "CREATE USER \`$DBUSER\`@localhost" > /dev/null
query="UPDATE mysql.user SET Password='$MD5' WHERE User='$DBUSER'"
else
# mariadb = 10
mysql_query "CREATE USER IF NOT EXISTS \`$DBUSER\` IDENTIFIED BY PASSWORD '$MD5'" > /dev/null
mysql_query "CREATE USER IF NOT EXISTS \`$DBUSER\`@localhost IDENTIFIED BY PASSWORD '$MD5'" > /dev/null
if [ "$mysql_ver_sub_sub" -ge 4 ]; then
#mariadb >= 10.4
query="SET PASSWORD FOR '$DBUSER'@'%' = '$MD5';"
query2="SET PASSWORD FOR '$DBUSER'@'localhost' = '$MD5';"
else
#mariadb < 10.4
query="UPDATE mysql.user SET Password='$MD5' WHERE User='$DBUSER'"
fi
fi
fi
mysql_query "GRANT ALL ON \`$DB\`.* TO \`$DBUSER\`@\`%\`" > /dev/null
mysql_query "GRANT ALL ON \`$DB\`.* TO \`$DBUSER\`@localhost" > /dev/null
mysql_query "$query" > /dev/null
if [ ! -z "$query2" ]; then
mysql_query "$query2" > /dev/null
fi
mysql_query "FLUSH PRIVILEGES" > /dev/null
}
# Rebuild PostgreSQL
rebuild_pgsql_database() {
host_str=$(grep "HOST='$HOST'" $HESTIA/conf/pgsql.conf)
parse_object_kv_list "$host_str"
export PGPASSWORD="$PASSWORD"
if [ -z $HOST ] || [ -z $USER ] || [ -z $PASSWORD ] || [ -z $TPL ]; then
echo "Error: postgresql config parsing failed"
if [ -n "$SENDMAIL" ]; then
echo "Can't parse PostgreSQL config" | $SENDMAIL -s "$subj" $email
fi
log_event "$E_PARSING" "$ARGUMENTS"
exit "$E_PARSING"
fi
query='SELECT VERSION()'
psql -h $HOST -U $USER -c "$query" > /dev/null 2>&1
if [ '0' -ne "$?" ]; then
echo "Error: Connection failed"
if [ -n "$SENDMAIL" ]; then
echo "Database connection to PostgreSQL host $HOST failed" \
| $SENDMAIL -s "$subj" $email
fi
log_event "$E_CONNECT" "$ARGUMENTS"
exit "$E_CONNECT"
fi
query="CREATE ROLE $DBUSER"
psql -h $HOST -U $USER -c "$query" > /dev/null 2>&1
query="UPDATE pg_authid SET rolpassword='$MD5' WHERE rolname='$DBUSER'"
psql -h $HOST -U $USER -c "$query" > /dev/null 2>&1
query="CREATE DATABASE $DB OWNER $DBUSER"
if [ "$TPL" = 'template0' ]; then
query="$query ENCODING '$CHARSET' TEMPLATE $TPL"
else
query="$query TEMPLATE $TPL"
fi
psql -h $HOST -U $USER -c "$query" > /dev/null 2>&1
query="GRANT ALL PRIVILEGES ON DATABASE $DB TO $DBUSER"
psql -h $HOST -U $USER -c "$query" > /dev/null 2>&1
query="GRANT CONNECT ON DATABASE template1 to $DBUSER"
psql -h $HOST -U $USER -c "$query" > /dev/null 2>&1
}
# Import MySQL dump
import_mysql_database() {
host_str=$(grep "HOST='$HOST'" $HESTIA/conf/mysql.conf)
parse_object_kv_list "$host_str"
if [ -z $HOST ] || [ -z $USER ] || [ -z $PASSWORD ]; then
echo "Error: mysql config parsing failed"
log_event "$E_PARSING" "$ARGUMENTS"
exit "$E_PARSING"
fi
if [ -f '/usr/bin/mariadb' ]; then
mariadb -h $HOST -u $USER -p$PASSWORD $DB < $1 > /dev/null 2>&1
else
mysql -h $HOST -u $USER -p$PASSWORD $DB < $1 > /dev/null 2>&1
fi
}
# Import PostgreSQL dump
import_pgsql_database() {
host_str=$(grep "HOST='$HOST'" $HESTIA/conf/pgsql.conf)
parse_object_kv_list "$host_str"
export PGPASSWORD="$PASSWORD"
if [ -z $HOST ] || [ -z $USER ] || [ -z $PASSWORD ] || [ -z $TPL ]; then
echo "Error: postgresql config parsing failed"
log_event "$E_PARSING" "$ARGUMENTS"
exit "$E_PARSING"
fi
psql -h $HOST -U $USER $DB < $1 > /dev/null 2>&1
}

196
func/remote.sh Normal file
View File

@@ -0,0 +1,196 @@
#!/bin/bash
#===========================================================================#
# #
# Hestia Control Panel - API Function Library #
# #
#===========================================================================#
# Check if script already running or not
is_procces_running() {
SCRIPT=$(basename $0)
for pid in $(pidof -x $SCRIPT); do
if [ $pid != $$ ]; then
check_result "$E_INUSE" "$SCRIPT is already running"
fi
done
}
send_api_cmd() {
if [ -n "$PASSWORD" ]; then
answer=$(curl -s -k \
--data-urlencode "user=$USER" \
--data-urlencode "password=$PASSWORD" \
--data-urlencode "returncode=yes" \
--data-urlencode "cmd=$1" \
--data-urlencode "arg1=$2" \
--data-urlencode "arg2=$3" \
--data-urlencode "arg3=$4" \
--data-urlencode "arg4=$5" \
--data-urlencode "arg5=$6" \
--data-urlencode "arg6=$7" \
--data-urlencode "arg7=$8" \
--data-urlencode "arg8=$9" \
https://$HOST:$PORT/api/)
else
answer=$(curl -s -k \
--data-urlencode "hash=$HASH" \
--data-urlencode "returncode=yes" \
--data-urlencode "cmd=$1" \
--data-urlencode "arg1=$2" \
--data-urlencode "arg2=$3" \
--data-urlencode "arg3=$4" \
--data-urlencode "arg4=$5" \
--data-urlencode "arg5=$6" \
--data-urlencode "arg6=$7" \
--data-urlencode "arg7=$8" \
--data-urlencode "arg8=$9" \
https://$HOST:$PORT/api/)
fi
if [ "$DEBUG_MODE" = "yes" ]; then
# log out going request if wanted for debugging
echo "$1 $2 $3 $4 $5 $6 $7 $8 $9" >> /var/log/hestia/api_out.log
fi
return $answer
}
send_api_file() {
if [ -n "$PASSWORD" ]; then
answer=$(curl -s -k \
--data-urlencode "user=$USER" \
--data-urlencode "password=$PASSWORD" \
--data-urlencode "returncode=yes" \
--data-urlencode "cmd=v-make-tmp-file" \
--data-urlencode "arg1=$(cat $1)" \
--data-urlencode "arg2=$2" \
https://$HOST:$PORT/api/)
else
answer=$(curl -s -k \
--data-urlencode "hash=$HASH" \
--data-urlencode "returncode=yes" \
--data-urlencode "cmd=v-make-tmp-file" \
--data-urlencode "arg1=$(cat $1)" \
--data-urlencode "arg2=$2" \
https://$HOST:$PORT/api/)
fi
return $answer
}
send_ssh_cmd() {
if [ -z "$IDENTITY_FILE" ] && [ "$USER" = 'root' ]; then
IDENTITY_FILE="/root/.ssh/id_rsa"
fi
if [ -z "$IDENTITY_FILE" ]; then
IDENTITY_FILE="/home/$USER/.ssh/id_rsa"
fi
if [ "$USER" = 'root' ]; then
args="$BIN/$1 \"$2\" \"$3\" \"$4\" \"$5\""
else
args="sudo $BIN/$1 \"$2\" \"$3\" \"$4\" \"$5\""
fi
ssh -i $IDENTITY_FILE $USER@$HOST -p $PORT "$args" > /dev/null 2>&1
if [ "$?" -ne '0' ]; then
return 1
else
return 0
fi
}
send_scp_file() {
if [ -z "$IDENTITY_FILE" ]; then
IDENTITY_FILE="/home/admin/.ssh/id_rsa"
fi
scp -P $PORT -i $IDENTITY_FILE $1 $USER@$HOST:$2 > /dev/null 2>&1
if [ "$?" -ne '0' ]; then
return 1
else
return 0
fi
}
is_dnshost_new() {
if [ -e "$HESTIA/conf/dns-cluster.conf" ]; then
check_host=$(grep "HOST='$host'" $HESTIA/conf/dns-cluster.conf)
if [ -n "$check_host" ]; then
check_result $E_EXISTS "remote dns host $host exists"
fi
fi
}
is_dnshost_alive() {
cluster_cmd v-list-sys-config
check_result $? "$type connection to $HOST failed" "$E_CONNECT"
cluster_cmd v-list-user "$DNS_USER"
check_result $? "$DNS_USER doesn't exist" "$E_CONNECT"
}
remote_dns_health_check() {
OLD_IFS="$IFS"
IFS=$'\n'
# Starting health-check
for str in $(grep "SUSPENDED='no'" $HESTIA/conf/dns-cluster.conf); do
# Reset user, password and hash vars
clear_dns_cluster_settings
# Parsing host values
parse_object_kv_list "$str"
# Checking host connection
cluster_cmd v-list-user "$DNS_USER"
if [ $? -ne 0 ]; then
# Creating error report
tmpfile=$(mktemp)
echo "$(basename $0) $*" > $tmpfile
echo -e "Error: $TYPE connection to $HOST failed.\n" >> $tmpfile
echo -n "Remote dns host has been suspended." >> $tmpfile
echo -n "After resolving issue run " >> $tmpfile
echo -e "following commands:\n" >> $tmpfile
echo "v-unsuspend-remote-dns-host $HOST" >> $tmpfile
echo "v-sync-dns-cluster $HOST" >> $tmpfile
echo -e "\n\n--\nHestia Control Panel\n$(hostname)" >> $tmpfile
if [ "$1" = 'no_email' ]; then
cat $tmpfile
else
subj="DNS sync failed"
email=$($BIN/v-get-user-value admin CONTACT)
cat $tmpfile | $SENDMAIL -s "$subj" $email
fi
# Deleting tmp file
rm -f $tmpfile
log_event "$E_CONNECT" "$ARGUMENTS"
# Suspending remote host
dconf="../../conf/dns-cluster"
update_object_value "$dconf" 'HOST' "$HOST" '$SUSPENDED' 'yes'
fi
done
IFS="$OLD_IFS"
}
cluster_cmd() {
case $TYPE in
ssh) send_ssh_cmd $* ;;
api) send_api_cmd $* ;;
esac
}
cluster_file() {
case $TYPE in
ssh) send_scp_file $* ;;
api) send_api_file $* ;;
esac
}
clear_dns_cluster_settings() {
unset USER
unset PASSWORD
unset HASH
}

568
func/syshealth.sh Normal file
View File

@@ -0,0 +1,568 @@
#!/bin/bash
#===========================================================================#
# #
# Hestia Control Panel - System Health Check and Repair Function Library #
# #
#===========================================================================#
# Read known configuration keys from $HESTIA/conf/defaults/$system.conf
function read_kv_config_file() {
local system=$1
if [ ! -f "$HESTIA/conf/defaults/$system.conf" ]; then
write_kv_config_file $system
fi
while read -r str; do
echo "$str"
done < <(cat $HESTIA/conf/defaults/$system.conf)
unset system
}
# Write known configuration keys to $HESTIA/conf/defaults/
function write_kv_config_file() {
# Ensure configuration directory exists
if [ ! -d "$HESTIA/conf/defaults/" ]; then
mkdir "$HESTIA/conf/defaults/"
fi
# Remove previous known good configuration
if [ -f "$HESTIA/conf/defaults/$system.conf" ]; then
rm -f $HESTIA/conf/defaults/$system.conf
fi
touch $HESTIA/conf/defaults/$system.conf
for key in $known_keys; do
echo $key >> $HESTIA/conf/defaults/$system.conf
done
}
# Sanitize configuration input
function sanitize_config_file() {
local system=$1
known_keys=$(read_kv_config_file "$system")
for key in $known_keys; do
unset $key
done
}
# Update list of known keys for web.conf files
function syshealth_update_web_config_format() {
# WEB DOMAINS
# Create array of known keys in configuration file
system="web"
known_keys="DOMAIN IP IP6 CUSTOM_DOCROOT CUSTOM_PHPROOT FASTCGI_CACHE FASTCGI_DURATION ALIAS TPL SSL SSL_FORCE SSL_HSTS SSL_HOME LETSENCRYPT FTP_USER FTP_MD5 FTP_PATH BACKEND PROXY PROXY_EXT STATS STATS_USER STATS_CRYPT REDIRECT REDIRECT_CODE AUTH_USER AUTH_HASH SUSPENDED TIME DATE"
write_kv_config_file
unset system
unset known_keys
}
# Update list of known keys for dns.conf files
function syshealth_update_dns_config_format() {
# DNS DOMAINS
# Create array of known keys in configuration file
system="dns"
known_keys="DOMAIN IP TPL TTL EXP SOA SERIAL SRC RECORDS DNSSEC KEY SLAVE MASTER SUSPENDED TIME DATE"
write_kv_config_file
unset system
unset known_keys
# DNS RECORDS
system="dns_records"
known_keys="ID RECORD TYPE PRIORITY VALUE SUSPENDED TIME DATE TTL"
write_kv_config_file
unset system
unset known_keys
}
# Update list of known keys for mail.conf files
function syshealth_update_mail_config_format() {
# MAIL DOMAINS
# Create array of known keys in configuration file
system="mail"
known_keys="DOMAIN ANTIVIRUS ANTISPAM DKIM WEBMAIL SSL LETSENCRYPT CATCHALL ACCOUNTS RATE_LIMIT REJECT U_DISK SUSPENDED TIME DATE"
write_kv_config_file
unset system
unset known_keys
}
function syshealth_update_mail_account_config_format() {
# MAIL ACCOUNTS
system="mail_accounts"
known_keys="ACCOUNT ALIAS AUTOREPLY FWD FWD_ONLY MD5 QUOTA RATE_LIMIT U_DISK SUSPENDED TIME DATE"
write_kv_config_file
unset system
unset known_keys
}
# Update list of known keys for user.conf files
function syshealth_update_user_config_format() {
# USER CONFIGURATION
# Create array of known keys in configuration file
system="user"
known_keys="NAME PACKAGE CONTACT CRON_REPORTS MD5 RKEY TWOFA QRCODE PHPCLI ROLE SUSPENDED SUSPENDED_USERS SUSPENDED_WEB SUSPENDED_DNS SUSPENDED_MAIL SUSPENDED_DB SUSPENDED_CRON IP_AVAIL IP_OWNED U_USERS U_DISK U_DISK_DIRS U_DISK_WEB U_DISK_MAIL U_DISK_DB U_BANDWIDTH U_WEB_DOMAINS U_WEB_SSL U_WEB_ALIASES U_DNS_DOMAINS U_DNS_RECORDS U_MAIL_DKIM U_MAIL_DKIM U_MAIL_ACCOUNTS U_MAIL_DOMAINS U_MAIL_SSL U_DATABASES U_CRON_JOBS U_BACKUPS LANGUAGE THEME NOTIFICATIONS PREF_UI_SORT TIME DATE"
write_kv_config_file
unset system
unset known_keys
# CRON JOB CONFIGURATION
# Create array of known keys in configuration file
system="cron"
known_keys="JOB MIN HOUR DAY MONTH WDAY CMD SUSPENDED TIME DATE"
write_kv_config_file
unset system
unset known_keys
}
# Update list of known keys for db.conf files
function syshealth_update_db_config_format() {
# DATABASE CONFIGURATION
# Create array of known keys in configuration file
system="db"
known_keys="DB DBUSER MD5 HOST TYPE CHARSET U_DISK SUSPENDED TIME DATE"
write_kv_config_file
unset system
unset known_keys
}
# Update list of known keys for ip.conf files
function syshealth_update_ip_config_format() {
# IP ADDRESS
# Create array of known keys in configuration file
system="ip"
known_keys="OWNER STATUS NAME U_SYS_USERS U_WEB_DOMAINS INTERFACE NETMASK NAT TIME DATE"
write_kv_config_file
unset system
unset known_keys
}
# Repair web domain configuration
function syshealth_repair_web_config() {
system="web"
sanitize_config_file "$system"
get_domain_values 'web'
prev="DOMAIN"
for key in $known_keys; do
if [ -z "${!key}" ]; then
add_object_key 'web' 'DOMAIN' "$domain" "$key" "$prev"
fi
prev=$key
done
}
function syshealth_repair_mail_config() {
system="mail"
sanitize_config_file "$system"
get_domain_values 'mail'
prev="DOMAIN"
for key in $known_keys; do
if [ -z "${!key}" ]; then
add_object_key 'mail' 'DOMAIN' "$domain" "$key" "$prev"
fi
prev=$key
done
}
function syshealth_repair_dns_config() {
system="dns"
sanitize_config_file "$system"
get_domain_values 'dns'
prev="DOMAIN"
for key in $known_keys; do
if [ -z "${!key}" ]; then
add_object_key 'dns' 'DOMAIN' "$domain" "$key" "$prev"
fi
prev=$key
done
}
function syshealth_repair_mail_account_config() {
system="mail_accounts"
sanitize_config_file "$system"
get_object_values "mail/$domain" 'ACCOUNT' "$account"
for key in $known_keys; do
if [ -z "${!key}" ]; then
add_object_key "mail/$domain" 'ACCOUNT' "$account" "$key" "$prev"
fi
prev=$key
done
}
function syshealth_update_system_config_format() {
# SYSTEM CONFIGURATION
# Create array of known keys in configuration file
system="system"
known_keys="ANTISPAM_SYSTEM ANTIVIRUS_SYSTEM API_ALLOWED_IP API BACKEND_PORT BACKUP_GZIP BACKUP_MODE BACKUP_SYSTEM CRON_SYSTEM DB_PMA_ALIAS DB_SYSTEM DISK_QUOTA DNS_SYSTEM ENFORCE_SUBDOMAIN_OWNERSHIP FILE_MANAGER FIREWALL_EXTENSION FIREWALL_SYSTEM FTP_SYSTEM IMAP_SYSTEM INACTIVE_SESSION_TIMEOUT LANGUAGE LOGIN_STYLE MAIL_SYSTEM PROXY_PORT PROXY_SSL_PORT PROXY_SYSTEM RELEASE_BRANCH STATS_SYSTEM THEME UPDATE_HOSTNAME_SSL UPGRADE_SEND_EMAIL UPGRADE_SEND_EMAIL_LOG WEB_BACKEND WEBMAIL_ALIAS WEBMAIL_SYSTEM WEB_PORT WEB_RGROUPS WEB_SSL WEB_SSL_PORT WEB_SYSTEM VERSION DISABLE_IP_CHECK"
write_kv_config_file
unset system
unset known_keys
}
# Restore System Configuration
# Replaces $HESTIA/conf/hestia.conf with "known good defaults" file ($HESTIA/conf/defaults/hestia.conf)
function syshealth_restore_system_config() {
if [ -f "$HESTIA/conf/defaults/hestia.conf" ]; then
mv $HESTIA/conf/hestia.conf $HESTIA/conf/hestia.conf.old
cp $HESTIA/conf/defaults/hestia.conf $HESTIA/conf/hestia.conf
rm -f $HESTIA/conf/hestia.conf.old
else
echo "ERROR: System default configuration file not found, aborting."
exit 1
fi
}
function check_key_exists() {
grep -e "^$1=" $HESTIA/conf/hestia.conf
}
# Repair System Configuration
# Adds missing variables to $HESTIA/conf/hestia.conf with safe default values
function syshealth_repair_system_config() {
# Release branch
if [[ -z $(check_key_exists 'RELEASE_BRANCH') ]]; then
echo "[ ! ] Adding missing variable to hestia.conf: RELEASE_BRANCH ('release')"
$BIN/v-change-sys-config-value 'RELEASE_BRANCH' 'release'
fi
# Webmail alias
if [ -n "$IMAP_SYSTEM" ]; then
if [[ -z $(check_key_exists 'WEBMAIL_ALIAS') ]]; then
echo "[ ! ] Adding missing variable to hestia.conf: WEBMAIL_ALIAS ('webmail')"
$BIN/v-change-sys-config-value 'WEBMAIL_ALIAS' 'webmail'
fi
fi
# phpMyAdmin/phpPgAdmin alias
if [ -n "$DB_SYSTEM" ]; then
if [ "$DB_SYSTEM" = "mysql" ]; then
if [[ -z $(check_key_exists 'DB_PMA_ALIAS') ]]; then
echo "[ ! ] Adding missing variable to hestia.conf: DB_PMA_ALIAS ('phpmyadmin)"
$BIN/v-change-sys-config-value 'DB_PMA_ALIAS' 'phpmyadmin'
fi
fi
if [ "$DB_SYSTEM" = "pgsql" ]; then
if [[ -z $(check_key_exists 'DB_PGA_ALIAS') ]]; then
echo "[ ! ] Adding missing variable to hestia.conf: DB_PGA_ALIAS ('phppgadmin')"
$BIN/v-change-sys-config-value 'DB_PGA_ALIAS' 'phppgadmin'
fi
fi
fi
# Backup compression level
if [[ -z $(check_key_exists 'BACKUP_GZIP') ]]; then
echo "[ ! ] Adding missing variable to hestia.conf: BACKUP_GZIP ('4')"
$BIN/v-change-sys-config-value 'BACKUP_GZIP' '4'
fi
# Theme
if [[ -z $(check_key_exists 'THEME') ]]; then
echo "[ ! ] Adding missing variable to hestia.conf: THEME ('dark')"
$BIN/v-change-sys-config-value 'THEME' 'dark'
fi
# Default language
if [[ -z $(check_key_exists 'LANGUAGE') ]]; then
echo "[ ! ] Adding missing variable to hestia.conf: LANGUAGE ('en')"
$BIN/v-change-sys-language 'LANGUAGE' 'en'
fi
# Disk Quota
if [[ -z $(check_key_exists 'DISK_QUOTA') ]]; then
echo "[ ! ] Adding missing variable to hestia.conf: DISK_QUOTA ('no')"
$BIN/v-change-sys-config-value 'DISK_QUOTA' 'no'
fi
# CRON daemon
if [[ -z $(check_key_exists 'CRON_SYSTEM') ]]; then
echo "[ ! ] Adding missing variable to hestia.conf: CRON_SYSTEM ('cron')"
$BIN/v-change-sys-config-value 'CRON_SYSTEM' 'cron'
fi
# Backend port
if [[ -z $(check_key_exists 'BACKEND_PORT') ]]; then
ORIGINAL_PORT=$(cat $HESTIA/nginx/conf/nginx.conf | grep -m 1 "listen" | sed 's/[^0-9]*//g')
echo "[ ! ] Adding missing variable to hestia.conf: BACKEND_PORT ('$ORIGINAL_PORT')"
$BIN/v-change-sys-config-value 'BACKEND_PORT' $ORIGINAL_PORT
fi
# Upgrade: Send email notification
if [[ -z $(check_key_exists 'UPGRADE_SEND_EMAIL') ]]; then
echo "[ ! ] Adding missing variable to hestia.conf: UPGRADE_SEND_EMAIL ('true')"
$BIN/v-change-sys-config-value 'UPGRADE_SEND_EMAIL' 'true'
fi
# Upgrade: Send email notification
if [[ -z $(check_key_exists 'UPGRADE_SEND_EMAIL_LOG') ]]; then
echo "[ ! ] Adding missing variable to hestia.conf: UPGRADE_SEND_EMAIL_LOG ('false')"
$BIN/v-change-sys-config-value 'UPGRADE_SEND_EMAIL_LOG' 'false'
fi
# File Manager
if [[ -z $(check_key_exists 'FILE_MANAGER') ]]; then
echo "[ ! ] Adding missing variable to hestia.conf: FILE_MANAGER ('true')"
$BIN/v-add-sys-filemanager quiet
fi
# Support for ZSTD / GZIP Change
if [[ -z $(check_key_exists 'BACKUP_MODE') ]]; then
echo "[ ! ] Setting zstd backup compression type as default..."
$BIN/v-change-sys-config-value "BACKUP_MODE" "zstd"
fi
# Login style switcher
if [[ -z $(check_key_exists 'LOGIN_STYLE') ]]; then
echo "[ ! ] Adding missing variable to hestia.conf: LOGIN_STYLE ('default')"
$BIN/v-change-sys-config-value "LOGIN_STYLE" "default"
fi
# Webmail clients
if [[ -z $(check_key_exists 'WEBMAIL_SYSTEM') ]]; then
if [ -d "/var/lib/roundcube" ]; then
echo "[ ! ] Adding missing variable to hestia.conf: WEBMAIL_SYSTEM ('roundcube')"
$BIN/v-change-sys-config-value "WEBMAIL_SYSTEM" "roundcube"
else
echo "[ ! ] Adding missing variable to hestia.conf: WEBMAIL_SYSTEM ('')"
$BIN/v-change-sys-config-value "WEBMAIL_SYSTEM" ""
fi
fi
# Inactive session timeout
if [[ -z $(check_key_exists 'INACTIVE_SESSION_TIMEOUT') ]]; then
echo "[ ! ] Adding missing variable to hestia.conf: INACTIVE_SESSION_TIMEOUT ('60')"
$BIN/v-change-sys-config-value "INACTIVE_SESSION_TIMEOUT" "60"
fi
# Enforce subdomain ownership
if [[ -z $(check_key_exists 'ENFORCE_SUBDOMAIN_OWNERSHIP') ]]; then
echo "[ ! ] Adding missing variable to hestia.conf: ENFORCE_SUBDOMAIN_OWNERSHIP ('yes')"
$BIN/v-change-sys-config-value "ENFORCE_SUBDOMAIN_OWNERSHIP" "yes"
fi
if [[ -z $(check_key_exists 'API') ]]; then
echo "[ ! ] Adding missing variable to hestia.conf: API ('no')"
$BIN/v-change-sys-config-value "API" "no"
fi
# Enable API V2
if [[ -z $(check_key_exists 'API_SYSTEM') ]]; then
echo "[ ! ] Adding missing variable to hestia.conf: API_SYSTEM ('0')"
$BIN/v-change-sys-config-value "API_SYSTEM" "0"
fi
# API access allowed IP's
if [ "$API" = "yes" ]; then
check_api_key=$(grep "API_ALLOWED_IP" $HESTIA/conf/hestia.conf)
if [ -z "$check_api_key" ]; then
if [[ -z $(check_key_exists 'API_ALLOWED_IP') ]]; then
echo "[ ! ] Adding missing variable to hestia.conf: API_ALLOWED_IP ('allow-all')"
$BIN/v-change-sys-config-value "API_ALLOWED_IP" "allow-all"
fi
fi
fi
# Debug mode
if [[ -z $(check_key_exists 'DEBUG_MODE') ]]; then
echo "[ ! ] Adding missing variable to hestia.conf: DEBUG_MODE ('false')"
$BIN/v-change-sys-config-value "DEBUG_MODE" "false"
fi
# Quick install plugin
if [[ -z $(check_key_exists 'PLUGIN_APP_INSTALLER') ]]; then
echo "[ ! ] Adding missing variable to hestia.conf: PLUGIN_APP_INSTALLER ('true')"
$BIN/v-change-sys-config-value "PLUGIN_APP_INSTALLER" "true"
fi
# Enable preview mode
if [[ -z $(check_key_exists 'POLICY_SYSTEM_ENABLE_BACON') ]]; then
echo "[ ! ] Adding missing variable to hestia.conf: POLICY_SYSTEM_ENABLE_BACON ('false')"
$BIN/v-change-sys-config-value "POLICY_SYSTEM_ENABLE_BACON" "false"
fi
# Hide system services
if [[ -z $(check_key_exists 'POLICY_SYSTEM_HIDE_SERVICES') ]]; then
echo "[ ! ] Adding missing variable to hestia.conf: POLICY_SYSTEM_HIDE_SERVICES ('no')"
$BIN/v-change-sys-config-value "POLICY_SYSTEM_HIDE_SERVICES" "no"
fi
# Password reset
if [[ -z $(check_key_exists 'POLICY_SYSTEM_PASSWORD_RESET') ]]; then
echo "[ ! ] Adding missing variable to hestia.conf: POLICY_SYSTEM_PASSWORD_RESET ('no')"
$BIN/v-change-sys-config-value "POLICY_SYSTEM_PASSWORD_RESET" "no"
fi
# Theme editor
if [[ -z $(check_key_exists 'POLICY_USER_CHANGE_THEME') ]]; then
echo "[ ! ] Adding missing variable to hestia.conf: POLICY_USER_CHANGE_THEME ('yes')"
$BIN/v-change-sys-config-value "POLICY_USER_CHANGE_THEME" "true"
fi
# Protect admin user
if [[ -z $(check_key_exists 'POLICY_SYSTEM_PROTECTED_ADMIN') ]]; then
echo "[ ! ] Adding missing variable to hestia.conf: POLICY_SYSTEM_PROTECTED_ADMIN ('no')"
$BIN/v-change-sys-config-value "POLICY_SYSTEM_PROTECTED_ADMIN" "no"
fi
# Allow user delete logs
if [[ -z $(check_key_exists 'POLICY_USER_DELETE_LOGS') ]]; then
echo "[ ! ] Adding missing variable to hestia.conf: POLICY_USER_DELETE_LOGS ('yes')"
$BIN/v-change-sys-config-value "POLICY_USER_DELETE_LOGS" "yes"
fi
# Allow users to delete details
if [[ -z $(check_key_exists 'POLICY_USER_EDIT_DETAILS') ]]; then
echo "[ ! ] Adding missing variable to hestia.conf: POLICY_USER_EDIT_DETAILS ('yes')"
$BIN/v-change-sys-config-value "POLICY_USER_EDIT_DETAILS" "yes"
fi
# Allow users to edit DNS templates
if [[ -z $(check_key_exists 'POLICY_USER_EDIT_DNS_TEMPLATES') ]]; then
echo "[ ! ] Adding missing variable to hestia.conf: POLICY_USER_EDIT_DNS_TEMPLATES ('yes')"
$BIN/v-change-sys-config-value "POLICY_USER_EDIT_DNS_TEMPLATES" "yes"
fi
# Allow users to edit web templates
if [[ -z $(check_key_exists 'POLICY_USER_EDIT_WEB_TEMPLATES') ]]; then
echo "[ ! ] Adding missing variable to hestia.conf: POLICY_USER_EDIT_WEB_TEMPLATES ('yes')"
$BIN/v-change-sys-config-value "POLICY_USER_EDIT_WEB_TEMPLATES" "true"
fi
# View user logs
if [[ -z $(check_key_exists 'POLICY_USER_VIEW_LOGS') ]]; then
echo "[ ! ] Adding missing variable to hestia.conf: POLICY_USER_VIEW_LOGS ('yes')"
$BIN/v-change-sys-config-value "POLICY_USER_VIEW_LOGS" "true"
fi
# Allow users to login (read only) when suspended
if [[ -z $(check_key_exists 'POLICY_USER_VIEW_SUSPENDED') ]]; then
echo "[ ! ] Adding missing variable to hestia.conf: POLICY_USER_VIEW_SUSPENDED ('no')"
$BIN/v-change-sys-config-value "POLICY_USER_VIEW_SUSPENDED" "no"
fi
# PHPMyadmin SSO key
if [[ -z $(check_key_exists 'PHPMYADMIN_KEY') ]]; then
echo "[ ! ] Adding missing variable to hestia.conf: PHPMYADMIN_KEY ('')"
$BIN/v-change-sys-config-value "PHPMYADMIN_KEY" ""
fi
# Use SMTP server for hestia internal mail
if [[ -z $(check_key_exists 'USE_SERVER_SMTP') ]]; then
echo "[ ! ] Adding missing variable to hestia.conf: USE_SERVER_SMTP ('')"
$BIN/v-change-sys-config-value "USE_SERVER_SMTP" "false"
fi
if [[ -z $(check_key_exists 'SERVER_SMTP_HOST') ]]; then
echo "[ ! ] Adding missing variable to hestia.conf: SERVER_SMTP_PORT ('')"
$BIN/v-change-sys-config-value "SERVER_SMTP_HOST" ""
fi
if [[ -z $(check_key_exists 'SERVER_SMTP_HOST') ]]; then
echo "[ ! ] Adding missing variable to hestia.conf: SERVER_SMTP_HOST ('')"
$BIN/v-change-sys-config-value "SERVER_SMTP_HOST" ""
fi
if [[ -z $(check_key_exists 'SERVER_SMTP_SECURITY') ]]; then
echo "[ ! ] Adding missing variable to hestia.conf: SERVER_SMTP_SECURITY ('')"
$BIN/v-change-sys-config-value "SERVER_SMTP_SECURITY" ""
fi
if [[ -z $(check_key_exists 'SERVER_SMTP_USER') ]]; then
echo "[ ! ] Adding missing variable to hestia.conf: SERVER_SMTP_USER ('')"
$BIN/v-change-sys-config-value "SERVER_SMTP_USER" ""
fi
if [[ -z $(check_key_exists 'SERVER_SMTP_PASSWD') ]]; then
echo "[ ! ] Adding missing variable to hestia.conf: SERVER_SMTP_PASSWD ('')"
$BIN/v-change-sys-config-value "SERVER_SMTP_PASSWD" ""
fi
if [[ -z $(check_key_exists 'SERVER_SMTP_ADDR') ]]; then
echo "[ ! ] Adding missing variable to hestia.conf: SERVER_SMTP_ADDR ('')"
$BIN/v-change-sys-config-value "SERVER_SMTP_ADDR" ""
fi
if [[ -z $(check_key_exists 'POLICY_CSRF_STRICTNESS') ]]; then
echo "[ ! ] Adding missing variable to hestia.conf: POLICY_CSRF_STRICTNESS ('')"
$BIN/v-change-sys-config-value "POLICY_CSRF_STRICTNESS" "1"
fi
if [[ -z $(check_key_exists 'DNS_CLUSTER_SYSTEM') ]]; then
echo "[ ! ] Adding missing variable to hestia.conf: DNS_CLUSTER_SYSTEM ('hestia')"
$BIN/v-change-sys-config-value "DNS_CLUSTER_SYSTEM" "hestia"
fi
if [[ -z $(check_key_exists 'DISABLE_IP_CHECK') ]]; then
echo "[ ! ] Adding missing variable to hestia.conf: DISABLE_IP_CHECK ('no')"
$BIN/v-change-sys-config-value "DISABLE_IP_CHECK" "no"
fi
if [[ -z $(check_key_exists 'APP_NAME') ]]; then
echo "[ ! ] Adding missing variable to hestia.conf: APP_NAME ('Hestia Control Panel')"
$BIN/v-change-sys-config-value "APP_NAME" "Hestia Control Panel"
fi
if [[ -z $(check_key_exists 'FROM_NAME') ]]; then
# Default is always APP_NAME
echo "[ ! ] Adding missing variable to hestia.conf: FROM_NAME ('')"
$BIN/v-change-sys-config-value "FROM_NAME" ""
fi
if [[ -z $(check_key_exists 'FROM_EMAIL') ]]; then
# Default is always noreply@hostname.com
echo "[ ! ] Adding missing variable to hestia.conf: FROM_EMAIL ('')"
$BIN/v-change-sys-config-value "FROM_EMAIL" ""
fi
if [[ -z $(check_key_exists 'SUBJECT_EMAIL') ]]; then
echo "[ ! ] Adding missing variable to hestia.conf: SUBJECT_EMAIL ('{{subject}}')"
$BIN/v-change-sys-config-value "SUBJECT_EMAIL" "{{subject}}"
fi
if [[ -z $(check_key_exists 'TITLE') ]]; then
echo "[ ! ] Adding missing variable to hestia.conf: TITLE ('{{page}} - {{hostname}} - {{appname}}')"
$BIN/v-change-sys-config-value "TITLE" "{{page}} - {{hostname}} - {{appname}}"
fi
if [[ -z $(check_key_exists 'HIDE_DOCS') ]]; then
echo "[ ! ] Adding missing variable to hestia.conf: HIDE_DOCS ('no')"
$BIN/v-change-sys-config-value "HIDE_DOCS" "no"
fi
if [[ -z $(check_key_exists 'POLICY_SYNC_ERROR_DOCUMENTS') ]]; then
echo "[ ! ] Adding missing variable to hestia.conf: POLICY_SYNC_ERROR_DOCUMENTS ('yes')"
$BIN/v-change-sys-config-value "POLICY_SYNC_ERROR_DOCUMENTS" "yes"
fi
if [[ -z $(check_key_exists 'POLICY_SYNC_SKELETON') ]]; then
echo "[ ! ] Adding missing variable to hestia.conf: POLICY_SYNC_SKELETON ('yes')"
$BIN/v-change-sys-config-value "POLICY_SYNC_SKELETON" "yes"
fi
if [[ -z $(check_key_exists 'POLICY_BACKUP_SUSPENDED_USERS') ]]; then
echo "[ ! ] Adding missing variable to hestia.conf: POLICY_BACKUP_SUSPENDED_USERS ('no')"
$BIN/v-change-sys-config-value "POLICY_BACKUP_SUSPENDED_USERS" "no"
fi
touch $HESTIA/conf/hestia.conf.new
while IFS='= ' read -r lhs rhs; do
if [[ ! $lhs =~ ^\ *# && -n $lhs ]]; then
rhs="${rhs%%^\#*}" # Del in line right comments
rhs="${rhs%%*( )}" # Del trailing spaces
rhs="${rhs%\'*}" # Del opening string quotes
rhs="${rhs#\'*}" # Del closing string quotes
fi
check_ckey=$(grep "^$lhs='" "$HESTIA/conf/hestia.conf.new")
if [ -z "$check_ckey" ]; then
echo "$lhs='$rhs'" >> "$HESTIA/conf/hestia.conf.new"
else
sed -i "s|^$lhs=.*|$lhs='$rhs'|g" "$HESTIA/conf/hestia.conf.new"
fi
done < $HESTIA/conf/hestia.conf
cmp --silent $HESTIA/conf/hestia.conf $HESTIA/conf/hestia.conf.new
if [ $? -ne 0 ]; then
echo "[ ! ] Duplicated keys found repair config"
rm $HESTIA/conf/hestia.conf
cp $HESTIA/conf/hestia.conf.new $HESTIA/conf/hestia.conf
rm $HESTIA/conf/hestia.conf.new
fi
}
# Repair System Cron Jobs
# Add default cron jobs to "admin" user account's cron tab
function syshealth_repair_system_cronjobs() {
$BIN/v-add-cron-job 'admin' '*/2' '*' '*' '*' '*' "sudo $BIN/v-update-sys-queue restart" '' 'no'
$BIN/v-add-cron-job 'admin' '10' '00' '*' '*' '*' "sudo $BIN/v-update-sys-queue daily" '' 'no'
$BIN/v-add-cron-job 'admin' '15' '02' '*' '*' '*' "sudo $BIN/v-update-sys-queue disk" '' 'no'
$BIN/v-add-cron-job 'admin' '10' '00' '*' '*' '*' "sudo $BIN/v-update-sys-queue traffic" '' 'no'
$BIN/v-add-cron-job 'admin' '30' '03' '*' '*' '*' "sudo $BIN/v-update-sys-queue webstats" '' 'no'
$BIN/v-add-cron-job 'admin' '*/5' '*' '*' '*' '*' "sudo $BIN/v-update-sys-queue backup" '' 'no'
$BIN/v-add-cron-job 'admin' '10' '05' '*' '*' '*' "sudo $BIN/v-backup-users" '' 'no'
$BIN/v-add-cron-job 'admin' '20' '00' '*' '*' '*' "sudo $BIN/v-update-user-stats" '' 'no'
$BIN/v-add-cron-job 'admin' '*/5' '*' '*' '*' '*' "sudo $BIN/v-update-sys-rrd" '' 'no'
$BIN/v-restart-cron
}

871
func/upgrade.sh Normal file
View File

@@ -0,0 +1,871 @@
#!/bin/bash
#===========================================================================#
# #
# Hestia Control Panel - Upgrade Function Library #
# #
#===========================================================================#
# Import system health check and repair library
# shellcheck source=/usr/local/hestia/func/syshealth.sh
source $HESTIA/func/syshealth.sh
#####################################################################
####### Functions & Initialization #######
#####################################################################
add_upgrade_message() {
if [ -f "$HESTIA_BACKUP/message.log" ]; then
echo -e $1 >> $HESTIA_BACKUP/message.log
echo -e "\n\n" >> $HESTIA_BACKUP/message.log
else
echo -e $1 > $HESTIA_BACKUP/message.log
fi
}
is_debug_build() {
if [[ "$new_version" =~ "alpha" ]] || [[ "$new_version" =~ "beta" ]]; then
DEBUG_MODE="true"
fi
# Remove pre-release designation tags from display version
DISPLAY_VER=$(echo $new_version | sed "s|~alpha||g" | sed "s|~beta||g")
}
upgrade_health_check() {
echo "============================================================================="
echo "[ ! ] Performing system health check before proceeding with installation... "
# Perform basic health check against hestia.conf to ensure that
# system variables exist and are set to expected defaults.
if [ -z "$VERSION" ]; then
export VERSION="1.1.0"
$BIN/v-change-sys-config-value 'VERSION' "$VERSION"
echo
echo "[ ! ] Unable to detect installed version of Hestia Control Panel."
echo " Setting default version to $VERSION and processing upgrade steps."
echo
fi
syshealth_repair_system_config
echo "[ * ] Health check complete. Starting upgrade from $VERSION to $new_version..."
echo "============================================================================="
}
upgrade_welcome_message() {
echo
echo ' _ _ _ _ ____ ____ '
echo ' | | | | ___ ___| |_(_) __ _ / ___| _ \ '
echo ' | |_| |/ _ \/ __| __| |/ _` | | | |_) | '
echo ' | _ | __/\__ \ |_| | (_| | |___| __/ '
echo ' |_| |_|\___||___/\__|_|\__,_|\____|_| '
echo " "
echo " Hestia Control Panel Software Update "
echo " Version: ${DISPLAY_VER}"
if [[ "$new_version" =~ "beta" ]]; then
echo " BETA RELEASE "
fi
if [[ "$new_version" =~ "alpha" ]]; then
echo " DEVELOPMENT SNAPSHOT "
echo " NOT INTENDED FOR PRODUCTION USE "
echo " USE AT YOUR OWN RISK "
fi
echo
echo "============================================================================="
echo
echo "[ ! ] IMPORTANT INFORMATION: "
echo
echo "Default configuration files and templates may be modified or replaced "
echo "during the upgrade process. You may restore these files from: "
echo ""
echo "Backup directory: $HESTIA_BACKUP/"
echo "Installation log: $LOG"
}
upgrade_welcome_message_log() {
echo "============================================================================="
echo "Hestia Control Panel Software Update Log"
echo "============================================================================="
echo
echo "OPERATING SYSTEM: $OS_TYPE ($OS_VERSION)"
echo "CURRENT VERSION: $VERSION"
echo "NEW VERSION: $new_version"
echo "RELEASE BRANCH: $RELEASE_BRANCH"
if [[ "$new_version" =~ "alpha" ]]; then
echo "BUILD TYPE: Development snapshot"
elif [[ "$new_version" =~ "beta" ]]; then
echo "BUILD TYPE: Beta release"
else
echo "BUILD TYPE: Production release"
fi
echo
echo "INSTALLER OPTIONS:"
echo "============================================================================="
echo "Send email notification on upgrade complete: $UPGRADE_SEND_EMAIL"
echo "Send installed log output to admin email: $UPGRADE_SEND_EMAIL_LOG"
echo
}
upgrade_step_message() {
echo
echo "[ - ] Now applying patches and updates for version v$version_step..."
}
upgrade_complete_message() {
# Echo message to console output
echo "============================================================================="
echo
echo "Upgrade complete! If you encounter any issues or find a bug, "
echo "please take a moment to report it to us on GitHub at the URL below: "
echo "https://github.com/hestiacp/hestiacp/issues "
echo
echo "Read the release notes to learn about new fixes and features: "
echo "https://github.com/hestiacp/hestiacp/blob/release/CHANGELOG.md "
echo
echo "We hope that you enjoy using this version of Hestia Control Panel, "
echo "have a wonderful day! "
echo
echo "Sincerely, "
echo "The Hestia Control Panel development team "
echo
echo "Web: https://www.hestiacp.com/ "
echo "Docs: https://docs.hestiacp.com/ "
echo "Forum: https://forum.hestiacp.com/ "
echo "GitHub: https://github.com/hestiacp/hestiacp/ "
echo
echo "Help support the Hestia Control Panel project by donating via PayPal: "
echo "https://www.hestiacp.com/donate "
echo
echo "Made with love & pride by the open-source community around the world. "
echo
echo "============================================================================="
echo
}
upgrade_complete_message_log() {
echo
echo "============================================================================="
echo "UPGRADE COMPLETE. "
echo "Please report any issues on GitHub: "
echo "https://github.com/hestiacp/hestiacp/issues "
echo "============================================================================="
echo
$BIN/v-log-action "system" "Info" "Updates" "Update installed (Version: $new_version)."
}
upgrade_cleanup_message() {
echo "============================================================================="
echo "Installation tasks complete, performing clean-up... "
echo "============================================================================="
}
upgrade_get_version() {
# Retrieve new version number for Hestia Control Panel from .deb package
new_version=$(dpkg -l | awk '$2=="hestia" { print $3 }')
}
upgrade_set_version() {
# Set new version number in hestia.conf
$BIN/v-change-sys-config-value "VERSION" "$@"
}
upgrade_set_branch() {
# Set branch in hestia.conf
DISPLAY_VER=$(echo "$1" | sed "s|~alpha||g" | sed "s|~beta||g")
if [ "$DISPLAY_VER" = "$1" ]; then
$BIN/v-change-sys-config-value "RELEASE_BRANCH" "release"
fi
}
upgrade_send_notification_to_panel() {
# Add notification to panel if variable is set to true or is not set
if [[ "$new_version" =~ "alpha" ]]; then
# Send notifications for development releases
$BIN/v-add-user-notification admin 'Development snapshot installed' '<p><span class="u-text-bold">Version:</span> '$new_version'<br><span class="u-text-bold">Code Branch:</span> '$RELEASE_BRANCH'</p><p>Please report any bugs by <a href="https://github.com/hestiacp/hestiacp/issues" target="_blank">opening an issue on GitHub</a>, and feel free to share your feedback on our <a href="https://forum.hestiacp.com" target="_blank">discussion forum</a>.</p><p><i class="fas fa-heart icon-red"></i> The Hestia Control Panel development team</p>'
elif [[ "$new_version" =~ "beta" ]]; then
# Send feedback notification for beta releases
$BIN/v-add-user-notification admin 'Thank you for testing Hestia Control Panel '$new_version'.' '<p>Please share your feedback with our development team through our <a href="https://forum.hestiacp.com" target="_blank">discussion forum</a>.</p><p>Found a bug? <a href="https://github.com/hestiacp/hestiacp/issues" target="_blank">Open an issue on GitHub</a>!</p><p><i class="fas fa-heart icon-red"></i> The Hestia Control Panel development team</p>'
else
# Send normal upgrade complete notification for stable releases
$BIN/v-add-user-notification admin 'Upgrade complete' '<p>Hestia Control Panel has been updated to <span class="u-text-bold">v'$new_version'</span>.</p><p><a href="https://github.com/hestiacp/hestiacp/blob/release/CHANGELOG.md" target="_blank">View release notes</a></p><p>Please report any bugs by <a href="https://github.com/hestiacp/hestiacp/issues" target="_blank">opening an issue on GitHub</a>.</p><p class="u-text-bold">Have a wonderful day!</p><p><i class="fas fa-heart icon-red"></i> The Hestia Control Panel development team</p>'
fi
}
upgrade_send_notification_to_email() {
if [ "$UPGRADE_SEND_EMAIL" = "true" ]; then
# Retrieve admin email address, sendmail path, and message temp file path
admin_email=$($BIN/v-list-user admin json | grep "CONTACT" | cut -d'"' -f4)
send_mail="$HESTIA/web/inc/mail-wrapper.php"
message_tmp_file="/tmp/hestia-upgrade-complete.txt"
# Create temporary file
touch $message_tmp_file
# Write message to file
echo "$HOSTNAME has been upgraded from Hestia Control Panel v$VERSION to v${new_version}." >> $message_tmp_file
echo "Installation log: $LOG" >> $message_tmp_file
echo "" >> $message_tmp_file
# Check for additional upgrade notes from update scripts.
if [[ -f "$HESTIA_BACKUP/message.log" ]]; then
echo "===================================================" >> $message_tmp_file
echo "The upgrade script has generated additional notifications, which must be heeded urgently:" >> $message_tmp_file
echo "" >> $message_tmp_file
cat $HESTIA_BACKUP/message.log >> $message_tmp_file
echo "" >> $message_tmp_file
echo "===================================================" >> $message_tmp_file
echo "" >> $message_tmp_file
fi
echo "What's new: https://github.com/hestiacp/hestiacp/blob/$RELEASE_BRANCH/CHANGELOG.md" >> $message_tmp_file
echo >> $message_tmp_file
echo "What to do if you run into issues:" >> $message_tmp_file
echo "- Check our forums for possible solutions: https://forum.hestiacp.com" >> $message_tmp_file
echo "- File an issue report on GitHub: https://github.com/hestiacp/hestiacp/issues" >> $message_tmp_file
echo "" >> $message_tmp_file
echo "Help support the Hestia Control Panel project by donating via PayPal: https://www.hestiacp.com/donate" >> $message_tmp_file
echo "===================================================" >> $message_tmp_file
echo "Have a wonderful day," >> $message_tmp_file
echo "The Hestia Control Panel development team" >> $message_tmp_file
# Read back message from file and pass through to sendmail
cat $message_tmp_file | $send_mail -s "Update Installed - v${new_version}" $admin_email
rm -f $message_tmp_file
fi
}
upgrade_send_log_to_email() {
if [ "$UPGRADE_SEND_EMAIL_LOG" = "true" ]; then
admin_email=$($BIN/v-list-user admin json | grep "CONTACT" | cut -d'"' -f4)
send_mail="$HESTIA/web/inc/mail-wrapper.php"
cat $LOG | $send_mail -s "Update Installation Log - v${new_version}" $admin_email
fi
}
upgrade_config_set_value() {
if [ -f "$HESTIA_BACKUP/upgrade.conf" ]; then
if [ "$2" = "true" ]; then
sed -i "s/$1='false'/$1='true'/g" $HESTIA_BACKUP/upgrade.conf
fi
fi
}
prepare_upgrade_config() {
mkdir -p $HESTIA_BACKUP
touch $HESTIA_BACKUP/upgrade.conf
while IFS='= ' read -r lhs rhs; do
if [[ ! $lhs =~ ^\ *# && -n $lhs ]]; then
rhs="${rhs%%\#*}" # Del in line right comments
rhs="${rhs%%*( )}" # Del trailing spaces
rhs="${rhs%\'*}" # Del opening string quotes
rhs="${rhs#\'*}" # Del closing string quotes
echo "$lhs='$rhs'" >> $HESTIA_BACKUP/upgrade.conf
fi
done < "$HESTIA/install/upgrade/upgrade.conf"
}
upgrade_init_backup() {
# Ensure that backup directories are created
# Hestia Control Panel configuration files
mkdir -p $HESTIA_BACKUP/conf/hestia/
# OpenSSL configuration files
mkdir -p $HESTIA_BACKUP/conf/openssl/
# Hosting Packages
mkdir -p $HESTIA_BACKUP/packages/
# Domain template files
mkdir -p $HESTIA_BACKUP/templates/
# System services (apache2, nginx, bind9, vsftpd, etc).
if [ -n "$WEB_SYSTEM" ]; then
mkdir -p $HESTIA_BACKUP/conf/$WEB_SYSTEM/
fi
if [ -n "$IMAP_SYSTEM" ]; then
mkdir -p $HESTIA_BACKUP/conf/$IMAP_SYSTEM/
fi
if [ -n "$MAIL_SYSTEM" ]; then
mkdir -p $HESTIA_BACKUP/conf/$MAIL_SYSTEM/
fi
if [ -n "$DNS_SYSTEM" ]; then
mkdir -p $HESTIA_BACKUP/conf/$DNS_SYSTEM/
fi
if [ -n "$PROXY_SYSTEM" ]; then
mkdir -p $HESTIA_BACKUP/conf/$PROXY_SYSTEM/
fi
if [ -n "$DB_SYSTEM" ]; then
if [[ "$DB_SYSTEM" =~ "mysql" ]]; then
mkdir -p $HESTIA_BACKUP/conf/mysql/
fi
if [[ "$DB_SYSTEM" =~ "pgsql" ]]; then
mkdir -p $HESTIA_BACKUP/conf/pgsql/
fi
fi
if [ -n "$FTP_SYSTEM" ]; then
mkdir -p $HESTIA_BACKUP/conf/$FTP_SYSTEM/
fi
if [ -n "$FIREWALL_SYSTEM" ]; then
mkdir -p $HESTIA_BACKUP/conf/$FIREWALL_SYSTEM/
fi
if [ -n "$FIREWALL_EXTENSION" ]; then
mkdir -p $HESTIA_BACKUP/conf/$FIREWALL_EXTENSION/
fi
if [ -e "/etc/ssh/sshd_config" ]; then
mkdir -p $HESTIA_BACKUP/conf/ssh/
fi
if [ -d "/etc/roundcube/" ]; then
mkdir -p $HESTIA_BACKUP/conf/roundcube/
fi
if [ -d "/etc/snappymail/" ]; then
mkdir -p $HESTIA_BACKUP/conf/snappymail/
fi
if [ -d "/etc/phpmyadmin/" ]; then
mkdir -p $HESTIA_BACKUP/conf/phpmyadmin/
fi
if [ -d "/etc/phppgadmin/" ]; then
mkdir -p $HESTIA_BACKUP/conf/phppgadmin/
fi
}
upgrade_init_logging() {
# Set log file path
LOG="$HESTIA_BACKUP/hst-upgrade-$(date +%d%m%Y%H%M).log"
# Create log file
touch $LOG
# Add message to system log
$BIN/v-log-action "system" "Info" "Updates" "Started update installation (Latest: $new_version, Previous: $VERSION)."
# Add warnings for pre-release builds
if [[ "$new_version" =~ "alpha" ]]; then
$BIN/v-log-action "system" "Warning" "Updates" "Development build for testing purposes only. Report bugs at https://github.com/hestiacp/hestiacp/issues/."
fi
if [[ "$new_version" =~ "beta" ]]; then
$BIN/v-log-action "system" "Warning" "Updates" "Beta release. Please report bugs at https://github.com/hestiacp/hestiacp/issues/."
fi
}
upgrade_start_backup() {
echo "============================================================================="
echo "[ * ] Backing up existing templates and configuration files..."
if [ "$DEBUG_MODE" = "true" ]; then
echo " - Packages"
fi
cp -fr $HESTIA/data/packages/* $HESTIA_BACKUP/packages/
if [ "$DEBUG_MODE" = "true" ]; then
echo " - Templates"
fi
cp -fr $HESTIA/data/templates/* $HESTIA_BACKUP/templates/
if [ "$DEBUG_MODE" = "true" ]; then
echo " - Configuration files:"
fi
# Hestia Control Panel configuration files
if [ "$DEBUG_MODE" = "true" ]; then
echo " ---- hestia"
fi
cp -fr $HESTIA/conf/* $HESTIA_BACKUP/conf/hestia/
# OpenSSL configuration files
if [ "$DEBUG_MODE" = "true" ]; then
echo " ---- openssl"
fi
cp -f /etc/ssl/*.cnf $HESTIA_BACKUP/conf/openssl/
# System service configuration files (apache2, nginx, bind9, vsftpd, etc).
if [ -n "$WEB_SYSTEM" ]; then
if [ "$DEBUG_MODE" = "true" ]; then
echo " ---- $WEB_SYSTEM"
fi
cp -fr /etc/$WEB_SYSTEM/* $HESTIA_BACKUP/conf/$WEB_SYSTEM/
fi
if [ -n "$PROXY_SYSTEM" ]; then
if [ "$DEBUG_MODE" = "true" ]; then
echo " ---- $PROXY_SYSTEM"
fi
cp -fr /etc/$PROXY_SYSTEM/* $HESTIA_BACKUP/conf/$PROXY_SYSTEM/
fi
if [ -n "$IMAP_SYSTEM" ]; then
if [ "$DEBUG_MODE" = "true" ]; then
echo " ---- $IMAP_SYSTEM"
fi
cp -fr /etc/$IMAP_SYSTEM/* $HESTIA_BACKUP/conf/$IMAP_SYSTEM/
fi
if [ -n "$MAIL_SYSTEM" ]; then
if [ "$DEBUG_MODE" = "true" ]; then
echo " ---- $MAIL_SYSTEM"
fi
cp -fr /etc/$MAIL_SYSTEM/* $HESTIA_BACKUP/conf/$MAIL_SYSTEM/
fi
if [ -n "$DNS_SYSTEM" ]; then
if [ "$DNS_SYSTEM" = "bind9" ]; then
if [ "$DEBUG_MODE" = "true" ]; then
echo " ---- $DNS_SYSTEM"
fi
cp -fr /etc/bind/* $HESTIA_BACKUP/conf/$DNS_SYSTEM/
fi
fi
if [ -n "$DB_SYSTEM" ]; then
if [[ "$DB_SYSTEM" =~ "mysql" ]]; then
if [ "$DEBUG_MODE" = "true" ]; then
echo " ---- mysql"
fi
cp -fr /etc/mysql/* $HESTIA_BACKUP/conf/mysql/
fi
if [[ "$DB_SYSTEM" =~ "pgsql" ]]; then
if [ "$DEBUG_MODE" = "true" ]; then
echo " ---- pgsql"
fi
# config for postgresql is stored in /etc/postgresql/version/main/
cp -fr /etc/postgresql/* $HESTIA_BACKUP/conf/pgsql/
fi
fi
if [ -n "$FTP_SYSTEM" ]; then
if [ "$DEBUG_MODE" = "true" ]; then
echo " ---- $FTP_SYSTEM"
fi
if [ "$FTP_SYSTEM" = "vsftpd" ]; then
cp -f /etc/$FTP_SYSTEM.conf $HESTIA_BACKUP/conf/$FTP_SYSTEM/
fi
if [ "$FTP_SYSTEM" = "proftpd" ]; then
cp -f /etc/proftpd/proftpd.conf $HESTIA_BACKUP/conf/$FTP_SYSTEM/
fi
fi
if [ -n "$FIREWALL_SYSTEM" ]; then
if [ "$DEBUG_MODE" = "true" ]; then
echo " ---- $FIREWALL_SYSTEM"
fi
[ -e "/etc/sysconfig/iptables" ] && cp -f /etc/sysconfig/iptables $HESTIA_BACKUP/conf/$FIREWALL_SYSTEM/
[ -e "/etc/iptables.rules" ] && cp -f /etc/iptables.rules $HESTIA_BACKUP/conf/$FIREWALL_SYSTEM/
fi
if [ -n "$FIREWALL_EXTENSION" ]; then
if [ "$DEBUG_MODE" = "true" ]; then
echo " ---- $FIREWALL_EXTENSION"
fi
cp -f /etc/$FIREWALL_EXTENSION/*.conf $HESTIA_BACKUP/conf/$FIREWALL_EXTENSION/
cp -f /etc/$FIREWALL_EXTENSION/*.local $HESTIA_BACKUP/conf/$FIREWALL_EXTENSION/
fi
if [ -e "/etc/ssh/sshd_config" ]; then
if [ "$DEBUG_MODE" = "true" ]; then
echo " ---- sshd"
fi
cp -fr /etc/ssh/* $HESTIA_BACKUP/conf/ssh/
fi
if [ -d "/etc/roundcube" ]; then
if [ "$DEBUG_MODE" = "true" ]; then
echo " ---- Roundcube"
fi
cp -fr /etc/roundcube/* $HESTIA_BACKUP/conf/roundcube
fi
if [ -d "/etc/snappymail" ]; then
if [ "$DEBUG_MODE" = "true" ]; then
echo " ---- SnappyMail"
fi
cp -fr /etc/snappymail/* $HESTIA_BACKUP/conf/snappymail
fi
if [ -d "/etc/phpmyadmin" ]; then
if [ "$DEBUG_MODE" = "true" ]; then
echo " ---- phpMyAdmin"
fi
cp -fr /etc/phpmyadmin/* $HESTIA_BACKUP/conf/phpmyadmin
fi
if [ -d "/etc/phppgadmin" ]; then
if [ "$DEBUG_MODE" = "true" ]; then
echo " ---- phppgadmin"
fi
cp -fr /etc/phppgadmin/* $HESTIA_BACKUP/conf/phppgadmin
fi
}
upgrade_refresh_config() {
source_conf "/usr/local/hestia/conf/hestia.conf"
}
upgrade_start_routine() {
# Parse version numbers for comparison
function check_version { echo "$@" | awk -F. '{ printf("%d%03d%03d%03d\n", $1,$2,$3,$4); }'; }
# Remove pre-release designation from version number for upgrade scripts
VERSION=$(echo "$VERSION" | sed "s/~\([a-zA-Z0-9].*\)//g")
# Get list of all available version steps and create array
upgrade_steps=$(ls -v $HESTIA/install/upgrade/versions/*.sh)
for script in $upgrade_steps; do
declare -a available_versions
available_versions+=($(echo $script | sed "s|/usr/local/hestia/install/upgrade/versions/||g" | sed "s|.sh||g"))
done
# Define variables for accessing supported versions
# Sort version by -V due to issues with version numbers 1.4.10 and higher
all_versions=$(printf "%s\n" "${available_versions[@]}" | sort -V)
oldest_version=$(printf "%s\n" "$all_versions" | head -n1)
latest_version=$(printf "%s\n" "$all_versions" | sort -V | tail -n1)
# Check for supported versions and process necessary upgrade steps
if [ $(check_version $latest_version) -gt $(check_version $VERSION) ]; then
for version_step in "${available_versions[@]}"; do
if [ $(check_version $VERSION) -lt $(check_version "$version_step") ]; then
upgrade_step_message
source $HESTIA/install/upgrade/versions/$version_step.sh
fi
done
upgrade_set_version "$VERSION"
upgrade_refresh_config
else
echo ""
echo "[ ! ] The latest version of Hestia Control Panel is already installed."
echo " Verifying configuration..."
echo ""
if [ -e "$HESTIA/install/upgrade/versions/$VERSION.sh" ]; then
source $HESTIA/install/upgrade/versions/$VERSION.sh
fi
VERSION="$new_version"
upgrade_set_version "$VERSION"
upgrade_refresh_config
fi
#####################################################################
####### End version-specific upgrade instruction sets #######
#####################################################################
}
upgrade_b2_tool() {
b2cli="/usr/local/bin/b2"
b2lnk="https://github.com/Backblaze/B2_Command_Line_Tool/releases/download/v$b2_v/b2-linux"
if [ -f "$b2cli" ]; then
b2_version=$($b2cli version | grep -o -E '[0-9].[0-9].[0-9]+' | head -1)
if version_ge "$b2_version" "$b2_v"; then
echo "[ * ] Backblaze CLI tool is up to date ($b2_v)..."
else
echo "[ * ] Upgrading Backblaze CLI tool to version $b2_v..."
rm $b2cli
wget -O $b2cli $b2lnk > /dev/null 2>&1
chmod +x $b2cli > /dev/null 2>&1
if [ ! -f "$b2cli" ]; then
echo "Error: Binary download failed, b2 doesn't work as expected."
exit 3
fi
fi
fi
}
upgrade_cloudflare_ip() {
if [ "$WEB_SYSTEM" = "nginx" ] || [ "$PROXY_SYSTEM" = "nginx" ]; then
cf_ips="$(curl -fsLm5 --retry 2 https://api.cloudflare.com/client/v4/ips)"
if [ -n "$cf_ips" ] && [ "$(echo "$cf_ips" | jq -r '.success//""')" = "true" ]; then
cf_inc="/etc/nginx/conf.d/cloudflare.inc"
echo "[ * ] Updating Cloudflare IP Ranges for NGINX..."
echo "# Cloudflare IP Ranges" > $cf_inc
echo "" >> $cf_inc
echo "# IPv4" >> $cf_inc
for ipv4 in $(echo "$cf_ips" | jq -r '.result.ipv4_cidrs[]//""' | sort); do
echo "set_real_ip_from $ipv4;" >> $cf_inc
done
echo "" >> $cf_inc
echo "# IPv6" >> $cf_inc
for ipv6 in $(echo "$cf_ips" | jq -r '.result.ipv6_cidrs[]//""' | sort); do
echo "set_real_ip_from $ipv6;" >> $cf_inc
done
echo "" >> $cf_inc
echo "real_ip_header CF-Connecting-IP;" >> $cf_inc
fi
fi
}
upgrade_phppgadmin() {
if [ -n "$(echo $DB_SYSTEM | grep -w 'pgsql')" ]; then
pga_release=$(cat /usr/share/phppgadmin/libraries/lib.inc.php | grep appVersion | head -n1 | cut -f2 -d\' | cut -f1 -d-)
if version_ge "$pga_release" "pga_v"; then
echo "[ * ] phppgadmin is up to date ($pga_release)..."
else
# Display upgrade information
echo "[ * ] Upgrading phppgadmin to version $pga_v..."
[ -d /usr/share/phppgadmin ] || mkdir -p /usr/share/phppgadmin
# Download latest phpMyAdmin release
wget --retry-connrefused --quiet https://github.com/hestiacp/phppgadmin/releases/download/v$pga_v/phppgadmin-v$pga_v.tar.gz
tar xzf phppgadmin-v$pga_v.tar.gz -C /usr/share/phppgadmin/
if ! version_ge "$pga_release" "7.14.0"; then
cp -f $HESTIA_INSTALL_DIR/pga/config.inc.php /etc/phppgadmin/
fi
if [ ! -f /usr/share/phppgadmin/conf/config.inc.php ]; then
ln -s /etc/phppgadmin/config.inc.php /usr/share/phppgadmin/conf
fi
rm -f phppgadmin-v$pga_v.tar.gz
fi
fi
}
upgrade_phpmyadmin() {
# Check if MariaDB/MySQL is installed on the server before attempting to install or upgrade phpMyAdmin
if [ -n "$(echo $DB_SYSTEM | grep -w 'mysql')" ]; then
pma_version=$(jq -r .version /usr/share/phpmyadmin/package.json)
if version_ge "$pma_version" "$pma_v"; then
echo "[ * ] phpMyAdmin is up to date (${pma_version})..."
# Update permissions
if [ -e /var/lib/phpmyadmin/blowfish_secret.inc.php ]; then
chown root:www-data /var/lib/phpmyadmin/blowfish_secret.inc.php
chmod 0640 /var/lib/phpmyadmin/blowfish_secret.inc.php
fi
else
# Display upgrade information
echo "[ * ] Upgrading phpMyAdmin to version $pma_v..."
[ -d /usr/share/phpmyadmin ] || mkdir -p /usr/share/phpmyadmin
# Download latest phpMyAdmin release
wget --quiet https://files.phpmyadmin.net/phpMyAdmin/$pma_v/phpMyAdmin-$pma_v-all-languages.tar.gz
# Unpack files
tar xzf phpMyAdmin-$pma_v-all-languages.tar.gz
# Delete file to prevent error
rm -rf /usr/share/phpmyadmin/doc/html
# Overwrite old files
cp -rf phpMyAdmin-$pma_v-all-languages/* /usr/share/phpmyadmin
# Set config and log directory
sed -i "s|'configFile' => ROOT_PATH . 'config.inc.php',|'configFile' => '/etc/phpmyadmin/config.inc.php',|g" /usr/share/phpmyadmin/libraries/vendor_config.php
# Create temporary folder and change permissions
if [ ! -d /usr/share/phpmyadmin/tmp ]; then
mkdir /usr/share/phpmyadmin/tmp
chown root:www-data /usr/share/phpmyadmin/tmp
chmod 0770 /usr/share/phpmyadmin/tmp
fi
if [ -e /var/lib/phpmyadmin/blowfish_secret.inc.php ]; then
chown root:www-data /var/lib/phpmyadmin/blowfish_secret.inc.php
chmod 0640 /var/lib/phpmyadmin/blowfish_secret.inc.php
fi
# Clean up source files
rm -fr phpMyAdmin-$pma_v-all-languages
rm -f phpMyAdmin-$pma_v-all-languages.tar.gz
fi
fi
}
upgrade_filemanager() {
FILE_MANAGER_CHECK=$(cat $HESTIA/conf/hestia.conf | grep "FILE_MANAGER='false'")
if [ -z "$FILE_MANAGER_CHECK" ]; then
if [ -f "$HESTIA/web/fm/version" ]; then
fm_version=$(cat $HESTIA/web/fm/version)
else
fm_version="1.0.0"
fi
if ! version_ge "$fm_version" "$fm_v"; then
echo "[ ! ] Upgrading File Manager to version $fm_v..."
# Reinstall the File Manager
$BIN/v-delete-sys-filemanager quiet yes
$BIN/v-add-sys-filemanager quiet
else
echo "[ * ] File Manager is up to date ($fm_v)..."
if [ "$UPGRADE_UPDATE_FILEMANAGER_CONFIG" = "true" ]; then
if [ -e "$HESTIA/web/fm/configuration.php" ]; then
echo "[ ! ] Updating File Manager configuration..."
# Update configuration.php
cp -f $HESTIA_INSTALL_DIR/filemanager/filegator/configuration.php $HESTIA/web/fm/configuration.php
# Set environment variable for interface
$BIN/v-change-sys-config-value 'FILE_MANAGER' 'true'
fi
fi
fi
fi
}
upgrade_roundcube() {
if [ -n "$(echo "$WEBMAIL_SYSTEM" | grep -w 'roundcube')" ]; then
if [ -d "/usr/share/roundcube" ]; then
echo "[ ! ] Roundcube: Updates are currently managed using the apt package manager"
echo " To upgrade to the latest version of Roundcube directly from upstream, from please run the command migrate_roundcube.sh located in: /usr/local/hestia/install/upgrade/manual/"
else
rc_version=$(cat /var/lib/roundcube/index.php | grep -o -E '[0-9].[0-9].[0-9]+' | head -1)
if ! version_ge "$rc_version" "$rc_v"; then
echo "[ ! ] Upgrading Roundcube to version $rc_v..."
$BIN/v-add-sys-roundcube
else
echo "[ * ] Roundcube is up to date ($rc_v)..."
fi
fi
fi
}
upgrade_snappymail() {
if [ -n "$(echo "$WEBMAIL_SYSTEM" | grep -w 'snappymail')" ]; then
sm_version=$(cat /var/lib/snappymail/data/VERSION)
if ! version_ge "$sm_version" "$sm_v"; then
echo "[ ! ] Upgrading SnappyMail to version $sm_v..."
$BIN/v-add-sys-snappymail
else
echo "[ * ] SnappyMail is up to date ($sm_v)..."
fi
fi
}
upgrade_dependencies() {
echo "[ ! ] Update Hestia PHP dependencies..."
$BIN/v-add-sys-dependencies
}
upgrade_rebuild_web_templates() {
if [ "$UPGRADE_UPDATE_WEB_TEMPLATES" = "true" ]; then
echo "[ ! ] Updating default web domain templates..."
$BIN/v-update-web-templates "no" "skip"
fi
}
upgrade_rebuild_mail_templates() {
if [ "$UPGRADE_UPDATE_MAIL_TEMPLATES" = "true" ]; then
echo "[ ! ] Updating default mail domain templates..."
$BIN/v-update-mail-templates "no" "skip"
fi
}
upgrade_rebuild_dns_templates() {
if [ "$UPGRADE_UPDATE_DNS_TEMPLATES" = "true" ]; then
echo "[ ! ] Updating default DNS zone templates..."
$BIN/v-update-dns-templates
fi
}
upgrade_rebuild_users() {
if [ "$UPGRADE_REBUILD_USERS" = "true" ]; then
if [ "$DEBUG_MODE" = "true" ]; then
echo "[ * ] Rebuilding user accounts and domains:..."
else
echo "[ * ] Rebuilding user accounts and domains, this may take a few minutes..."
fi
for user in $($BIN/v-list-sys-users plain); do
export restart="no"
if [ "$DEBUG_MODE" = "true" ]; then
echo " - $user:"
else
echo " - $user..."
fi
if [ -n "$WEB_SYSTEM" ]; then
if [ "$DEBUG_MODE" = "true" ]; then
echo " ---- Web domains..."
$BIN/v-rebuild-web-domains "$user" 'no'
else
$BIN/v-rebuild-web-domains "$user" 'no' > /dev/null 2>&1
fi
fi
if [ -n "$DNS_SYSTEM" ]; then
if [ "$DEBUG_MODE" = "true" ]; then
echo " ---- DNS zones..."
$BIN/v-rebuild-dns-domains "$user" 'no'
else
$BIN/v-rebuild-dns-domains "$user" 'no' > /dev/null 2>&1
fi
fi
if [ -n "$MAIL_SYSTEM" ]; then
if [ "$DEBUG_MODE" = "true" ]; then
echo " ---- Mail domains..."
$BIN/v-rebuild-mail-domains "$user" 'no'
else
$BIN/v-rebuild-mail-domains "$user" 'no' > /dev/null 2>&1
fi
fi
if [ "$DEBUG_MODE" = "true" ]; then
echo " ---- User configuration..."
$BIN/v-rebuild-user "$user" 'no'
else
$BIN/v-rebuild-user "$user" 'no' > /dev/null 2>&1
fi
done
fi
}
update_whitelabel_logo() {
$BIN/v-update-white-label-logo
}
upgrade_replace_default_config() {
syshealth_update_web_config_format
syshealth_update_mail_config_format
syshealth_update_mail_account_config_format
syshealth_update_dns_config_format
syshealth_update_db_config_format
syshealth_update_user_config_format
}
upgrade_restart_services() {
if [ "$UPGRADE_RESTART_SERVICES" = "true" ]; then
echo "[ * ] Restarting services..."
sleep 2
if [ -n "$MAIL_SYSTEM" ]; then
if [ "$DEBUG_MODE" = "true" ]; then
echo " - $MAIL_SYSTEM"
fi
$BIN/v-restart-mail 'yes'
fi
if [ -n "$IMAP_SYSTEM" ]; then
if [ "$DEBUG_MODE" = "true" ]; then
echo " - $IMAP_SYSTEM"
fi
$BIN/v-restart-service "$IMAP_SYSTEM"
fi
if [ -n "$WEB_SYSTEM" ]; then
if [ "$DEBUG_MODE" = "true" ]; then
echo " - $WEB_SYSTEM"
fi
$BIN/v-restart-web 'yes'
fi
if [ -n "$PROXY_SYSTEM" ]; then
if [ "$DEBUG_MODE" = "true" ]; then
echo " - $PROXY_SYSTEM"
fi
$BIN/v-restart-proxy 'yes'
fi
if [ -n "$DNS_SYSTEM" ]; then
if [ "$DEBUG_MODE" = "true" ]; then
echo " - $DNS_SYSTEM"
fi
$BIN/v-restart-dns 'yes'
fi
if [ -n "$WEB_BACKEND" ]; then
versions_list=$($BIN/v-list-sys-php plain)
for v in $versions_list; do
if [ "$DEBUG_MODE" = "true" ]; then
echo " - php$v-fpm"
fi
$BIN/v-restart-service "php$v-fpm" 'yes'
done
fi
if [ -n "$FTP_SYSTEM" ]; then
if [ "$DEBUG_MODE" = "true" ]; then
echo " - $FTP_SYSTEM"
fi
$BIN/v-restart-ftp 'yes'
fi
if [ -n "$FIREWALL_EXTENSION" ]; then
if [ "$DEBUG_MODE" = "true" ]; then
echo " - $FIREWALL_EXTENSION"
fi
$BIN/v-restart-service "$FIREWALL_EXTENSION"
fi
# Restart SSH daemon service
if [ "$DEBUG_MODE" = "true" ]; then
echo " - sshd"
fi
$BIN/v-restart-service ssh
fi
# Always restart the Hestia Control Panel service
if [ "$DEBUG_MODE" = "true" ]; then
echo " - hestia"
fi
$BIN/v-restart-service hestia
}