Initial
This commit is contained in:
81
bin/v-acknowledge-user-notification
Executable file
81
bin/v-acknowledge-user-notification
Executable file
@@ -0,0 +1,81 @@
|
||||
#!/bin/bash
|
||||
# info: update user notification
|
||||
# options: USER NOTIFICATION
|
||||
#
|
||||
# example: v-acknowledge-user-notification
|
||||
#
|
||||
# This function updates user notification.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
id=$2
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '2' "$#" 'USER NOTIFICATION'
|
||||
if [ "$id" = "all" ]; then
|
||||
is_format_valid 'user'
|
||||
else
|
||||
is_format_valid 'user' 'id'
|
||||
fi
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Updating notification
|
||||
if [ "$id" = 'all' ]; then
|
||||
for id in $(v-list-user-notifications admin plain | cut -f1); do
|
||||
update_object_value 'notifications' 'NID' "$id" '$ACK' 'yes' 2> /dev/null
|
||||
done
|
||||
else
|
||||
update_object_value 'notifications' 'NID' "$id" '$ACK' 'yes' 2> /dev/null
|
||||
|
||||
# Checking last notification
|
||||
if [ -e "$USER_DATA/notifications.conf" ]; then
|
||||
if [ -z "$(grep NID= $USER_DATA/notifications.conf)" ]; then
|
||||
notice='no'
|
||||
fi
|
||||
if [ -z "$(grep "ACK='no'" $USER_DATA/notifications.conf)" ]; then
|
||||
notice='no'
|
||||
fi
|
||||
else
|
||||
notice='no'
|
||||
fi
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Updating notification counter
|
||||
if [ "$notice" = 'no' ]; then
|
||||
if [ -z "$(grep NOTIFICATIONS $USER_DATA/user.conf)" ]; then
|
||||
sed -i "s/^TIME/NOTIFICATIONS='no'\nTIME/g" $USER_DATA/user.conf
|
||||
else
|
||||
update_user_value "$user" '$NOTIFICATIONS' "no"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Logging
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
106
bin/v-add-access-key
Executable file
106
bin/v-add-access-key
Executable file
@@ -0,0 +1,106 @@
|
||||
#!/bin/bash
|
||||
# info: generate access key
|
||||
# options: USER [PERMISSIONS] [COMMENT] [FORMAT]
|
||||
#
|
||||
# example: v-add-access-key admin v-purge-nginx-cache,v-list-mail-accounts comment json
|
||||
#
|
||||
# The "PERMISSIONS" argument is optional for the admin user only.
|
||||
# This function creates a key file in $HESTIA/data/access-keys/
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
permissions=$2
|
||||
comment=$3
|
||||
format=${4-shell}
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
keygen() {
|
||||
local LENGTH=${1:-20}
|
||||
local USE_SPECIAL_CHARACTERS="${2:-no}"
|
||||
|
||||
local MATRIX='0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
|
||||
if [[ "$USE_SPECIAL_CHARACTERS" == "yes" ]]; then
|
||||
MATRIX+='_-='
|
||||
fi
|
||||
|
||||
local PASS N
|
||||
while [ ${N:=1} -le $LENGTH ]; do
|
||||
PASS="$PASS${MATRIX:$(($RANDOM % ${#MATRIX})):1}"
|
||||
let N+=1
|
||||
done
|
||||
|
||||
echo "$PASS"
|
||||
}
|
||||
|
||||
access_key_id="$(keygen)"
|
||||
secret_access_key="$(keygen 40 yes)"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
# Remove whitespace and bin path from permissions
|
||||
permissions="$(cleanup_key_permissions "$permissions")"
|
||||
|
||||
time_n_date=$(date +'%T %F')
|
||||
time=$(echo "$time_n_date" | cut -f 1 -d \ )
|
||||
date=$(echo "$time_n_date" | cut -f 2 -d \ )
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '1' "$#" 'USER [PERMISSIONS] [COMMENT] [FORMAT]'
|
||||
is_format_valid 'user' 'comment' 'format'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_key_permissions_format_valid "$permissions" "$user"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
if [ ! -d "$HESTIA/data/access-keys/" ]; then
|
||||
mkdir -p $HESTIA/data/access-keys/
|
||||
chown root:root $HESTIA/data/access-keys/
|
||||
chmod 750 $HESTIA/data/access-keys/
|
||||
fi
|
||||
|
||||
if [[ -e "$HESTIA/data/access-keys/${access_key_id}" ]]; then
|
||||
while [[ -e "$HESTIA/data/access-keys/${access_key_id}" ]]; do
|
||||
access_key_id=$(keygen)
|
||||
done
|
||||
fi
|
||||
|
||||
echo "SECRET_ACCESS_KEY='$secret_access_key'" > "$HESTIA/data/access-keys/${access_key_id}"
|
||||
echo "USER='$user'" >> "$HESTIA/data/access-keys/${access_key_id}"
|
||||
echo "PERMISSIONS='$permissions'" >> "$HESTIA/data/access-keys/${access_key_id}"
|
||||
echo "COMMENT='$comment'" >> "$HESTIA/data/access-keys/${access_key_id}"
|
||||
echo "TIME='$time'" >> "$HESTIA/data/access-keys/${access_key_id}"
|
||||
echo "DATE='$date'" >> "$HESTIA/data/access-keys/${access_key_id}"
|
||||
# TODO Index reserved for future implementation
|
||||
echo "EXPIRES_IN=''" >> "$HESTIA/data/access-keys/${access_key_id}"
|
||||
echo "IP=''" >> "$HESTIA/data/access-keys/${access_key_id}"
|
||||
|
||||
chmod 640 "$HESTIA/data/access-keys/${access_key_id}"
|
||||
|
||||
$BIN/v-list-access-key "$access_key_id" "$format"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Logging
|
||||
log_history "Access key $access_key_id generated" "Warning" "$user" "API"
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
344
bin/v-add-backup-host
Executable file
344
bin/v-add-backup-host
Executable file
@@ -0,0 +1,344 @@
|
||||
#!/bin/bash
|
||||
# info: add backup host
|
||||
# options: TYPE HOST USERNAME PASSWORD [PATH] [PORT]
|
||||
#
|
||||
# example: v-add-backup-host sftp backup.acme.com admin p4$$w@Rd
|
||||
# v-add-backup-host b2 bucketName keyID applicationKey
|
||||
#
|
||||
# Add a new remote backup location. Currently SFTP, FTP and Backblaze are supported
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
type=$1
|
||||
host=$2
|
||||
user=$3
|
||||
raw_password=$4
|
||||
HIDE=4
|
||||
password=$(perl -e 'print quotemeta shift(@ARGV)' "${raw_password}")
|
||||
path=${5-/backup}
|
||||
port=$6
|
||||
|
||||
# CPU Architecture
|
||||
arch=$(arch)
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
# Fetch current verison B2 CLI tool
|
||||
source_conf "$HESTIA/install/upgrade/upgrade.conf"
|
||||
|
||||
# Paths
|
||||
b2cli="/usr/local/bin/b2"
|
||||
b2lnk="https://github.com/Backblaze/B2_Command_Line_Tool/releases/download/v$b2_v/b2-linux"
|
||||
|
||||
# Defining ftp command function
|
||||
ftpc() {
|
||||
ftp -p -n $host $port << EOF
|
||||
quote USER $user
|
||||
quote PASS $password
|
||||
binary
|
||||
$1
|
||||
$2
|
||||
$3
|
||||
quit
|
||||
EOF
|
||||
}
|
||||
|
||||
# Defining sftp command function
|
||||
sftpc() {
|
||||
if [ "$privatekey" != "yes" ]; then
|
||||
expect -f "-" "$@" << EOF
|
||||
set count 0
|
||||
spawn /usr/bin/sftp -o StrictHostKeyChecking=no -o Port=$port $user@$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
|
||||
}
|
||||
|
||||
"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 count 0
|
||||
spawn /usr/bin/sftp -o StrictHostKeyChecking=no -o Port=$port -i $raw_password $user@$host
|
||||
expect {
|
||||
|
||||
-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
|
||||
}
|
||||
|
||||
"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
|
||||
}
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
if [ "$type" != 'local' ]; then
|
||||
check_args '2' "$#" "TYPE HOST USERNAME PASSWORD [PATH] [PORT]"
|
||||
is_format_valid 'host' 'path' 'port'
|
||||
is_type_valid 'sftp,ftp,b2,rclone' "$type"
|
||||
is_username_format_valid "$user" "username"
|
||||
privatekey="no"
|
||||
if [ -f "$raw_password" ]; then
|
||||
if [[ $(cat "$raw_password" | grep "OPENSSH PRIVATE") ]]; then
|
||||
privatekey="yes"
|
||||
password="$raw_password"
|
||||
else
|
||||
is_password_valid
|
||||
fi
|
||||
else
|
||||
is_password_valid
|
||||
fi
|
||||
format_no_quotes "$password" "password"
|
||||
|
||||
if [ "$type" = 'sftp' ]; then
|
||||
which expect > /dev/null 2>&1
|
||||
check_result $? "expect command not found" "$E_NOTEXIST"
|
||||
fi
|
||||
if [ "$type" != 'b2' ] && [ "$type" != 'rclone' ]; then
|
||||
if ! (is_ip_format_valid "$host" > /dev/null); then
|
||||
host "$host" > /dev/null 2>&1
|
||||
check_result $? "host connection failed" "$E_CONNECT"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Checking network connection
|
||||
if [ "$type" = 'ftp' ]; then
|
||||
if [ -z $port ]; then
|
||||
port=21
|
||||
fi
|
||||
fconn=$(ftpc 2>&1)
|
||||
ferror=$(echo $fconn \
|
||||
| grep -i -e failed -e error -e "can't" -e "not conn" -e "incorrect")
|
||||
if [ -n "$ferror" ]; then
|
||||
echo "Error: can't login to ftp $user@$host"
|
||||
log_event "$E_CONNECT" "$ARGUMENTS"
|
||||
exit "$E_CONNECT"
|
||||
fi
|
||||
|
||||
# Checking write permissions
|
||||
if [ -z $path ]; then
|
||||
ftmpdir="vst.bK76A9SUkt"
|
||||
else
|
||||
ftpc "mkdir $path" > /dev/null 2>&1
|
||||
ftmpdir="$path/vst.bK76A9SUkt"
|
||||
fi
|
||||
ftp_result=$(ftpc "mkdir $ftmpdir" "rm $ftmpdir" | grep -v Trying)
|
||||
if [ -n "$ftp_result" ]; then
|
||||
echo "$ftp_result"
|
||||
rm -rf $tmpdir
|
||||
echo "Error: can't create $ftmpdir folder on the ftp"
|
||||
log_event "$E_FTP" "$ARGUMENTS"
|
||||
exit "$E_FTP"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$type" = 'sftp' ]; then
|
||||
if [ -z $port ]; then
|
||||
port=22
|
||||
fi
|
||||
if [ -z $path ]; then
|
||||
sftmpdir="vst.bK76A9SUkt"
|
||||
sftpc "mkdir $sftmpdir" "rmdir $sftmpdir" > /dev/null 2>&1
|
||||
else
|
||||
if sftpc "mkdir $path" > /dev/null 2>&1; then
|
||||
sftmpdir="$path/vst.bK76A9SUkt"
|
||||
sftpc "mkdir $sftmpdir" "rmdir $sftmpdir" > /dev/null 2>&1
|
||||
else
|
||||
sftmpdir="$path/vst.bK76A9SUkt"
|
||||
sftpc "mkdir $sftmpdir" "rmdir $sftmpdir" > /dev/null 2>&1
|
||||
fi
|
||||
fi
|
||||
rc=$?
|
||||
if [[ "$rc" != 0 ]]; then
|
||||
case $rc in
|
||||
$E_CONNECT) echo "Error: can't login to sftp $user@$host" ;;
|
||||
$E_FTP) echo "Error: can't create temp folder on the sftp host" ;;
|
||||
esac
|
||||
log_event "$rc" "$ARGUMENTS"
|
||||
exit "$rc"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$type" = 'b2' ]; then
|
||||
# Download b2 binary
|
||||
if [ ! -f "$b2cli" ]; then
|
||||
if [ "$arch" = 'aarch64' ] || [ "$arch" = 'arm64' ]; then
|
||||
echo "Error: B2 binary for arm64 must be downloaded manually."
|
||||
exit 3
|
||||
else
|
||||
wget -O $b2cli $b2lnk > /dev/null 2>&1
|
||||
chmod +x $b2cli > /dev/null 2>&1
|
||||
fi
|
||||
if [ ! -f "$b2cli" ]; then
|
||||
echo "Error: Binary download failed, b2 doesn't work as expected."
|
||||
exit 3
|
||||
fi
|
||||
fi
|
||||
|
||||
# Validate b2 binary
|
||||
b2version="$(b2 version)"
|
||||
if [[ ! "$b2version" =~ "b2 command line tool" ]]; then
|
||||
echo "Error: Binary download failed, b2 doesn't work as expected."
|
||||
exit 3
|
||||
fi
|
||||
|
||||
b2 clear-account > /dev/null 2>&1
|
||||
b2 authorize-account "$user" "$raw_password" > /dev/null 2>&1
|
||||
b2 ls --long "$host" "$user" > /dev/null 2>&1
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
check_result "$E_CONNECT" "b2 failed to verify connection"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$type" = 'rclone' ]; then
|
||||
curl -s https://rclone.org/install.sh | bash /dev/null > /dev/null 2>&1
|
||||
# Verify account exists
|
||||
if [ ! -z "$(cat /root/.config/rclone/rclone.conf | grep "\[$host\]")" ]; then
|
||||
echo "test" > /tmp/hestia-backup.txt
|
||||
# Try to upload a single file
|
||||
if [ -z "$path" ]; then
|
||||
rclone copy /tmp/hestia-backup.txt $host:/hestia-backup.txt
|
||||
rclone delete $host:/hestia-backup.txt
|
||||
else
|
||||
rclone copy /tmp/hestia-backup.txt $host:$path/hestia-backup.txt
|
||||
rclone delete $host:$path/hestia-backup.txt
|
||||
fi
|
||||
else
|
||||
check_result "$E_CONNECT" "Rclone config does not exist"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Adding backup host
|
||||
if [ $type == 'ftp' ] || [ $type = 'sftp' ]; then
|
||||
new_timestamp
|
||||
str="HOST='$host'\nUSERNAME='$user'\nPASSWORD='$password'\nPRIVATEKEY='$privatekey'"
|
||||
str="$str\nBPATH='$path'\nPORT='$port'\nTIME='$time'\nDATE='$date'"
|
||||
echo -e "$str" > $HESTIA/conf/$type.backup.conf
|
||||
chmod 660 $HESTIA/conf/$type.backup.conf
|
||||
elif [ $type == 'b2' ]; then
|
||||
new_timestamp
|
||||
str="BUCKET='$host'\nB2_KEYID='$user'\nB2_KEY='$raw_password'"
|
||||
str="$str\nTIME='$time'\nDATE='$date'"
|
||||
echo -e "$str" > $HESTIA/conf/$type.backup.conf
|
||||
chmod 660 $HESTIA/conf/$type.backup.conf
|
||||
elif [ $type == "rclone" ]; then
|
||||
new_timestamp
|
||||
str="HOST='$host'\nBPATH='$path'"
|
||||
str="$str\nTIME='$time'\nDATE='$date'"
|
||||
echo -e "$str" > $HESTIA/conf/$type.backup.conf
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Update hestia.conf
|
||||
if [ -z "$(grep BACKUP_SYSTEM $HESTIA/conf/hestia.conf)" ]; then
|
||||
echo "BACKUP_SYSTEM='$type'" >> $HESTIA/conf/hestia.conf
|
||||
else
|
||||
bckp=$(echo "$BACKUP_SYSTEM,$type" \
|
||||
| sed "s/,/\n/g" \
|
||||
| sort -r -u \
|
||||
| sed "/^$/d" \
|
||||
| sed ':a;N;$!ba;s/\n/,/g')
|
||||
sed -i "s/BACKUP_SYSTEM=.*/BACKUP_SYSTEM='$bckp'/g" $HESTIA/conf/hestia.conf
|
||||
fi
|
||||
|
||||
# Logging
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
99
bin/v-add-cron-hestia-autoupdate
Executable file
99
bin/v-add-cron-hestia-autoupdate
Executable file
@@ -0,0 +1,99 @@
|
||||
#!/bin/bash
|
||||
# info: add cron job for hestia automatic updates
|
||||
# options: MODE
|
||||
#
|
||||
# This function adds a cronjob for hestia automatic updates
|
||||
# that can be downloaded from apt or git.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=admin
|
||||
mode=$1
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
is_system_enabled "$CRON_SYSTEM" 'CRON_SYSTEM'
|
||||
is_package_full 'CRON_JOBS'
|
||||
get_next_cronjob
|
||||
check_cron_apt=$(grep 'v-update-sys-hestia-all' $USER_DATA/cron.conf)
|
||||
check_cron_git=$(grep 'v-update-sys-hestia-git' $USER_DATA/cron.conf)
|
||||
if [ -n "$check_cron_apt" ] || [ -n "$check_cron_git" ]; then
|
||||
exit
|
||||
fi
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Generating timestamp
|
||||
time_n_date=$(date +'%T %F')
|
||||
time=$(echo "$time_n_date" | cut -f 1 -d \ )
|
||||
date=$(echo "$time_n_date" | cut -f 2 -d \ )
|
||||
|
||||
# Define time somewhere at night
|
||||
if [ -z "$mode" ] || [ "$mode" = "apt" ]; then
|
||||
min=$(generate_password '012345' '2')
|
||||
hour=$(generate_password '1234567' '1')
|
||||
day='*'
|
||||
month='*'
|
||||
wday='*'
|
||||
command="sudo $BIN/v-update-sys-hestia-all"
|
||||
fi
|
||||
|
||||
if [ "$mode" = "git" ]; then
|
||||
min='0'
|
||||
hour='0'
|
||||
day='*'
|
||||
month='*'
|
||||
wday='*'
|
||||
command="sudo $BIN/v-update-sys-hestia-git"
|
||||
fi
|
||||
|
||||
# Concatenating cron string
|
||||
str="JOB='$job' MIN='$min' HOUR='$hour' DAY='$day' MONTH='$month' WDAY='$wday'"
|
||||
str="$str CMD='$command' SUSPENDED='no' TIME='$time' DATE='$date'"
|
||||
|
||||
# Adding to crontab
|
||||
echo "$str" >> $HESTIA/data/users/$user/cron.conf
|
||||
|
||||
# Changing permissions
|
||||
chmod 660 $HESTIA/data/users/$user/cron.conf
|
||||
|
||||
# Sort jobs by id number
|
||||
sort_cron_jobs
|
||||
|
||||
# Sync cronjobs with system cron
|
||||
sync_cron_jobs
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Increasing cron value
|
||||
increase_user_value "$user" '$U_CRON_JOBS'
|
||||
|
||||
# Restarting cron
|
||||
$BIN/v-restart-cron
|
||||
check_result $? "Cron restart failed" > /dev/null
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "system" "Info" "Updates" "Automatic updates enabled."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
93
bin/v-add-cron-job
Executable file
93
bin/v-add-cron-job
Executable file
@@ -0,0 +1,93 @@
|
||||
#!/bin/bash
|
||||
# info: add cron job
|
||||
# options: USER MIN HOUR DAY MONTH WDAY COMMAND [JOB] [RESTART]
|
||||
#
|
||||
# example: v-add-cron-job admin * * * * * sudo /usr/local/hestia/bin/v-backup-users
|
||||
#
|
||||
# This function adds a job to cron daemon. When executing commands, any output
|
||||
# is mailed to user's email if parameter REPORTS is set to 'yes'.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
min=$2
|
||||
hour=$3
|
||||
day=$4
|
||||
month=$5
|
||||
wday=$6
|
||||
command=$(echo $7 | sed "s/'/%quote%/g")
|
||||
job=$8
|
||||
restart=$9
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
HIDE=7
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '7' "$#" 'USER MIN HOUR DAY MONTH WDAY COMMAND [JOB] [RESTART]'
|
||||
is_format_valid 'user' 'min' 'hour' 'day' 'month' 'wday' 'command'
|
||||
is_system_enabled "$CRON_SYSTEM" 'CRON_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_package_full 'CRON_JOBS'
|
||||
get_next_cronjob
|
||||
is_format_valid 'job'
|
||||
is_format_valid 'restart'
|
||||
is_object_new 'cron' 'JOB' "$job"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Generating timestamp
|
||||
time_n_date=$(date +'%T %F')
|
||||
time=$(echo "$time_n_date" | cut -f 1 -d \ )
|
||||
date=$(echo "$time_n_date" | cut -f 2 -d \ )
|
||||
|
||||
# Concatenating cron string
|
||||
str="JOB='$job' MIN='$min' HOUR='$hour' DAY='$day' MONTH='$month' WDAY='$wday'"
|
||||
str="$str CMD='$command' SUSPENDED='no' TIME='$time' DATE='$date'"
|
||||
|
||||
# Adding to crontab
|
||||
echo "$str" >> $HESTIA/data/users/$user/cron.conf
|
||||
|
||||
# Changing permissions
|
||||
chmod 660 $HESTIA/data/users/$user/cron.conf
|
||||
|
||||
# Sort jobs by id number
|
||||
sort_cron_jobs
|
||||
|
||||
# Sync cronjobs with system crond
|
||||
sync_cron_jobs
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Increasing cron value
|
||||
increase_user_value $user '$U_CRON_JOBS'
|
||||
|
||||
# Restarting cron
|
||||
$BIN/v-restart-cron "$restart"
|
||||
check_result $? "Cron restart failed" > /dev/null
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "Cron Jobs" "Cron job added (ID: $job, Command: $command)"
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
46
bin/v-add-cron-letsencrypt-job
Executable file
46
bin/v-add-cron-letsencrypt-job
Executable file
@@ -0,0 +1,46 @@
|
||||
#!/bin/bash
|
||||
# info: add cron job for Let's Encrypt certificates
|
||||
# options: NONE
|
||||
#
|
||||
# This function adds a new cron job for Let's Encrypt.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
is_system_enabled "$CRON_SYSTEM" 'CRON_SYSTEM'
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Add cron job
|
||||
cmd="sudo $BIN/v-update-sys-queue letsencrypt"
|
||||
check_cron=$(grep "$cmd" $HESTIA/data/users/admin/cron.conf 2> /dev/null)
|
||||
if [ -z "$check_cron" ] && [ -n "$CRON_SYSTEM" ]; then
|
||||
$BIN/v-add-cron-job admin '*/5' '*' '*' '*' '*' "$cmd"
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Logging
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
60
bin/v-add-cron-reports
Executable file
60
bin/v-add-cron-reports
Executable file
@@ -0,0 +1,60 @@
|
||||
#!/bin/bash
|
||||
# info: add cron reports
|
||||
# options: USER
|
||||
#
|
||||
# example: v-add-cron-reports admin
|
||||
#
|
||||
# This function for enabling reports on cron tasks and administrative
|
||||
# notifications.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '1' "$#" 'USER'
|
||||
is_format_valid 'user'
|
||||
is_system_enabled "$CRON_SYSTEM" 'CRON_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Changing user report value
|
||||
update_user_value "$user" '$CRON_REPORTS' 'yes'
|
||||
|
||||
# Sync system cron with user
|
||||
sync_cron_jobs
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Restart cron
|
||||
$BIN/v-restart-cron
|
||||
check_result $? "Cron restart failed" > /dev/null
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "Cron Jobs" "Cron job notifications and reporting enabled."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
46
bin/v-add-cron-restart-job
Executable file
46
bin/v-add-cron-restart-job
Executable file
@@ -0,0 +1,46 @@
|
||||
#!/bin/bash
|
||||
# info: add cron reports
|
||||
# options: NONE
|
||||
#
|
||||
# This function for enabling restart cron tasks
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
is_system_enabled "$CRON_SYSTEM" 'CRON_SYSTEM'
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Add cron job
|
||||
cmd="sudo $BIN/v-update-sys-queue restart"
|
||||
check_cron=$(grep "$cmd" $HESTIA/data/users/admin/cron.conf 2> /dev/null)
|
||||
if [ -z "$check_cron" ] && [ -n "$CRON_SYSTEM" ]; then
|
||||
$BIN/v-add-cron-job admin '*' '*' '*' '*' '*' "$cmd"
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Logging
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
113
bin/v-add-database
Executable file
113
bin/v-add-database
Executable file
@@ -0,0 +1,113 @@
|
||||
#!/bin/bash
|
||||
# info: add database
|
||||
# options: USER DATABASE DBUSER DBPASS [TYPE] [HOST] [CHARSET]
|
||||
#
|
||||
# example: v-add-database admin wordpress_db matt qwerty123
|
||||
#
|
||||
# This function creates the database concatenating username and user_db.
|
||||
# Supported types of databases you can get using v-list-sys-config script.
|
||||
# If the host isn't stated and there are few hosts configured on the server,
|
||||
# then the host will be defined by one of three algorithms. "First" will choose
|
||||
# the first host in the list. "Random" will chose the host by a chance.
|
||||
# "Weight" will distribute new database through hosts evenly. Algorithm and
|
||||
# types of supported databases is designated in the main configuration file.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
database="$user"_"$2"
|
||||
dbuser="$user"_"$3"
|
||||
password=$4
|
||||
HIDE=4
|
||||
type=${5-mysql}
|
||||
host=$6
|
||||
charset=${7-UTF8MB4}
|
||||
charset=$(echo "$charset" | tr '[:lower:]' '[:upper:]')
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/db.sh
|
||||
source $HESTIA/func/db.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
if [ "$type" = "pgsql" ]; then
|
||||
database=$(echo "$user"_"$2" | tr '[:upper:]' '[:lower:]')
|
||||
dbuser=$(echo "$user"_"$3" | tr '[:upper:]' '[:lower:]')
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '4' "$#" 'USER DATABASE DBUSER DBPASS [TYPE] [HOST] [CHARSET]'
|
||||
is_format_valid 'user' 'database' 'dbuser' 'charset'
|
||||
is_system_enabled "$DB_SYSTEM" 'DB_SYSTEM'
|
||||
is_type_valid "$DB_SYSTEM" "$type"
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_new 'db' 'DB' "$database"
|
||||
is_object_new 'db' 'DBUSER' "$dbuser"
|
||||
get_next_dbhost
|
||||
is_object_valid "../../../conf/$type" 'HOST' "$host"
|
||||
is_object_unsuspended "../../../conf/$type" 'DBHOST' "$host"
|
||||
#is_charset_valid
|
||||
is_package_full 'DATABASES'
|
||||
is_password_valid
|
||||
|
||||
if [ "$type" = "pgsql" ]; then
|
||||
exclude="-"
|
||||
if [[ "$dbuser" =~ $exclude ]]; then
|
||||
check_result "$E_INVALID" "invalid database user format"
|
||||
fi
|
||||
if [[ "$database" =~ $exclude ]]; then
|
||||
check_result "$E_INVALID" "invalid database format"
|
||||
fi
|
||||
fi
|
||||
|
||||
dbpass="$password"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Switching on db type
|
||||
case $type in
|
||||
mysql) add_mysql_database ;;
|
||||
pgsql) add_pgsql_database ;;
|
||||
esac
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Generating timestamp
|
||||
time_n_date=$(date +'%T %F')
|
||||
time=$(echo "$time_n_date" | cut -f 1 -d \ )
|
||||
date=$(echo "$time_n_date" | cut -f 2 -d \ )
|
||||
|
||||
# Adding db to db conf
|
||||
str="DB='$database' DBUSER='$dbuser' MD5='$md5' HOST='$host' TYPE='$type'"
|
||||
str="$str CHARSET='$charset' U_DISK='0' SUSPENDED='no' TIME='$time'"
|
||||
str="$str DATE='$date'"
|
||||
echo "$str" >> $USER_DATA/db.conf
|
||||
chmod 660 $USER_DATA/db.conf
|
||||
|
||||
# Increasing counters
|
||||
increase_dbhost_values
|
||||
increase_user_value "$user" '$U_DATABASES'
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "Databases" "Added new database $database ($type)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
169
bin/v-add-database-host
Executable file
169
bin/v-add-database-host
Executable file
@@ -0,0 +1,169 @@
|
||||
#!/bin/bash
|
||||
# info: add new database server
|
||||
# options: TYPE HOST DBUSER DBPASS [MAX_DB] [CHARSETS] [TEMPLATE] [PORT]
|
||||
#
|
||||
# example: v-add-database-host mysql localhost alice p@$$wOrd
|
||||
#
|
||||
# This function add new database server to the server pool. It supports local
|
||||
# and remote database servers, which is useful for clusters. By adding a host
|
||||
# you can set limit for number of databases on a host. Template parameter is
|
||||
# used only for PostgreSQL and has an default value "template1". You can read
|
||||
# more about templates in official PostgreSQL documentation.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
type=$1
|
||||
host=$2
|
||||
dbuser=$3
|
||||
password=$4
|
||||
HIDE=4
|
||||
max_db=${5-500}
|
||||
charsets=${6}
|
||||
template=${7}
|
||||
port=${8}
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/db.sh
|
||||
source $HESTIA/func/db.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
is_mysql_host_alive() {
|
||||
mycnf=$(mktemp)
|
||||
echo "[client]" > $mycnf
|
||||
echo "host='$host'" >> $mycnf
|
||||
echo "user='$dbuser'" >> $mycnf
|
||||
echo "password='$password'" >> $mycnf
|
||||
echo "port='$port'" >> $mycnf
|
||||
|
||||
chmod 600 $mycnf
|
||||
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 [ "$?" -ne '0' ]; then
|
||||
echo "Error: MySQL connection to $host failed"
|
||||
rm $mycnf
|
||||
log_event "$E_CONNECT" "$ARGUMENTS"
|
||||
exit "$E_CONNECT"
|
||||
fi
|
||||
|
||||
if [ -f '/usr/bin/mariadb' ]; then
|
||||
grants=$(mariadb --defaults-file=$mycnf -e 'SHOW GRANTS FOR CURRENT_USER();')
|
||||
else
|
||||
grants=$(mysql --defaults-file=$mycnf -e 'SHOW GRANTS FOR CURRENT_USER();')
|
||||
fi
|
||||
|
||||
if [ "$?" -ne '0' ]; then
|
||||
echo "Error: MySQL connection to $host failed"
|
||||
rm $mycnf
|
||||
log_event "$E_CONNECT" "$ARGUMENTS"
|
||||
exit "$E_CONNECT"
|
||||
fi
|
||||
|
||||
# Check allow to grant user
|
||||
check_grants=$(echo $grants | grep "WITH GRANT OPTION")
|
||||
if [ -z "$check_grants" ]; then
|
||||
echo "Error: MySQL connection to $host failed. Unable to grant other users"
|
||||
rm $mycnf
|
||||
log_event "$E_CONNECT" "$ARGUMENTS"
|
||||
exit "$E_CONNECT"
|
||||
fi
|
||||
rm $mycnf
|
||||
}
|
||||
|
||||
is_pgsql_host_alive() {
|
||||
export PGPASSWORD="$dbpass"
|
||||
psql -h $host -U $dbuser -p $port -c "SELECT VERSION()" > /dev/null 2>&1
|
||||
if [ "$?" -ne '0' ]; then
|
||||
echo "Error: PostgreSQL connection to $host failed"
|
||||
log_event "$E_CONNECT" "$ARGUMENTS"
|
||||
exit "$E_CONNECT"
|
||||
fi
|
||||
}
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
args_usage='TYPE HOST DBUSER DBPASS [MAX_DB] [CHARSETS] [TPL] [PORT]'
|
||||
check_args '4' "$#" "$args_usage"
|
||||
|
||||
if [ -z $charsets ]; then charsets="UTF8,LATIN1,WIN1250,WIN1251,WIN1252,WIN1256,WIN1258,KOI8"; fi
|
||||
if [ -z $template ]; then template="template1"; fi
|
||||
|
||||
database_set_default_ports
|
||||
|
||||
is_format_valid 'host' 'dbuser' 'max_db' 'charsets' 'template' 'port'
|
||||
is_system_enabled "$DB_SYSTEM" 'DB_SYSTEM'
|
||||
is_type_valid "$DB_SYSTEM" "$type"
|
||||
is_dbhost_new
|
||||
is_password_valid
|
||||
dbpass="$password"
|
||||
|
||||
case $type in
|
||||
mysql) is_mysql_host_alive ;;
|
||||
pgsql) is_pgsql_host_alive ;;
|
||||
esac
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Generating timestamp
|
||||
time_n_date=$(date +'%T %F')
|
||||
time=$(echo "$time_n_date" | cut -f 1 -d \ )
|
||||
date=$(echo "$time_n_date" | cut -f 2 -d \ )
|
||||
|
||||
# Concatenating db host string
|
||||
case $type in
|
||||
mysql)
|
||||
str="HOST='$host' USER='$dbuser' PASSWORD='$dbpass'"
|
||||
str="$str CHARSETS='$charsets' MAX_DB='$max_db' U_SYS_USERS=''"
|
||||
str="$str U_DB_BASES='0' SUSPENDED='no' TIME='$time' DATE='$date' PORT='$port'"
|
||||
;;
|
||||
pgsql)
|
||||
str="HOST='$host' USER='$dbuser' PASSWORD='$dbpass'"
|
||||
str="$str CHARSETS='$charsets' TPL='$template' MAX_DB='$max_db'"
|
||||
str="$str U_SYS_USERS='' U_DB_BASES='0' SUSPENDED='no'"
|
||||
str="$str TIME='$time' DATE='$date' PORT='$port'"
|
||||
;;
|
||||
esac
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Adding host to conf
|
||||
echo "$str" >> $HESTIA/conf/$type.conf
|
||||
chmod 660 $HESTIA/conf/$type.conf
|
||||
|
||||
# Updating hestia.conf
|
||||
if [ -z "$(grep DB_SYSTEM $HESTIA/conf/hestia.conf)" ]; then
|
||||
echo "DB_SYSTEM='$type'" >> $HESTIA/conf/hestia.conf
|
||||
else
|
||||
db=$(echo "$DB_SYSTEM,$type" \
|
||||
| sed "s/,/\n/g" \
|
||||
| sort -r -u \
|
||||
| sed "/^$/d" \
|
||||
| sed ':a;N;$!ba;s/\n/,/g')
|
||||
sed -i "s/DB_SYSTEM=.*/DB_SYSTEM='$db'/g" $HESTIA/conf/hestia.conf
|
||||
fi
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "system" "Info" "Database" "Added external $type database server ($host) to the system."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
87
bin/v-add-database-temp-user
Executable file
87
bin/v-add-database-temp-user
Executable file
@@ -0,0 +1,87 @@
|
||||
#!/bin/bash
|
||||
# info: add temp database user
|
||||
# options: USER DATABASE [TYPE] [HOST] [TTL]
|
||||
#
|
||||
# example: v-add-database-temp-user wordress wordpress_db mysql
|
||||
#
|
||||
# This function creates an temporary database user mysql_sso_db_XXXXXXXX and a random password
|
||||
# The user has an limited validity and only granted access to the specific database
|
||||
# Returns json to be read SSO Script
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
database="$2"
|
||||
type=${3-mysql}
|
||||
host=$4
|
||||
ttl=$5
|
||||
|
||||
if [ "$ttl" == '' ]; then
|
||||
ttl=60
|
||||
fi
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/db.sh
|
||||
source $HESTIA/func/db.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '2' "$#" 'USER DATABASE [TYPE] [HOST] [TTL]'
|
||||
is_format_valid 'user' 'database' 'ttl'
|
||||
is_type_valid "$DB_SYSTEM" "$type"
|
||||
is_system_enabled "$DB_SYSTEM" 'DB_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'db' 'DB' "$database"
|
||||
is_object_unsuspended 'db' 'DB' "$database"
|
||||
get_next_dbhost
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Get database values
|
||||
get_database_values
|
||||
|
||||
#generate password and unique user
|
||||
dbpass=$(generate_password)
|
||||
dbuser="hestia_sso_$(generate_password)"
|
||||
|
||||
add_mysql_database_temp_user
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Error: Unable to create temp user"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
if [[ "$ttl" -gt 0 ]]; then
|
||||
echo "$BIN/v-delete-database-temp-user $user $database $dbuser mysql $host" | at "now +${ttl} minute" > /dev/null 2>&1
|
||||
fi
|
||||
echo '{
|
||||
"login": {
|
||||
"user": "'$dbuser'",
|
||||
"password": "'$dbpass'"
|
||||
}
|
||||
}'
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "Databases" "Granted user $dbuser access to database $database."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
exit
|
||||
222
bin/v-add-dns-domain
Executable file
222
bin/v-add-dns-domain
Executable file
@@ -0,0 +1,222 @@
|
||||
#!/bin/bash
|
||||
# info: add dns domain
|
||||
# options: USER DOMAIN IP [NS1] [NS2] [NS3] [NS4] [NS5] [NS6] [NS7] [NS8] [RESTART]
|
||||
#
|
||||
# example: v-add-dns-domain admin example.com ns1.example.com ns2.example.com '' '' '' '' '' '' yes
|
||||
#
|
||||
# This function adds DNS zone with records defined in the template. If the exp
|
||||
# argument isn't stated, the expiration date value will be set to next year.
|
||||
# The soa argument is responsible for the relevant record. By default the first
|
||||
# user's NS server is used. TTL is set as common for the zone and for all of
|
||||
# its records with a default value of 14400 seconds.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
ip=$3
|
||||
ns1=$4
|
||||
ns2=$5
|
||||
ns3=$6
|
||||
ns4=$7
|
||||
ns5=$8
|
||||
ns6=$9
|
||||
ns7=${10}
|
||||
ns8=${11}
|
||||
restart=${12}
|
||||
dnssec=${13}
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# shellcheck source=/usr/local/hestia/func/rebuild.sh
|
||||
source $HESTIA/func/rebuild.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# Additional argument formatting
|
||||
format_domain
|
||||
format_domain_idn
|
||||
domain_utf=$(idn2 --quiet -d "$domain_idn")
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '3' "$#" 'USER DOMAIN IP [NS1] [NS2] [NS3] [..] [NS8] [RESTART]'
|
||||
is_format_valid 'user' 'domain' 'ip'
|
||||
is_system_enabled "$DNS_SYSTEM" 'DNS_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
|
||||
if [ "$($BIN/v-list-dns-domain $user $domain_utf plain | cut -f 1) " != "$domain" ]; then
|
||||
is_domain_new 'dns' "$domain_utf"
|
||||
fi
|
||||
if [ "$($BIN/v-list-dns-domain $user $domain_idn plain | cut -f 1) " != "$domain" ]; then
|
||||
is_domain_new 'dns' "$domain_idn"
|
||||
else
|
||||
is_domain_new 'dns' "$domain"
|
||||
fi
|
||||
if [ -z "$(is_ip_format_valid $domain)" ]; then
|
||||
echo "Error: Invalid domain format. IP address detected as input."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -n "$restart" ]; then
|
||||
is_format_valid 'restart'
|
||||
fi
|
||||
|
||||
if [ -n "$dnssec" ]; then
|
||||
is_boolean_format_valid "$dnssec" 'dnssec'
|
||||
fi
|
||||
|
||||
is_package_full 'DNS_DOMAINS'
|
||||
template=$(get_user_value '$DNS_TEMPLATE')
|
||||
is_dns_template_valid "$template"
|
||||
|
||||
is_base_domain_owner "$domain"
|
||||
|
||||
if [ -n "$ns1" ]; then
|
||||
ns1=$(echo $4 | sed -e 's/\.*$//g' -e 's/^\.*//g')
|
||||
is_format_valid 'ns1'
|
||||
fi
|
||||
if [ -n "$ns2" ]; then
|
||||
ns2=$(echo $5 | sed -e 's/\.*$//g' -e 's/^\.*//g')
|
||||
is_format_valid 'ns2'
|
||||
fi
|
||||
if [ -n "$ns3" ]; then
|
||||
ns3=$(echo $6 | sed -e 's/\.*$//g' -e 's/^\.*//g')
|
||||
is_format_valid 'ns3'
|
||||
fi
|
||||
if [ -n "$ns4" ]; then
|
||||
ns4=$(echo $7 | sed -e 's/\.*$//g' -e 's/^\.*//g')
|
||||
is_format_valid 'ns4'
|
||||
fi
|
||||
if [ -n "$ns5" ]; then
|
||||
ns5=$(echo $8 | sed -e 's/\.*$//g' -e 's/^\.*//g')
|
||||
is_format_valid 'ns5'
|
||||
fi
|
||||
if [ -n "$ns6" ]; then
|
||||
ns6=$(echo $9 | sed -e 's/\.*$//g' -e 's/^\.*//g')
|
||||
is_format_valid 'ns6'
|
||||
fi
|
||||
if [ -n "$ns7" ]; then
|
||||
ns7=$(echo ${10} | sed -e 's/\.*$//g' -e 's/^\.*//g')
|
||||
is_format_valid 'ns7'
|
||||
fi
|
||||
if [ -n "$ns8" ]; then
|
||||
ns8=$(echo ${11} | sed -e 's/\.*$//g' -e 's/^\.*//g')
|
||||
is_format_valid 'ns8'
|
||||
fi
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Defining NS variables
|
||||
if [ -z $ns2 ]; then
|
||||
i=1
|
||||
ns=$(get_user_value '$NS')
|
||||
for nameserver in ${ns//,/ }; do
|
||||
eval ns$i=$nameserver
|
||||
((++i))
|
||||
done
|
||||
fi
|
||||
soa="$ns1"
|
||||
exp=$(date +%F -d "+ 1 year")
|
||||
serial=$(date +'%Y%m%d01')
|
||||
ttl=14400
|
||||
|
||||
# Reading template
|
||||
template_data=$(cat "$DNSTPL/$template.tpl")
|
||||
|
||||
# Deleting unused nameservers
|
||||
if [ -z "$ns3" ]; then
|
||||
template_data=$(echo "$template_data" | grep -v %ns3%)
|
||||
fi
|
||||
if [ -z "$ns4" ]; then
|
||||
template_data=$(echo "$template_data" | grep -v %ns4%)
|
||||
fi
|
||||
if [ -z "$ns5" ]; then
|
||||
template_data=$(echo "$template_data" | grep -v %ns5%)
|
||||
fi
|
||||
if [ -z "$ns6" ]; then
|
||||
template_data=$(echo "$template_data" | grep -v %ns6%)
|
||||
fi
|
||||
if [ -z "$ns7" ]; then
|
||||
template_data=$(echo "$template_data" | grep -v %ns7%)
|
||||
fi
|
||||
if [ -z "$ns8" ]; then
|
||||
template_data=$(echo "$template_data" | grep -v %ns8%)
|
||||
fi
|
||||
if [ -z "$dnssec" ]; then
|
||||
dnssec="no"
|
||||
fi
|
||||
|
||||
# Generating timestamp
|
||||
time_n_date=$(date +'%T %F')
|
||||
time=$(echo "$time_n_date" | cut -f 1 -d \ )
|
||||
date=$(echo "$time_n_date" | cut -f 2 -d \ )
|
||||
|
||||
# Adding dns zone to the user config
|
||||
echo "$template_data" \
|
||||
| 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/%ns5%/$ns5/g" \
|
||||
-e "s/%ns6%/$ns6/g" \
|
||||
-e "s/%ns7%/$ns7/g" \
|
||||
-e "s/%ns8%/$ns8/g" \
|
||||
-e "s/%time%/$time/g" \
|
||||
-e "s/%date%/$date/g" > $USER_DATA/dns/$domain.conf
|
||||
|
||||
chmod 660 $USER_DATA/dns/$domain.conf
|
||||
records="$(wc -l $USER_DATA/dns/$domain.conf | cut -f 1 -d ' ')"
|
||||
|
||||
# Adding dns.conf record
|
||||
dns_rec="DOMAIN='$domain' IP='$ip' TPL='$template' TTL='$ttl' EXP='$exp'"
|
||||
dns_rec="$dns_rec SOA='$soa' SERIAL='$serial' SRC='' RECORDS='$records'"
|
||||
dns_rec="$dns_rec DNSSEC='$dnssec' KEY='' SLAVE='no' MASTER='' SUSPENDED='no' TIME='$time' DATE='$date'"
|
||||
|
||||
echo "$dns_rec" >> $USER_DATA/dns.conf
|
||||
chmod 660 $USER_DATA/dns.conf
|
||||
|
||||
rebuild_dns_domain_conf
|
||||
|
||||
# Updating dns-cluster queue
|
||||
if [ "$DNS_CLUSTER" = "yes" ]; then
|
||||
cmd="$BIN/v-add-remote-dns-domain $user $domain yes"
|
||||
echo "$cmd" >> $HESTIA/data/queue/dns-cluster.pipe
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Increasing domain value
|
||||
increase_user_value "$user" '$U_DNS_DOMAINS'
|
||||
increase_user_value "$user" '$U_DNS_RECORDS' "$records"
|
||||
|
||||
# Restart named
|
||||
$BIN/v-restart-dns $restart
|
||||
check_result $? "DNS restart failed"
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "DNS" "Added new DNS domain (Name: $domain)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
91
bin/v-add-dns-on-web-alias
Executable file
91
bin/v-add-dns-on-web-alias
Executable file
@@ -0,0 +1,91 @@
|
||||
#!/bin/bash
|
||||
# info: add dns domain or dns record after web domain alias
|
||||
# options: USER ALIAS IP [RESTART]
|
||||
#
|
||||
# example: v-add-dns-on-web-alias admin www.example.com 8.8.8.8
|
||||
#
|
||||
# This function adds dns domain or dns record based on web domain alias.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
alias=$2
|
||||
ip=$3
|
||||
restart=$4
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '3' "$#" 'USER ALIAS IP [RESTART]'
|
||||
is_format_valid 'user' 'alias' 'ip' 'restart'
|
||||
is_system_enabled "$DNS_SYSTEM" 'DNS_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
if [ -e "$USER_DATA/dns/$alias.conf" ]; then
|
||||
exit
|
||||
fi
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Logging
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
# Define additional vars
|
||||
sub_domain=$(echo "$alias" | awk -F '.' '{print $1}')
|
||||
top_domain=$(echo "$alias" | sed -e "s/^$sub_domain.//")
|
||||
domain_lvl=$(echo "$alias" | grep -o "\." | wc -l)
|
||||
|
||||
# Adding second level domain
|
||||
if [ "$domain_lvl" -eq 1 ] || [ "${#top_domain}" -le '6' ]; then
|
||||
$BIN/v-add-dns-domain \
|
||||
"$user" "$alias" "$ip" '' '' '' '' '' '' '' '' "$restart" >> /dev/null
|
||||
exit
|
||||
fi
|
||||
|
||||
# Adding top-level domain and then its sub
|
||||
$BIN/v-add-dns-domain "$user" "$top_domain" "$ip" '' '' '' '' '' '' '' '' "$restart" >> /dev/null
|
||||
|
||||
# Checking top-level domain
|
||||
if [ ! -e "$USER_DATA/dns/$top_domain.conf" ]; then
|
||||
exit
|
||||
fi
|
||||
|
||||
# Checking subdomain record
|
||||
if [ "$sub_domain" == '*' ]; then
|
||||
check_record=$(grep -w "RECORD='\*'" $USER_DATA/dns/$top_domain.conf)
|
||||
else
|
||||
check_record=$(grep -w "RECORD='$sub_domain'" $USER_DATA/dns/$top_domain.conf)
|
||||
fi
|
||||
|
||||
# Adding subdomain record
|
||||
if [ -z "$check_record" ]; then
|
||||
$BIN/v-add-dns-record \
|
||||
"$user" "$top_domain" "$sub_domain" A "$ip" '' '' "$restart" >> /dev/null
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# No logging
|
||||
|
||||
exit
|
||||
172
bin/v-add-dns-record
Executable file
172
bin/v-add-dns-record
Executable file
@@ -0,0 +1,172 @@
|
||||
#!/bin/bash
|
||||
# info: add dns record
|
||||
# options: USER DOMAIN RECORD TYPE VALUE [PRIORITY] [ID] [RESTART] [TTL]
|
||||
#
|
||||
# example: v-add-dns-record admin acme.com www A 162.227.73.112
|
||||
#
|
||||
# This function is used to add a new DNS record. Complex records of TXT, MX and
|
||||
# SRV types can be used by a filling in the 'value' argument. This function also
|
||||
# gets an ID parameter for definition of certain record identifiers or for the
|
||||
# regulation of records.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
domain_idn=$2
|
||||
record=$(idn2 --quiet -d "$3")
|
||||
record=$(echo "$record" | tr '[:upper:]' '[:lower:]')
|
||||
rtype=$(echo "$4" | tr '[:lower:]' '[:upper:]')
|
||||
dvalue=$5
|
||||
priority=$6
|
||||
id=$7
|
||||
restart=$8
|
||||
ttl=$9
|
||||
quiet=${10}
|
||||
|
||||
if [ -z "$priority" ]; then
|
||||
priority=10
|
||||
fi
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# shellcheck source=/usr/local/hestia/func/rebuild.sh
|
||||
source $HESTIA/func/rebuild.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# Null priority for none MX/SRV records
|
||||
if [ "$rtype" != 'MX' ] && [ "$rtype" != 'SRV' ]; then
|
||||
priority=''
|
||||
fi
|
||||
|
||||
# Add trailing dot at the end of NS/CNAME/MX/PTR/SRV record
|
||||
if [[ $rtype =~ ^NS|CNAME|MX|PTR|SRV ]]; then
|
||||
trailing_dot=$(echo $dvalue | grep "\.$")
|
||||
if [ -z "$trailing_dot" ]; then
|
||||
dvalue="$dvalue."
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ $rtype =~ ^NS|CNAME|MX|PTR|SRV ]]; then
|
||||
dvalue=$(idn2 --quiet "$dvalue")
|
||||
record=$(idn2 --quiet "$record")
|
||||
fi
|
||||
|
||||
# Cleanup quotes on dvalue
|
||||
# - [CAA] records will be left unchanged
|
||||
# - [SRV] will be stripped of double quotes even when containing spaces
|
||||
# - [DNSKEY] will be stripped of double quotes even when containing spaces
|
||||
# - Rest of record types will be striped of quotes and the final string
|
||||
# will be enclosed in double quotes if containing spaces or semicolons
|
||||
|
||||
if [ "$rtype" != "CAA" ]; then
|
||||
dvalue=${dvalue//\"/}
|
||||
# Add support for DS key
|
||||
if [ "$rtype" != "DNSKEY" ] && [ "$rtype" != "DS" ]; then
|
||||
if [ "$rtype" != 'SRV' ] && [[ "$dvalue" =~ [\;[:space:]] ]]; then
|
||||
dvalue='"'"$dvalue"'"'
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$record" = "@" ] && [ "$rtype" = "CNAME" ]; then
|
||||
check_result $E_INVALID "CNAME on root is not allowed"
|
||||
fi
|
||||
|
||||
# Additional argument formatting
|
||||
format_domain
|
||||
format_domain_idn
|
||||
# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ?
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '5' "$#" 'USER DOMAIN RECORD TYPE VALUE [PRIORITY] [ID] [RESTART] [TTL]'
|
||||
is_format_valid 'user' 'domain' 'record' 'rtype' 'dvalue'
|
||||
is_system_enabled "$DNS_SYSTEM" 'DNS_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'dns' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'dns' 'DOMAIN' "$domain"
|
||||
is_package_full 'DNS_RECORDS'
|
||||
get_next_dnsrecord
|
||||
is_format_valid 'id'
|
||||
is_object_new "dns/$domain" 'ID' "$id"
|
||||
is_dns_fqnd "$rtype" "$dvalue"
|
||||
is_dns_nameserver_valid "$domain" "$rtype" "$dvalue"
|
||||
is_format_valid 'ttl'
|
||||
if [ -n "$restart" ]; then
|
||||
is_format_valid 'restart'
|
||||
fi
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Generating timestamp
|
||||
time_n_date=$(date +'%T %F')
|
||||
time=$(echo "$time_n_date" | cut -f 1 -d \ )
|
||||
date=$(echo "$time_n_date" | cut -f 2 -d \ )
|
||||
|
||||
# Adding record
|
||||
zone="$USER_DATA/dns/$domain.conf"
|
||||
dns_rec="ID='$id' RECORD='$record' TYPE='$rtype' PRIORITY='$priority'"
|
||||
dns_rec="$dns_rec VALUE='$dvalue' SUSPENDED='no' TIME='$time' DATE='$date'"
|
||||
[ -n "$ttl" ] && dns_rec="$dns_rec TTL='$ttl'"
|
||||
echo "$dns_rec" >> $zone
|
||||
chmod 660 $zone
|
||||
|
||||
# Sorting records
|
||||
sort_dns_records
|
||||
|
||||
# Update serial
|
||||
update_domain_serial
|
||||
# Updating zone
|
||||
if [[ "$DNS_SYSTEM" =~ named|bind ]]; then
|
||||
# Do full rebuild due DNS SEC
|
||||
rebuild_dns_domain_conf
|
||||
fi
|
||||
|
||||
# Updating dns-cluster queue
|
||||
if [ "$DNS_CLUSTER" = "yes" ]; then
|
||||
# Check for first sync
|
||||
dlock=$(grep "domain $user $domain" $HESTIA/data/queue/dns-cluster.pipe)
|
||||
if [ -z "$dlock" ]; then
|
||||
cmd="$BIN/v-add-remote-dns-record $user $domain $id"
|
||||
echo "$cmd" >> $HESTIA/data/queue/dns-cluster.pipe
|
||||
fi
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Update counters
|
||||
records="$(wc -l $USER_DATA/dns/$domain.conf | cut -f1 -d ' ')"
|
||||
update_object_value 'dns' 'DOMAIN' "$domain" '$RECORDS' "$records"
|
||||
increase_user_value "$user" '$U_DNS_RECORDS'
|
||||
|
||||
# Restart named
|
||||
$BIN/v-restart-dns "$restart"
|
||||
check_result $? "$E_RESTART" 'dns failed to restart'
|
||||
|
||||
# Logging
|
||||
if [ "$quiet" != "yes" ]; then
|
||||
$BIN/v-log-action "$user" "Info" "DNS" "Added DNS record (Type: $rtype, Value: $record, Domain: $domain)."
|
||||
fi
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
100
bin/v-add-domain
Executable file
100
bin/v-add-domain
Executable file
@@ -0,0 +1,100 @@
|
||||
#!/bin/bash
|
||||
# info: add web/dns/mail domain
|
||||
# options: USER DOMAIN [IP] [RESTART]
|
||||
#
|
||||
# example: v-add-domain admin example.com
|
||||
#
|
||||
# This function adds web/dns/mail domain to a server.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
ip=$3
|
||||
restart=$4
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/ip.sh
|
||||
source $HESTIA/func/ip.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
check_args '2' "$#" 'USER DOMAIN [IP] [RESTART]'
|
||||
is_format_valid 'user' 'domain' 'restart'
|
||||
if [ -n "$ip" ]; then
|
||||
is_format_valid 'ip'
|
||||
fi
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Get ip if it wasn't defined
|
||||
if [ -z "$ip" ]; then
|
||||
get_user_ip
|
||||
if [ -z "$ip" ]; then
|
||||
check_result "$E_NOTEXIST" "no available IP address"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Working on web domain
|
||||
if [ -n "$WEB_SYSTEM" ]; then
|
||||
check1=$(is_package_full 'WEB_DOMAINS')
|
||||
if [ $? -eq 0 ]; then
|
||||
$BIN/v-add-web-domain "$user" "$domain" "$ip" 'no'
|
||||
check_result $? "can't add web domain"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Working on DNS domain
|
||||
if [ -n "$DNS_SYSTEM" ]; then
|
||||
check2=$(is_package_full 'DNS_DOMAINS')
|
||||
if [ $? -eq 0 ]; then
|
||||
$BIN/v-add-dns-domain "$user" "$domain" "$ip" "" "" "" "" "" "" "" "" "no"
|
||||
check_result $? "can't add dns domain"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Working on mail domain
|
||||
if [ -n "$MAIL_SYSTEM" ]; then
|
||||
check3=$(is_package_full 'MAIL_DOMAINS')
|
||||
if [ $? -eq 0 ]; then
|
||||
$BIN/v-add-mail-domain $user $domain 'no'
|
||||
check_result $? "can't add mail domain"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ "$check1" != '' && "$check2" != '' && "$check3" != '' ]]; then
|
||||
check_result 8 "Package limit reached"
|
||||
fi
|
||||
|
||||
# Restarting services
|
||||
$BIN/v-restart-web "$restart"
|
||||
check_result $? "can't restart web" > /dev/null
|
||||
|
||||
$BIN/v-restart-proxy "$restart"
|
||||
check_result $? "can't restart proxy" > /dev/null
|
||||
|
||||
$BIN/v-restart-dns "$restart"
|
||||
check_result $? "can't restart dns" > /dev/null
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
exit
|
||||
118
bin/v-add-fastcgi-cache
Executable file
118
bin/v-add-fastcgi-cache
Executable file
@@ -0,0 +1,118 @@
|
||||
#!/bin/bash
|
||||
# info: Enable FastCGI cache for nginx
|
||||
# options: USER DOMAIN [DURATION] [RESTART]
|
||||
#
|
||||
# example: v-add-fastcgi-cache user domain.tld 30m
|
||||
#
|
||||
# This function enables FastCGI cache for nginx
|
||||
# Acceptable values for duration is time in seconds (10s) minutes (10m) or days (10d)
|
||||
# Add "yes" as last parameter to restart nginx
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
duration=${3-2m}
|
||||
restart=${4-no}
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '2' "$#" 'USER DOMAIN [DURATION] [RESTART]'
|
||||
is_format_valid 'user' 'domain' 'restart'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'web' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'web' 'DOMAIN' "$domain"
|
||||
|
||||
if ! [[ "$duration" =~ ^[0-9].*[s|m|d]$ ]]; then
|
||||
echo "Invalid duration"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
if [[ "$duration" =~ ^[0].*[s|m|d]$ ]]; then
|
||||
echo "Invalid duration"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Load domain data
|
||||
parse_object_kv_list $(grep "DOMAIN='$domain'" $USER_DATA/web.conf)
|
||||
|
||||
# Check that nginx is not in proxy mode
|
||||
if [ "$WEB_SYSTEM" != 'nginx' ]; then
|
||||
echo "Error: nginx is in proxy mode"
|
||||
exit "$E_NOTEXIST"
|
||||
fi
|
||||
|
||||
fastcgi="$HOMEDIR/$user/conf/web/$domain/$WEB_SYSTEM.fastcgi_cache.conf"
|
||||
no_cache='$no_cache'
|
||||
|
||||
cat << EOF > $fastcgi
|
||||
fastcgi_cache $domain;
|
||||
fastcgi_cache_valid 200 $duration;
|
||||
fastcgi_cache_valid 301 302 10m;
|
||||
fastcgi_cache_valid 404 10m;
|
||||
fastcgi_cache_bypass $no_cache;
|
||||
fastcgi_no_cache $no_cache;
|
||||
set $no_cache 0;
|
||||
EOF
|
||||
|
||||
chown root:$user $fastcgi
|
||||
chmod 640 $fastcgi
|
||||
|
||||
str="fastcgi_cache_path /var/cache/nginx/micro/$domain levels=1:2"
|
||||
str="$str keys_zone=$domain:10m max_size=512m inactive=30m use_temp_path=off;"
|
||||
conf='/etc/nginx/conf.d/fastcgi_cache_pool.conf'
|
||||
if [ -f "$conf" ]; then
|
||||
if [ -z "$(grep "=${domain}:" $conf)" ]; then
|
||||
echo "$str" >> $conf
|
||||
fi
|
||||
else
|
||||
echo "$str" >> $conf
|
||||
fi
|
||||
|
||||
mkdir -p /var/cache/nginx/micro/$domain
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
if [ -z "$FASTCGI_CACHE" ]; then
|
||||
add_object_key "web" 'DOMAIN' "$domain" 'FASTCGI_CACHE' 'ALIAS'
|
||||
fi
|
||||
if [ -z "$FASTCGI_DURATION" ]; then
|
||||
add_object_key "web" 'DOMAIN' "$domain" 'FASTCGI_DURATION' 'ALIAS'
|
||||
fi
|
||||
|
||||
# Set FastCGI cache flag to enabled
|
||||
update_object_value 'web' 'DOMAIN' "$domain" '$FASTCGI_CACHE' 'yes'
|
||||
update_object_value 'web' 'DOMAIN' "$domain" '$FASTCGI_DURATION' "$duration"
|
||||
|
||||
# Restart web server
|
||||
$BIN/v-restart-web "$restart"
|
||||
check_result $? "Web server restart failed" > /dev/null
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "Web" "FastCGI cache enabled (Domain: $domain)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
91
bin/v-add-firewall-ban
Executable file
91
bin/v-add-firewall-ban
Executable file
@@ -0,0 +1,91 @@
|
||||
#!/bin/bash
|
||||
# info: add firewall blocking rule
|
||||
# options: IP CHAIN
|
||||
#
|
||||
# example: v-add-firewall-ban 37.120.129.20 MAIL
|
||||
#
|
||||
# This function adds new blocking rule to system firewall
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
ip=$1
|
||||
chain=$(echo $2 | tr '[:lower:]' '[:upper:]')
|
||||
|
||||
# Defining absolute path for iptables and modprobe
|
||||
iptables="/sbin/iptables"
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/firewall.sh
|
||||
source $HESTIA/func/firewall.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '2' "$#" 'IP CHAIN'
|
||||
is_format_valid 'ip' 'chain'
|
||||
is_system_enabled "$FIREWALL_SYSTEM" 'FIREWALL_SYSTEM'
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Self heal iptables links
|
||||
heal_iptables_links
|
||||
|
||||
# Checking server ip
|
||||
if [ -e "$HESTIA/data/ips/$ip" ] || [ "$ip" = '127.0.0.1' ]; then
|
||||
exit
|
||||
fi
|
||||
|
||||
# Checking ip exclusions
|
||||
excludes="$HESTIA/data/firewall/excludes.conf"
|
||||
check_excludes=$(grep "^$ip$" $excludes 2> /dev/null)
|
||||
if [ -n "$check_excludes" ]; then
|
||||
exit
|
||||
fi
|
||||
|
||||
# Checking ip in banlist
|
||||
conf="$HESTIA/data/firewall/banlist.conf"
|
||||
check_ip=$(grep "IP='$ip' CHAIN='$chain'" $conf 2> /dev/null)
|
||||
if [ -n "$check_ip" ]; then
|
||||
exit
|
||||
fi
|
||||
|
||||
# Adding chain
|
||||
$BIN/v-add-firewall-chain $chain
|
||||
|
||||
# Generating timestamp
|
||||
time_n_date=$(date +'%T %F')
|
||||
time=$(echo "$time_n_date" | cut -f 1 -d \ )
|
||||
date=$(echo "$time_n_date" | cut -f 2 -d \ )
|
||||
|
||||
# Adding ip to banlist
|
||||
echo "IP='$ip' CHAIN='$chain' TIME='$time' DATE='$date'" >> $conf
|
||||
$iptables -I fail2ban-$chain 1 -s $ip \
|
||||
-j REJECT --reject-with icmp-port-unreachable 2> /dev/null
|
||||
|
||||
# Changing permissions
|
||||
chmod 660 $conf
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "system" "Warning" "Firewall" "Banned IP address $ip."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
130
bin/v-add-firewall-chain
Executable file
130
bin/v-add-firewall-chain
Executable file
@@ -0,0 +1,130 @@
|
||||
#!/bin/bash
|
||||
# info: add firewall chain
|
||||
# options: CHAIN [PORT] [PROTOCOL] [PROTOCOL]
|
||||
#
|
||||
# example: v-add-firewall-chain CRM 5678 TCP
|
||||
#
|
||||
# This function adds new rule to system firewall
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
chain=$(echo $1 | tr '[:lower:]' '[:upper:]')
|
||||
port=$2
|
||||
port_ext=$2
|
||||
protocol=${4-TCP}
|
||||
protocol=$(echo $protocol | tr '[:lower:]' '[:upper:]')
|
||||
|
||||
# Defining absolute path to iptables
|
||||
iptables="/sbin/iptables"
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/firewall.sh
|
||||
source $HESTIA/func/firewall.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# Get hestia port by reading nginx.conf
|
||||
hestiaport=$(grep -m 1 'listen' $HESTIA/nginx/conf/nginx.conf | awk '{print $2}' | sed "s|;||")
|
||||
if [ -z "$hestiaport" ]; then
|
||||
hestiaport=8083
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '1' "$#" 'CHAIN [PORT] [PROTOCOL]'
|
||||
is_format_valid 'chain' 'port_ext' 'protocol'
|
||||
is_system_enabled "$FIREWALL_SYSTEM" 'FIREWALL_SYSTEM'
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Self heal iptables links
|
||||
heal_iptables_links
|
||||
|
||||
# Checking known chains
|
||||
case $chain in
|
||||
SSH) # Get ssh port by reading ssh config file.
|
||||
sshport=$(grep '^Port ' /etc/ssh/sshd_config | head -1 | cut -d ' ' -f 2)
|
||||
if [ -z "$sshport" ]; then
|
||||
sshport=22
|
||||
fi
|
||||
port=$sshport
|
||||
protocol=TCP
|
||||
;;
|
||||
FTP)
|
||||
port=21
|
||||
protocol=TCP
|
||||
;;
|
||||
MAIL)
|
||||
port='25,465,587,110,995,143,993'
|
||||
protocol=TCP
|
||||
;;
|
||||
DNS)
|
||||
port=53
|
||||
protocol=UDP
|
||||
;;
|
||||
WEB)
|
||||
port='80,443'
|
||||
protocol=TCP
|
||||
;;
|
||||
DB)
|
||||
port='3306,5432'
|
||||
protocol=TCP
|
||||
;;
|
||||
HESTIA)
|
||||
port=$hestiaport
|
||||
protocol=TCP
|
||||
;;
|
||||
RECIDIVE)
|
||||
port='1:65535'
|
||||
protocol=TCP
|
||||
;;
|
||||
*) check_args '2' "$#" 'CHAIN PORT' ;;
|
||||
esac
|
||||
|
||||
# Adding chain
|
||||
$iptables -N fail2ban-$chain 2> /dev/null
|
||||
if [ $? -eq 0 ]; then
|
||||
$iptables -A fail2ban-$chain -j RETURN
|
||||
|
||||
# Adding multiport module
|
||||
if [[ "$port" =~ ,|-|: ]]; then
|
||||
port_str="-m multiport --dports $port"
|
||||
else
|
||||
port_str="--dport $port"
|
||||
fi
|
||||
$iptables -I INPUT -p $protocol $port_str -j fail2ban-$chain
|
||||
fi
|
||||
|
||||
# Preserving chain
|
||||
chains=$HESTIA/data/firewall/chains.conf
|
||||
check_chain=$(grep "CHAIN='$chain'" $chains 2> /dev/null)
|
||||
if [ -z "$check_chain" ]; then
|
||||
echo "CHAIN='$chain' PORT='$port' PROTOCOL='$protocol'" >> $chains
|
||||
fi
|
||||
|
||||
# Changing permissions
|
||||
chmod 660 $chains
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "system" "Info" "Firewall" "Added service to firewall (Service: $chain, Port: $port, Protocol: $protocol)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
205
bin/v-add-firewall-ipset
Executable file
205
bin/v-add-firewall-ipset
Executable file
@@ -0,0 +1,205 @@
|
||||
#!/bin/bash
|
||||
# info: add firewall ipset
|
||||
# options: NAME [SOURCE] [IPVERSION] [AUTOUPDATE] [REFRESH]
|
||||
#
|
||||
# example: v-add-firewall-ipset country-nl "https://raw.githubusercontent.com/ipverse/rir-ip/master/country/nl/ipv4-aggregated.txt"
|
||||
#
|
||||
# This function adds new ipset to system firewall
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
ip_name=${1}
|
||||
data_source=${2}
|
||||
ip_version=${3:-v4}
|
||||
autoupdate=${4:-yes}
|
||||
refresh=${5:-no}
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '1' "$#" 'NAME [SOURCE] [IPVERSION] [AUTOUPDATE] [FORCE]'
|
||||
is_format_valid 'ip_name'
|
||||
is_boolean_format_valid "$autoupdate" 'Automatically update IP list (yes/no)'
|
||||
is_boolean_format_valid "$refresh" 'Refresh IP list (yes/no)'
|
||||
is_system_enabled "$FIREWALL_SYSTEM" 'FIREWALL_SYSTEM'
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
# Define variables for ipset configuration
|
||||
ipset_hstobject='../../data/firewall/ipset'
|
||||
IPSET_BIN="$(command -v ipset)"
|
||||
IPSET_PATH="$HESTIA/data/firewall/ipset"
|
||||
|
||||
# Ensure ipset is installed
|
||||
if [ -z "$IPSET_BIN" ]; then
|
||||
if [ -f '/etc/redhat-release' ]; then
|
||||
dnf install -q -y ipset > /dev/null
|
||||
else
|
||||
apt-get --quiet --yes install ipset > /dev/null
|
||||
fi
|
||||
check_result $? "Installing IPset package"
|
||||
|
||||
IPSET_BIN="$(which ipset)"
|
||||
check_result $? "IPset binary not found"
|
||||
fi
|
||||
|
||||
# Ensure ipset configuration path and master file exist before attempting to parse
|
||||
mkdir -p "$IPSET_PATH"
|
||||
if [ ! -f "$HESTIA/data/firewall/ipset.conf" ]; then
|
||||
touch $HESTIA/data/firewall/ipset.conf
|
||||
fi
|
||||
|
||||
if [ -z "$data_source" ]; then
|
||||
if [ ! -f "${IPSET_PATH}.conf" ] || [[ ! $(grep "LISTNAME='$ip_name'" "${IPSET_PATH}.conf") ]]; then
|
||||
check_args '2' "$#" 'NAME SOURCE [IPVERSION] [AUTOUPDATE] [FORCE]'
|
||||
fi
|
||||
|
||||
data_source="$(get_object_value "$ipset_hstobject" 'LISTNAME' "$ip_name" '$SOURCE')"
|
||||
ip_version="$(get_object_value "$ipset_hstobject" 'LISTNAME' "$ip_name" '$IP_VERSION')"
|
||||
else
|
||||
is_object_new "$ipset_hstobject" 'LISTNAME' "$ip_name"
|
||||
fi
|
||||
|
||||
if [ "$ip_version" != "v4" ] && [ "$ip_version" != "v6" ]; then
|
||||
check_result "$E_INVALID" "invalid ip version, valid: (v4|v6)"
|
||||
fi
|
||||
|
||||
if ! echo "$data_source" | egrep -q '^(https?|script|file):'; then
|
||||
check_result "$E_INVALID" "invalid ipset source, valid: (http[s]://|script:|file:)"
|
||||
fi
|
||||
|
||||
IPSET_FILE="${ip_name}.${ip_version}"
|
||||
IPSET_MIN_SIZE=10
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Generate ip lists file if missing or required refresh
|
||||
if [ ! -f "${IPSET_PATH}/${IPSET_FILE}.iplist" ] || [ "$refresh" = "yes" ]; then
|
||||
|
||||
iplist_tempfile=$(mktemp)
|
||||
|
||||
if [[ "$data_source" =~ ^https?:// ]]; then
|
||||
|
||||
wget --tries=3 --timeout=15 --read-timeout=15 --waitretry=3 --no-dns-cache --quiet "$data_source" -O "$iplist_tempfile"
|
||||
check_result $? "Downloading ip list"
|
||||
|
||||
# Advanced: execute script with the same basename for aditional pre-processing
|
||||
# ex:
|
||||
if [ -x "${IPSET_PATH}/${IPSET_FILE}.sh" ]; then
|
||||
if [ -e '/etc/redhat-release' ]; then
|
||||
preprocess_output="$(cat "$iplist_tempfile" | setpriv --clear-groups --reuid nobody --regid nobody -- ${IPSET_PATH}/${IPSET_FILE}.sh "$ip_name" "$iplist_tempfile")"
|
||||
else
|
||||
preprocess_output="$(cat "$iplist_tempfile" | setpriv --clear-groups --reuid nobody --regid nogroup -- ${IPSET_PATH}/${IPSET_FILE}.sh "$ip_name" "$iplist_tempfile")"
|
||||
fi
|
||||
check_result $? "Preprocessing script failed (${IPSET_FILE}.sh)"
|
||||
[[ "$preprocess_output" ]] && echo "$preprocess_output" > "$iplist_tempfile"
|
||||
fi
|
||||
|
||||
elif [[ "$data_source" =~ ^script:/ ]]; then
|
||||
|
||||
# Generate the ip list file trough a external script
|
||||
# ex: compiling a ip list from multiple sources on demand
|
||||
if [ -x "${data_source#script:}" ]; then
|
||||
if [ -e '/etc/redhat-release' ]; then
|
||||
setpriv --clear-groups --reuid nobody --regid nobody -- ${data_source#script:} "$ip_name" > "$iplist_tempfile"
|
||||
else
|
||||
setpriv --clear-groups --reuid nobody --regid nogroup -- ${data_source#script:} "$ip_name" > "$iplist_tempfile"
|
||||
fi
|
||||
check_result $? "Running custom ip list update script"
|
||||
|
||||
fi
|
||||
|
||||
elif [[ "$data_source" =~ ^file:/ ]]; then
|
||||
|
||||
# Use a external ip-list file managed by other apps
|
||||
# ex: Using a ip list that is continuously updated
|
||||
[ -f "${data_source#file:}" ] && cp -f "${data_source#file:}" "$iplist_tempfile"
|
||||
|
||||
fi
|
||||
|
||||
# Cleanup ip list
|
||||
sed -r -i -e 's/[;#].*$//' -e 's/[ \t]*$//' -e '/^$/d' "$iplist_tempfile"
|
||||
if [[ $ip_version == 'v4' ]]; then
|
||||
sed -i -r -n -e '/^((1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])/p' "$iplist_tempfile"
|
||||
elif [[ $ip_version == 'v6' ]]; then
|
||||
sed -i -r -n -e '/^([0-9a-fA-F]{0,4}:){1,7}[0-9a-fA-F]{0,4}/p' "$iplist_tempfile"
|
||||
fi
|
||||
|
||||
# Validate iplist file size
|
||||
iplist_size=$(sed -r -e '/^#|^$/d' "$iplist_tempfile" | wc -l)
|
||||
[[ "$iplist_size" -le "$IPSET_MIN_SIZE" ]] && check_result "$E_INVALID" "IP list file too small (<${IPSET_MIN_SIZE}), ignoring"
|
||||
mv -f "$iplist_tempfile" "${IPSET_PATH}/${IPSET_FILE}.iplist"
|
||||
|
||||
fi
|
||||
|
||||
# Load ipset in kernel
|
||||
inet_ver="inet"
|
||||
[ "$ip_version" == "v6" ] && inet_ver="inet6"
|
||||
|
||||
$IPSET_BIN -quiet create -exist "$ip_name" hash:net family $inet_ver
|
||||
$IPSET_BIN -quiet destroy "${ip_name}-tmp"
|
||||
$IPSET_BIN create "${ip_name}-tmp" -exist hash:net family $inet_ver maxelem 1048576
|
||||
$IPSET_BIN flush "${ip_name}-tmp"
|
||||
|
||||
sed -rn -e '/^#|^$/d' -e "s/^(.*)/add ${ip_name}-tmp \\1/p" "${IPSET_PATH}/${IPSET_FILE}.iplist" | $IPSET_BIN -quiet restore
|
||||
check_result $? "Populating ipset table"
|
||||
|
||||
$IPSET_BIN swap "${ip_name}-tmp" "${ip_name}"
|
||||
$IPSET_BIN -quiet destroy "${ip_name}-tmp"
|
||||
|
||||
# Generating timestamp
|
||||
time_n_date=$(date +'%T %F')
|
||||
time=$(echo "$time_n_date" | cut -f 1 -d \ )
|
||||
date=$(echo "$time_n_date" | cut -f 2 -d \ )
|
||||
|
||||
if [ ! -f "${IPSET_PATH}.conf" ] || [ -z "$(get_object_value "$ipset_hstobject" 'LISTNAME' "$ip_name" '$LISTNAME')" ]; then
|
||||
|
||||
# Concatenating rule
|
||||
str="LISTNAME='$ip_name' IP_VERSION='$ip_version' SOURCE='$data_source'"
|
||||
str="$str AUTOUPDATE='$autoupdate' SUSPENDED='no'"
|
||||
str="$str TIME='$time' DATE='$date'"
|
||||
echo "$str" >> $HESTIA/data/firewall/ipset.conf
|
||||
log_type="added"
|
||||
|
||||
elif [ "$refresh" = "yes" ]; then
|
||||
|
||||
# Update iplist last regen time
|
||||
update_object_value "$ipset_hstobject" 'LISTNAME' "$ip_name" '$TIME' "$time"
|
||||
update_object_value "$ipset_hstobject" 'LISTNAME' "$ip_name" '$DATE' "$date"
|
||||
log_type="refreshed"
|
||||
|
||||
fi
|
||||
|
||||
# Changing permissions
|
||||
chmod 660 $HESTIA/data/firewall/ipset.conf
|
||||
chmod 660 "${IPSET_PATH}/${IPSET_FILE}.iplist"
|
||||
|
||||
# Install ipset daily cron updater
|
||||
if ! grep --silent --no-messages "v-update-firewall-ipset" $HESTIA/data/queue/daily.pipe; then
|
||||
cmd="$BIN/v-update-firewall-ipset yes"
|
||||
echo "$cmd" >> $HESTIA/data/queue/daily.pipe
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "system" "Info" "Firewall" "IPset IP list ${log_type:-loaded} (Name: $ip_name, IP version: $ip_version, Autoupdate: $autoupdate)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
109
bin/v-add-firewall-rule
Executable file
109
bin/v-add-firewall-rule
Executable file
@@ -0,0 +1,109 @@
|
||||
#!/bin/bash
|
||||
# info: add firewall rule
|
||||
# options: ACTION IP PORT [PROTOCOL] [COMMENT] [RULE]
|
||||
#
|
||||
# example: v-add-firewall-rule DROP 185.137.111.77 25
|
||||
#
|
||||
# This function adds new rule to system firewall
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
action=$(echo $1 | tr '[:lower:]' '[:upper:]')
|
||||
ip=$2
|
||||
port_ext=$3
|
||||
protocol=${4-TCP}
|
||||
protocol=$(echo $protocol | tr '[:lower:]' '[:upper:]')
|
||||
comment=$5
|
||||
rule=$6
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# Get next firewall rule id
|
||||
get_next_fw_rule() {
|
||||
if [ -z "$rule" ]; then
|
||||
curr_str=$(grep "RULE=" $HESTIA/data/firewall/rules.conf \
|
||||
| cut -f 2 -d \' | sort -n | tail -n1)
|
||||
rule="$((curr_str + 1))"
|
||||
fi
|
||||
}
|
||||
|
||||
sort_fw_rules() {
|
||||
cat $HESTIA/data/firewall/rules.conf \
|
||||
| sort -n -k 2 -t \' > $HESTIA/data/firewall/rules.conf.tmp
|
||||
mv -f $HESTIA/data/firewall/rules.conf.tmp \
|
||||
$HESTIA/data/firewall/rules.conf
|
||||
}
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '3' "$#" 'ACTION IP PORT [PROTOCOL] [COMMENT] [RULE]'
|
||||
is_format_valid 'action' 'protocol' 'port_ext'
|
||||
is_system_enabled "$FIREWALL_SYSTEM" 'FIREWALL_SYSTEM'
|
||||
get_next_fw_rule
|
||||
is_format_valid 'rule'
|
||||
is_object_new '../../data/firewall/rules' 'RULE' "$rule"
|
||||
if [ -n "$comment" ]; then
|
||||
is_format_valid 'comment'
|
||||
fi
|
||||
if [[ "$ip" =~ ^ipset: ]]; then
|
||||
ipset_name="${ip#ipset:}"
|
||||
$BIN/v-list-firewall-ipset plain | grep "^$ipset_name\s" > /dev/null
|
||||
check_result $? 'ipset object not found' "$E_NOTEXIST"
|
||||
else
|
||||
is_format_valid 'ip'
|
||||
fi
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Generating timestamp
|
||||
time_n_date=$(date +'%T %F')
|
||||
time=$(echo "$time_n_date" | cut -f 1 -d \ )
|
||||
date=$(echo "$time_n_date" | cut -f 2 -d \ )
|
||||
|
||||
# Concatenating rule
|
||||
str="RULE='$rule' ACTION='$action' PROTOCOL='$protocol' PORT='$port_ext'"
|
||||
str="$str IP='$ip' COMMENT='$comment' SUSPENDED='no'"
|
||||
str="$str TIME='$time' DATE='$date'"
|
||||
|
||||
# Adding to config
|
||||
echo "$str" >> $HESTIA/data/firewall/rules.conf
|
||||
|
||||
# Changing permissions
|
||||
chmod 660 $HESTIA/data/firewall/rules.conf
|
||||
|
||||
# Sorting firewall rules by id number
|
||||
sort_fw_rules
|
||||
|
||||
# Updating system firewall
|
||||
$BIN/v-update-firewall
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Fix missing port value in log if zero
|
||||
if [ -z "$port" ]; then
|
||||
port="0"
|
||||
fi
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "system" "Info" "Firewall" "Added firewall rule (Action: $action, Port: $port, Protocol: $protocol)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
85
bin/v-add-fs-archive
Executable file
85
bin/v-add-fs-archive
Executable file
@@ -0,0 +1,85 @@
|
||||
#!/bin/bash
|
||||
# info: archive directory
|
||||
# options: USER ARCHIVE SOURCE [SOURCE...]
|
||||
#
|
||||
# example: v-add-fs-archive admin archive.tar readme.txt
|
||||
#
|
||||
# This function creates tar archive
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
user=$1
|
||||
archive=$2
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '3' "$#" 'USER ARCHIVE FILE [FILE_2] [FILE_3] [FILE ...]'
|
||||
is_format_valid 'user'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
# Checking user homedir
|
||||
homedir=$(grep "^$user:" /etc/passwd | cut -f 6 -d :)
|
||||
if [ -z "$homedir" ]; then
|
||||
echo "Error: user home directory doesn't exist"
|
||||
exit 12
|
||||
fi
|
||||
|
||||
# Checking archive
|
||||
if [ -e "$archive" ]; then
|
||||
echo "Error: archive already exist $archive"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Checking source path
|
||||
IFS=$'\n'
|
||||
i=1
|
||||
for src in $*; do
|
||||
if [ "$i" -gt 2 ]; then
|
||||
rpath=$(readlink -f "$src")
|
||||
if [ -z "$(echo $rpath | egrep "^/tmp|^$homedir")" ]; then
|
||||
echo "Error: invalid source path $src"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
((i++))
|
||||
done
|
||||
|
||||
i=1
|
||||
for src in $*; do
|
||||
if [ "$i" -gt 2 ]; then
|
||||
# Deleting leading home path
|
||||
src=$(echo "$src" | sed -e "s|/home/$user/||")
|
||||
|
||||
# Creating tar.gz archive
|
||||
user_exec tar -rf "${archive/.gz/}" -C /home/$user $src > /dev/null 2>&1
|
||||
if [ "$?" -ne 0 ]; then
|
||||
echo "Error: archive $archive was not created"
|
||||
exit 3
|
||||
fi
|
||||
fi
|
||||
((i++))
|
||||
done
|
||||
|
||||
# Checking gzip
|
||||
if [[ "$archive" =~ \.gz$ ]]; then
|
||||
user_exec gzip "${archive/.gz/}" > /dev/null 2>&1
|
||||
if [ "$?" -ne 0 ]; then
|
||||
echo "Error: archive $archive was not gziped"
|
||||
exit 3
|
||||
fi
|
||||
fi
|
||||
|
||||
exit
|
||||
55
bin/v-add-fs-directory
Executable file
55
bin/v-add-fs-directory
Executable file
@@ -0,0 +1,55 @@
|
||||
#!/bin/bash
|
||||
# info: add directory
|
||||
# options: USER DIRECTORY
|
||||
#
|
||||
# example: v-add-fs-directory admin mybar
|
||||
#
|
||||
# This function creates new directory on the file system
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
user=$1
|
||||
dst_dir=$2
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '2' "$#" 'USER DIR'
|
||||
is_format_valid 'user'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
# Checking user homedir
|
||||
homedir=$(grep "^$user:" /etc/passwd | cut -f 6 -d :)
|
||||
if [ -z "$homedir" ]; then
|
||||
echo "Error: user home directory doesn't exist"
|
||||
exit 12
|
||||
fi
|
||||
|
||||
# Checking destination path
|
||||
rpath=$(readlink -f "$dst_dir")
|
||||
if [ -z "$(echo $rpath | egrep "^/tmp|^$homedir")" ]; then
|
||||
echo "Error: invalid destination path $dst_dir"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# Adding directory
|
||||
user_exec mkdir -p "$dst_dir" > /dev/null 2>&1
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Error: directory $dst_dir was not created"
|
||||
exit 3
|
||||
fi
|
||||
|
||||
# Exiting
|
||||
exit
|
||||
55
bin/v-add-fs-file
Executable file
55
bin/v-add-fs-file
Executable file
@@ -0,0 +1,55 @@
|
||||
#!/bin/bash
|
||||
# info: add file
|
||||
# options: USER FILE
|
||||
#
|
||||
# example: v-add-fs-file admin readme.md
|
||||
#
|
||||
# This function creates new files on file system
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
user=$1
|
||||
dst_file=$2
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '2' "$#" 'USER FILE'
|
||||
is_format_valid 'user'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
# Checking user homedir
|
||||
homedir=$(grep "^$user:" /etc/passwd | cut -f 6 -d :)
|
||||
if [ -z $homedir ]; then
|
||||
echo "Error: user home directory doesn't exist"
|
||||
exit 12
|
||||
fi
|
||||
|
||||
# Checking destination path
|
||||
rpath=$(readlink -f "$dst_file")
|
||||
if [ -z "$(echo $rpath | egrep "^/tmp|^$homedir")" ]; then
|
||||
echo "Error: invalid destination path $dst_file"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# Creating file
|
||||
user_exec touch "$dst_file" > /dev/null 2>&1
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Error: file $dst_file was not created"
|
||||
exit 3
|
||||
fi
|
||||
|
||||
# Exiting
|
||||
exit
|
||||
629
bin/v-add-letsencrypt-domain
Executable file
629
bin/v-add-letsencrypt-domain
Executable file
@@ -0,0 +1,629 @@
|
||||
#!/bin/bash
|
||||
# info: check letsencrypt domain
|
||||
# options: USER DOMAIN [ALIASES] [MAIL]
|
||||
#
|
||||
# example: v-add-letsencrypt-domain admin wonderland.com www.wonderland.com,demo.wonderland.com
|
||||
# example: v-add-letsencrypt-domain admin wonderland.com '' yes
|
||||
#
|
||||
# This function check and validates domain with Let's Encrypt
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
aliases=$3
|
||||
mail=${4// /}
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# LE API
|
||||
LE_API='https://acme-v02.api.letsencrypt.org'
|
||||
|
||||
if [[ "$LE_STAGING" = 'yes' ]]; then
|
||||
LE_API='https://acme-staging-v02.api.letsencrypt.org'
|
||||
fi
|
||||
|
||||
# encode base64
|
||||
encode_base64() {
|
||||
cat | base64 | tr '+/' '-_' | tr -d '\r\n='
|
||||
}
|
||||
|
||||
# Let's Encrypt v2 curl function
|
||||
query_le_v2() {
|
||||
protected='{"nonce": "'$3'",'
|
||||
protected=''$protected' "url": "'$1'",'
|
||||
protected=''$protected' "alg": "RS256", "kid": "'$KID'"}'
|
||||
content="Content-Type: application/jose+json"
|
||||
|
||||
payload_=$(echo -n "$2" | encode_base64)
|
||||
protected_=$(echo -n "$protected" | encode_base64)
|
||||
signature_=$(printf "%s" "$protected_.$payload_" \
|
||||
| openssl dgst -sha256 -binary -sign $USER_DATA/ssl/user.key \
|
||||
| encode_base64)
|
||||
|
||||
post_data='{"protected":"'"$protected_"'",'
|
||||
post_data=$post_data'"payload":"'"$payload_"'",'
|
||||
post_data=$post_data'"signature":"'"$signature_"'"}'
|
||||
|
||||
# Save http response to file passed as "$4" arg or print to stdout if not provided
|
||||
# http response headers are always sent to stdout
|
||||
local save_to_file=${4:-"/dev/stdout"}
|
||||
curl --location --user-agent "HestiaCP" --insecure --retry 5 --retry-connrefused --silent --dump-header /dev/stdout --data "$post_data" "$1" --header "$content" --output "$save_to_file"
|
||||
debug_log "API call" "exit status: $?"
|
||||
}
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '2' "$#" 'USER DOMAIN [ALIASES] [MAIL]'
|
||||
is_format_valid 'user' 'domain' 'aliases'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
if [ -n "$mail" ]; then
|
||||
is_boolean_format_valid "$mail" 'mail'
|
||||
fi
|
||||
|
||||
# Set DNS CAA record retrieval commands
|
||||
if [ -n "$DNS_SYSTEM" ]; then
|
||||
dns_domain=$($BIN/v-list-dns-domains "$user" | grep "$domain" | cut -d' ' -f1)
|
||||
caa_record=$($BIN/v-list-dns-records "$user" "$domain" | grep -i "CAA" | grep -i "letsencrypt.org" | cut -d' ' -f1)
|
||||
fi
|
||||
|
||||
if [ -z "$mail" ] || [ "$mail" = 'no' ]; then
|
||||
mail=''
|
||||
is_system_enabled "$WEB_SYSTEM" 'WEB_SYSTEM'
|
||||
is_object_valid 'web' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'web' 'DOMAIN' "$domain"
|
||||
get_domain_values 'web'
|
||||
# check if alias is the letsencrypt wildcard domain, if not, make the normal checks
|
||||
if [[ "$aliases" != "*.$domain" ]]; then
|
||||
for alias in $(echo "$aliases" | tr ',' '\n' | sort -u); do
|
||||
check_alias="$(echo $ALIAS | tr ',' '\n' | grep ^$alias$)"
|
||||
if [ -z "$check_alias" ]; then
|
||||
check_result "$E_NOTEXIST" "domain alias $alias doesn't exist"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
else
|
||||
is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM'
|
||||
is_object_valid 'mail' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'mail' 'DOMAIN' "$domain"
|
||||
fi
|
||||
|
||||
# Dump debug info
|
||||
debug_log() {
|
||||
echo -e "\n==[${1}]==\n${2}\n" >> "$log_file"
|
||||
}
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Generate correct variables for mail domain SSL certificates
|
||||
if [ -n "$mail" ]; then
|
||||
root_domain=$domain
|
||||
domain="mail.$root_domain"
|
||||
webmail=$(get_object_value "mail" "DOMAIN" "$root_domain" '$WEBMAIL')
|
||||
if [ -n "$webmail" ]; then
|
||||
aliases="$WEBMAIL_ALIAS.$root_domain"
|
||||
fi
|
||||
else
|
||||
parse_object_kv_list $(grep "DOMAIN='$domain'" $USER_DATA/web.conf)
|
||||
|
||||
domain_redirect="$REDIRECT"
|
||||
if [[ -n "$domain_redirect" ]]; then
|
||||
domain_redirect_code="$REDIRECT_CODE"
|
||||
$BIN/v-delete-web-domain-redirect $user $domain
|
||||
fi
|
||||
|
||||
domain_forcessl="$SSL_FORCE"
|
||||
if [[ "$domain_forcessl" == 'yes' ]]; then
|
||||
$BIN/v-delete-web-domain-ssl-force $user $domain
|
||||
fi
|
||||
fi
|
||||
|
||||
log_file="/var/log/hestia/LE-${user}-${domain}.log"
|
||||
touch "$log_file"
|
||||
chmod 600 "$log_file"
|
||||
|
||||
echo -e "\n\n=============================
|
||||
Date Time: $(date +%Y-%m-%d) $(date +%H:%M:%S)
|
||||
WEB_SYSTEM: ${WEB_SYSTEM}
|
||||
PROXY_SYSTEM: ${PROXY_SYSTEM}
|
||||
user: ${user}
|
||||
domain: ${domain}
|
||||
" >> "$log_file"
|
||||
|
||||
# Registering LetsEncrypt user account
|
||||
$BIN/v-add-letsencrypt-user $user
|
||||
if [ "$?" -ne 0 ]; then
|
||||
touch $HESTIA/data/queue/letsencrypt.pipe
|
||||
sed -i "/ $domain /d" $HESTIA/data/queue/letsencrypt.pipe
|
||||
send_notice "LETSENCRYPT" "Account registration failed ($user)"
|
||||
check_result "$E_CONNECT" "LE account registration ($user)" > /dev/null
|
||||
fi
|
||||
|
||||
# Parsing LetsEncrypt account data
|
||||
source $USER_DATA/ssl/le.conf
|
||||
|
||||
# Checking wildcard alias
|
||||
if [ "$aliases" = "*.$domain" ]; then
|
||||
wildcard='yes'
|
||||
proto="dns-01"
|
||||
if [ ! -e "$HESTIA/data/users/$user/dns/$domain.conf" ]; then
|
||||
check_result "$E_NOTEXIST" "DNS domain $domain doesn't exist"
|
||||
fi
|
||||
else
|
||||
proto="http-01"
|
||||
fi
|
||||
|
||||
echo -e "
|
||||
- aliases: ${aliases}
|
||||
- proto: ${proto}
|
||||
- wildcard: ${wildcard}
|
||||
" >> "$log_file"
|
||||
|
||||
# Check if dns records exist for requested domain/aliases
|
||||
if [ "$proto" = "http-01" ]; then
|
||||
for identifier in $(echo $domain,$aliases | tr ',' '\n' | sort -u); do
|
||||
if [[ "$identifier" = *[![:ascii:]]* ]]; then
|
||||
identifier=$(idn2 --quiet $identifier)
|
||||
fi
|
||||
if ! nslookup "${identifier}" > /dev/null 2>&1; then
|
||||
# Attempt against Cloudflare DNS
|
||||
if ! nslookup "${identifier}" 1.1.1.1 > /dev/null 2>&1; then
|
||||
check_result "$E_NOTEXIST" "DNS record for $identifier doesn't exist"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
# Ensure DNS CAA record exists for Let's Encrypt before requesting certificate
|
||||
if [ -n "$DNS_SYSTEM" ]; then
|
||||
# Check for DNS zone
|
||||
if [ "$dns_domain" = "$domain" ]; then
|
||||
# Replace DNS domain CAA records with Let's Encrypt values
|
||||
if [ -z "$caa_record" ]; then
|
||||
$BIN/v-add-dns-record "$user" "$domain" '@' 'CAA' '0 issue "letsencrypt.org"'
|
||||
else
|
||||
$BIN/v-delete-dns-record "$user" "$domain" "$caa_record"
|
||||
$BIN/v-add-dns-record "$user" "$domain" '@' 'CAA' '0 issue "letsencrypt.org"'
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Requesting nonce / STEP 1
|
||||
answer=$(curl --user-agent "HestiaCP" -s -I "$LE_API/directory")
|
||||
nonce=$(echo "$answer" | grep -i nonce | cut -f2 -d \ | tr -d '\r\n')
|
||||
status=$(echo "$answer" | grep HTTP/ | tail -n1 | cut -f 2 -d ' ')
|
||||
|
||||
debug_log "Step 1" "- status: ${status}\n- nonce: ${nonce}\n- answer: ${answer}"
|
||||
|
||||
if [[ "$status" -ne 200 ]]; then
|
||||
# Delete DNS CAA record
|
||||
if [ -n "$DNS_SYSTEM" ]; then
|
||||
if [ "$dns_domain" = "$domain" ]; then
|
||||
if [ -n "$caa_record" ]; then
|
||||
$BIN/v-delete-dns-record "$user" "$domain" "$caa_record"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
check_result "$E_CONNECT" "Let's Encrypt nonce request status $status ($domain)"
|
||||
fi
|
||||
|
||||
# Placing new order / STEP 2
|
||||
url="$LE_API/acme/new-order"
|
||||
payload='{"identifiers":['
|
||||
for identifier in $(echo $domain,$aliases | tr ',' '\n' | sort -u); do
|
||||
if [[ "$identifier" = *[![:ascii:]]* ]]; then
|
||||
identifier=$(idn2 --quiet $identifier)
|
||||
fi
|
||||
payload=$payload'{"type":"dns","value":"'$identifier'"},'
|
||||
done
|
||||
payload=$(echo "$payload" | sed "s/,$//")
|
||||
payload=$payload']}'
|
||||
answer=$(query_le_v2 "$url" "$payload" "$nonce")
|
||||
nonce=$(echo "$answer" | grep -i nonce | cut -f2 -d \ | tr -d '\r\n')
|
||||
authz=$(echo "$answer" | grep "acme/authz" | cut -f2 -d '"')
|
||||
finalize=$(echo "$answer" | grep 'finalize":' | cut -f4 -d '"')
|
||||
status=$(echo "$answer" | grep HTTP/ | tail -n1 | cut -f2 -d ' ')
|
||||
order=$(echo -e "$answer" | grep -i location | cut -f2 -d \ | tr -d '\r\n')
|
||||
|
||||
debug_log "Step 2" "- status: ${status}\n- nonce: ${nonce}\n- authz: ${authz}\n- finalize: ${finalize}\n- payload: ${payload}\n- answer: ${answer}\n order: ${order}"
|
||||
|
||||
if [[ "$status" -ne 201 ]]; then
|
||||
# Delete DNS CAA record
|
||||
if [ -n "$DNS_SYSTEM" ]; then
|
||||
if [ "$dns_domain" = "$domain" ]; then
|
||||
if [ -n "$caa_record" ]; then
|
||||
$BIN/v-delete-dns-record "$user" "$domain" "$caa_record"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
check_result $E_CONNECT "Let's Encrypt new auth status $status ($domain)"
|
||||
fi
|
||||
|
||||
# Requesting authorization token / STEP 3
|
||||
for auth in $authz; do
|
||||
payload=''
|
||||
answer=$(query_le_v2 "$auth" "$payload" "$nonce")
|
||||
url=$(echo "$answer" | grep -A3 $proto | grep -m1 url | cut -f 4 -d \")
|
||||
token=$(echo "$answer" | grep -A3 $proto | grep token | cut -f 4 -d \")
|
||||
nonce=$(echo "$answer" | grep -i nonce | cut -f2 -d \ | tr -d '\r\n')
|
||||
status=$(echo "$answer" | grep HTTP/ | tail -n1 | cut -f 2 -d ' ')
|
||||
|
||||
debug_log "Step 3" "- status: ${status}\n- nonce: ${nonce}\n- url: ${url}\n- token: ${token}\n- answer: ${answer}"
|
||||
|
||||
if [[ "$status" -ne 200 ]]; then
|
||||
# Delete DNS CAA record
|
||||
if [ -n "$DNS_SYSTEM" ]; then
|
||||
dns_domain=$($BIN/v-list-dns-domains "$user" | grep "$domain" | cut -d' ' -f1)
|
||||
caa_record=$($BIN/v-list-dns-records "$user" "$domain" | grep -i "letsencrypt" | cut -d' ' -f1)
|
||||
|
||||
if [ "$dns_domain" = "$domain" ]; then
|
||||
if [ -n "$caa_record" ]; then
|
||||
$BIN/v-delete-dns-record "$user" "$domain" "$caa_record"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
check_result "$E_CONNECT" "Let's Encrypt acme/authz bad status $status ($domain)"
|
||||
fi
|
||||
|
||||
# Accepting challenge / STEP 4
|
||||
if [ "$wildcard" = 'yes' ]; then
|
||||
record=$(printf "%s" "$token.$THUMB" \
|
||||
| openssl dgst -sha256 -binary | encode_base64)
|
||||
old_records=$($BIN/v-list-dns-records "$user" "$domain" plain | grep 'TXT')
|
||||
old_records=$(echo "$old_records" | grep _acme-challenge | cut -f 1)
|
||||
for old_record in $old_records; do
|
||||
$BIN/v-delete-dns-record "$user" "$domain" "$old_record"
|
||||
done
|
||||
$BIN/v-add-dns-record "$user" "$domain" "_acme-challenge" "TXT" "$record"
|
||||
check_result $? "DNS _acme-challenge record wasn't created ($domain)"
|
||||
else
|
||||
if [ -z "$mail" ]; then
|
||||
if [ "$WEB_SYSTEM" = 'nginx' ] || [ "$PROXY_SYSTEM" = 'nginx' ]; then
|
||||
conf="$HOMEDIR/$user/conf/web/$domain/nginx.conf_letsencrypt"
|
||||
sconf="$HOMEDIR/$user/conf/web/$domain/nginx.ssl.conf_letsencrypt"
|
||||
echo 'location ~ "^/\.well-known/acme-challenge/([-_A-Za-z0-9]+)$" {' \
|
||||
> $conf
|
||||
echo ' default_type text/plain;' >> $conf
|
||||
echo ' return 200 "$1.'$THUMB'";' >> $conf
|
||||
echo '}' >> $conf
|
||||
if [ ! -e "$sconf" ]; then
|
||||
ln -s "$conf" "$sconf"
|
||||
fi
|
||||
if [ -n "$PROXY_SYSTEM" ]; then
|
||||
$BIN/v-restart-proxy
|
||||
check_result $? "Proxy restart failed" > /dev/null
|
||||
fi
|
||||
else
|
||||
# Get root directory from configuration
|
||||
domain_config="$HOMEDIR/$user/conf/web/$domain"
|
||||
if [ -f "$domain_config/apache2.conf" ]; then
|
||||
well_known="$(cat $domain_config/apache2.conf | egrep \
|
||||
'^\s+DocumentRoot' | awk '{split($0, a, " "); \
|
||||
print a[2]}')/.well-known"
|
||||
else
|
||||
well_known="$(cat $domain_config/nginx.conf | egrep '^\s+root' \
|
||||
| awk '{split($0, a, " "); print a[2]}' \
|
||||
| sed 's/;$//')/.well-known"
|
||||
fi
|
||||
acme_challenge="$well_known/acme-challenge"
|
||||
mkdir -p $acme_challenge
|
||||
echo "$token.$THUMB" > $acme_challenge/$token
|
||||
chown -R $user:$user $well_known
|
||||
fi
|
||||
else
|
||||
if [ "$WEB_SYSTEM" = 'nginx' ] || [ "$PROXY_SYSTEM" = 'nginx' ]; then
|
||||
conf="$HOMEDIR/$user/conf/mail/$root_domain/nginx.conf_letsencrypt"
|
||||
sconf="$HOMEDIR/$user/conf/mail/$root_domain/nginx.ssl.conf_letsencrypt"
|
||||
echo 'location ~ "^/\.well-known/acme-challenge/([-_A-Za-z0-9]+)$" {' \
|
||||
> $conf
|
||||
echo ' default_type text/plain;' >> $conf
|
||||
echo ' return 200 "$1.'$THUMB'";' >> $conf
|
||||
echo '}' >> $conf
|
||||
if [ ! -e "$sconf" ]; then
|
||||
ln -s "$conf" "$sconf"
|
||||
fi
|
||||
if [ -n "$PROXY_SYSTEM" ]; then
|
||||
$BIN/v-restart-proxy
|
||||
check_result $? "Proxy restart failed" > /dev/null
|
||||
fi
|
||||
else
|
||||
get_object_value 'mail' 'DOMAIN' "$root_domain" "WEBMAIL"
|
||||
if [ -n "$WEBMAIL" ]; then
|
||||
well_known="/var/lib/$WEBMAIL/.well-known"
|
||||
acme_challenge="$well_known/acme-challenge"
|
||||
mkdir -p $acme_challenge
|
||||
echo "$token.$THUMB" > $acme_challenge/$token
|
||||
chown -R $user:$user $well_known
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
if [ "$WEB_SYSTEM" = 'nginx' ]; then
|
||||
$BIN/v-restart-web
|
||||
check_result $? "Web restart failed" > /dev/null
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$DNS_CLUSTER" = "yes" ]; then
|
||||
$BIN/v-update-sys-queue dns-cluster
|
||||
fi
|
||||
|
||||
# Requesting ACME validation / STEP 5
|
||||
validation_check=$(echo "$answer" | grep '"valid"')
|
||||
if [[ -n "$validation_check" ]]; then
|
||||
validation='valid'
|
||||
else
|
||||
validation='pending'
|
||||
sleep 5
|
||||
fi
|
||||
|
||||
# Doing pol check on status
|
||||
i=1
|
||||
while [ "$validation" = 'pending' ]; do
|
||||
payload='{}'
|
||||
answer=$(query_le_v2 "$url" "$payload" "$nonce")
|
||||
validation=$(echo "$answer" | grep -A1 $proto | tail -n1 | cut -f4 -d \")
|
||||
nonce=$(echo "$answer" | grep -i nonce | cut -f2 -d \ | tr -d '\r\n')
|
||||
status=$(echo "$answer" | grep HTTP/ | tail -n1 | cut -f 2 -d ' ')
|
||||
details=$(echo "$answer" | grep detail | cut -f 1 -d ',' | cut -f 2-4 -d ':' | cut -f 2 -d '"')
|
||||
|
||||
debug_log "Step 5" "- status: ${status}\n- url: ${url}\n- nonce: ${nonce}\n- validation: ${validation}\n- details: ${details}\n- answer: ${answer}"
|
||||
|
||||
if [[ "$status" -ne 200 ]]; then
|
||||
# Delete DNS CAA record
|
||||
if [ -n "$DNS_SYSTEM" ]; then
|
||||
dns_domain=$($BIN/v-list-dns-domains "$user" | grep "$domain" | cut -d' ' -f1)
|
||||
caa_record=$($BIN/v-list-dns-records "$user" "$domain" | grep -i "letsencrypt" | cut -d' ' -f1)
|
||||
|
||||
if [ "$dns_domain" = "$domain" ]; then
|
||||
if [ -n "$caa_record" ]; then
|
||||
$BIN/v-delete-dns-record "$user" "$domain" "$caa_record"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
# Download debug info from LE server
|
||||
result=$(wget -qO- $url)
|
||||
debug_log "Debug information Step 5" "$result"
|
||||
details=$(echo $result | jq '.error.detail')
|
||||
error_code=$(echo $result | jq '.error.status')
|
||||
|
||||
debug_log "Abort Step 5" "=> Wrong status"
|
||||
check_result "$E_CONNECT" "Let's Encrypt validation status $status ($domain). Details: $error_code:$details"
|
||||
fi
|
||||
|
||||
i=$((i + 1))
|
||||
if [ "$i" -gt 10 ]; then
|
||||
# Delete DNS CAA record
|
||||
if [ -n "$DNS_SYSTEM" ]; then
|
||||
dns_domain=$($BIN/v-list-dns-domains "$user" | grep "$domain" | cut -d' ' -f1)
|
||||
caa_record=$($BIN/v-list-dns-records "$user" "$domain" | grep -i "letsencrypt" | cut -d' ' -f1)
|
||||
|
||||
if [ "$dns_domain" = "$domain" ]; then
|
||||
if [ -n "$caa_record" ]; then
|
||||
$BIN/v-delete-dns-record "$user" "$domain" "$caa_record"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
debug_log "Abort Step 5" "=> Too many validation retries"
|
||||
check_result "$E_CONNECT" "Let's Encrypt domain validation timeout ($domain)"
|
||||
fi
|
||||
sleep $((i * 2))
|
||||
done
|
||||
if [ "$validation" = 'invalid' ]; then
|
||||
# Delete DNS CAA record
|
||||
if [ -n "$DNS_SYSTEM" ]; then
|
||||
dns_domain=$($BIN/v-list-dns-domains "$user" | grep "$domain" | cut -d' ' -f1)
|
||||
caa_record=$($BIN/v-list-dns-records "$user" "$domain" | grep -i "letsencrypt" | cut -d' ' -f1)
|
||||
|
||||
if [ "$dns_domain" = "$domain" ]; then
|
||||
if [ -n "$caa_record" ]; then
|
||||
$BIN/v-delete-dns-record "$user" "$domain" "$caa_record"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
check_result "$E_CONNECT" "Let's Encrypt domain verification failed ($domain)"
|
||||
fi
|
||||
done
|
||||
|
||||
# Generating new ssl certificate
|
||||
ssl_dir=$($BIN/v-generate-ssl-cert "$domain" "info@$domain" "US" "California" \
|
||||
"San Francisco" "Hestia" "IT" "$aliases" | tail -n1 | awk '{print $2}')
|
||||
|
||||
# Sending CSR to finalize order / STEP 6
|
||||
csr=$(openssl req -in $ssl_dir/$domain.csr -outform DER | encode_base64)
|
||||
payload='{"csr":"'$csr'"}'
|
||||
answer=$(query_le_v2 "$finalize" "$payload" "$nonce")
|
||||
nonce=$(echo "$answer" | grep -i nonce | cut -f2 -d \ | tr -d '\r\n')
|
||||
status=$(echo "$answer" | grep HTTP/ | tail -n1 | cut -f 2 -d ' ')
|
||||
certificate=$(echo "$answer" | grep 'certificate":' | cut -f4 -d '"')
|
||||
|
||||
debug_log "Step 6" "- status: ${status}\n- nonce: ${nonce}\n- payload: ${payload}\n- certificate: ${certificate}\n- answer: ${answer}"
|
||||
|
||||
if [[ "$status" -ne 200 ]]; then
|
||||
[ -d "$ssl_dir" ] && rm -rf "$ssl_dir"
|
||||
check_result "$E_CONNECT" "Let's Encrypt finalize bad status $status ($domain)"
|
||||
fi
|
||||
|
||||
if [ -z "$certificate" ]; then
|
||||
validation="processing"
|
||||
i=1
|
||||
while [ "$validation" = "processing" ]; do
|
||||
answer=$(query_le_v2 "$order" "" "$nonce")
|
||||
i=$((i + 1))
|
||||
|
||||
nonce=$(echo "$answer" | grep -i nonce | cut -f2 -d \ | tr -d '\r\n')
|
||||
status=$(echo "$answer" | grep HTTP/ | tail -n1 | cut -f 2 -d ' ')
|
||||
validation=$(echo "$answer" | grep 'status":' | cut -f4 -d '"')
|
||||
certificate=$(echo "$answer" | grep 'certificate":' | cut -f4 -d '"')
|
||||
sleep $((i * 2)) # Sleep for 2s, 4s, 6s, 8s
|
||||
if [ $i -gt 10 ]; then
|
||||
check_result "$E_CONNECT" "Certificate processing timeout ($domain)"
|
||||
fi
|
||||
debug_log "Step 7" "- status: ${status}\n- nonce: ${nonce}\n- payload: ${payload}\n- certificate: ${certificate}\n- answer: ${answer}"
|
||||
done
|
||||
fi
|
||||
|
||||
# Downloading signed certificate / STEP 7
|
||||
status=0
|
||||
retry=0
|
||||
|
||||
while [[ $status != 200 && $retry -lt 3 ]]; do
|
||||
|
||||
answer=$(query_le_v2 "$certificate" "" "$nonce" "$ssl_dir/$domain.pem")
|
||||
status=$(echo "$answer" | grep HTTP/ | tail -n1 | cut -f 2 -d ' ')
|
||||
|
||||
debug_log "Step 8" "- status: ${status}\n- retry: ${retry}\n- answer: ${answer}"
|
||||
|
||||
if [[ $status != 200 ]]; then
|
||||
retry=$((retry + 1))
|
||||
sleep $((retry * 2)) # Sleep for 2s, 4s, 6s, 8s
|
||||
fi
|
||||
|
||||
done
|
||||
|
||||
# Fallback on depreciated download method for certs (unauthenticated GET)
|
||||
if [[ $status != 200 ]]; then
|
||||
answer=$(curl --insecure --user-agent "HestiaCP" --retry 5 --retry-connrefused --silent --dump-header /dev/stdout "$certificate" --output "$ssl_dir/$domain.pem")
|
||||
status=$(echo "$answer" | grep HTTP/ | tail -n1 | cut -f 2 -d ' ')
|
||||
|
||||
debug_log "Step 8 - Fallback" "- status: ${status}\n- answer: ${answer}"
|
||||
fi
|
||||
|
||||
debug_log "CERT DIR" "$(ls -las "$ssl_dir/")"
|
||||
debug_log "CERT PEM" "$(cat "$ssl_dir/$domain.pem")"
|
||||
|
||||
if [[ "$status" -ne 200 ]]; then
|
||||
[ -d "$ssl_dir" ] && rm -rf "$ssl_dir"
|
||||
check_result "$E_NOTEXIST" "Let's Encrypt downloading signed cert failed status:$status ($domain)"
|
||||
fi
|
||||
|
||||
# Splitting up downloaded pem
|
||||
crt_end=$(grep -n 'END CERTIFICATE' $ssl_dir/$domain.pem | head -n1 | cut -f1 -d:)
|
||||
head -n $crt_end $ssl_dir/$domain.pem > $ssl_dir/$domain.crt
|
||||
|
||||
pem_lines=$(wc -l $ssl_dir/$domain.pem | cut -f 1 -d ' ')
|
||||
ca_end=$(grep -n 'BEGIN CERTIFICATE' $ssl_dir/$domain.pem | tail -n1 | cut -f 1 -d :)
|
||||
ca_end=$((pem_lines - crt_end + 1))
|
||||
tail -n $ca_end $ssl_dir/$domain.pem > $ssl_dir/$domain.ca
|
||||
|
||||
debug_log "CERT CRT" "$(cat "$ssl_dir/$domain.crt")"
|
||||
debug_log "CERT CA-1" "$(cat "$ssl_dir/$domain.ca")"
|
||||
# Temporary fix for double "END CERTIFICATE"
|
||||
if [[ $(head -n 1 $ssl_dir/$domain.ca) = "-----END CERTIFICATE-----" ]]; then
|
||||
sed -i '1,2d' $ssl_dir/$domain.ca
|
||||
fi
|
||||
debug_log "CERT CA-2" "$(cat "$ssl_dir/$domain.ca")"
|
||||
|
||||
# Rename certs for mail
|
||||
if [ -n "$mail" ]; then
|
||||
mv $ssl_dir/$domain.ca $ssl_dir/$root_domain.ca
|
||||
mv $ssl_dir/$domain.crt $ssl_dir/$root_domain.crt
|
||||
mv $ssl_dir/$domain.csr $ssl_dir/$root_domain.csr
|
||||
mv $ssl_dir/$domain.key $ssl_dir/$root_domain.key
|
||||
mv $ssl_dir/$domain.pem $ssl_dir/$root_domain.pem
|
||||
fi
|
||||
|
||||
# Adding SSL
|
||||
if [ -z "$mail" ]; then
|
||||
ssl_home="$(get_object_value 'web' 'DOMAIN' "$domain" '$SSL_HOME')"
|
||||
ssl_enabled="$(get_object_value 'web' 'DOMAIN' "$domain" '$SSL')"
|
||||
if [ "$ssl_enabled" = "yes" ]; then
|
||||
$BIN/v-update-web-domain-ssl "$user" "$domain" "$ssl_dir" "updatessl"
|
||||
else
|
||||
$BIN/v-add-web-domain-ssl "$user" "$domain" "$ssl_dir" "$ssl_home" "updatessl"
|
||||
fi
|
||||
else
|
||||
# TODO replace with v-update-mail-domain-ssl if ssl is enabled
|
||||
ssl_enabled="$(get_object_value 'mail' 'DOMAIN' "$root_domain" '$SSL')"
|
||||
if [ "$ssl_enabled" = "yes" ]; then
|
||||
$BIN/v-update-mail-domain-ssl "$user" "$root_domain" "$ssl_dir" "updatessl"
|
||||
else
|
||||
$BIN/v-add-mail-domain-ssl "$user" "$root_domain" "$ssl_dir" "updatessl"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$?" -ne '0' ]; then
|
||||
[ -d "$ssl_dir" ] && rm -rf "$ssl_dir"
|
||||
touch $HESTIA/data/queue/letsencrypt.pipe
|
||||
sed -i "/ $domain /d" $HESTIA/data/queue/letsencrypt.pipe
|
||||
send_notice 'LETSENCRYPT' "$domain certificate installation failed ($domain)"
|
||||
check_result $? "SSL install" > /dev/null
|
||||
fi
|
||||
|
||||
# Adding LE autorenew cronjob
|
||||
if [ -z "$(grep v-update-lets $HESTIA/data/users/admin/cron.conf)" ]; then
|
||||
min=$(generate_password '012345' '2')
|
||||
hour=$(generate_password '1234567' '1')
|
||||
cmd="sudo $BIN/v-update-letsencrypt-ssl"
|
||||
$BIN/v-add-cron-job admin "$min" "$hour" '*' '*' '*' "$cmd" > /dev/null
|
||||
fi
|
||||
|
||||
# Updating letsencrypt key
|
||||
if [ -z "$mail" ]; then
|
||||
if [ -z "$LETSENCRYPT" ]; then
|
||||
add_object_key "web" 'DOMAIN' "$domain" 'LETSENCRYPT' 'FTP_USER'
|
||||
add_object_key "web" 'DOMAIN' "$domain" 'LETSENCRYPT_FAIL_COUNT' 'LETSENCRYPT'
|
||||
fi
|
||||
update_object_value 'web' 'DOMAIN' "$domain" '$LETSENCRYPT' 'yes'
|
||||
update_object_value 'web' 'DOMAIN' "$domain" '$LETSENCRYPT_FAIL_COUNT' "0"
|
||||
|
||||
if [[ "$domain_forcessl" == 'yes' ]]; then
|
||||
$BIN/v-add-web-domain-ssl-force $user $domain
|
||||
fi
|
||||
if [[ -n "$domain_redirect" ]]; then
|
||||
$BIN/v-add-web-domain-redirect $user $domain $domain_redirect $domain_redirect_code
|
||||
fi
|
||||
|
||||
else
|
||||
if [ -z "$LETSENCRYPT" ]; then
|
||||
add_object_key "mail" 'DOMAIN' "$root_domain" 'LETSENCRYPT'
|
||||
add_object_key "mail" 'DOMAIN' "$root_domain" 'LETSENCRYPT_FAIL_COUNT' 'LETSENCRYPT'
|
||||
fi
|
||||
update_object_value 'mail' 'DOMAIN' "$root_domain" '$LETSENCRYPT' 'yes'
|
||||
update_object_value 'mail' 'DOMAIN' "$root_domain" '$LETSENCRYPT_FAIL_COUNT' "0"
|
||||
fi
|
||||
|
||||
# Remove challenge folder if exist
|
||||
if [ -n "$well_known" ]; then
|
||||
rm -fr $well_known
|
||||
fi
|
||||
|
||||
# Remove temporary SSL folder
|
||||
[ -d "$ssl_dir" ] && rm -rf "$ssl_dir"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Deleting task from queue
|
||||
touch $HESTIA/data/queue/letsencrypt.pipe
|
||||
sed -i "/ $domain /d" $HESTIA/data/queue/letsencrypt.pipe
|
||||
|
||||
# Notifying user
|
||||
send_notice 'LETSENCRYPT' "$domain SSL has been installed successfully"
|
||||
|
||||
# Logging
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
# Cleanup debug since the SSL was issues successfully
|
||||
rm -f "$log_file"
|
||||
|
||||
exit
|
||||
98
bin/v-add-letsencrypt-host
Executable file
98
bin/v-add-letsencrypt-host
Executable file
@@ -0,0 +1,98 @@
|
||||
#!/bin/bash
|
||||
# info: add letsencrypt for host and backend
|
||||
# options: NONE
|
||||
#
|
||||
# example: v-add-letsencrypt-host
|
||||
#
|
||||
# This function check and validates the backend certificate and generate
|
||||
# a new let's encrypt certificate.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
# Argument definition
|
||||
domain=$(hostname -f)
|
||||
if [ -z $domain ]; then
|
||||
domain=$HOSTNAME
|
||||
fi
|
||||
user="$($BIN/v-search-domain-owner "$domain" web)"
|
||||
[[ -z "$user" ]] && user="admin"
|
||||
|
||||
USER_DATA=$HESTIA/data/users/$user
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
is_format_valid 'user' 'domain' 'aliases'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_system_enabled "$WEB_SYSTEM" 'WEB_SYSTEM'
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Check if hostname already exists as domain
|
||||
if [ "$($BIN/v-list-web-domain $user $domain plain | cut -f 1)" != "$domain" ]; then
|
||||
# Create web domain for hostname
|
||||
$BIN/v-add-web-domain "$user" "$domain"
|
||||
fi
|
||||
|
||||
# Validate web domain
|
||||
is_object_valid 'web' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'web' 'DOMAIN' "$domain"
|
||||
get_domain_values 'web'
|
||||
|
||||
# Load domain data
|
||||
parse_object_kv_list $(grep "DOMAIN='$domain'" $USER_DATA/web.conf)
|
||||
|
||||
# Set ssl installation to yes
|
||||
add_ssl="yes"
|
||||
|
||||
if [ "$SSL" = "yes" ]; then
|
||||
# Valildate SSL Certificate
|
||||
if [ -e "$USER_DATA/ssl/$domain.ca" ]; then
|
||||
if openssl verify -CAfile <(openssl x509 -in $USER_DATA/ssl/$domain.ca) $USER_DATA/ssl/$domain.pem | grep -q "$domain.pem: OK"; then
|
||||
add_ssl="no"
|
||||
fi
|
||||
else
|
||||
if openssl verify $USER_DATA/ssl/$domain.pem | grep -q "$domain.pem: OK"; then
|
||||
add_ssl="no"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Add let's encrypt ssl if needed
|
||||
if [ "$add_ssl" = "yes" ]; then
|
||||
# Add let's encrypt ssl
|
||||
$BIN/v-add-letsencrypt-domain "$user" "$domain"
|
||||
check_result $? "Let's Encrypt SSL creation failed" "$E_UPDATE"
|
||||
fi
|
||||
|
||||
# Add certificate to backend
|
||||
$BIN/v-update-host-certificate "$user" "$domain"
|
||||
|
||||
# Enable automatic ssl forward and hsts
|
||||
$BIN/v-add-web-domain-ssl-force "$user" "$domain" > /dev/null 2>&1
|
||||
$BIN/v-add-web-domain-ssl-hsts "$user" "$domain" > /dev/null 2>&1
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
exit
|
||||
148
bin/v-add-letsencrypt-user
Executable file
148
bin/v-add-letsencrypt-user
Executable file
@@ -0,0 +1,148 @@
|
||||
#!/bin/bash
|
||||
# info: register letsencrypt user account
|
||||
# options: USER
|
||||
#
|
||||
# example: v-add-letsencrypt-user bob
|
||||
#
|
||||
# This function creates and register LetsEncrypt account
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# LE API
|
||||
LE_API='https://acme-v02.api.letsencrypt.org'
|
||||
|
||||
if [[ "$LE_STAGING" = 'yes' ]]; then
|
||||
LE_API='https://acme-staging-v02.api.letsencrypt.org'
|
||||
fi
|
||||
|
||||
# encode base64
|
||||
encode_base64() {
|
||||
cat | base64 | tr '+/' '-_' | tr -d '\r\n='
|
||||
}
|
||||
|
||||
# Let's Encrypt v2 curl function
|
||||
query_le_v2() {
|
||||
protected='{"nonce": "'$3'",'
|
||||
protected=''$protected' "url": "'$1'",'
|
||||
protected=''$protected' "alg": "RS256", "jwk": '$jwk'}'
|
||||
content="Content-Type: application/jose+json"
|
||||
|
||||
payload_=$(echo -n "$2" | encode_base64)
|
||||
protected_=$(echo -n "$protected" | encode_base64)
|
||||
signature_=$(printf "%s" "$protected_.$payload_" \
|
||||
| openssl dgst -sha256 -binary -sign $USER_DATA/ssl/user.key \
|
||||
| encode_base64)
|
||||
|
||||
post_data='{"protected":"'"$protected_"'",'
|
||||
post_data=$post_data'"payload":"'"$payload_"'",'
|
||||
post_data=$post_data'"signature":"'"$signature_"'"}'
|
||||
|
||||
curl --user-agent "HestiaCP" -s -i -d "$post_data" "$1" -H "$content"
|
||||
}
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '1' "$#" 'USER'
|
||||
is_format_valid 'user'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
if [ -e "$USER_DATA/ssl/le.conf" ]; then
|
||||
source "$USER_DATA/ssl/le.conf"
|
||||
fi
|
||||
if [ -n "$KID" ]; then
|
||||
exit
|
||||
fi
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Defining user email
|
||||
if [[ -z "$EMAIL" ]]; then
|
||||
EMAIL=$(get_user_value '$CONTACT')
|
||||
fi
|
||||
|
||||
# Defining user agreement
|
||||
agreement=''
|
||||
|
||||
# Generating user key
|
||||
KEY="$USER_DATA/ssl/user.key"
|
||||
if [ ! -e "$KEY" ]; then
|
||||
openssl genrsa -out "$KEY" 4096 > /dev/null 2>&1
|
||||
chmod 600 $KEY
|
||||
fi
|
||||
|
||||
# Defining key exponent
|
||||
if [ -z "$EXPONENT" ]; then
|
||||
EXPONENT=$(openssl pkey -inform pem -in "$KEY" -noout -text_pub \
|
||||
| grep Exponent: | cut -f 2 -d '(' | cut -f 1 -d ')' | sed -e 's/x//' \
|
||||
| xxd -r -p | encode_base64)
|
||||
fi
|
||||
|
||||
# Defining key modulus
|
||||
if [ -z "$MODULUS" ]; then
|
||||
MODULUS=$(openssl rsa -in "$KEY" -modulus -noout \
|
||||
| sed -e 's/^Modulus=//' | xxd -r -p | encode_base64)
|
||||
fi
|
||||
|
||||
# Defining JWK
|
||||
jwk='{"e":"'$EXPONENT'","kty":"RSA","n":"'"$MODULUS"'"}'
|
||||
|
||||
# Defining key thumbnail
|
||||
if [ -z "$THUMB" ]; then
|
||||
THUMB="$(echo -n "$jwk" | openssl dgst -sha256 -binary | encode_base64)"
|
||||
fi
|
||||
|
||||
# Requesting ACME nonce
|
||||
nonce=$(curl -s -I "$LE_API/directory" | grep -i nonce | cut -f2 -d\ | tr -d '\r\n')
|
||||
|
||||
# Creating ACME account
|
||||
url="$LE_API/acme/new-acct"
|
||||
payload='{"termsOfServiceAgreed": true}'
|
||||
answer=$(query_le_v2 "$url" "$payload" "$nonce")
|
||||
kid=$(echo "$answer" | grep -i location: | cut -f2 -d ' ' | tr -d '\r')
|
||||
|
||||
# Checking answer status
|
||||
status=$(echo "$answer" | grep HTTP/ | tail -n1 | cut -f2 -d ' ')
|
||||
if [[ "${status:0:2}" -ne "20" ]]; then
|
||||
check_result "$E_CONNECT" "Let's Encrypt acc registration failed $status"
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Adding le.conf
|
||||
if [ ! -e "$USER_DATA/ssl/le.conf" ]; then
|
||||
echo "EXPONENT='$EXPONENT'" > $USER_DATA/ssl/le.conf
|
||||
echo "MODULUS='$MODULUS'" >> $USER_DATA/ssl/le.conf
|
||||
echo "THUMB='$THUMB'" >> $USER_DATA/ssl/le.conf
|
||||
echo "EMAIL='$EMAIL'" >> $USER_DATA/ssl/le.conf
|
||||
echo "KID='$kid'" >> $USER_DATA/ssl/le.conf
|
||||
chmod 660 $USER_DATA/ssl/le.conf
|
||||
else
|
||||
sed -i '/^KID=/d' $USER_DATA/ssl/le.conf
|
||||
echo "KID='$kid'" >> $USER_DATA/ssl/le.conf
|
||||
fi
|
||||
|
||||
# Logging
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
139
bin/v-add-mail-account
Executable file
139
bin/v-add-mail-account
Executable file
@@ -0,0 +1,139 @@
|
||||
#!/bin/bash
|
||||
# info: add mail domain account
|
||||
# options: USER DOMAIN ACCOUNT PASSWORD [QUOTA]
|
||||
#
|
||||
# example: v-add-mail-account user example.com john P4$$vvOrD
|
||||
#
|
||||
# This function add new email account.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
domain_idn=$2
|
||||
account=$3
|
||||
password=$4
|
||||
HIDE=4
|
||||
quota=${5-unlimited}
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# shellcheck source=/usr/local/hestia/func/syshealth.sh
|
||||
source $HESTIA/func/syshealth.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# Additional argument formatting
|
||||
if [[ "$account" =~ [[:upper:]] ]]; then
|
||||
account=$(echo "$account" | tr '[:upper:]' '[:lower:]')
|
||||
fi
|
||||
|
||||
format_domain
|
||||
format_domain_idn
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '4' "$#" 'USER DOMAIN ACCOUNT PASSWORD [QUOTA]'
|
||||
is_format_valid 'user' 'domain' 'account'
|
||||
if [ "$quota" != 'unlimited' ]; then
|
||||
is_format_valid 'quota'
|
||||
fi
|
||||
is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'mail' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'mail' 'DOMAIN' "$domain"
|
||||
is_package_full 'MAIL_ACCOUNTS'
|
||||
is_mail_new "$account"
|
||||
is_password_valid
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Generating hashed password
|
||||
|
||||
if [ -n "$(doveadm pw -l | grep BLF-CRYPT)" ]; then
|
||||
set +H # disable ! style history substitution
|
||||
md5="$(doveadm pw -s BLF-CRYPT -p "$password")"
|
||||
elif [ -n "$(doveadm pw -l | grep ARGON2ID)" ]; then
|
||||
# Fall back on Argon2id if bcrypt is not available
|
||||
set +H # disable ! style history substitution
|
||||
md5="$(doveadm pw -s ARGON2ID -p "$password")"
|
||||
else
|
||||
# Fall back on MD5 if neither bcrypt nor argon2id is available
|
||||
salt=$(generate_password "$PW_MATRIX" "8")
|
||||
md5="{MD5}$($BIN/v-generate-password-hash md5 $salt <<< $password)"
|
||||
fi
|
||||
# Adding account info into password file
|
||||
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
|
||||
fi
|
||||
|
||||
# Create mail account folder (mailbox)
|
||||
mkdir $HOMEDIR/$user/mail/$domain_idn/$account
|
||||
chown $user:mail $HOMEDIR/$user/mail/$domain_idn/$account
|
||||
chmod 700 $HOMEDIR/$user/mail/$domain_idn/$account
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Generating timestamp
|
||||
time_n_date=$(date +'%T %F')
|
||||
time=$(echo "$time_n_date" | cut -f 1 -d \ )
|
||||
date=$(echo "$time_n_date" | cut -f 2 -d \ )
|
||||
|
||||
if [[ "$quota" -eq '0' ]]; then
|
||||
quota='unlimited'
|
||||
fi
|
||||
|
||||
str="ACCOUNT='$account' ALIAS='' AUTOREPLY='no' FWD='' FWD_ONLY=''"
|
||||
str="$str MD5='$md5' QUOTA='$quota' U_DISK='0' SUSPENDED='no'"
|
||||
str="$str TIME='$time' DATE='$date'"
|
||||
echo "$str" >> $USER_DATA/mail/$domain.conf
|
||||
chmod 660 $USER_DATA/mail/$domain.conf
|
||||
|
||||
syshealth_repair_mail_account_config
|
||||
|
||||
touch $HOMEDIR/$user/conf/mail/$domain/limits
|
||||
|
||||
user_rate_limit=$(get_object_value 'mail' 'DOMAIN' "$domain" '$RATE_LIMIT')
|
||||
if [ -n "$user_rate_limit" ]; then
|
||||
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
|
||||
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
|
||||
|
||||
# Increase mail accounts counter
|
||||
accounts=$(wc -l $USER_DATA/mail/$domain.conf | cut -f 1 -d ' ')
|
||||
increase_user_value "$user" '$U_MAIL_ACCOUNTS'
|
||||
update_object_value 'mail' 'DOMAIN' "$domain" '$ACCOUNTS' "$accounts"
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "Mail" "Added new mail account ($account@$domain)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
80
bin/v-add-mail-account-alias
Executable file
80
bin/v-add-mail-account-alias
Executable file
@@ -0,0 +1,80 @@
|
||||
#!/bin/bash
|
||||
# info: add mail account alias aka nickname
|
||||
# options: USER DOMAIN ACCOUNT ALIAS
|
||||
#
|
||||
# example: v-add-mail-account-alias admin acme.com alice alicia
|
||||
#
|
||||
# This function add new email alias.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
domain_idn=$2
|
||||
account=$3
|
||||
malias=$4
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# Additional argument formatting
|
||||
format_domain
|
||||
format_domain_idn
|
||||
# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ?
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '4' "$#" 'USER DOMAIN ACCOUNT ALIAS'
|
||||
is_format_valid 'user' 'domain' 'account' 'malias'
|
||||
is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'mail' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'mail' 'DOMAIN' "$domain"
|
||||
is_object_valid "mail/$domain" 'ACCOUNT' "$account"
|
||||
is_object_unsuspended "mail/$domain" 'ACCOUNT' "$account"
|
||||
is_mail_new "$malias"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Adding exim alias
|
||||
if [[ "$MAIL_SYSTEM" =~ exim ]]; then
|
||||
str="$malias@$domain_idn:$account@$domain_idn"
|
||||
echo "$str" >> $HOMEDIR/$user/conf/mail/$domain/aliases
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Adding hestia alias
|
||||
aliases=$(get_object_value "mail/$domain" 'ACCOUNT' "$account" '$ALIAS')
|
||||
if [ -z "$aliases" ]; then
|
||||
aliases="$malias"
|
||||
else
|
||||
aliases="$aliases,$malias"
|
||||
fi
|
||||
update_object_value "mail/$domain" 'ACCOUNT' "$account" '$ALIAS' "$aliases"
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "Mail" "Added alias $malias to mail account $account@$domain."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
85
bin/v-add-mail-account-autoreply
Executable file
85
bin/v-add-mail-account-autoreply
Executable file
@@ -0,0 +1,85 @@
|
||||
#!/bin/bash
|
||||
# info: add mail account autoreply message
|
||||
# options: USER DOMAIN ACCOUNT MESSAGE
|
||||
#
|
||||
# example: v-add-mail-account-autoreply admin example.com user Hello from e-mail!
|
||||
#
|
||||
# This function add new email account.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
domain_idn=$2
|
||||
account=$3
|
||||
autoreply=$4
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# Define mail user
|
||||
if [ "$MAIL_SYSTEM" = 'exim4' ]; then
|
||||
MAIL_USER=Debian-exim
|
||||
else
|
||||
MAIL_USER=exim
|
||||
fi
|
||||
|
||||
# Additional argument formatting
|
||||
format_domain
|
||||
format_domain_idn
|
||||
# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ?
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '4' "$#" 'USER DOMAIN ACCOUNT MESSAGE'
|
||||
is_format_valid 'user' 'domain' 'account' 'autoreply'
|
||||
is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'mail' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'mail' 'DOMAIN' "$domain"
|
||||
is_object_valid "mail/$domain" 'ACCOUNT' "$account"
|
||||
is_object_unsuspended "mail/$domain" 'ACCOUNT' "$account"
|
||||
# is_object_value_empty "mail/$domain" 'ACCOUNT' "$account" '$AUTOREPLY'
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Adding exim autoreply
|
||||
if [[ "$MAIL_SYSTEM" =~ exim ]]; then
|
||||
msg="$HOMEDIR/$user/conf/mail/$domain/autoreply.$account.msg"
|
||||
echo -e "$autoreply" > $msg
|
||||
chown $MAIL_USER:mail $msg
|
||||
chmod 660 $msg
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Adding autoreply message
|
||||
echo -e "$autoreply" > $USER_DATA/mail/$account@$domain.msg
|
||||
chmod 660 $USER_DATA/mail/$account@$domain.msg
|
||||
update_object_value "mail/$domain" 'ACCOUNT' "$account" '$AUTOREPLY' 'yes'
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "Mail" "Added auto-reply message for mail account $account@$domain."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
88
bin/v-add-mail-account-forward
Executable file
88
bin/v-add-mail-account-forward
Executable file
@@ -0,0 +1,88 @@
|
||||
#!/bin/bash
|
||||
# info: add mail account forward address
|
||||
# options: USER DOMAIN ACCOUNT FORWARD
|
||||
#
|
||||
# example: v-add-mail-account-forward admin acme.com alice bob
|
||||
#
|
||||
# This function add new email account.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
domain_idn=$2
|
||||
account=$3
|
||||
email_forward=$4
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# Additional argument formatting
|
||||
format_domain
|
||||
format_domain_idn
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '4' "$#" 'USER DOMAIN ACCOUNT FORWARD'
|
||||
is_format_valid 'user' 'domain' 'account'
|
||||
if [ "$email_forward" != ':blackhole:' ]; then
|
||||
is_format_valid 'email_forward'
|
||||
fi
|
||||
is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'mail' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'mail' 'DOMAIN' "$domain"
|
||||
is_object_valid "mail/$domain" 'ACCOUNT' "$account"
|
||||
is_object_unsuspended "mail/$domain" 'ACCOUNT' "$account"
|
||||
fwd=$(get_object_value "mail/$domain" 'ACCOUNT' "$account" '$FWD')
|
||||
if [ -n "$(echo $fwd | grep -w "$email_forward")" ]; then
|
||||
echo "Error: forward $email_forward exists"
|
||||
log_event "$E_EXISTS" "$ARGUMENTS"
|
||||
exit $E_EXISTS
|
||||
fi
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Define fwd string
|
||||
if [ -z "$fwd" ]; then
|
||||
fwd="$email_forward"
|
||||
else
|
||||
fwd="$fwd,$email_forward"
|
||||
fi
|
||||
|
||||
# Adding forward to exim
|
||||
if [[ "$MAIL_SYSTEM" =~ exim ]]; then
|
||||
sed -i "/^$account@$domain_idn:/ d" $HOMEDIR/$user/conf/mail/$domain/aliases
|
||||
echo "$account@$domain_idn:$fwd" >> $HOMEDIR/$user/conf/mail/$domain/aliases
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Updating config
|
||||
update_object_value "mail/$domain" 'ACCOUNT' "$account" '$FWD' "$fwd"
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Warning" "Mail" "Mail forwarding on mail account $account@$domain enabled (send to: $email_forward)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
86
bin/v-add-mail-account-fwd-only
Executable file
86
bin/v-add-mail-account-fwd-only
Executable file
@@ -0,0 +1,86 @@
|
||||
#!/bin/bash
|
||||
# info: add mail account forward-only flag
|
||||
# options: USER DOMAIN ACCOUNT
|
||||
#
|
||||
# example: v-add-mail-account-fwd-only admin example.com user
|
||||
#
|
||||
# This function adds fwd-only flag
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
domain_idn=$2
|
||||
account=$3
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# Define mail user
|
||||
if [ "$MAIL_SYSTEM" = 'exim4' ]; then
|
||||
MAIL_USER=Debian-exim
|
||||
else
|
||||
MAIL_USER=exim
|
||||
fi
|
||||
|
||||
# Additional argument formatting
|
||||
format_domain
|
||||
format_domain_idn
|
||||
# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ?
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '3' "$#" 'USER DOMAIN ACCOUNT'
|
||||
is_format_valid 'user' 'domain' 'account'
|
||||
is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'mail' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'mail' 'DOMAIN' "$domain"
|
||||
is_object_valid "mail/$domain" 'ACCOUNT' "$account"
|
||||
is_object_unsuspended "mail/$domain" 'ACCOUNT' "$account"
|
||||
fwd=$(get_object_value "mail/$domain" 'ACCOUNT' "$account" '$FWD')
|
||||
if [ -z "$fwd" ]; then
|
||||
echo "Error: forward doesn't exist"
|
||||
log_event "$E_NOTEXIST" "$ARGUMENTS"
|
||||
exit "$E_NOTEXIST"
|
||||
fi
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Adding account to fwd_only
|
||||
if [[ "$MAIL_SYSTEM" =~ exim ]]; then
|
||||
echo "$account" >> $HOMEDIR/$user/conf/mail/$domain/fwd_only
|
||||
chown -R $MAIL_USER:mail $HOMEDIR/$user/conf/mail/$domain/fwd_only
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Updating config
|
||||
add_object_key "mail/$domain" 'ACCOUNT' "$account" 'FWD_ONLY' 'MD5'
|
||||
update_object_value "mail/$domain" 'ACCOUNT' "$account" '$FWD_ONLY' "yes"
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Warning" "Mail" "Forward-only flag enabled on mail account $account@$domain."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
224
bin/v-add-mail-domain
Executable file
224
bin/v-add-mail-domain
Executable file
@@ -0,0 +1,224 @@
|
||||
#!/bin/bash
|
||||
# info: add mail domain
|
||||
# options: USER DOMAIN [ANTISPAM] [ANTIVIRUS] [DKIM] [DKIM_SIZE] [RESTART] [REJECT_SPAM]
|
||||
#
|
||||
# example: v-add-mail-domain admin mydomain.tld
|
||||
#
|
||||
# This function adds MAIL domain.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
antispam=${3-yes}
|
||||
antivirus=${4-yes}
|
||||
dkim=${5-yes}
|
||||
dkim_size=${6-1024}
|
||||
restart="$7"
|
||||
reject=${8-no}
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# shellcheck source=/usr/local/hestia/func/ip.sh
|
||||
source $HESTIA/func/ip.sh
|
||||
# shellcheck source=/usr/local/hestia/func/syshealth.sh
|
||||
source $HESTIA/func/syshealth.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# Define mail user
|
||||
if [ "$MAIL_SYSTEM" = 'exim4' ]; then
|
||||
MAIL_USER=Debian-exim
|
||||
else
|
||||
MAIL_USER=exim
|
||||
fi
|
||||
|
||||
# Additional argument formatting
|
||||
format_domain
|
||||
format_domain_idn
|
||||
domain_utf=$(idn2 --quiet -d "$domain_idn")
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '2' "$#" 'USER DOMAIN [ANTISPAM] [ANTIVIRUS] [DKIM] [DKIM_SIZE] [RESTART] [REJECT_SPAM]'
|
||||
is_format_valid 'user' 'domain' 'antispam' 'antivirus' 'dkim' 'dkim_size' 'restart' 'reject'
|
||||
is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
|
||||
if [ "$($BIN/v-list-mail-domain $user $domain_utf plain | cut -f 1) " != "$domain" ]; then
|
||||
is_domain_new 'mail' "$domain_utf"
|
||||
fi
|
||||
if [ "$($BIN/v-list-mail-domain $user $domain_idn plain | cut -f 1) " != "$domain" ]; then
|
||||
is_domain_new 'mail' "$domain_idn"
|
||||
else
|
||||
is_domain_new 'mail' "$domain"
|
||||
fi
|
||||
if [ -z "$(is_ip_format_valid $domain)" ]; then
|
||||
echo "Error: Invalid domain format. IP address detected as input."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
is_package_full 'MAIL_DOMAINS'
|
||||
is_dir_symlink $HOMEDIR/$user/mail
|
||||
|
||||
is_base_domain_owner "$domain"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
source_conf "$USER_DATA/user.conf"
|
||||
# Inherit web domain local ip address
|
||||
domain_ip=$(get_object_value 'web' 'DOMAIN' "$domain" '$IP')
|
||||
if [ ! -z "$domain_ip" ]; then
|
||||
local_ip=$(get_real_ip "$domain_ip")
|
||||
is_ip_valid "$local_ip" "$user"
|
||||
else
|
||||
get_user_ip
|
||||
fi
|
||||
|
||||
# Generating timestamp
|
||||
new_timestamp
|
||||
|
||||
if [ -z "$ANTISPAM_SYSTEM" ]; then
|
||||
antispam="no"
|
||||
reject="no"
|
||||
fi
|
||||
if [ -z "$ANTIVIRUS_SYSTEM" ]; then
|
||||
antivirus="no"
|
||||
fi
|
||||
|
||||
# Adding domain to mail.conf
|
||||
s="DOMAIN='$domain' ANTIVIRUS='$antivirus' ANTISPAM='$antispam' REJECT='$reject' DKIM='$dkim' WEBMAIL=''"
|
||||
s="$s SSL='no' LETSENCRYPT='no' CATCHALL='' ACCOUNTS='0' RATE_LIMIT='$RATE_LIMIT' U_DISK='0' SUSPENDED='no' TIME='$time'"
|
||||
s="$s DATE='$date'"
|
||||
echo $s >> $USER_DATA/mail.conf
|
||||
touch $USER_DATA/mail/$domain.conf
|
||||
|
||||
syshealth_repair_mail_config
|
||||
|
||||
# Generating DKIM keys
|
||||
if [ "$dkim" = 'yes' ]; then
|
||||
openssl genrsa -out $USER_DATA/mail/$domain.pem $dkim_size &> /dev/null
|
||||
openssl rsa -pubout -in $USER_DATA/mail/$domain.pem \
|
||||
-out $USER_DATA/mail/$domain.pub &> /dev/null
|
||||
fi
|
||||
|
||||
# Set permissions
|
||||
chmod 660 $USER_DATA/mail/$domain.*
|
||||
chmod 660 $USER_DATA/mail.conf
|
||||
|
||||
# Building exim configs
|
||||
if [[ "$MAIL_SYSTEM" =~ exim ]]; then
|
||||
mkdir $HOMEDIR/$user/conf/mail/$domain
|
||||
mkdir $HOMEDIR/$user/mail/$domain_idn
|
||||
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/accounts
|
||||
ln -s $HOMEDIR/$user/conf/mail/$domain \
|
||||
/etc/$MAIL_SYSTEM/domains/$domain_idn
|
||||
|
||||
# Seeting outgoing ip address
|
||||
if [ -n "$local_ip" ]; then
|
||||
echo "$local_ip" > $HOMEDIR/$user/conf/mail/$domain/ip
|
||||
fi
|
||||
|
||||
if [ -n "$ANTISPAM_SYSTEM" ]; then
|
||||
# Adding antispam protection
|
||||
if [ "$antispam" = 'yes' ]; then
|
||||
touch "$HOMEDIR/$user/conf/mail/$domain/antispam"
|
||||
fi
|
||||
if [ "$reject" = 'yes' ]; then
|
||||
touch "$HOMEDIR/$user/conf/mail/$domain/reject_spam"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -n "$ANTIVIRUS_SYSTEM" ]; then
|
||||
# Adding antivirus protection
|
||||
if [ "$antivirus" = 'yes' ]; then
|
||||
touch "$HOMEDIR/$user/conf/mail/$domain/antivirus"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Adding dkim support
|
||||
if [ "$dkim" = 'yes' ]; then
|
||||
cp -f $USER_DATA/mail/$domain.pem \
|
||||
$HOMEDIR/$user/conf/mail/$domain/dkim.pem
|
||||
fi
|
||||
|
||||
# Set permission
|
||||
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
|
||||
|
||||
# Set ownership
|
||||
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
|
||||
|
||||
# Adding dkim dns records
|
||||
if [ -n "$DNS_SYSTEM" ] && [ "$dkim" = 'yes' ]; then
|
||||
check_dns_domain=$(is_object_valid 'dns' 'DOMAIN' "$domain")
|
||||
if [ "$?" -eq 0 ]; then
|
||||
p=$(cat $USER_DATA/mail/$domain.pub | grep -v ' KEY---' | tr -d '\n')
|
||||
record='_domainkey'
|
||||
policy="\"t=y; o=~;\""
|
||||
$BIN/v-add-dns-record "$user" "$domain" "$record" TXT "$policy" '' '' 'no' '' 'yes'
|
||||
|
||||
record='mail._domainkey'
|
||||
selector="\"v=DKIM1\; k=rsa\; p=$p\""
|
||||
$BIN/v-add-dns-record "$user" "$domain" "$record" TXT "$selector" '' '' 'yes' '' 'yes'
|
||||
fi
|
||||
fi
|
||||
|
||||
# Add webmail configuration to mail domain
|
||||
if [ -n "$WEB_SYSTEM" ] || [ -n "$PROXY_SYSTEM" ]; then
|
||||
if [ -n "$IMAP_SYSTEM" ]; then
|
||||
$BIN/v-add-mail-domain-webmail "$user" "$domain" '' 'no'
|
||||
fi
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Increasing domain value
|
||||
increase_user_value "$user" '$U_MAIL_DOMAINS'
|
||||
|
||||
if [ "$dkim" = 'yes' ]; then
|
||||
increase_user_value "$user" '$U_MAIL_DKIM'
|
||||
fi
|
||||
|
||||
# Restarting web server
|
||||
$BIN/v-restart-web "$restart"
|
||||
check_result $? "Web restart failed" > /dev/null
|
||||
|
||||
# Restarting proxy server
|
||||
$BIN/v-restart-proxy "$restart"
|
||||
check_result $? "Proxy restart failed" > /dev/null
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "Mail" "Added new mail domain ($domain)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
69
bin/v-add-mail-domain-antispam
Executable file
69
bin/v-add-mail-domain-antispam
Executable file
@@ -0,0 +1,69 @@
|
||||
#!/bin/bash
|
||||
# info: add mail domain antispam support
|
||||
# options: USER DOMAIN
|
||||
#
|
||||
# example: v-add-mail-domain-antispam admin mydomain.tld
|
||||
#
|
||||
# This function enables spamassasin for incoming emails.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
domain_idn=$2
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# Additional argument formatting
|
||||
format_domain
|
||||
format_domain_idn
|
||||
# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ?
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '2' "$#" 'USER DOMAIN'
|
||||
is_format_valid 'user' 'domain'
|
||||
is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'mail' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'mail' 'DOMAIN' "$domain"
|
||||
is_object_value_empty 'mail' 'DOMAIN' "$domain" '$ANTISPAM'
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Adding antispam flag
|
||||
if [[ "$MAIL_SYSTEM" =~ exim ]]; then
|
||||
touch $HOMEDIR/$user/conf/mail/$domain/antispam
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Adding antispam in config
|
||||
update_object_value 'mail' 'DOMAIN' "$domain" '$ANTISPAM' 'yes'
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "Mail" "Anti-spam protection enabled (Domain: $domain)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
69
bin/v-add-mail-domain-antivirus
Executable file
69
bin/v-add-mail-domain-antivirus
Executable file
@@ -0,0 +1,69 @@
|
||||
#!/bin/bash
|
||||
# info: add mail domain antivirus support
|
||||
# options: USER DOMAIN
|
||||
#
|
||||
# example: v-add-mail-domain-antivirus admin mydomain.tld
|
||||
#
|
||||
# This function enables clamav scan for incoming emails.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
domain_idn=$2
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# Additional argument formatting
|
||||
format_domain
|
||||
format_domain_idn
|
||||
# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ?
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '2' "$#" 'USER DOMAIN'
|
||||
is_format_valid 'user' 'domain'
|
||||
is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'mail' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'mail' 'DOMAIN' "$domain"
|
||||
is_object_value_empty 'mail' 'DOMAIN' "$domain" '$ANTIVIRUS'
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Adding antivirus flag
|
||||
if [[ "$MAIL_SYSTEM" =~ exim ]]; then
|
||||
touch $HOMEDIR/$user/conf/mail/$domain/antivirus
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Adding antivirus in config
|
||||
update_object_value 'mail' 'DOMAIN' "$domain" '$ANTIVIRUS' 'yes'
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "Mail" "Anti-virus scanning enabled (Domain: $domain)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
70
bin/v-add-mail-domain-catchall
Executable file
70
bin/v-add-mail-domain-catchall
Executable file
@@ -0,0 +1,70 @@
|
||||
#!/bin/bash
|
||||
# info: add mail domain catchall account
|
||||
# options: USER DOMAIN EMAIL
|
||||
#
|
||||
# example: v-add-mail-domain-catchall admin example.com master@example.com
|
||||
#
|
||||
# This function enables catchall account for incoming emails.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
domain_idn=$2
|
||||
email="$3"
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# Additional argument formatting
|
||||
format_domain
|
||||
format_domain_idn
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '3' "$#" 'USER DOMAIN EMAIL'
|
||||
is_format_valid 'user' 'domain' 'email'
|
||||
is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'mail' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'mail' 'DOMAIN' "$domain"
|
||||
is_object_value_empty 'mail' 'DOMAIN' "$domain" '$CATCHALL'
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Adding catchall alias
|
||||
if [[ "$MAIL_SYSTEM" =~ exim ]]; then
|
||||
sed -i "/*@$domain_idn:/d" $HOMEDIR/$user/conf/mail/$domain/aliases
|
||||
echo "*@$domain_idn:$email" >> $HOMEDIR/$user/conf/mail/$domain/aliases
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Adding antispam in config
|
||||
update_object_value 'mail' 'DOMAIN' "$domain" '$CATCHALL' "$email"
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Warning" "Mail" "Catch-all forwarding enabled (Domain: $domain, Send to: $email)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
98
bin/v-add-mail-domain-dkim
Executable file
98
bin/v-add-mail-domain-dkim
Executable file
@@ -0,0 +1,98 @@
|
||||
#!/bin/bash
|
||||
# info: add mail domain dkim support
|
||||
# options: USER DOMAIN [DKIM_SIZE]
|
||||
#
|
||||
# example: v-add-mail-domain-dkim admin acme.com
|
||||
#
|
||||
# This function adds DKIM signature to outgoing domain emails.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
domain_idn=$2
|
||||
dkim_size=${3-2048}
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# Define mail user
|
||||
if [ "$MAIL_SYSTEM" = 'exim4' ]; then
|
||||
MAIL_USER=Debian-exim
|
||||
else
|
||||
MAIL_USER=exim
|
||||
fi
|
||||
|
||||
# Additional argument formatting
|
||||
format_domain
|
||||
format_domain_idn
|
||||
# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ?
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '2' "$#" 'USER DOMAIN [DKIM_SIZE]'
|
||||
is_format_valid 'user' 'domain' 'dkim_size'
|
||||
is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'mail' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'mail' 'DOMAIN' "$domain"
|
||||
is_object_value_empty 'mail' 'DOMAIN' "$domain" '$DKIM'
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Generating dkim
|
||||
openssl genrsa -out $USER_DATA/mail/$domain.pem $dkim_size &> /dev/null
|
||||
openssl rsa -pubout -in $USER_DATA/mail/$domain.pem \
|
||||
-out $USER_DATA/mail/$domain.pub &> /dev/null
|
||||
chmod 660 $USER_DATA/mail/$domain.*
|
||||
|
||||
# Adding dkim keys
|
||||
if [[ "$MAIL_SYSTEM" =~ exim ]]; then
|
||||
cp $USER_DATA/mail/$domain.pem $HOMEDIR/$user/conf/mail/$domain/dkim.pem
|
||||
chown $MAIL_USER:mail $HOMEDIR/$user/conf/mail/$domain/dkim.pem
|
||||
chmod 660 $HOMEDIR/$user/conf/mail/$domain/dkim.pem
|
||||
fi
|
||||
|
||||
# Adding dns records
|
||||
if [ -n "$DNS_SYSTEM" ] && [ -e "$USER_DATA/dns/$domain.conf" ]; then
|
||||
p=$(cat $USER_DATA/mail/$domain.pub | grep -v ' KEY---' | tr -d '\n')
|
||||
record="_domainkey"
|
||||
policy="\"t=y\; o=~\;\""
|
||||
$BIN/v-add-dns-record "$user" "$domain" "$record" TXT "$policy" '' '' 'no' '' 'yes'
|
||||
|
||||
record="mail._domainkey"
|
||||
selector="\"v=DKIM1\; k=rsa\; p=$p\""
|
||||
$BIN/v-add-dns-record "$user" "$domain" "$record" TXT "$selector" '' '' 'yes' '' 'yes'
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Adding dkim in config
|
||||
update_object_value 'mail' 'DOMAIN' "$domain" '$DKIM' 'yes'
|
||||
increase_user_value "$user" '$U_MAIL_DKIM'
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "Mail" "DKIM message signing enabled (Domain: $domain)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
71
bin/v-add-mail-domain-reject
Executable file
71
bin/v-add-mail-domain-reject
Executable file
@@ -0,0 +1,71 @@
|
||||
#!/bin/bash
|
||||
# info: add mail domain reject spam support
|
||||
# options: USER DOMAIN
|
||||
# labels: mail
|
||||
#
|
||||
# example: v-add-mail-domain-reject admin mydomain.tld
|
||||
#
|
||||
# The function enables spam rejection for incoming emails.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variable&Function #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
domain_idn=$2
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# Additional argument formatting
|
||||
format_domain
|
||||
format_domain_idn
|
||||
# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ?
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '2' "$#" 'USER DOMAIN'
|
||||
is_format_valid 'user' 'domain'
|
||||
is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'mail' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'mail' 'DOMAIN' "$domain"
|
||||
is_object_value_empty 'mail' 'DOMAIN' "$domain" '$REJECT'
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Adding antivirus flag
|
||||
if [[ "$MAIL_SYSTEM" =~ exim ]]; then
|
||||
# Reject spam > 10 when enabled
|
||||
touch $HOMEDIR/$user/conf/mail/$domain/reject_spam
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Adding antivirus in config
|
||||
update_object_value 'mail' 'DOMAIN' "$domain" '$REJECT' 'yes'
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "Mail" "Anti-virus scanning enabled (Domain: $domain)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
81
bin/v-add-mail-domain-smtp-relay
Executable file
81
bin/v-add-mail-domain-smtp-relay
Executable file
@@ -0,0 +1,81 @@
|
||||
#!/bin/bash
|
||||
# info: Add mail domain smtp relay support
|
||||
# options: USER DOMAIN HOST [USERNAME] [PASSWORD] [PORT]
|
||||
#
|
||||
# example: v-add-mail-domain-smtp-relay user domain.tld srv.smtprelay.tld uname123 pass12345
|
||||
#
|
||||
# This function adds mail domain smtp relay support.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
host=$3
|
||||
username=$4
|
||||
password=$5
|
||||
port=${6-587}
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '3' "$#" 'USER DOMAIN HOST [USERNAME] [PASSWORD] [PORT]'
|
||||
is_format_valid 'port' 'user' 'domain' 'host'
|
||||
is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'mail' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'mail' 'DOMAIN' "$domain"
|
||||
is_password_valid "$password" "Password"
|
||||
is_username_format_valid "$username" "Username"
|
||||
format_no_quotes "$password" "Password"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
cat > /etc/exim4/domains/${domain}/smtp_relay.conf << EOL
|
||||
host:$host
|
||||
port:$port
|
||||
user:$username
|
||||
pass:$password
|
||||
EOL
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Adding smtp relay values in config
|
||||
if [ -z "$U_SMTP_RELAY" ]; then
|
||||
add_object_key 'mail' 'DOMAIN' "$domain" 'U_SMTP_RELAY' 'ACCOUNTS'
|
||||
add_object_key 'mail' 'DOMAIN' "$domain" 'U_SMTP_RELAY_HOST' 'ACCOUNTS'
|
||||
add_object_key 'mail' 'DOMAIN' "$domain" 'U_SMTP_RELAY_PORT' 'ACCOUNTS'
|
||||
add_object_key 'mail' 'DOMAIN' "$domain" 'U_SMTP_RELAY_USERNAME' 'ACCOUNTS'
|
||||
add_object_key 'mail' 'DOMAIN' "$domain" 'U_SMTP_RELAY_PASSWORD' 'ACCOUNTS'
|
||||
fi
|
||||
|
||||
update_object_value 'mail' 'DOMAIN' "$domain" '$U_SMTP_RELAY' 'true'
|
||||
update_object_value 'mail' 'DOMAIN' "$domain" '$U_SMTP_RELAY_HOST' "$host"
|
||||
update_object_value 'mail' 'DOMAIN' "$domain" '$U_SMTP_RELAY_PORT' "$port"
|
||||
update_object_value 'mail' 'DOMAIN' "$domain" '$U_SMTP_RELAY_USERNAME' "$username"
|
||||
update_object_value 'mail' 'DOMAIN' "$domain" '$U_SMTP_RELAY_PASSWORD' "$password"
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "Mail" "SMTP Relay enabled (Domain: $domain, Host: $host, Port: $port)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
144
bin/v-add-mail-domain-ssl
Executable file
144
bin/v-add-mail-domain-ssl
Executable file
@@ -0,0 +1,144 @@
|
||||
#!/bin/bash
|
||||
# info: add mail SSL for $domain
|
||||
# options: USER DOMAIN SSL_DIR [RESTART]
|
||||
#
|
||||
# This function turns on SSL support for a mail domain. Parameter ssl_dir
|
||||
# is a path to a directory where 2 or 3 ssl files can be found. Certificate file
|
||||
# mail.domain.tld.crt and its key mail.domain.tld.key are mandatory. Certificate
|
||||
# authority mail.domain.tld.ca file is optional.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
ssl_dir=$3
|
||||
restart="$4"
|
||||
|
||||
# Additional argument formatting
|
||||
if [[ "$domain" =~ [[:upper:]] ]]; then
|
||||
domain=$(echo "$domain" | tr '[:upper:]' '[:lower:]')
|
||||
fi
|
||||
if [[ "$domain" =~ ^www\..* ]]; then
|
||||
domain=$(echo "$domain" | sed -e "s/^www.//")
|
||||
fi
|
||||
if [[ "$domain" =~ .*\.$ ]]; then
|
||||
domain=$(echo "$domain" | sed -e "s/\.$//")
|
||||
fi
|
||||
|
||||
domain_idn=$(idn2 --quiet "$domain")
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# shellcheck source=/usr/local/hestia/func/ip.sh
|
||||
source $HESTIA/func/ip.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# Additional argument formatting
|
||||
format_domain
|
||||
format_domain_idn
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '3' "$#" 'USER DOMAIN SSL_DIR [RESTART]'
|
||||
is_format_valid 'user' 'domain' 'ssl_dir'
|
||||
is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'mail' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'mail' 'DOMAIN' "$domain"
|
||||
is_object_value_empty 'mail' 'DOMAIN' "$domain" '$SSL'
|
||||
is_web_domain_cert_valid
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
if [ -n "$restart" ]; then
|
||||
is_format_valid "$restart"
|
||||
fi
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Inherit web domain local ip address
|
||||
domain_ip=$(get_object_value 'web' 'DOMAIN' "$domain" '$IP')
|
||||
if [ -n "$domain_ip" ]; then
|
||||
local_ip=$(get_real_ip "$domain_ip")
|
||||
is_ip_valid "$local_ip" "$user"
|
||||
else
|
||||
get_user_ip
|
||||
fi
|
||||
|
||||
# Call routine to add SSL configuration to mail domain
|
||||
add_mail_ssl_config
|
||||
|
||||
if [ "$WEBMAIL" == "roundcube" ]; then
|
||||
WEBMAIL_TEMPLATE="default"
|
||||
if [ -n "$PROXY_SYSTEM" ]; then
|
||||
PROXY_TEMPLATE="default"
|
||||
fi
|
||||
# Add webmail configuration to mail domain
|
||||
WEBMAIL_TEMPLATE="default"
|
||||
if [ "$WEB_SYSTEM" = "nginx" ]; then
|
||||
WEBMAIL_TEMPLATE="web_system"
|
||||
fi
|
||||
elif [ "$WEBMAIL" == "snappymail" ]; then
|
||||
WEBMAIL_TEMPLATE="snappymail"
|
||||
if [ -n "$PROXY_SYSTEM" ]; then
|
||||
PROXY_TEMPLATE="default_snappymail"
|
||||
fi
|
||||
elif [ "$WEBMAIL" == "rainloop" ]; then
|
||||
WEBMAIL_TEMPLATE="rainloop"
|
||||
if [ -n "$PROXY_SYSTEM" ]; then
|
||||
PROXY_TEMPLATE="default_rainloop"
|
||||
fi
|
||||
else
|
||||
WEBMAIL_TEMPLATE="disabled"
|
||||
if [ -n "$PROXY_SYSTEM" ]; then
|
||||
PROXY_TEMPLATE="default_disabled"
|
||||
fi
|
||||
fi
|
||||
|
||||
add_webmail_config "$WEB_SYSTEM" "${WEBMAIL_TEMPLATE}.stpl"
|
||||
|
||||
if [ -n "$PROXY_SYSTEM" ]; then
|
||||
add_webmail_config "$PROXY_SYSTEM" "${PROXY_TEMPLATE}.stpl"
|
||||
fi
|
||||
|
||||
# Increase value for domain
|
||||
increase_user_value "$user" '$U_MAIL_SSL'
|
||||
|
||||
# Set SSL as enabled in configuration
|
||||
update_object_value 'mail' 'DOMAIN' "$domain" '$SSL' "yes"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Restarting mail server
|
||||
$BIN/v-restart-mail "$restart"
|
||||
check_result $? "Mail restart failed" > /dev/null
|
||||
|
||||
# Restarting web server
|
||||
$BIN/v-restart-web "$restart"
|
||||
check_result $? "Web restart failed" > /dev/null
|
||||
|
||||
# Restarting proxy server
|
||||
$BIN/v-restart-proxy "$restart"
|
||||
check_result $? "Proxy restart failed" > /dev/null
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "Mail" "SSL enabled (Domain: $domain)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
190
bin/v-add-mail-domain-webmail
Executable file
190
bin/v-add-mail-domain-webmail
Executable file
@@ -0,0 +1,190 @@
|
||||
#!/bin/bash
|
||||
# info: add webmail support for a domain
|
||||
# options: USER DOMAIN [WEBMAIL] [RESTART] [QUIET]
|
||||
#
|
||||
# example: v-add-sys-webmail user domain.com
|
||||
# example: v-add-sys-webmail user domain.com snappymail
|
||||
# example: v-add-sys-webmail user domain.com roundcube
|
||||
#
|
||||
# This function enables webmail client for a mail domain.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
webmail=$3
|
||||
restart="$4"
|
||||
quiet=$5
|
||||
|
||||
if [ -z "$restart" ]; then
|
||||
restart="yes"
|
||||
fi
|
||||
|
||||
# Additional argument formatting
|
||||
if [[ "$domain" =~ [[:upper:]] ]]; then
|
||||
domain=$(echo "$domain" | tr '[:upper:]' '[:lower:]')
|
||||
fi
|
||||
if [[ "$domain" =~ ^www\..* ]]; then
|
||||
domain=$(echo "$domain" | sed -e "s/^www.//")
|
||||
fi
|
||||
if [[ "$domain" =~ .*\.$ ]]; then
|
||||
domain=$(echo "$domain" | sed -e "s/\.$//")
|
||||
fi
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# shellcheck source=/usr/local/hestia/func/ip.sh
|
||||
source $HESTIA/func/ip.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# Additional argument formatting
|
||||
format_domain
|
||||
format_domain_idn
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
if [ -z "$webmail" ]; then
|
||||
for client in ${WEBMAIL_SYSTEM//,/ }; do
|
||||
webmail="$client"
|
||||
done
|
||||
fi
|
||||
|
||||
check_args '2' "$#" 'USER DOMAIN [WEBMAIL] [RESTART]'
|
||||
is_format_valid 'user' 'domain' 'restart'
|
||||
is_system_enabled "$WEB_SYSTEM" 'WEB_SYSTEM'
|
||||
is_system_enabled "$IMAP_SYSTEM" 'IMAP_SYSTEM'
|
||||
is_type_valid "$WEBMAIL_SYSTEM disabled" "$webmail"
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'mail' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'mail' 'DOMAIN' "$domain"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Inherit web domain local ip address
|
||||
domain_ip=$(get_object_value 'web' 'DOMAIN' "$domain" '$IP')
|
||||
if [ -n "$domain_ip" ]; then
|
||||
local_ip=$(get_real_ip "$domain_ip")
|
||||
is_ip_valid "$local_ip" "$user"
|
||||
|
||||
ip=$local_ip
|
||||
nat_ip=$(get_ip_value '$NAT')
|
||||
if [ -n "$nat_ip" ]; then
|
||||
ip=$nat_ip
|
||||
fi
|
||||
else
|
||||
get_user_ip
|
||||
fi
|
||||
|
||||
# Verify that webmail alias variable exists and create it if it does not
|
||||
if [ -z "$WEBMAIL_ALIAS" ]; then
|
||||
$BIN/v-change-sys-config-value 'WEBMAIL_ALIAS' "webmail"
|
||||
else
|
||||
# Ensure DNS record exists if Hestia is hosting DNS zones
|
||||
if [ -n "$DNS_SYSTEM" ]; then
|
||||
dns_domain=$($BIN/v-list-dns-domains $user | grep $domain | cut -d' ' -f1)
|
||||
webmail_record=$($BIN/v-list-dns-records $user $domain | grep -i " $WEBMAIL_ALIAS " | cut -d' ' -f1)
|
||||
if [ "$dns_domain" = "$domain" ]; then
|
||||
if [ "$WEBMAIL_ALIAS" != "mail" ]; then
|
||||
#Prevent mail.domain.com to be cycled
|
||||
if [ -z "$webmail_record" ]; then
|
||||
if [ "$quiet" = "yes" ]; then
|
||||
$BIN/v-add-dns-record "$user" "$domain" "$WEBMAIL_ALIAS" A "$ip" '' '' "$restart" '' 'yes'
|
||||
else
|
||||
$BIN/v-add-dns-record "$user" "$domain" "$WEBMAIL_ALIAS" A "$ip" '' '' "$restart" '' 'yes'
|
||||
fi
|
||||
else
|
||||
if [ "$quiet" = "yes" ]; then
|
||||
$BIN/v-delete-dns-record "$user" "$domain" "$webmail_record" "$restart" 'yes'
|
||||
$BIN/v-add-dns-record "$user" "$domain" "$WEBMAIL_ALIAS" A "$ip" '' '' "$restart" '' 'yes'
|
||||
else
|
||||
$BIN/v-delete-dns-record "$user" "$domain" "$webmail_record" "$restart" 'yes'
|
||||
$BIN/v-add-dns-record "$user" "$domain" "$WEBMAIL_ALIAS" A "$ip" '' '' "$restart" '' 'yes'
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$webmail" == "roundcube" ]; then
|
||||
WEBMAIL_TEMPLATE="default"
|
||||
if [ -n "$PROXY_SYSTEM" ]; then
|
||||
PROXY_TEMPLATE="default"
|
||||
fi
|
||||
# Add webmail configuration to mail domain
|
||||
WEBMAIL_TEMPLATE="default"
|
||||
if [ "$WEB_SYSTEM" = "nginx" ]; then
|
||||
WEBMAIL_TEMPLATE="web_system"
|
||||
fi
|
||||
elif [ -f "$HESTIA/data/templates/mail/$WEB_SYSTEM/$webmail.tpl" ]; then
|
||||
WEBMAIL_TEMPLATE="$webmail"
|
||||
if [ -n "$PROXY_SYSTEM" ]; then
|
||||
PROXY_TEMPLATE="default_$webmail"
|
||||
fi
|
||||
else
|
||||
WEBMAIL_TEMPLATE="disabled"
|
||||
if [ -n "$PROXY_SYSTEM" ]; then
|
||||
PROXY_TEMPLATE="default_disabled"
|
||||
fi
|
||||
fi
|
||||
|
||||
add_webmail_config "$WEB_SYSTEM" "${WEBMAIL_TEMPLATE}.tpl"
|
||||
|
||||
if [ -n "$PROXY_SYSTEM" ]; then
|
||||
add_webmail_config "$PROXY_SYSTEM" "${PROXY_TEMPLATE}.tpl"
|
||||
fi
|
||||
|
||||
# Enable SSL for webmail if available
|
||||
if [ -f $HOMEDIR/$user/conf/mail/$domain/ssl/$domain.crt ] || [ "$SSL" = 'yes' ]; then
|
||||
add_webmail_config "$WEB_SYSTEM" "${WEBMAIL_TEMPLATE}.stpl"
|
||||
|
||||
if [ -n "$PROXY_SYSTEM" ]; then
|
||||
add_webmail_config "$PROXY_SYSTEM" "${PROXY_TEMPLATE}.stpl"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
WEBMAIL=$(get_object_value 'web' 'DOMAIN' "$domain" "$WEBMAIL")
|
||||
if [ -z "$WEBMAIL" ]; then
|
||||
add_object_key 'mail' 'DOMAIN' "$domain" 'WEBMAIL' 'SSL'
|
||||
fi
|
||||
|
||||
# Set SSL as enabled in configuration
|
||||
update_object_value 'mail' 'DOMAIN' "$domain" '$WEBMAIL' "$webmail"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
if [ "$restart" = 'yes' ]; then
|
||||
# Restarting web server
|
||||
$BIN/v-restart-web "$restart"
|
||||
check_result $? "Web restart failed" > /dev/null
|
||||
|
||||
$BIN/v-restart-proxy "$restart"
|
||||
check_result $? "Proxy restart failed" > /dev/null
|
||||
fi
|
||||
|
||||
# Logging
|
||||
if [ "$quiet" != 'yes' ]; then
|
||||
$BIN/v-log-action "$user" "Info" "Mail" "Webmail access enabled (Domain: $domain)."
|
||||
fi
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
124
bin/v-add-remote-dns-domain
Executable file
124
bin/v-add-remote-dns-domain
Executable file
@@ -0,0 +1,124 @@
|
||||
#!/bin/bash
|
||||
# info: add remote dns domain
|
||||
# options: USER DOMAIN [FLUSH]
|
||||
#
|
||||
# example: v-add-remote-dns-domain admin mydomain.tld yes
|
||||
#
|
||||
# This function synchronise dns domain with the remote server.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
flush=$3
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/remote.sh
|
||||
source $HESTIA/func/remote.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '2' "$#" 'USER DOMAIN [FLUSH]'
|
||||
is_format_valid 'user' 'domain'
|
||||
if [ -n "$flush" ]; then
|
||||
is_type_valid "records yes no" "$flush"
|
||||
fi
|
||||
is_system_enabled "$DNS_CLUSTER" 'DNS_CLUSTER'
|
||||
is_procces_running
|
||||
remote_dns_health_check
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Parsing domain record
|
||||
str=$(grep "DOMAIN='$domain'" $USER_DATA/dns.conf 2> /dev/null)
|
||||
if [ -z "$str" ]; then
|
||||
pipe="$HESTIA/data/queue/dns-cluster.pipe"
|
||||
queue_str=$(grep -n "$SCRIPT $1 $2 " $pipe | cut -f1 -d: | head -n1)
|
||||
if [ -n "$queue_str" ]; then
|
||||
sed -i "$queue_str d" $pipe
|
||||
fi
|
||||
exit
|
||||
fi
|
||||
if [ "$DNS_CLUSTER_SYSTEM" = "hestia-zone" ]; then
|
||||
str=$(echo "$str" | sed "s/SLAVE='no'/SLAVE='yes'/g")
|
||||
str=$(echo "$str" | sed "s/SLAVE=''/SLAVE='yes'/g")
|
||||
ip=$(ip addr | grep 'inet ' | grep global | head -n1 | awk '{print $2}' | cut -f1 -d/)
|
||||
source_conf $HESTIA/data/ips/$ip
|
||||
if [ -z $NAT ]; then
|
||||
str=$(echo "$str" | sed "s/MASTER=''/MASTER='$ip'/g")
|
||||
else
|
||||
str=$(echo "$str" | sed "s/MASTER=''/MASTER='$NAT'/g")
|
||||
fi
|
||||
fi
|
||||
|
||||
IFS=$'\n'
|
||||
for cluster in $(grep "SUSPENDED='no'" $HESTIA/conf/dns-cluster.conf); do
|
||||
# Reset user, password and hash vars
|
||||
clear_dns_cluster_settings
|
||||
|
||||
# Parsing remote dns host parameters
|
||||
parse_object_kv_list "$cluster"
|
||||
|
||||
# Parsing domain parameters
|
||||
parse_object_kv_list "$str"
|
||||
|
||||
if [ "$DNS_CLUSTER_SYSTEM" = "hestia-zone" ]; then
|
||||
# Syncing domain data
|
||||
cluster_cmd v-insert-dns-domain $DNS_USER "$str" $HOSTNAME $flush 'no'
|
||||
check_result $? "$HOST connection failed" "$E_CONNECT"
|
||||
|
||||
cluster_cmd v-rebuild-dns-domain $DNS_USER $domain 'yes' 'no'
|
||||
check_result $? "$HOST connection failed" "$E_CONNECT"
|
||||
|
||||
else
|
||||
# Syncing domain data
|
||||
cluster_cmd v-insert-dns-domain $DNS_USER "$str" $HOSTNAME $flush 'no'
|
||||
check_result $? "$HOST connection failed" "$E_CONNECT"
|
||||
|
||||
# Syncing domain records
|
||||
tmp_file="/tmp/vst-sync.$DOMAIN"
|
||||
cluster_file $USER_DATA/dns/$DOMAIN.conf $tmp_file
|
||||
check_result $? "$HOST connection failed" "$E_CONNECT"
|
||||
|
||||
# Inserting synced records
|
||||
cluster_cmd v-insert-dns-records $DNS_USER $DOMAIN $tmp_file 'no'
|
||||
check_result $? "$HOST connection failed" "$E_CONNECT"
|
||||
|
||||
# Rebuilding dns zone
|
||||
cluster_cmd v-rebuild-dns-domain $DNS_USER $domain 'yes' 'no'
|
||||
check_result $? "$HOST connection failed" "$E_CONNECT"
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$DNS_CLUSTER_SYSTEM" = "hestia-zone" ]; then
|
||||
rndc notify $domain > /dev/null 2>&1
|
||||
fi
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Updating pipe
|
||||
rm -f $tmpfile
|
||||
pipe="$HESTIA/data/queue/dns-cluster.pipe"
|
||||
str=$(grep -n "$SCRIPT $1 $2 " $pipe | cut -f1 -d: | head -n1)
|
||||
if [ -n "$str" ]; then
|
||||
sed -i "$str d" $pipe
|
||||
fi
|
||||
|
||||
exit
|
||||
131
bin/v-add-remote-dns-host
Executable file
131
bin/v-add-remote-dns-host
Executable file
@@ -0,0 +1,131 @@
|
||||
#!/bin/bash
|
||||
# info: add new remote dns host
|
||||
# options: HOST PORT USER PASSWORD [TYPE] [DNS_USER]
|
||||
#
|
||||
# example: v-add-remote-dns-host slave.your_host.com 8083 admin your_passw0rd
|
||||
#
|
||||
# example: v-add-remote-dns-host slave.your_host.com 8083 api_key ''
|
||||
#
|
||||
# This function adds remote dns server to the dns cluster.
|
||||
# As alternative api_key generated on the slave server.
|
||||
# See v-generate-api-key can be used to connect the remote dns server
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
host=$1
|
||||
HOST=$host
|
||||
port=$2
|
||||
PORT=$port
|
||||
user=$3
|
||||
USER=$user
|
||||
hash=$user
|
||||
HASH=$user
|
||||
password=$4
|
||||
HIDE=4
|
||||
PASSWORD=$password
|
||||
type=${5}
|
||||
TYPE="$type"
|
||||
dns_user=${6-dns-cluster}
|
||||
DNS_USER=$dns_user
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/remote.sh
|
||||
source $HESTIA/func/remote.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
if [ -z "$type" ]; then
|
||||
type='api'
|
||||
TYPE="$type"
|
||||
fi
|
||||
|
||||
args_usage='HOST PORT USER [PASSWORD] [TYPE] [DNS_USER]'
|
||||
check_args '3' "$#" "$args_usage"
|
||||
is_format_valid 'host' 'port' 'dns_user'
|
||||
if [ -z "$password" ]; then
|
||||
is_format_valid 'hash'
|
||||
else
|
||||
is_format_valid 'user'
|
||||
fi
|
||||
is_type_valid "api ssh" "$type"
|
||||
is_system_enabled "$DNS_SYSTEM" 'DNS_SYSTEM'
|
||||
is_password_valid
|
||||
is_dnshost_new
|
||||
is_dnshost_alive
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Generating timestamp
|
||||
time_n_date=$(date +'%T %F')
|
||||
time=$(echo "$time_n_date" | cut -f 1 -d \ )
|
||||
date=$(echo "$time_n_date" | cut -f 2 -d \ )
|
||||
|
||||
if [ -z "$password" ]; then
|
||||
# Concatentating dns host string
|
||||
str="HOST='$host' PORT='$port' HASH='$hash'"
|
||||
str="$str DNS_USER='$dns_user' TYPE='$type' SUSPENDED='no'"
|
||||
str="$str TIME='$time' DATE='$date'"
|
||||
else
|
||||
# Concatentating dns host string
|
||||
str="HOST='$host' PORT='$port' USER='$user' PASSWORD='$password'"
|
||||
str="$str DNS_USER='$dns_user' TYPE='$type' SUSPENDED='no'"
|
||||
str="$str TIME='$time' DATE='$date'"
|
||||
fi
|
||||
|
||||
# Adding host to dns-cluster.conf
|
||||
echo "$str" >> $HESTIA/conf/dns-cluster.conf
|
||||
chmod 660 $HESTIA/conf/dns-cluster.conf
|
||||
|
||||
# Enabling DNS_CLUSTER
|
||||
if [ -z "$(grep DNS_CLUSTER= $HESTIA/conf/hestia.conf)" ]; then
|
||||
sed -i "s/^STATS_/DNS_CLUSTER='yes'\nSTATS_/g" $HESTIA/conf/hestia.conf
|
||||
else
|
||||
sed -i "s/DNS_CLUSTER=.*/DNS_CLUSTER='yes'/g" $HESTIA/conf/hestia.conf
|
||||
fi
|
||||
|
||||
# Enabling remote dns-cluster queue
|
||||
cluster_cmd v-add-cron-restart-job
|
||||
check_result $? "$HOST connection failed" "$E_CONNECT"
|
||||
|
||||
# Loop trough domains to generate new serial
|
||||
for dns_user in $($BIN/v-list-sys-users plain); do
|
||||
for dns_domain in $($BIN/v-list-dns-domains $dns_user plain | cut -f1); do
|
||||
$BIN/v-rebuild-dns-domain $dns_user $dns_domain "no" "yes"
|
||||
done
|
||||
done
|
||||
|
||||
# Syncing all domains
|
||||
$BIN/v-sync-dns-cluster
|
||||
check_result $? "$HOST sync failed" "$E_CONNECT"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Adding local dns-cluster cron job
|
||||
cmd="sudo $BIN/v-update-sys-queue dns-cluster"
|
||||
check_cron=$(grep "$cmd" $HESTIA/data/users/admin/cron.conf 2> /dev/null)
|
||||
if [ -z "$check_cron" ] && [ ! -z "$CRON_SYSTEM" ]; then
|
||||
$BIN/v-add-cron-job admin '*/5' '*' '*' '*' '*' "$cmd"
|
||||
fi
|
||||
|
||||
# Logging
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
98
bin/v-add-remote-dns-record
Executable file
98
bin/v-add-remote-dns-record
Executable file
@@ -0,0 +1,98 @@
|
||||
#!/bin/bash
|
||||
# info: add remote dns domain record
|
||||
# options: USER DOMAIN ID
|
||||
#
|
||||
# example: v-add-remote-dns-record bob acme.com 23
|
||||
#
|
||||
# This function synchronise dns domain with the remote server.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
id=$3
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/remote.sh
|
||||
source $HESTIA/func/remote.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '3' "$#" 'USER DOMAIN ID'
|
||||
is_format_valid 'user' 'domain' 'id'
|
||||
is_system_enabled "$DNS_CLUSTER" 'DNS_CLUSTER'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_valid 'dns' 'DOMAIN' "$domain"
|
||||
is_procces_running
|
||||
remote_dns_health_check
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Parsing record
|
||||
str=$(grep "ID='$id'" $USER_DATA/dns/$domain.conf)
|
||||
if [ -z "$str" ]; then
|
||||
pipe="$HESTIA/data/queue/dns-cluster.pipe"
|
||||
queue_str=$(grep -n "$SCRIPT $1 $2 $3$" $pipe | cut -f1 -d: | head -n1)
|
||||
if [ -n "$queue_str" ]; then
|
||||
sed -i "$queue_str d" $pipe
|
||||
fi
|
||||
exit
|
||||
fi
|
||||
# $DNS_CLUSTER_SYSTEM = "hestia-zone" doesn't need to be uopdated
|
||||
|
||||
if [ "$DNS_CLUSTER_SYSTEM" != "hestia-zone" ]; then
|
||||
IFS=$'\n'
|
||||
for cluster in $(grep "SUSPENDED='no'" $HESTIA/conf/dns-cluster.conf); do
|
||||
|
||||
# Reset user, password and hash vars
|
||||
clear_dns_cluster_settings
|
||||
|
||||
# Parsing remote host parameters
|
||||
parse_object_kv_list "$cluster"
|
||||
|
||||
# Syncing serial
|
||||
str=$(grep "DOMAIN='$domain'" $USER_DATA/dns.conf)
|
||||
# Parsing domain parameters
|
||||
parse_object_kv_list "$str"
|
||||
|
||||
cluster_cmd v-insert-dns-domain $DNS_USER "$str" $HOSTNAME 'domain' 'no'
|
||||
check_result $? "$HOST connection failed (soa sync)" "$E_CONNECT"
|
||||
|
||||
# Syncing record
|
||||
str=$(grep "ID='$id'" $USER_DATA/dns/$domain.conf)
|
||||
cluster_cmd v-insert-dns-record $DNS_USER $domain "$str" 'no'
|
||||
check_result $? "$HOST connection failed (record sync)" "$E_CONNECT"
|
||||
|
||||
# Rebuilding dns zone
|
||||
cluster_cmd v-rebuild-dns-domain $DNS_USER $domain 'yes' 'no'
|
||||
check_result $? "$HOST connection failed (rebuild)" "$E_CONNECT"
|
||||
done
|
||||
fi
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Updating pipe
|
||||
pipe="$HESTIA/data/queue/dns-cluster.pipe"
|
||||
str=$(grep -n "$SCRIPT $1 $2 $3$" $pipe | cut -f1 -d: | head -n1)
|
||||
if [ -n "$str" ]; then
|
||||
sed -i "$str d" $pipe
|
||||
fi
|
||||
|
||||
exit
|
||||
49
bin/v-add-sys-api-ip
Executable file
49
bin/v-add-sys-api-ip
Executable file
@@ -0,0 +1,49 @@
|
||||
#!/bin/bash
|
||||
# info: add IP address to API allow list
|
||||
# options: IP
|
||||
#
|
||||
# example: v-add-sys-api-ip 1.1.1.1
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
ip46=${1// /}
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/ip.sh
|
||||
source $HESTIA/func/ip.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '1' "$#" 'IP'
|
||||
is_format_valid 'ip46'
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
if [ "$API_ALLOWED_IP" != "" ]; then
|
||||
$BIN/v-change-sys-config-value 'API_ALLOWED_IP' "$API_ALLOWED_IP,$ip46"
|
||||
else
|
||||
$BIN/v-change-sys-config-value 'API_ALLOWED_IP' "$ip46"
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "system" "Warning" "System" "Added new IP address added to Allowed IP API (IP: $ip46)"
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
109
bin/v-add-sys-dependencies
Executable file
109
bin/v-add-sys-dependencies
Executable file
@@ -0,0 +1,109 @@
|
||||
#!/bin/bash
|
||||
# Add php dependencies to Hestia
|
||||
# options: [MODE]
|
||||
#
|
||||
# This function install PHPMailer and quoteshellarg as via composer
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
# upgrade config file
|
||||
source "$HESTIA/install/upgrade/upgrade.conf"
|
||||
|
||||
MODE=$1
|
||||
user="admin"
|
||||
|
||||
PM_INSTALL_DIR="$HESTIA/web/inc"
|
||||
QUICK_INSTALL_DIR="$HESTIA/web/src"
|
||||
COMPOSER_BIN="$HOMEDIR/$user/.composer/composer"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Checking root permissions
|
||||
if [ "x$(id -u)" != 'x0' ]; then
|
||||
echo "ERROR: v-add-sys-dependencies can be run executed only by root user"
|
||||
exit 10
|
||||
fi
|
||||
|
||||
# Ensure that $HESTIA (/usr/local/hestia/) and other variables are valid.
|
||||
if [ -z "$HESTIA" ]; then
|
||||
HESTIA="/usr/local/hestia"
|
||||
fi
|
||||
|
||||
if [ -z "$HOMEDIR" ] || [ -z "$HESTIA_INSTALL_DIR" ]; then
|
||||
echo "ERROR: Environment variables not present, installation aborted."
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# Ensure that Composer is installed for the user before continuing as it is a dependency of the PHPMailer.
|
||||
if [ ! -f "$COMPOSER_BIN" ]; then
|
||||
$BIN/v-add-user-composer "$user"
|
||||
if [ $? -ne 0 ]; then
|
||||
$BIN/v-add-user-notification admin 'Composer installation failed!' '<p class="u-text-bold">Hestia will not work without Composer.</p><p>Please try running the installer manually from a shell session:<br><code>v-add-sys-dependencies</code></p><p>If this continues, <a href="https://github.com/hestiacp/hestiacp/issues" target="_blank">open an issue on GitHub</a>.</p>'
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
cd "$PM_INSTALL_DIR"
|
||||
rm --recursive --force ${PM_INSTALL_DIR}/vendor
|
||||
mkdir -p ${PM_INSTALL_DIR}/vendor
|
||||
chown $user: -R ${PM_INSTALL_DIR}/vendor
|
||||
|
||||
openssl_installed=$(/usr/local/hestia/php/bin/php -m | grep openssl)
|
||||
if [ -z "$openssl_installed" ]; then
|
||||
COMPOSER_HOME="$HOMEDIR/$user/.config/composer" user_exec /usr/bin/php $COMPOSER_BIN --quiet --no-dev install
|
||||
else
|
||||
COMPOSER_HOME="$HOMEDIR/$user/.config/composer" user_exec $HESTIA_PHP $COMPOSER_BIN --quiet --no-dev install
|
||||
fi
|
||||
|
||||
# Check if installation was successful, if not abort script and throw error message notification and clean-up
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "ERROR: PHPMailer installation failed!"
|
||||
echo "Please report this to our development team:"
|
||||
echo "https://github.com/hestiacp/hestiacp/issues"
|
||||
$BIN/v-add-user-notification admin 'Hestia PHP dependencies installation failed!' '<p>Please <a href="https://github.com/hestiacp/hestiacp/issues" target="_blank">open an issue on GitHub</a> to report this to our development team.</p>'
|
||||
# Installation failed, clean up files
|
||||
rm --recursive --force ${PM_INSTALL_DIR}/vendor
|
||||
$BIN/v-change-sys-config-value 'USE_SERVER_SMTP' 'n'
|
||||
$BIN/v-log-action "system" "Error" "Plugins" "PHP dependencies installation failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cd "$QUICK_INSTALL_DIR"
|
||||
rm --recursive --force ${QUICK_INSTALL_DIR}/vendor
|
||||
mkdir -p ${QUICK_INSTALL_DIR}/vendor
|
||||
chown $user: -R ${QUICK_INSTALL_DIR}/vendor
|
||||
|
||||
if [ -z "$openssl_installed" ]; then
|
||||
COMPOSER_HOME="$HOMEDIR/$user/.config/composer" user_exec /usr/bin/php $COMPOSER_BIN --quiet --no-dev install
|
||||
else
|
||||
COMPOSER_HOME="$HOMEDIR/$user/.config/composer" user_exec $HESTIA_PHP $COMPOSER_BIN --quiet --no-dev install
|
||||
fi
|
||||
|
||||
# Set permissions
|
||||
chown root: -R "${PM_INSTALL_DIR}/vendor"
|
||||
chown root: -R "${QUICK_INSTALL_DIR}/vendor"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Logging #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
$BIN/v-log-action "system" "Info" "Plugins" "PHPMailer enabled (Version: $pm_v)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
119
bin/v-add-sys-filemanager
Executable file
119
bin/v-add-sys-filemanager
Executable file
@@ -0,0 +1,119 @@
|
||||
#!/bin/bash
|
||||
# info: add file manager functionality to Hestia Control Panel
|
||||
# options: [MODE]
|
||||
#
|
||||
# This function installs the File Manager on the server
|
||||
# for access through the Web interface.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
# load config file
|
||||
source_conf "$HESTIA/install/upgrade/upgrade.conf"
|
||||
|
||||
MODE=$1
|
||||
user="admin"
|
||||
|
||||
FM_INSTALL_DIR="$HESTIA/web/fm"
|
||||
FM_FILE="filegator_latest"
|
||||
FM_URL="https://github.com/filegator/static/raw/master/builds/filegator_latest.zip"
|
||||
COMPOSER_BIN="$HOMEDIR/$user/.composer/composer"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Checking root permissions
|
||||
if [ "x$(id -u)" != 'x0' ]; then
|
||||
echo "ERROR: v-add-sys-filemanager can be run executed only by root user"
|
||||
exit 10
|
||||
fi
|
||||
|
||||
# Ensure that $HESTIA (/usr/local/hestia/) and other variables are valid.
|
||||
if [ -z "$HESTIA" ]; then
|
||||
HESTIA="/usr/local/hestia"
|
||||
fi
|
||||
|
||||
if [ -z "$HOMEDIR" ] || [ -z "$HESTIA_INSTALL_DIR" ]; then
|
||||
echo "ERROR: Environment variables not present, installation aborted."
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# Ensure that Composer is installed for the user before continuing as it is a dependency of the File Manager.
|
||||
if [ ! -f "$COMPOSER_BIN" ]; then
|
||||
$BIN/v-add-user-composer "$user"
|
||||
if [ $? -ne 0 ]; then
|
||||
$BIN/v-add-user-notification admin 'Composer installation failed!' '<p class="u-text-bold">The File Manager will not work without Composer.</p><p>Please try running the installer manually from a shell session:<br><code>v-add-sys-filemanager</code></p><p>If this continues, <a href="https://github.com/hestiacp/hestiacp/issues" target="_blank">open an issue on GitHub</a>.</p>'
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
openssl_installed=$(/usr/local/hestia/php/bin/php -m | grep openssl)
|
||||
|
||||
rm --recursive --force "$FM_INSTALL_DIR"
|
||||
mkdir -p "$FM_INSTALL_DIR"
|
||||
cd "$FM_INSTALL_DIR"
|
||||
|
||||
[ ! -f "${FM_INSTALL_DIR}/${FM_FILE}" ] && wget "$FM_URL" --quiet -O "${FM_INSTALL_DIR}/${FM_FILE}.zip"
|
||||
|
||||
unzip -qq "${FM_INSTALL_DIR}/${FM_FILE}.zip"
|
||||
mv --force ${FM_INSTALL_DIR}/filegator/* "${FM_INSTALL_DIR}"
|
||||
rm --recursive --force ${FM_INSTALL_DIR}/${FM_FILE}
|
||||
[[ -f "${FM_INSTALL_DIR}/${FM_FILE}" ]] && rm "${FM_INSTALL_DIR}/${FM_FILE}"
|
||||
|
||||
cp --recursive --force ${HESTIA_INSTALL_DIR}/filemanager/filegator/* "${FM_INSTALL_DIR}"
|
||||
|
||||
chown $user: -R "${FM_INSTALL_DIR}"
|
||||
|
||||
if [ -z "$openssl_installed" ]; then
|
||||
COMPOSER_HOME="$HOMEDIR/$user/.config/composer" user_exec /usr/bin/php $COMPOSER_BIN --quiet --no-dev install
|
||||
else
|
||||
COMPOSER_HOME="$HOMEDIR/$user/.config/composer" user_exec /usr/local/hestia/php/bin/php $COMPOSER_BIN --quiet --no-dev install
|
||||
fi
|
||||
|
||||
# Check if installation was successful, if not abort script and throw error message notification and clean-up
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "ERROR: File Manager installation failed!"
|
||||
echo "Please report this to our development team:"
|
||||
echo "https://github.com/hestiacp/hestiacp/issues"
|
||||
$BIN/v-add-user-notification admin 'File Manager installation failed!' '<p>Please <a href="https://github.com/hestiacp/hestiacp/issues" target="_blank">open an issue on GitHub</a> to report this to our development team.</p>'
|
||||
# Installation failed, clean up files
|
||||
rm --recursive --force ${FM_INSTALL_DIR}
|
||||
$BIN/v-change-sys-config-value 'FILE_MANAGER' 'false'
|
||||
$BIN/v-log-action "system" "Error" "Plugins" "File Manager installation failed (Version: $fm_v)."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Add configuration file
|
||||
cp -f $HESTIA_INSTALL_DIR/filemanager/filegator/configuration.php $HESTIA/web/fm/configuration.php
|
||||
|
||||
echo "$fm_v" > "${FM_INSTALL_DIR}/version"
|
||||
# Set permissions
|
||||
chown root: -R "${FM_INSTALL_DIR}"
|
||||
chown $user: "${FM_INSTALL_DIR}/private"
|
||||
chown $user: "${FM_INSTALL_DIR}/private/logs"
|
||||
chown $user: "${FM_INSTALL_DIR}/repository"
|
||||
|
||||
$BIN/v-change-sys-config-value 'FILE_MANAGER' 'true'
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Logging #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
$BIN/v-log-action "system" "Info" "Plugins" "File Manager enabled (Version: $fm_v)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
56
bin/v-add-sys-firewall
Executable file
56
bin/v-add-sys-firewall
Executable file
@@ -0,0 +1,56 @@
|
||||
#!/bin/bash
|
||||
# info: add system firewall
|
||||
# options: NONE
|
||||
#
|
||||
# example: v-add-sys-firewall
|
||||
#
|
||||
# This function enables the system firewall.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
if [ "$FIREWALL_SYSTEM" = 'iptables' ]; then
|
||||
exit
|
||||
fi
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Adding default ruleset
|
||||
if [ -z "$(ls -A $HESTIA/data/firewall 2> /dev/null)" ]; then
|
||||
cp -rf $HESTIA_COMMON_DIR/firewall $HESTIA/data/
|
||||
rm -f $HESTIA/data/firewall/ipset/blacklist.sh $HESTIA/data/firewall/ipset/blacklist.ipv6.sh
|
||||
fi
|
||||
|
||||
# Updating FIREWAL_SYSTEM value
|
||||
$BIN/v-change-sys-config-value "FIREWALL_SYSTEM" "iptables"
|
||||
|
||||
# Updating firewall rules
|
||||
$BIN/v-update-firewall
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "system" "Info" "Firewall" "System firewall enabled."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
234
bin/v-add-sys-ip
Executable file
234
bin/v-add-sys-ip
Executable file
@@ -0,0 +1,234 @@
|
||||
#!/bin/bash
|
||||
# info: add system IP address
|
||||
# options: IP NETMASK [INTERFACE] [USER] [IP_STATUS] [IP_NAME] [NAT_IP]
|
||||
#
|
||||
# example: v-add-sys-ip 203.0.113.1 255.255.255.0
|
||||
#
|
||||
# This function adds IP address into a system. It also creates rc scripts. You
|
||||
# can specify IP name which will be used as root domain for temporary aliases.
|
||||
# For example, if you set a1.myhosting.com as name, each new domain created on
|
||||
# this IP will automatically receive alias $domain.a1.myhosting.com. Of course
|
||||
# you must have wildcard record *.a1.myhosting.com pointed to IP. This feature
|
||||
# is very handy when customer wants to test domain before dns migration.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
ip="${1// /}"
|
||||
netmask="$2"
|
||||
|
||||
# Get interface name
|
||||
# First try to detect which interface the IP address resides on
|
||||
iface="$(ip -d -j addr show | jq --arg IP "$ip" -r '.[] | if .addr_info[].local == $IP then .ifname else empty end')"
|
||||
# If that fails, detect the default interface as a fallback
|
||||
if [ -z "$iface" ]; then
|
||||
iface="$(ip -d -j route show | jq -r '.[] | if .dst == "default" then .dev else empty end')"
|
||||
fi
|
||||
|
||||
iface="${3-$iface}"
|
||||
user="${4-admin}"
|
||||
ip_status="${5-shared}"
|
||||
ip_name="$6"
|
||||
nat_ip="$7"
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/ip.sh
|
||||
source $HESTIA/func/ip.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '2' "$#" 'IP NETMASK [INTERFACE] [USER] [STATUS] [NAME] [NATED_IP]'
|
||||
is_format_valid 'ip' 'netmask' 'iface' 'user' 'ip_status'
|
||||
is_ip_free
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
if [ -n "$ip_name" ]; then
|
||||
is_format_valid 'ip_name'
|
||||
fi
|
||||
if [ -n "$nat_ip" ]; then
|
||||
is_format_valid 'nat_ip'
|
||||
fi
|
||||
if [ "$user" != "admin" ]; then
|
||||
ip_status="dedicated"
|
||||
fi
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
cidr="$(convert_netmask "$netmask")"
|
||||
broadcast="$(get_broadcast "$ip" "$netmask")"
|
||||
|
||||
sys_ip_check="$(ip addr | grep -w "$ip")"
|
||||
if [ -z "$sys_ip_check" ]; then
|
||||
# Adding system IP
|
||||
ip addr add "$ip/$cidr" dev "$iface" broadcast "$broadcast" label "$iface"
|
||||
|
||||
# Check if netplan is in use and generate configuration file
|
||||
if [ -n "$(netplan generate --mapping "$iface" 2> /dev/null | grep networkd)" ]; then
|
||||
netplan="true"
|
||||
else
|
||||
netplan="false"
|
||||
fi
|
||||
|
||||
if [ "$netplan" = "true" ]; then
|
||||
if [ -f "/etc/netplan/60-hestia.yaml" ]; then
|
||||
sys_ip=" - $ip/$cidr"
|
||||
else
|
||||
sys_ip="# Added by Hestia, please do not edit the file manually!"
|
||||
sys_ip="$sys_ip\nnetwork:"
|
||||
sys_ip="$sys_ip\n version: 2"
|
||||
sys_ip="$sys_ip\n renderer: networkd"
|
||||
sys_ip="$sys_ip\n ethernets:"
|
||||
sys_ip="$sys_ip\n $iface:"
|
||||
sys_ip="$sys_ip\n addresses:"
|
||||
sys_ip="$sys_ip\n - $ip/$cidr"
|
||||
fi
|
||||
IFS='%'
|
||||
echo -e "$sys_ip" >> /etc/netplan/60-hestia.yaml
|
||||
unset IFS
|
||||
else
|
||||
sys_ip="\n# Added by Hestia Control Panel"
|
||||
sys_ip="$sys_ip\nauto $iface"
|
||||
sys_ip="$sys_ip\niface $iface inet static"
|
||||
sys_ip="$sys_ip\naddress $ip"
|
||||
sys_ip="$sys_ip\nnetmask $netmask"
|
||||
echo -e $sys_ip >> /etc/network/interfaces
|
||||
fi
|
||||
fi
|
||||
|
||||
# Generating timestamp
|
||||
new_timestamp
|
||||
|
||||
# Adding Hestia IP
|
||||
echo "OWNER='$user'
|
||||
STATUS='$ip_status'
|
||||
NAME='$ip_name'
|
||||
U_SYS_USERS=''
|
||||
U_WEB_DOMAINS='0'
|
||||
INTERFACE='$iface'
|
||||
NETMASK='$netmask'
|
||||
NAT='$nat_ip'
|
||||
TIME='$time'
|
||||
DATE='$date'" > $HESTIA/data/ips/$ip
|
||||
chmod 660 $HESTIA/data/ips/$ip
|
||||
|
||||
# WEB support
|
||||
if [ -n "$WEB_SYSTEM" ]; then
|
||||
web_conf="/etc/$WEB_SYSTEM/conf.d/$ip.conf"
|
||||
rm -f "$web_conf"
|
||||
|
||||
if [ "$WEB_SYSTEM" = 'httpd' ] || [ "$WEB_SYSTEM" = 'apache2' ]; then
|
||||
if [ -z "$(/usr/sbin/apachectl -v | grep Apache/2.4)" ]; then
|
||||
echo "NameVirtualHost $ip:$WEB_PORT" > "$web_conf"
|
||||
fi
|
||||
echo "Listen $ip:$WEB_PORT" >> "$web_conf"
|
||||
cat $HESTIA_INSTALL_DIR/apache2/unassigned.conf >> "$web_conf"
|
||||
sed -i 's/directIP/'$ip'/g' "$web_conf"
|
||||
sed -i 's/directPORT/'$WEB_PORT'/g' "$web_conf"
|
||||
|
||||
elif [ "$WEB_SYSTEM" = 'nginx' ]; then
|
||||
cp -f $HESTIA_INSTALL_DIR/nginx/unassigned.inc "$web_conf"
|
||||
sed -i 's/directIP/'$ip'/g' "$web_conf"
|
||||
process_http2_directive "$web_conf"
|
||||
fi
|
||||
|
||||
if [ "$WEB_SSL" = 'mod_ssl' ]; then
|
||||
if [ -z "$(/usr/sbin/apachectl -v | grep Apache/2.4)" ]; then
|
||||
sed -i "1s/^/NameVirtualHost $ip:$WEB_SSL_PORT\n/" "$web_conf"
|
||||
fi
|
||||
sed -i "1s/^/Listen $ip:$WEB_SSL_PORT\n/" "$web_conf"
|
||||
sed -i 's/directSSLPORT/'$WEB_SSL_PORT'/g' "$web_conf"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Proxy support
|
||||
if [ -n "$PROXY_SYSTEM" ]; then
|
||||
cat $WEBTPL/$PROXY_SYSTEM/proxy_ip.tpl \
|
||||
| sed -e "s/%ip%/$ip/g" \
|
||||
-e "s/%web_port%/$WEB_PORT/g" \
|
||||
-e "s/%proxy_port%/$PROXY_PORT/g" \
|
||||
-e "s/%proxy_ssl_port%/$PROXY_SSL_PORT/g" \
|
||||
> /etc/$PROXY_SYSTEM/conf.d/$ip.conf
|
||||
|
||||
process_http2_directive "/etc/$PROXY_SYSTEM/conf.d/$ip.conf"
|
||||
|
||||
# mod_extract_forwarded
|
||||
fw_conf="/etc/$WEB_SYSTEM/conf.d/mod_extract_forwarded.conf"
|
||||
if [ -e "$fw_conf" ]; then
|
||||
ips=$(grep 'MEFaccept ' "$fw_conf" | grep -v '#' | head -n1)
|
||||
sed -i "s/$ips/$ips $ip/g" "$fw_conf"
|
||||
fi
|
||||
|
||||
# mod_rpaf
|
||||
rpaf_conf="/etc/$WEB_SYSTEM/mods-enabled/rpaf.conf"
|
||||
if [ -e "$rpaf_conf" ]; then
|
||||
rpaf_str="$(grep RPAFproxy_ips "$rpaf_conf")"
|
||||
[ -z "$rpaf_str" ] && sed -i 's|</IfModule>|RPAFproxy_ips\n</IfModule>|' "$rpaf_conf" && rpaf_str='RPAFproxy_ips'
|
||||
rpaf_str="$rpaf_str $ip"
|
||||
sed -i "s/.*RPAFproxy_ips.*/$rpaf_str/" "$rpaf_conf"
|
||||
fi
|
||||
|
||||
# mod_remoteip
|
||||
remoteip_conf="/etc/$WEB_SYSTEM/mods-enabled/remoteip.conf"
|
||||
if [ -e "$remoteip_conf" ]; then
|
||||
if [ "$(grep -ic "$ip" "$remoteip_conf")" -eq "0" ]; then
|
||||
sed -i "s/<\/IfModule>/RemoteIPInternalProxy $ip\n<\/IfModule>/g" "$remoteip_conf"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Updating user counters
|
||||
increase_user_value "$user" '$IP_OWNED'
|
||||
if [ "$user" = 'admin' ]; then
|
||||
if [ "$ip_status" = 'shared' ]; then
|
||||
for hestia_user in $($BIN/v-list-sys-users plain); do
|
||||
increase_user_value "$hestia_user" '$IP_AVAIL'
|
||||
done
|
||||
else
|
||||
increase_user_value 'admin' '$IP_AVAIL'
|
||||
fi
|
||||
else
|
||||
increase_user_value "$user" '$IP_AVAIL'
|
||||
increase_user_value 'admin' '$IP_AVAIL'
|
||||
fi
|
||||
|
||||
# Restarting web server
|
||||
$BIN/v-restart-web
|
||||
check_result $? "Web restart failed" > /dev/null
|
||||
|
||||
# Restarting proxy server
|
||||
if [ -n "$PROXY_SYSTEM" ]; then
|
||||
$BIN/v-restart-proxy
|
||||
check_result $? "Proxy restart failed" > /dev/null
|
||||
fi
|
||||
|
||||
# Restarting firewall
|
||||
if [ -n "$FIREWALL_SYSTEM" ]; then
|
||||
$BIN/v-update-firewall
|
||||
fi
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "system" "Info" "Network" "Added new IP address to the system (IP: $ip)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
120
bin/v-add-sys-pma-sso
Executable file
120
bin/v-add-sys-pma-sso
Executable file
@@ -0,0 +1,120 @@
|
||||
#!/bin/bash
|
||||
# info: enables support for single sign on phpMyAdmin
|
||||
# options: [mode]
|
||||
#
|
||||
# example: v-add-sys-pma-sso
|
||||
#
|
||||
# This function enables support for SSO to phpMyAdmin
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
MODE=$1
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
PMA_INSTALL="/usr/share/phpmyadmin"
|
||||
PMA_CONFIG="/etc/phpmyadmin"
|
||||
|
||||
|
||||
WWW_USER="www-data"
|
||||
if [ -f /etc/redhat-release ]; then
|
||||
WWW_USER="apache"
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
# Checking root permissions
|
||||
if [ "x$(id -u)" != 'x0' ]; then
|
||||
echo "Error: Script can be run executed only by root"
|
||||
exit 10
|
||||
fi
|
||||
|
||||
if [ -n "$PHPMYADMIN_KEY" ] && [ "$PHPMYADMIN_KEY" != "" ]; then
|
||||
echo "Error: SSO has been installed before to reenable it please run v-delete-sys-pma-sso first"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -f "/usr/share/phpmyadmin/hestia-sso.php" ]; then
|
||||
echo "Error: hestia-sso.php is already installed"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
if [ -f "/usr/local/hesta/web/api/index.php" ]; then
|
||||
echo "Error: API script not installed"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
if [ "API_SYSTEM" = "0" ]; then
|
||||
echo "Error: API is not enabled"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Generate the keys to secure everything
|
||||
phpmyadminkey=$(generate_password)
|
||||
apikey=$($BIN/v-add-access-key 'admin' 'phpmyadmin-sso' 'phpMyAdmin' 'plain')
|
||||
|
||||
# copy config dir to /usr/share/phpmyadmin/
|
||||
cp -f $HESTIA_COMMON_DIR/phpmyadmin/hestia-sso.php $PMA_INSTALL/hestia-sso.php
|
||||
chmod 640 $PMA_INSTALL/hestia-sso.php
|
||||
chown root:$WWW_USER $PMA_INSTALL/hestia-sso.php
|
||||
|
||||
sed -i "s/%PHPMYADMIN_KEY%/$phpmyadminkey/g" $PMA_INSTALL/hestia-sso.php
|
||||
sed -i "s/%API_KEY%/$apikey/g" $PMA_INSTALL/hestia-sso.php
|
||||
sed -i "s/%API_HOST_NAME%/$(hostname)/g" $PMA_INSTALL/hestia-sso.php
|
||||
sed -i "s/%API_HESTIA_PORT%/$BACKEND_PORT/g" $PMA_INSTALL/hestia-sso.php
|
||||
|
||||
# Check if config already contains the keys
|
||||
touch $PMA_CONFIG/hestia-sso.inc.php
|
||||
chmod 640 $PMA_CONFIG/hestia-sso.inc.php
|
||||
chown root:$WWW_USER $PMA_CONFIG/hestia-sso.inc.php
|
||||
|
||||
echo "<?php
|
||||
if(isset(\$_GET['hestia_token']) || isset(\$_COOKIE['SignonSession'])){
|
||||
\$cfg['Servers'][\$i]['auth_type'] = 'signon';
|
||||
\$cfg['Servers'][\$i]['SignonSession'] = 'SignonSession';
|
||||
\$cfg['Servers'][\$i]['SignonURL'] = 'hestia-sso.php';
|
||||
\$cfg['Servers'][\$i]['LogoutURL'] = 'hestia-sso.php?logout=1';
|
||||
}
|
||||
?>" >> $PMA_CONFIG/hestia-sso.inc.php
|
||||
|
||||
file=$(cat $PMA_CONFIG/config.inc.php)
|
||||
if ! [[ "$file" =~ hestia-sso.inc.php ]]; then
|
||||
if [[ $file =~ "//Add Hestia SSO code here" ]]; then
|
||||
sed -i "s|//Add Hestia SSO code here|//Add Hestia SSO code here\n include ('$PMA_CONFIG/hestia-sso.inc.php');|g" $PMA_CONFIG/config.inc.php
|
||||
else
|
||||
echo "include ('$PMA_CONFIG/hestia-sso.inc.php');" >> $PMA_CONFIG/config.inc.php
|
||||
fi
|
||||
fi
|
||||
|
||||
$BIN/v-change-sys-config-value 'PHPMYADMIN_KEY' "$phpmyadminkey"
|
||||
|
||||
if [ -z "$(echo $API_ALLOWED_IP | grep 127.0.0.1)" ]; then
|
||||
$BIN/v-add-sys-api-ip "127.0.0.1"
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Logging #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
if [ "$MODE" != "quiet" ]; then
|
||||
echo "PMA Hestia-SSO plugin has been successfully installed"
|
||||
fi
|
||||
$BIN/v-log-action "system" "Info" "Plugins" "phpMyAdmin Single Sign-On has been enabled."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
106
bin/v-add-sys-quota
Executable file
106
bin/v-add-sys-quota
Executable file
@@ -0,0 +1,106 @@
|
||||
#!/bin/bash
|
||||
# info: add system quota
|
||||
# options: NONE
|
||||
#
|
||||
# example: v-add-sys-quota
|
||||
#
|
||||
# This function enables filesystem quota on /home partition
|
||||
# Some kernels do require additional packages to be installed first
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variable & Function #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Ensure that quota kernel modules are installed
|
||||
kernel_module_check=$(find /lib/modules/$(uname -r) -type f -name '*quota_v*.ko*' | egrep '.*' && [ $? -eq 0 ])
|
||||
if [ -z "$kernel_module_check" ]; then
|
||||
# Install kernel modules for quota support.
|
||||
# Requires reboot to activate updated kernel.
|
||||
echo "Installing required kernel modules for quota support..."
|
||||
reboot_req="Y"
|
||||
apt-get -qq install linux-image-extra-virtual -y
|
||||
check_result $? "kernel module installation failed" "$E_UPDATE"
|
||||
fi
|
||||
|
||||
# Checking quota package
|
||||
quota=$(which --skip-alias --skip-functions quota 2> /dev/null)
|
||||
if [ $? -ne 0 ]; then
|
||||
if [ -f "/etc/redhat-release" ]; then
|
||||
dnf -y install quota > /dev/null 2>&1
|
||||
else
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
apt-get -y install quota > /dev/null 2>&1
|
||||
fi
|
||||
check_result $? "quota package installation failed" "$E_UPDATE"
|
||||
fi
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Adding group and user quota on /home partition
|
||||
mnt=$(df -P /home | awk '{print $6}' | tail -n1)
|
||||
lnr=$(cat -n /etc/fstab | grep -v "#" | awk '{print $1,$3}' | grep "$mnt$" | cut -f 1 -d ' ')
|
||||
opt=$(sed -n ${lnr}p /etc/fstab | awk '{print $4}')
|
||||
fnd='usrquota\|grpquota\|usrjquota=aquota.user\|grpjquota=aquota.group\|jqfmt=vfsv0'
|
||||
if [ $(echo $opt | tr ',' '\n' | grep -x $fnd | wc -l) -ne 5 ]; then
|
||||
old=$(echo $(echo $opt | tr ',' '\n' | grep -v 'usrquota\|grpquota\|usrjquota=\|grpjquota=\|jqfmt=') | tr ' ' ',')
|
||||
new='usrquota,grpquota,usrjquota=aquota.user,grpjquota=aquota.group,jqfmt=vfsv0'
|
||||
sed -i "$lnr s/$opt/$old,$new/" /etc/fstab
|
||||
mount -o remount "$mnt"
|
||||
fi
|
||||
|
||||
# Adding v2 group and user quota index
|
||||
if [ ! -e "$mnt/aquota.user" ] || [ ! -e "$mnt/aquota.group" ]; then
|
||||
quotacheck -avcugm > /dev/null 2>&1
|
||||
fi
|
||||
|
||||
# Adding quotacheck on reboot
|
||||
touch /forcequotacheck
|
||||
|
||||
# Adding cron job
|
||||
echo '#!/bin/bash' > /etc/cron.daily/quotacheck
|
||||
echo 'touch /forcequotacheck' >> /etc/cron.daily/quotacheck
|
||||
chmod a+x /etc/cron.daily/quotacheck
|
||||
|
||||
# Enabling group and user quota
|
||||
if [ -n "$(quotaon -pa | grep " $mnt " | grep 'user\|group' | grep 'is off')" ]; then
|
||||
quotaon -v $mnt
|
||||
check_result $? "quota can't be enabled in $mnt" "$E_DISK"
|
||||
fi
|
||||
|
||||
# Updating hestia.conf value
|
||||
if [ -z "$(grep DISK_QUOTA $HESTIA/conf/hestia.conf)" ]; then
|
||||
echo "DISK_QUOTA='yes'" >> $HESTIA/conf/hestia.conf
|
||||
else
|
||||
sed -i "s/DISK_QUOTA=.*/DISK_QUOTA='yes'/g" $HESTIA/conf/hestia.conf
|
||||
fi
|
||||
|
||||
# Rebuilding user quota
|
||||
for user in $($BIN/v-list-sys-users plain); do
|
||||
$BIN/v-update-user-quota "$user"
|
||||
done
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "system" "Info" "Plugins" "System Quota enforcement enabled."
|
||||
log_history "system quota enforcement enabled"
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
216
bin/v-add-sys-roundcube
Executable file
216
bin/v-add-sys-roundcube
Executable file
@@ -0,0 +1,216 @@
|
||||
#!/bin/bash
|
||||
# info: Install Roundcube webmail client
|
||||
# options: [MODE]
|
||||
#
|
||||
# This function installs the Roundcube webmail client.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
source $HESTIA/func/db.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
# upgrade config file
|
||||
source "$HESTIA/install/upgrade/upgrade.conf"
|
||||
|
||||
MODE=$2
|
||||
UPDATE="no"
|
||||
# Version and Download paths
|
||||
RC_FILE="roundcubemail-$rc_v-complete.tar.gz"
|
||||
RC_EXTRACT="roundcubemail-$rc_v"
|
||||
# Downloading full version
|
||||
RC_URL="https://github.com/roundcube/roundcubemail/releases/download/$rc_v/roundcubemail-$rc_v-complete.tar.gz"
|
||||
|
||||
# Folder paths
|
||||
RC_INSTALL_DIR="/var/lib/roundcube"
|
||||
RC_CONFIG_DIR="/etc/roundcube"
|
||||
RC_LOG="/var/log/roundcube"
|
||||
|
||||
WWW_USER="www-data"
|
||||
if [ -f /etc/redhat-release ]; then
|
||||
WWW_USER="apache"
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Checking root permissions
|
||||
if [ "x$(id -u)" != 'x0' ]; then
|
||||
echo "ERROR: v-add-sys-roundcube can be run executed only by root user"
|
||||
exit 10
|
||||
fi
|
||||
|
||||
# Ensure that $HESTIA (/usr/local/hestia/) and other variables are valid.
|
||||
if [ -z "$HESTIA" ]; then
|
||||
HESTIA="/usr/local/hestia"
|
||||
fi
|
||||
|
||||
if [ -z "$HOMEDIR" ] || [ -z "$HESTIA_COMMON_DIR" ]; then
|
||||
echo "ERROR: Environment variables not present, installation aborted."
|
||||
exit 2
|
||||
fi
|
||||
|
||||
if [ -z "$(echo "$DB_SYSTEM" | grep -w 'mysql')" ]; then
|
||||
echo "ERROR: Mysql not available. Installation aborted"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
if [ -d "/usr/share/roundcube" ]; then
|
||||
echo "ERROR: Install done from apt source, unable to continue"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# Get current version
|
||||
if [ -f "/var/lib/roundcube/index.php" ]; then
|
||||
version=$(cat $RC_INSTALL_DIR/index.php | grep -o -E '[0-9].[0-9].[0-9]+' | head -1)
|
||||
if [ "$version" == "$rc_v" ]; then
|
||||
echo "Error: Installed version ($version) is equal to the available version ($rc_v)"
|
||||
exit 2
|
||||
else
|
||||
UPDATE="yes"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
if [ "$UPDATE" == "no" ]; then
|
||||
rm -f -r $RC_INSTALL_DIR
|
||||
rm -f -r $RC_CONFIG_DIR
|
||||
|
||||
mkdir -p $RC_INSTALL_DIR/
|
||||
mkdir -p $RC_CONFIG_DIR/
|
||||
|
||||
cd "$RC_INSTALL_DIR"
|
||||
[ ! -f "${RC_INSTALL_DIR}/${RC_FILE}" ] && wget "$RC_URL" --retry-connrefused --quiet -O "${RC_INSTALL_DIR}/${RC_FILE}"
|
||||
|
||||
tar xzf $RC_FILE
|
||||
cp -rT $RC_EXTRACT $RC_INSTALL_DIR
|
||||
|
||||
# Delete old config folder
|
||||
cp $RC_INSTALL_DIR/config/defaults.inc.php $RC_CONFIG_DIR/defaults.inc.php
|
||||
rm -f -r $RC_INSTALL_DIR/config/
|
||||
ln -s $RC_CONFIG_DIR/ ./config
|
||||
# Replace with Hestia config
|
||||
cp -f $HESTIA_COMMON_DIR/roundcube/main.inc.php $RC_CONFIG_DIR/config.inc.php
|
||||
cp -f $HESTIA_COMMON_DIR/roundcube/mimetypes.php $RC_CONFIG_DIR/mimetypes.php
|
||||
chmod 644 $RC_CONFIG_DIR/*.php
|
||||
|
||||
cp -f $HESTIA_COMMON_DIR/roundcube/hestia.php $RC_INSTALL_DIR/plugins/password/drivers/
|
||||
mkdir -p $RC_CONFIG_DIR/plugins/password
|
||||
mkdir -p $RC_CONFIG_DIR/plugins/newmail_notifier
|
||||
mkdir -p $RC_CONFIG_DIR/plugins/zipdownload
|
||||
|
||||
# Allow changes to the respective config / Create symlinks to /etc/roundcube/
|
||||
cp -f $HESTIA_COMMON_DIR/roundcube/config.inc.php $RC_CONFIG_DIR/plugins/password/config.inc.php
|
||||
ln -s $RC_CONFIG_DIR/plugins/password/config.inc.php ./plugins/password/config.inc.php
|
||||
cp -f $HESTIA_COMMON_DIR/roundcube/plugins/config_newmail_notifier.inc.php $RC_CONFIG_DIR/plugins/newmail_notifier/config.inc.php
|
||||
ln -s $RC_CONFIG_DIR/plugins/newmail_notifier/config.inc.php ./plugins/newmail_notifier/config.inc.php
|
||||
cp -f $HESTIA_COMMON_DIR/roundcube/plugins/config_zipdownload.inc.php $RC_CONFIG_DIR/plugins/zipdownload/config.inc.php
|
||||
ln -s $RC_CONFIG_DIR/plugins/zipdownload/config.inc.php ./plugins/zipdownload/config.inc.php
|
||||
|
||||
# Set up correct permissions roundcube
|
||||
chown -R root:$WWW_USER $RC_CONFIG_DIR/
|
||||
chmod 751 -R $RC_CONFIG_DIR
|
||||
chmod 644 $RC_CONFIG_DIR/config.inc.php
|
||||
chmod 644 $RC_CONFIG_DIR/plugins/password/config.inc.php
|
||||
chmod 644 $RC_CONFIG_DIR/plugins/newmail_notifier/config.inc.php
|
||||
chmod 644 $RC_CONFIG_DIR/plugins/zipdownload/config.inc.php
|
||||
|
||||
# Add robots.txt
|
||||
echo "User-agent: *" > /var/lib/roundcube/robots.txt
|
||||
echo "Disallow: /" >> /var/lib/roundcube/robots.txt
|
||||
|
||||
chown -R root:$WWW_USER $RC_INSTALL_DIR
|
||||
|
||||
# Log file
|
||||
if [ ! -d $RC_LOG ]; then
|
||||
mkdir $RC_LOG
|
||||
fi
|
||||
chown apache:$WWW_USER $RC_LOG
|
||||
chmod 751 $RC_LOG
|
||||
|
||||
if [ ! -z "$(echo "$DB_SYSTEM" | grep -E 'mysql|pgsql')" ]; then
|
||||
host='localhost'
|
||||
database='roundcube'
|
||||
dbuser="$database"
|
||||
dbpass=$(generate_password)
|
||||
charset='UTF8'
|
||||
sed -i "s/%password%/$dbpass/g" $RC_CONFIG_DIR/config.inc.php
|
||||
|
||||
if [ ! -z "$(echo "$DB_SYSTEM" | grep -w 'mysql')" ]; then
|
||||
add_mysql_database
|
||||
mysql_query "USE $database; $(< /var/lib/roundcube/SQL/mysql.initial.sql)"
|
||||
else
|
||||
add_pgsql_database
|
||||
psql_query "USE $database; $(< /var/lib/roundcube/SQL/postgres.initial.sql)"
|
||||
fi
|
||||
fi
|
||||
|
||||
# TODO: Add support for PostgreSQL
|
||||
|
||||
rcDesKey="$(openssl rand -base64 30 | tr -d "/" | cut -c1-24)"
|
||||
sed -i "s/%des_key%/$rcDesKey/g" $RC_CONFIG_DIR/config.inc.php
|
||||
# Update server hostname in password change plugin
|
||||
sed -i "s/localhost/$(hostname)/g" $RC_CONFIG_DIR/plugins/password/config.inc.php
|
||||
|
||||
# Clean up
|
||||
rm -f -r $RC_INSTALL_DIR/installer
|
||||
rm -f -r $RC_INSTALL_DIR/$RC_FILE
|
||||
rm -f -r $RC_INSTALL_DIR/$RC_EXTRACT
|
||||
|
||||
# Updating hestia.conf
|
||||
if [ -z "$(grep WEBMAIL_SYSTEM $HESTIA/conf/hestia.conf)" ]; then
|
||||
$BIN/v-change-sys-config-value 'WEBMAIL_SYSTEM' 'roundcube'
|
||||
else
|
||||
if [ -z "$(echo "$WEBMAIL_SYSTEM" | grep -w 'roundcube')" ]; then
|
||||
if [ ! -z "$WEBMAIL_SYSTEM" ]; then
|
||||
$BIN/v-change-sys-config-value 'WEBMAIL_SYSTEM' "roundcube,$WEBMAIL_SYSTEM"
|
||||
else
|
||||
$BIN/v-change-sys-config-value 'WEBMAIL_SYSTEM' "roundcube"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
phpenmod mcrypt > /dev/null 2>&1
|
||||
else
|
||||
cd "$RC_INSTALL_DIR"
|
||||
[ ! -f "${RC_INSTALL_DIR}/${RC_FILE}" ] && wget "$RC_URL" --quiet -O "${RC_INSTALL_DIR}/${RC_FILE}"
|
||||
|
||||
tar xzf $RC_FILE
|
||||
|
||||
# Run Roundcube upgrade script
|
||||
$RC_INSTALL_DIR/$RC_EXTRACT/bin/installto.sh -y $RC_INSTALL_DIR > /dev/null 2>&1
|
||||
$RC_INSTALL_DIR/bin/update.sh --version "$version" > /dev/null 2>&1
|
||||
$RC_INSTALL_DIR/bin/indexcontacts.sh > /dev/null 2>&1
|
||||
chown -R root:$WWW_USER $RC_INSTALL_DIR
|
||||
|
||||
#clean up the mess
|
||||
if [ -d "$RC_INSTALL_DIR/installer" ]; then
|
||||
rm -f -r $RC_INSTALL_DIR/installer
|
||||
fi
|
||||
rm -f -r $RC_INSTALL_DIR/$RC_FILE
|
||||
rm -f -r $RC_INSTALL_DIR/$RC_EXTRACT
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
if [ "$UPDATE" = "yes" ]; then
|
||||
$BIN/v-log-action "system" "Info" "Plugins" "Roundcube updated (Version: $version)."
|
||||
else
|
||||
$BIN/v-log-action "system" "Info" "Plugins" "Roundcube enabled (Version: $version)."
|
||||
fi
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
99
bin/v-add-sys-sftp-jail
Executable file
99
bin/v-add-sys-sftp-jail
Executable file
@@ -0,0 +1,99 @@
|
||||
#!/bin/bash
|
||||
# info: add system sftp jail
|
||||
# options: [RESTART]
|
||||
#
|
||||
# example: v-add-sys-sftp-jail yes
|
||||
#
|
||||
# This function enables sftp jailed environment.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
restart=$1
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Checking sshd directives
|
||||
config='/etc/ssh/sshd_config'
|
||||
sftp_n=$(grep -n "Subsystem.*sftp" $config | grep -v internal | grep -v ":#")
|
||||
sftp_i=$(grep -n "^# Hestia SFTP Chroot" $config)
|
||||
|
||||
# Disabling normal sftp
|
||||
if [ -n "$sftp_n" ]; then
|
||||
fline=$(echo $sftp_n | cut -f 1 -d :)
|
||||
sed -i "${fline}s/Subsystem.*sftp/#Subsystem sftp/" $config
|
||||
restart='yes'
|
||||
fi
|
||||
|
||||
# Enabling jailed sftp
|
||||
if [ -z "$sftp_i" ]; then
|
||||
echo " " >> $config
|
||||
echo "# Hestia SFTP Chroot" >> $config
|
||||
echo "Match User sftp_dummy99" >> $config
|
||||
echo "ChrootDirectory %h" >> $config
|
||||
echo " X11Forwarding no" >> $config
|
||||
echo " AllowTCPForwarding no" >> $config
|
||||
echo " ForceCommand internal-sftp" >> $config
|
||||
restart='yes'
|
||||
fi
|
||||
|
||||
# Validating opensshd config
|
||||
if [ "$restart" = 'yes' ]; then
|
||||
subj="OpenSSH restart failed"
|
||||
email=$(grep CONTACT $HESTIA/data/users/admin/user.conf | cut -f 2 -d \')
|
||||
/usr/sbin/sshd -t > /dev/null 2>&1
|
||||
if [ "$?" -ne 0 ]; then
|
||||
mail_text="OpenSSH can not be restarted. Please check config:
|
||||
\n\n$(/usr/sbin/sshd -t)"
|
||||
echo -e "$mail_text" | $SENDMAIL -s "$subj" $email
|
||||
else
|
||||
service ssh restart > /dev/null 2>&1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Checking users
|
||||
shells="rssh|nologin"
|
||||
for user in $(grep "$HOMEDIR" /etc/passwd | egrep "$shells" | cut -f 1 -d:); do
|
||||
# Include all users v-add-user-sftp-jail will handle it
|
||||
$BIN/v-add-user-sftp-jail "$user" "no"
|
||||
done
|
||||
|
||||
# Restart ssh service
|
||||
if [ "$restart" = 'no' ]; then
|
||||
# Skip restart of SSH daemon
|
||||
echo "" > /dev/null 2>&1
|
||||
else
|
||||
service ssh restart > /dev/null 2>&1
|
||||
fi
|
||||
|
||||
# Add v-add-sys-sftp-jail to startup
|
||||
if [ ! -e "/etc/cron.d/hestia-sftp" ]; then
|
||||
echo "@reboot root sleep 60 && /usr/local/hestia/bin/v-add-sys-sftp-jail > /dev/null" > /etc/cron.d/hestia-sftp
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Logging
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
63
bin/v-add-sys-smtp
Executable file
63
bin/v-add-sys-smtp
Executable file
@@ -0,0 +1,63 @@
|
||||
#!/bin/bash
|
||||
# info: Add SMTP Account for logging, notification and internal mail
|
||||
# options: DOMAIN PORT SMTP_SECURITY USERNAME PASSWORD EMAIL
|
||||
#
|
||||
# example: v-add-sys-smtp example.com 587 STARTTLS test@domain.com securepassword test@example.com
|
||||
#
|
||||
# This function allows configuring a SMTP account for the server to use
|
||||
# for logging, notification and warn emails etc.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
domain=$1
|
||||
port=$2
|
||||
smtp_security=$3
|
||||
username=$4
|
||||
password=$5
|
||||
email=$6
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '6' "$#" 'DOMAIN PORT SMTP_SECURITY USERNAME PASSWORD EMAIL'
|
||||
is_format_valid 'domain' 'port' 'email' 'password'
|
||||
is_username_format_valid "$username" 'username'
|
||||
format_no_quotes "$password" 'passowrd'
|
||||
is_common_format_valid "$smtp_security" "SMTP_SECURITY"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
change_sys_value "USE_SERVER_SMTP" 'true'
|
||||
change_sys_value "SERVER_SMTP_HOST" "$domain"
|
||||
change_sys_value "SERVER_SMTP_PORT" "$port"
|
||||
change_sys_value "SERVER_SMTP_SECURITY" "$smtp_security"
|
||||
change_sys_value "SERVER_SMTP_USER" "$username"
|
||||
change_sys_value "SERVER_SMTP_PASSWD" "$password"
|
||||
change_sys_value "SERVER_SMTP_ADDR" "$email"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "system" "Info" "Mail" "Server SMTP enabled."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
64
bin/v-add-sys-smtp-relay
Executable file
64
bin/v-add-sys-smtp-relay
Executable file
@@ -0,0 +1,64 @@
|
||||
#!/bin/bash
|
||||
# info: add system wide smtp relay support
|
||||
# options: HOST [USERNAME] [PASSWORD] [PORT]
|
||||
#
|
||||
# example: v-add-sys-smtp-relay srv.smtprelay.tld uname123 pass12345
|
||||
#
|
||||
# This function adds system wide smtp relay support.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
host=$1
|
||||
username=$2
|
||||
password=$3
|
||||
port=${4-587}
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '1' "$#" 'HOST [USERNAME] [PASSWORD] [PORT]'
|
||||
is_format_valid 'port' 'host' 'password'
|
||||
is_username_format_valid "$username" 'username'
|
||||
format_no_quotes "$password" 'passowrd'
|
||||
is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM'
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
change_sys_value 'SMTP_RELAY' 'true'
|
||||
change_sys_value 'SMTP_RELAY_HOST' "$host"
|
||||
change_sys_value 'SMTP_RELAY_PORT' "$port"
|
||||
change_sys_value 'SMTP_RELAY_USER' "$username"
|
||||
|
||||
cat > /etc/exim4/smtp_relay.conf << EOL
|
||||
host:$host
|
||||
port:$port
|
||||
user:$username
|
||||
pass:$password
|
||||
EOL
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "system" "Info" "Mail" "Server-wide SMTP Relay enabled (Host: $host, Port: $port)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
174
bin/v-add-sys-snappymail
Executable file
174
bin/v-add-sys-snappymail
Executable file
@@ -0,0 +1,174 @@
|
||||
#!/bin/bash
|
||||
# info: Install SnappyMail webmail client
|
||||
# options: [MODE]
|
||||
#
|
||||
# This function installs the SnappyMail webmail client.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
# upgrade config file
|
||||
source "$HESTIA/install/upgrade/upgrade.conf"
|
||||
|
||||
MODE=$1
|
||||
UPDATE="no"
|
||||
# Version and Download paths
|
||||
# Version to be moved to upgrade script
|
||||
SM_FILE="snappymail-latest.tar.gz"
|
||||
# For removal of folder
|
||||
SM_EXTRACT_MAIN="snappymail"
|
||||
|
||||
# Downloading full version
|
||||
SM_URL="https://snappymail.eu/repository/latest.tar.gz"
|
||||
|
||||
# Folder paths
|
||||
SM_INSTALL_DIR="/var/lib/snappymail"
|
||||
SM_CONFIG_DIR="/etc/snappymail"
|
||||
SM_LOG="/var/log/snappymail"
|
||||
|
||||
WWW_USER="www-data"
|
||||
if [ -f /etc/redhat-release ]; then
|
||||
WWW_USER="apache"
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Checking root permissions
|
||||
if [ "x$(id -u)" != 'x0' ]; then
|
||||
echo "ERROR: v-add-sys-snappymail can only be executed by the root user"
|
||||
exit 10
|
||||
fi
|
||||
|
||||
# Ensure that $HESTIA (/usr/local/hestia/) and other variables are valid.
|
||||
if [ -z "$HESTIA" ]; then
|
||||
HESTIA="/usr/local/hestia"
|
||||
fi
|
||||
|
||||
if [ -z "$HOMEDIR" ] || [ -z "$HESTIA_INSTALL_DIR" ]; then
|
||||
echo "ERROR: Environment variables not present, installation aborted."
|
||||
exit 2
|
||||
fi
|
||||
|
||||
if [ -z "$(echo "$DB_SYSTEM" | grep -w 'mysql')" ]; then
|
||||
echo "ERROR: Mysql not available. Installation aborted"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# Get current version
|
||||
if [ -f "/var/lib/snappymail/data/VERSION" ]; then
|
||||
version=$(cat $SM_INSTALL_DIR/data/VERSION)
|
||||
if [ "$version" == "$sm_v" ]; then
|
||||
echo "Error: Installed version ($version) is equal to the available version ($sm_v)"
|
||||
exit 2
|
||||
else
|
||||
UPDATE="yes"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
if [ "$UPDATE" == "no" ]; then
|
||||
rm -f -r $SM_INSTALL_DIR
|
||||
rm -f -r $SM_CONFIG_DIR
|
||||
|
||||
mkdir $SM_INSTALL_DIR
|
||||
mkdir $SM_CONFIG_DIR
|
||||
|
||||
cd "$SM_INSTALL_DIR"
|
||||
[ ! -f "${SM_INSTALL_DIR}/${SM_FILE}" ] && wget "$SM_URL" --retry-connrefused --quiet -O "${SM_INSTALL_DIR}/${SM_FILE}"
|
||||
|
||||
if [ ! -f "${SM_INSTALL_DIR}/${SM_FILE}" ]; then
|
||||
echo "ERROR: Download failed, installation aborted."
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# Get current version
|
||||
|
||||
key=$(openssl rand -hex 4)
|
||||
|
||||
admin_account="admin_$key"
|
||||
admin_password=$(generate_password)
|
||||
|
||||
echo "Username: admin_$key" > ~/.snappymail
|
||||
echo "Password: $admin_password" >> ~/.snappymail
|
||||
echo "Secret key: admin_$key" >> ~/.snappymail
|
||||
|
||||
tar -xzf ${SM_INSTALL_DIR}/${SM_FILE}
|
||||
|
||||
mv ./data $SM_CONFIG_DIR/
|
||||
ln -s $SM_CONFIG_DIR/data/ ./data
|
||||
|
||||
if [ -f '/usr/bin/mariadb' ]; then
|
||||
mariadb -e "CREATE DATABASE snappymail" 2>&1
|
||||
r=$(generate_password)
|
||||
mariadb -e "GRANT ALL ON snappymail.*
|
||||
TO snappymail@localhost IDENTIFIED BY '$r'"
|
||||
else
|
||||
mysql -e "CREATE DATABASE snappymail" 2>&1
|
||||
r=$(generate_password)
|
||||
mysql -e "GRANT ALL ON snappymail.*
|
||||
TO snappymail@localhost IDENTIFIED BY '$r'"
|
||||
fi
|
||||
php -f $HESTIA_COMMON_DIR/snappymail/install.php "admin_$key" "$admin_password" "$r" "$BACKEND_PORT"
|
||||
|
||||
chown -R $WWW_USER:$WWW_USER ./data
|
||||
chown -R $WWW_USER:$WWW_USER $SM_CONFIG_DIR/
|
||||
|
||||
rm ${SM_INSTALL_DIR}/${SM_FILE}
|
||||
# Add robots.txt
|
||||
echo "User-agent: *" > $SM_INSTALL_DIR/robots.txt
|
||||
echo "Disallow: /" >> $SM_INSTALL_DIR/robots.txt
|
||||
|
||||
# Updating hestia.conf
|
||||
if [ -z "$(grep WEBMAIL_SYSTEM $HESTIA/conf/hestia.conf)" ]; then
|
||||
$BIN/v-change-sys-config-value 'WEBMAIL_SYSTEM' 'snappymail'
|
||||
else
|
||||
if [ -z "$(echo "$WEBMAIL_SYSTEM" | grep -w 'snappymail')" ]; then
|
||||
if [ -n "$WEBMAIL_SYSTEM" ]; then
|
||||
$BIN/v-change-sys-config-value 'WEBMAIL_SYSTEM' "snappymail,$WEBMAIL_SYSTEM"
|
||||
else
|
||||
$BIN/v-change-sys-config-value 'WEBMAIL_SYSTEM' "snappymail"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
else
|
||||
[ ! -f "${SM_INSTALL_DIR}/${SM_FILE}" ] && wget "$SM_URL" --quiet -O "${SM_INSTALL_DIR}/${SM_FILE}"
|
||||
version=$(cat $SM_INSTALL_DIR/data/VERSION)
|
||||
|
||||
tar -xzf snappymail-latest.tar.gz "data/VERSION" $SM_INSTALL_DIR/
|
||||
version_source=$(cat $SM_INSTALL_DIR/VERSION)
|
||||
|
||||
# Check version inside .tar.gz file in case hestia didn't update yet
|
||||
if [ "$version" != "$version_source" ]; then
|
||||
tar -xzf ${SM_INSTALL_DIR}/${SM_FILE}
|
||||
rm $SM_INSTALL_DIR/$SM_FILE
|
||||
fi
|
||||
rm ${SM_INSTALL_DIR}/VERSION
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
if [ "$UPDATE" = "yes" ]; then
|
||||
$BIN/v-log-action "system" "Info" "Plugins" "SnappyMail updated (Version: $version)."
|
||||
else
|
||||
$BIN/v-log-action "system" "Info" "Plugins" "SnappyMail enabled (Version: $version)."
|
||||
fi
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
286
bin/v-add-user
Executable file
286
bin/v-add-user
Executable file
@@ -0,0 +1,286 @@
|
||||
#!/bin/bash
|
||||
# info: add system user
|
||||
# options: USER PASSWORD EMAIL [PACKAGE] [NAME] [LASTNAME]
|
||||
#
|
||||
# example: v-add-user admin2 P4$$w@rD bgates@aol.com
|
||||
#
|
||||
# This function creates new user account.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
password=$2
|
||||
HIDE=2
|
||||
email=$3
|
||||
package=${4-default}
|
||||
name=$5
|
||||
# Last name has been added for backward compatibility with WHMCS / Blesta VestaCP Plugins
|
||||
if [ -n "$6" ]; then
|
||||
name="$name $6"
|
||||
fi
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
is_user_free() {
|
||||
# these names may cause issues with MariaDB/MySQL database names and should be reserved:
|
||||
# sudo has been added due to Privilege escalation as sudo group has always sudo permission
|
||||
check_sysuser=$(php -r '$reserved_names=array("aria", "aria_log", "mysql", "mysql_upgrade", "ib", "ib_buffer",
|
||||
"ddl", "ddl_recovery", "performance", "sudo"); if(in_array(strtolower($argv[1]), $reserved_names, true)){echo implode(", ", $reserved_names);}' "$user")
|
||||
if [ -n "$check_sysuser" ]; then
|
||||
check_result "$E_INVALID" "The user name '$user' is reserved and cannot be used. List of reserved names: $check_sysuser"
|
||||
return
|
||||
fi
|
||||
check_sysuser=$(cut -f 1 -d : /etc/passwd | grep "^$user$")
|
||||
if [ -n "$check_sysuser" ] || [ -e "$USER_DATA" ]; then
|
||||
check_result "$E_EXISTS" "user $user exists"
|
||||
fi
|
||||
}
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '3' "$#" 'USER PASSWORD EMAIL [PACKAGE] [NAME] '
|
||||
is_format_valid 'user' 'email' 'package'
|
||||
if [ -n "$name" ]; then
|
||||
is_format_valid 'name'
|
||||
fi
|
||||
|
||||
is_user_free "$user"
|
||||
is_password_valid
|
||||
is_package_valid
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Parsing package data
|
||||
pkg_data=$(cat $HESTIA/data/packages/$package.pkg | egrep -v "TIME|DATE")
|
||||
|
||||
# Checking shell
|
||||
shell_conf=$(echo "$pkg_data" | grep 'SHELL' | cut -f 2 -d \')
|
||||
shell=$(grep -w "$shell_conf" /etc/shells | head -n1)
|
||||
|
||||
# Adding user
|
||||
/usr/sbin/useradd "$user" -s "$shell" -c "$email" -m -d "$HOMEDIR/$user" -U
|
||||
check_result $? "user creation failed" "$E_INVALID"
|
||||
|
||||
# Adding password
|
||||
echo "$user:$password" | /usr/sbin/chpasswd
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
# Delete user on failure
|
||||
/usr/sbin/deluser "$user" > /dev/null 2>&1
|
||||
echo "Error: Password not accepted due to PAM restrictions"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# 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"
|
||||
|
||||
# Building directory tree
|
||||
mkdir $HOMEDIR/$user/conf
|
||||
|
||||
if [ -n "$WEB_SYSTEM" ]; then
|
||||
mkdir $HOMEDIR/$user/conf/web $HOMEDIR/$user/web $HOMEDIR/$user/tmp
|
||||
chmod 751 $HOMEDIR/$user/conf/web
|
||||
chmod 700 $HOMEDIR/$user/tmp
|
||||
chown $user:$user $HOMEDIR/$user/tmp
|
||||
chown root:$user $HOMEDIR/$user/web/
|
||||
fi
|
||||
|
||||
if [ -n "$MAIL_SYSTEM" ]; then
|
||||
mkdir $HOMEDIR/$user/conf/mail $HOMEDIR/$user/mail
|
||||
chmod 751 $HOMEDIR/$user/mail
|
||||
chmod 755 $HOMEDIR/$user/conf/mail
|
||||
fi
|
||||
|
||||
if [ -n "$DNS_SYSTEM" ]; then
|
||||
if [ "$DNS_SYSTEM" = 'named' ]; then
|
||||
dns_group='named'
|
||||
else
|
||||
dns_group='bind'
|
||||
fi
|
||||
mkdir $HOMEDIR/$user/conf/dns
|
||||
chmod 771 $HOMEDIR/$user/conf/dns
|
||||
chown root:$dns_group $HOMEDIR/$user/conf/dns
|
||||
fi
|
||||
|
||||
# Create default writeable folders
|
||||
mkdir $HOMEDIR/$user/.config \
|
||||
$HOMEDIR/$user/.cache \
|
||||
$HOMEDIR/$user/.local \
|
||||
$HOMEDIR/$user/.composer \
|
||||
$HOMEDIR/$user/.vscode-server \
|
||||
$HOMEDIR/$user/.ssh \
|
||||
$HOMEDIR/$user/.npm
|
||||
|
||||
chown $user:$user \
|
||||
$HOMEDIR/$user/.config \
|
||||
$HOMEDIR/$user/.cache \
|
||||
$HOMEDIR/$user/.local \
|
||||
$HOMEDIR/$user/.composer \
|
||||
$HOMEDIR/$user/.vscode-server \
|
||||
$HOMEDIR/$user/.ssh \
|
||||
$HOMEDIR/$user/.npm
|
||||
|
||||
# Set permissions
|
||||
chmod a+x $HOMEDIR/$user
|
||||
chattr +i $HOMEDIR/$user/conf > /dev/null 2>&1
|
||||
|
||||
# Adding user dir
|
||||
mkdir -p $USER_DATA/ssl $USER_DATA/dns $USER_DATA/mail
|
||||
|
||||
# Creating configuration files and pipes
|
||||
touch $USER_DATA/backup.conf \
|
||||
$USER_DATA/history.log \
|
||||
$USER_DATA/stats.log \
|
||||
$USER_DATA/web.conf \
|
||||
$USER_DATA/dns.conf \
|
||||
$USER_DATA/mail.conf \
|
||||
$USER_DATA/db.conf \
|
||||
$USER_DATA/cron.conf
|
||||
|
||||
chmod 770 $USER_DATA \
|
||||
$USER_DATA/ssl \
|
||||
$USER_DATA/dns \
|
||||
$USER_DATA/mail
|
||||
|
||||
chmod 660 $USER_DATA/backup.conf \
|
||||
$USER_DATA/history.log \
|
||||
$USER_DATA/stats.log \
|
||||
$USER_DATA/web.conf \
|
||||
$USER_DATA/dns.conf \
|
||||
$USER_DATA/mail.conf \
|
||||
$USER_DATA/db.conf \
|
||||
$USER_DATA/cron.conf
|
||||
|
||||
# Updating queue pipes
|
||||
echo "$BIN/v-update-user-disk $user" >> $HESTIA/data/queue/disk.pipe
|
||||
if [ -n "$WEB_SYSTEM" ]; then
|
||||
echo "$BIN/v-update-web-domains-traff $user" \
|
||||
>> $HESTIA/data/queue/traffic.pipe
|
||||
echo "$BIN/v-update-web-domains-disk $user" >> $HESTIA/data/queue/disk.pipe
|
||||
fi
|
||||
if [ -n "$MAIL_SYSTEM" ]; then
|
||||
echo "$BIN/v-update-mail-domains-disk $user" >> $HESTIA/data/queue/disk.pipe
|
||||
fi
|
||||
|
||||
if [ -n "$DB_SYSTEM" ]; then
|
||||
echo "$BIN/v-update-databases-disk $user" >> $HESTIA/data/queue/disk.pipe
|
||||
fi
|
||||
|
||||
# Generating timestamp
|
||||
time_n_date=$(date +'%T %F')
|
||||
time=$(echo "$time_n_date" | cut -f 1 -d \ )
|
||||
date=$(echo "$time_n_date" | cut -f 2 -d \ )
|
||||
|
||||
# Filling user config
|
||||
if [ "$user" != 'admin' ]; then
|
||||
ip_avail=$($BIN/v-list-user-ips admin plain | grep -w shared | wc -l)
|
||||
u_users=0
|
||||
else
|
||||
ip_avail=0
|
||||
u_users=1
|
||||
fi
|
||||
|
||||
echo "NAME='$name'
|
||||
PACKAGE='$package'
|
||||
$pkg_data
|
||||
CONTACT='$email'
|
||||
CRON_REPORTS='yes'
|
||||
MD5='$(awk -v user=$user -F : 'user == $1 {print $2}' /etc/shadow)'
|
||||
RKEY='$(generate_password)'
|
||||
TWOFA=''
|
||||
QRCODE=''
|
||||
PHPCLI=''
|
||||
ROLE='user'
|
||||
SUSPENDED='no'
|
||||
SUSPENDED_USERS='0'
|
||||
SUSPENDED_WEB='0'
|
||||
SUSPENDED_DNS='0'
|
||||
SUSPENDED_MAIL='0'
|
||||
SUSPENDED_DB='0'
|
||||
SUSPENDED_CRON='0'
|
||||
IP_AVAIL='$ip_avail'
|
||||
IP_OWNED='0'
|
||||
U_USERS='$u_users'
|
||||
U_DISK='0'
|
||||
U_DISK_DIRS='0'
|
||||
U_DISK_WEB='0'
|
||||
U_DISK_MAIL='0'
|
||||
U_DISK_DB='0'
|
||||
U_BANDWIDTH='0'
|
||||
U_WEB_DOMAINS='0'
|
||||
U_WEB_SSL='0'
|
||||
U_WEB_ALIASES='0'
|
||||
U_DNS_DOMAINS='0'
|
||||
U_DNS_RECORDS='0'
|
||||
U_MAIL_DOMAINS='0'
|
||||
U_MAIL_DKIM='0'
|
||||
U_MAIL_ACCOUNTS='0'
|
||||
U_MAIL_SSL='0'
|
||||
U_DATABASES='0'
|
||||
U_CRON_JOBS='0'
|
||||
U_BACKUPS='0'
|
||||
LANGUAGE=''
|
||||
THEME=''
|
||||
NOTIFICATIONS='no'
|
||||
PREF_UI_SORT='name'
|
||||
LOGIN_DISABLED='no'
|
||||
LOGIN_USE_IPLIST='no'
|
||||
LOGIN_ALLOW_IPS=''
|
||||
TIME='$time'
|
||||
DATE='$date'" > $USER_DATA/user.conf
|
||||
chmod 660 $USER_DATA/user.conf
|
||||
|
||||
# Updating quota
|
||||
if [ "$DISK_QUOTA" = 'yes' ]; then
|
||||
$BIN/v-update-user-quota "$user"
|
||||
fi
|
||||
|
||||
# Updating admin counter
|
||||
if [ "$user" != 'admin' ]; then
|
||||
increase_user_value 'admin' '$U_USERS'
|
||||
fi
|
||||
|
||||
# Run template trigger
|
||||
if [ -x "$HESTIA/data/packages/$package.sh" ]; then
|
||||
$HESTIA/data/packages/$package.sh "$user" "$email" "$name"
|
||||
fi
|
||||
|
||||
# Adding jailed sftp env
|
||||
$BIN/v-add-user-sftp-jail $user
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "system" "Info" "Users" "User account added (Name: $user)."
|
||||
$BIN/v-log-action "$user" "Info" "System" "Welcome!"
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
64
bin/v-add-user-2fa
Executable file
64
bin/v-add-user-2fa
Executable file
@@ -0,0 +1,64 @@
|
||||
#!/bin/bash
|
||||
# info: add 2fa to existing user
|
||||
# options: USER
|
||||
#
|
||||
# example: v-add-user-2fa admin
|
||||
#
|
||||
# This function creates a new 2fa token for user.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '1' "$#" 'USER'
|
||||
is_format_valid 'user' 'system'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Reading user values
|
||||
source $USER_DATA/user.conf
|
||||
|
||||
# Check if 2FA is already enabled
|
||||
if [ -n "$TWOFA" ]; then
|
||||
echo "Error: 2FA already enabled"
|
||||
exit "$E_EXISTS"
|
||||
fi
|
||||
|
||||
# Get secret and qr code from 2fa library
|
||||
data=$($HESTIA_PHP $HESTIA/web/inc/2fa/secret.php)
|
||||
|
||||
# Split to secret and qrcode using delimiter
|
||||
IFS='-' read -r -a array <<< "$data"
|
||||
secret=${array[0]}
|
||||
qrcode=${array[1]}
|
||||
|
||||
# Save the secret in user config (needs encryption?)
|
||||
update_user_value "$user" '$TWOFA' "$secret"
|
||||
update_user_value "$user" '$QRCODE' "$qrcode"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
exit
|
||||
95
bin/v-add-user-composer
Executable file
95
bin/v-add-user-composer
Executable file
@@ -0,0 +1,95 @@
|
||||
#!/bin/bash
|
||||
# info: add composer (php dependency manager) for a user
|
||||
# options: USER
|
||||
#
|
||||
# example: v-add-user-composer user [version]
|
||||
#
|
||||
# This function adds support for composer (php dependency manager)
|
||||
# Homepage: <https://getcomposer.org/>
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
version=${2-2}
|
||||
|
||||
if [ -z "$HESTIA" ]; then
|
||||
HESTIA="/usr/local/hestia"
|
||||
fi
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '1' "$#" 'USER [VERSION]'
|
||||
is_format_valid 'user'
|
||||
is_number_format_valid "$version" "version"
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
|
||||
[ -z "$HOMEDIR" ] && check_result "$E_NOTEXIST" "Hestia environment vars not present"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
COMPOSER_DIR="$HOMEDIR/$user/.composer"
|
||||
COMPOSER_BIN="$COMPOSER_DIR/composer"
|
||||
|
||||
if [ -f "$COMPOSER_BIN" ]; then
|
||||
echo "Composer already available"
|
||||
exit
|
||||
fi
|
||||
|
||||
[ -z "$(readlink -m "$COMPOSER_DIR" | egrep "^$HOMEDIR/$user/")" ] && check_result "$E_FORBIDEN" "Path outside of user homedir (Composer dir)"
|
||||
[ -z "$(readlink -m "$COMPOSER_BIN" | egrep "^$HOMEDIR/$user/")" ] && check_result "$E_FORBIDEN" "Path outside of user homedir (Composer bin)"
|
||||
[ -z "$(readlink -m "$HOMEDIR/$user/.config/" | egrep "^$HOMEDIR/$user/")" ] && check_result "$E_FORBIDEN" "Path outside of user homedir (.conf)"
|
||||
|
||||
mkdir -p "$COMPOSER_DIR"
|
||||
chown $user: "$COMPOSER_DIR"
|
||||
mkdir -p "$HOMEDIR/$user/.config"
|
||||
chown $user: "$HOMEDIR/$user/.config"
|
||||
echo "alias composer=/home/"$user"/.composer/composer" >> /home/$user/.bash_aliases
|
||||
|
||||
COMPOSER_SETUP_FILE=$(mktemp)
|
||||
check_result $? "Create temp file"
|
||||
chown $user: "$COMPOSER_SETUP_FILE"
|
||||
|
||||
signature="$(curl --silent --show-error https://composer.github.io/installer.sig)"
|
||||
check_result $? "Download signature"
|
||||
|
||||
user_exec wget --tries=3 --timeout=15 --read-timeout=15 --waitretry=3 --no-dns-cache https://getcomposer.org/installer --quiet -O "$COMPOSER_SETUP_FILE"
|
||||
check_result $? "Download composer installer"
|
||||
|
||||
if [[ "$signature" != $(sha384sum "$COMPOSER_SETUP_FILE" | cut -f 1 -d " ") ]]; then
|
||||
rm -f "$COMPOSER_SETUP_FILE"
|
||||
check_result "$E_INVALID" "Composer signature does not match"
|
||||
fi
|
||||
|
||||
COMPOSER_HOME="$HOMEDIR/$user/.config/composer" user_exec /usr/bin/php "$COMPOSER_SETUP_FILE" --quiet "--$version" --install-dir="$COMPOSER_DIR" --filename=composer
|
||||
check_result $? "Composer install failed"
|
||||
|
||||
[ -f "$COMPOSER_SETUP_FILE" ] && rm -f "$COMPOSER_SETUP_FILE"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "Plugins" "Composer support enabled."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
79
bin/v-add-user-notification
Executable file
79
bin/v-add-user-notification
Executable file
@@ -0,0 +1,79 @@
|
||||
#!/bin/bash
|
||||
# info: add user notification
|
||||
# options: USER TOPIC NOTICE [TYPE]
|
||||
#
|
||||
# This function adds a new user notification to the panel.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
topic=$(echo $2 | sed "s/'/%quote%/g")
|
||||
notice=$(echo $3 | sed "s/'/%quote%/g")
|
||||
type=$4
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '2' "$#" 'USER TOPIC NOTICE [TYPE]'
|
||||
is_format_valid 'user' 'topic' 'notice'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Defining notification id
|
||||
if [ -e "$USER_DATA/notifications.conf" ]; then
|
||||
nid=$(grep "NID=" $USER_DATA/notifications.conf | cut -f 2 -d \')
|
||||
nid=$(echo "$nid" | sort -n | tail -n1)
|
||||
if [ -n "$nid" ]; then
|
||||
nid="$((nid + 1))"
|
||||
else
|
||||
nid=1
|
||||
fi
|
||||
else
|
||||
nid=1
|
||||
fi
|
||||
|
||||
# Generating timestamp
|
||||
time_n_date=$(date +'%T %F')
|
||||
time=$(echo "$time_n_date" | cut -f 1 -d \ )
|
||||
date=$(echo "$time_n_date" | cut -f 2 -d \ )
|
||||
|
||||
# Concatenating string
|
||||
str="NID='$nid' TOPIC='$topic' NOTICE='$notice' TYPE='$type'"
|
||||
str="$str ACK='no' TIME='$time' DATE='$date'"
|
||||
|
||||
# Adding to config
|
||||
echo "$str" >> $USER_DATA/notifications.conf
|
||||
|
||||
# Changing permissions
|
||||
chmod 660 $USER_DATA/notifications.conf
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Updating notification counter
|
||||
if [ -z "$(grep NOTIFICATIONS $USER_DATA/user.conf)" ]; then
|
||||
sed -i "s/^TIME/NOTIFICATIONS='yes'\nTIME/g" $USER_DATA/user.conf
|
||||
else
|
||||
update_user_value "$user" '$NOTIFICATIONS' "yes"
|
||||
fi
|
||||
|
||||
exit
|
||||
154
bin/v-add-user-package
Executable file
154
bin/v-add-user-package
Executable file
@@ -0,0 +1,154 @@
|
||||
#!/bin/bash
|
||||
# info: adding user package
|
||||
# options: tmpfile PACKAGE [REWRITE]
|
||||
#
|
||||
# This function adds new user package to the system.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
tmpfile=$1
|
||||
package=$2
|
||||
rewrite=$3
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
is_package_consistent() {
|
||||
source_conf "$tmpfile"
|
||||
if [ "$WEB_DOMAINS" != 'unlimited' ]; then
|
||||
is_int_format_valid "$WEB_DOMAINS" 'WEB_DOMAINS'
|
||||
fi
|
||||
if [ "$WEB_ALIASES" != 'unlimited' ]; then
|
||||
is_int_format_valid "$WEB_ALIASES" 'WEB_ALIASES'
|
||||
fi
|
||||
if [ "$DNS_DOMAINS" != 'unlimited' ]; then
|
||||
is_int_format_valid "$DNS_DOMAINS" 'DNS_DOMAINS'
|
||||
fi
|
||||
if [ "$DNS_RECORDS" != 'unlimited' ]; then
|
||||
is_int_format_valid "$DNS_RECORDS" 'DNS_RECORDS'
|
||||
fi
|
||||
if [ "$MAIL_DOMAINS" != 'unlimited' ]; then
|
||||
is_int_format_valid "$MAIL_DOMAINS" 'MAIL_DOMAINS'
|
||||
fi
|
||||
if [ "$MAIL_ACCOUNTS" != 'unlimited' ]; then
|
||||
is_int_format_valid "$MAIL_ACCOUNTS" 'MAIL_ACCOUNTS'
|
||||
fi
|
||||
if [ "$DATABASES" != 'unlimited' ]; then
|
||||
is_int_format_valid "$DATABASES" 'DATABASES'
|
||||
fi
|
||||
if [ "$CRON_JOBS" != 'unlimited' ]; then
|
||||
is_int_format_valid "$CRON_JOBS" 'CRON_JOBS'
|
||||
fi
|
||||
|
||||
is_int_format_valid "$RATE_LIMIT" 'RATE_LIMIT'
|
||||
|
||||
if [ "$DISK_QUOTA" != 'unlimited' ]; then
|
||||
is_int_format_valid "$DISK_QUOTA" 'DISK_QUOTA'
|
||||
fi
|
||||
if [ "$BANDWIDTH" != 'unlimited' ]; then
|
||||
is_int_format_valid "$BANDWIDTH" 'BANDWIDTH'
|
||||
fi
|
||||
is_int_format_valid "$BACKUPS" 'BACKUPS'
|
||||
if [ -n "$WEB_TEMPLATE" ]; then
|
||||
is_web_template_valid "$WEB_TEMPLATE"
|
||||
fi
|
||||
if [ -n "$BACKEND_TEMPLATE" ]; then
|
||||
is_backend_template_valid "$BACKEND_TEMPLATE"
|
||||
fi
|
||||
if [ -n "$PROXY_TEMPLATE" ]; then
|
||||
is_proxy_template_valid "$PROXY_TEMPLATE"
|
||||
fi
|
||||
if [ -n "$DNS_TEMPLATE" ]; then
|
||||
is_dns_template_valid "$DNS_TEMPLATE"
|
||||
fi
|
||||
if [ -n "$NS" ]; then
|
||||
IFS=',' read -r -a nameservers <<< "$NS"
|
||||
i=1
|
||||
for ns in "${nameservers[@]}"; do
|
||||
is_domain_format_valid "$ns" "ns$i"
|
||||
i=$((i + 1))
|
||||
done
|
||||
fi
|
||||
|
||||
is_format_valid_shell "$SHELL"
|
||||
}
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '2' "$#" 'PKG_DIR PACKAGE' 'rewrite'
|
||||
is_format_valid 'package'
|
||||
if [ "$rewrite" != 'yes' ]; then
|
||||
is_package_new "$package"
|
||||
else
|
||||
is_package_valid "$package"
|
||||
fi
|
||||
|
||||
if [ ! -f "$tmpfile" ]; then
|
||||
echo "$tmpfile does not exists"
|
||||
exit "$E_NOTEXIST"
|
||||
fi
|
||||
|
||||
is_package_consistent
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Generating timestamp
|
||||
time_n_date=$(date +'%T %F')
|
||||
time=$(echo "$time_n_date" | cut -f 1 -d \ )
|
||||
date=$(echo "$time_n_date" | cut -f 2 -d \ )
|
||||
|
||||
SHELL=$(basename $SHELL)
|
||||
echo "WEB_TEMPLATE='$WEB_TEMPLATE'
|
||||
PROXY_TEMPLATE='$PROXY_TEMPLATE'
|
||||
BACKEND_TEMPLATE='$BACKEND_TEMPLATE'
|
||||
DNS_TEMPLATE='$DNS_TEMPLATE'
|
||||
WEB_DOMAINS='$WEB_DOMAINS'
|
||||
WEB_ALIASES='$WEB_ALIASES'
|
||||
DNS_DOMAINS='$DNS_DOMAINS'
|
||||
DNS_RECORDS='$DNS_RECORDS'
|
||||
MAIL_DOMAINS='$MAIL_DOMAINS'
|
||||
MAIL_ACCOUNTS='$MAIL_ACCOUNTS'
|
||||
RATE_LIMIT='$RATE_LIMIT'
|
||||
DATABASES='$DATABASES'
|
||||
CRON_JOBS='$CRON_JOBS'
|
||||
DISK_QUOTA='$DISK_QUOTA'
|
||||
BANDWIDTH='$BANDWIDTH'
|
||||
NS='$NS'
|
||||
SHELL='$SHELL'
|
||||
BACKUPS='$BACKUPS'
|
||||
TIME='$time'
|
||||
DATE='$date'
|
||||
" > "$HESTIA/data/packages/$package.pkg"
|
||||
|
||||
chmod 644 "$HESTIA/data/packages/$package.pkg"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Logging
|
||||
if [ "$rewrite" != 'yes' ]; then
|
||||
$BIN/v-log-action "system" "Info" "Packages" "Package added (Name: $package)."
|
||||
else
|
||||
$BIN/v-log-action "system" "Info" "Packages" "Package limits updated (Name: $package)."
|
||||
fi
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
94
bin/v-add-user-sftp-jail
Executable file
94
bin/v-add-user-sftp-jail
Executable file
@@ -0,0 +1,94 @@
|
||||
#!/bin/bash
|
||||
# info: add user sftp jail
|
||||
# options: USER [RESTART]
|
||||
#
|
||||
# example: v-add-user-sftp-jail admin
|
||||
#
|
||||
# This function enables sftp jailed environment
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
restart=$2
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '1' "$#" 'USER'
|
||||
is_format_valid 'user'
|
||||
check=$(is_object_valid 'user' 'USER' "$user")
|
||||
if [ $? -ne 0 ]; then
|
||||
user_str=$(grep "^$user:" /etc/passwd | egrep "rssh|nologin")
|
||||
#try to detect "owner" of the ftp_user if not found dont set it up
|
||||
user_owner=$(echo $user_str | cut -f6 -d : | cut -f3 -d /)
|
||||
is_object_valid 'user' 'USER' "$user_owner"
|
||||
fi
|
||||
user_str=$(grep "^$user:" /etc/passwd | egrep "rssh|nologin")
|
||||
if [ -z "$user_str" ]; then
|
||||
exit
|
||||
fi
|
||||
|
||||
# Get current users and split into array
|
||||
ssh_users=$(grep -A1 "^# Hestia SFTP Chroot" /etc/ssh/sshd_config | sed -n 2p | sed 's/Match User //')
|
||||
IFS=',' read -r -a users <<< "$ssh_users"
|
||||
|
||||
# Check if jail exist
|
||||
match_string="$ssh_users,"
|
||||
if [[ "$match_string" =~ ,$user, ]]; then
|
||||
if [[ -d /home/$user && -z "$(find /home/$user -user root -print -prune -o -prune)" ]]; then
|
||||
chown root:root /home/$user
|
||||
fi
|
||||
exit
|
||||
fi
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Add user to array
|
||||
users+=($user)
|
||||
|
||||
# Write new user list to config
|
||||
users=$(
|
||||
IFS=','
|
||||
echo "${users[*]// /|}"
|
||||
IFS=$' \t\n'
|
||||
)
|
||||
sed -i "s/$ssh_users/$users/g" /etc/ssh/sshd_config
|
||||
|
||||
# Set home folder permission to root
|
||||
if [ -d "/home/$user" ]; then
|
||||
chown root:root /home/$user
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Restart ssh service
|
||||
if [ "$restart" = 'no' ]; then
|
||||
# Skip restart of SSH daemon
|
||||
echo "" > /dev/null 2>&1
|
||||
else
|
||||
service ssh restart > /dev/null 2>&1
|
||||
fi
|
||||
|
||||
# Logging
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
82
bin/v-add-user-sftp-key
Executable file
82
bin/v-add-user-sftp-key
Executable file
@@ -0,0 +1,82 @@
|
||||
#!/bin/bash
|
||||
# info: add user sftp key
|
||||
# options: USER [TTL]
|
||||
#
|
||||
# This function creates and updates SSH keys for used with the File Manager.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
ttl=$2
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '1' "$#" 'USER [TTL]'
|
||||
is_format_valid 'user' 'ttl'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
PRVKEY_FILE="$HOMEDIR/$user/.ssh/hst-filemanager-key"
|
||||
PUBKEY_FILE="$HOMEDIR/$user/.ssh/hst-filemanager-key.pub"
|
||||
AUTHKEY_FILE="$HOMEDIR/$user/.ssh/authorized_keys"
|
||||
|
||||
[ -z "$(readlink -f "$PRVKEY_FILE" | egrep "^$HOMEDIR/$user/.ssh/")" ] && check_result "$E_FORBIDEN" "Invalid private key file path"
|
||||
[ -z "$(readlink -f "$PUBKEY_FILE" | egrep "^$HOMEDIR/$user/.ssh/")" ] && check_result "$E_FORBIDEN" "Invalid public key file path"
|
||||
[ -z "$(readlink -f "$AUTHKEY_FILE" | egrep "^$HOMEDIR/$user/.ssh/")" ] && check_result "$E_FORBIDEN" "Invalid authorized keys path"
|
||||
|
||||
if [ ! -f "${PRVKEY_FILE}" ]; then
|
||||
ssh-keygen -q -b 1024 -t rsa -f "${PRVKEY_FILE}" -N ""
|
||||
rm "${PUBKEY_FILE}"
|
||||
new_privkey=true
|
||||
fi
|
||||
|
||||
if [ ! -f "${AUTHKEY_FILE}" ] || [ "$new_privkey" = true ]; then
|
||||
pubkey_str="$(ssh-keygen -y -f ${PRVKEY_FILE})"
|
||||
pubkey_desc="filemanager.ssh.key"
|
||||
|
||||
if grep --quiet --no-messages -F "$pubkey_desc" "${AUTHKEY_FILE}"; then
|
||||
sed -i "/filemanager\.ssh\.key\$/d" "${AUTHKEY_FILE}"
|
||||
fi
|
||||
|
||||
# make sure authorized_keys is ending with EOL
|
||||
[ -f "${AUTHKEY_FILE}" ] && sed -i '$a\' "${AUTHKEY_FILE}"
|
||||
|
||||
expire=0
|
||||
if [[ "$ttl" -gt 0 ]]; then
|
||||
expire=$(date +%s -d "+${ttl} min")
|
||||
echo "rm ${PRVKEY_FILE}" | at "now +${ttl} minute" > /dev/null 2>&1
|
||||
fi
|
||||
echo "from=\"127.0.0.1\",command=\"internal-sftp\",restrict ${pubkey_str} TS:${expire} ${pubkey_desc}" >> "${AUTHKEY_FILE}"
|
||||
fi
|
||||
|
||||
#
|
||||
chown ${user}: "${AUTHKEY_FILE}"
|
||||
chown admin: "${PRVKEY_FILE}"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Logging
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
73
bin/v-add-user-ssh-key
Executable file
73
bin/v-add-user-ssh-key
Executable file
@@ -0,0 +1,73 @@
|
||||
#!/bin/bash
|
||||
# info: add ssh key
|
||||
# options: USER KEY
|
||||
#
|
||||
# example: v-add-user-ssh-key user 'valid ssh key'
|
||||
#
|
||||
# Function check if $user/.ssh/authorized_keys exists and create it.
|
||||
# After that it append the new key(s)
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
key=$2
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '2' "$#" 'USER SSH_PUBLIC_KEY'
|
||||
is_format_valid 'user'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Reading user values
|
||||
source $USER_DATA/user.conf
|
||||
|
||||
AUTHKEY_FILE="$HOMEDIR/$user/.ssh/authorized_keys"
|
||||
[ -z "$(readlink -f "$AUTHKEY_FILE" | egrep "^$HOMEDIR/$user/.ssh/")" ] && check_result "$E_FORBIDEN" "Invalid authorized keys path"
|
||||
|
||||
# Check if file exits
|
||||
if [ ! -f "$AUTHKEY_FILE" ]; then
|
||||
v-add-fs-file "$user" "${AUTHKEY_FILE}"
|
||||
fi
|
||||
|
||||
[ -z "$key" ] && check_result "$E_NOTEXIST" "Empty ssh public key"
|
||||
|
||||
if ! echo "$key" | ssh-keygen -l -f - > /dev/null 2>&1; then
|
||||
check_result "$E_PARSING" "Validating user private key"
|
||||
fi
|
||||
|
||||
# Make sure authorized_keys ends with EOL
|
||||
[ -f "${AUTHKEY_FILE}" ] && sed -i '$a\' "${AUTHKEY_FILE}"
|
||||
|
||||
# Append key data to file
|
||||
echo "$key" >> "$AUTHKEY_FILE"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "System" "Added a new SSH key."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
69
bin/v-add-user-wp-cli
Executable file
69
bin/v-add-user-wp-cli
Executable file
@@ -0,0 +1,69 @@
|
||||
#!/bin/bash
|
||||
# info: add wp-cli for a user
|
||||
# options: USER
|
||||
#
|
||||
# example: v-add-user-wp-cli user
|
||||
#
|
||||
# This function adds support for wp-cli to the user account
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
|
||||
if [ -z "$HESTIA" ]; then
|
||||
HESTIA="/usr/local/hestia"
|
||||
fi
|
||||
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '1' "$#" 'USER'
|
||||
is_format_valid 'user'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
WPCLI_DIR="/home/$user/.wp-cli"
|
||||
WPCLI_BIN="$WPCLI_DIR/wp"
|
||||
|
||||
if [ -f "$WPCLI_BIN" ]; then
|
||||
check_result "$E_EXISTS" "For user name '$user' WP-CLI already available!"
|
||||
exit
|
||||
fi
|
||||
|
||||
[ -z "$(readlink -m "$WPCLI_DIR" | egrep "^$HOMEDIR/$user/")" ] && check_result "$E_FORBIDEN" "Path outside of user homedir (WP Cli dir)"
|
||||
[ -z "$(readlink -m "$WPCLI_BIN" | egrep "^$HOMEDIR/$user/")" ] && check_result "$E_FORBIDEN" "Path outside of user homedir (WP Cli bin)"
|
||||
|
||||
mkdir -p "$WPCLI_DIR"
|
||||
chown $user:$user "$WPCLI_DIR"
|
||||
|
||||
user_exec wget --tries=3 --timeout=15 --read-timeout=15 --waitretry=3 --no-dns-cache --quiet -O "$WPCLI_BIN" https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
|
||||
user_exec chmod +x "$WPCLI_BIN"
|
||||
user_exec echo -e "#add wp-cli alias for user\nalias wp='php $WPCLI_BIN'" >> ~/.bashrc
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "Plugins" "WP-CLI support enabled."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
257
bin/v-add-web-domain
Executable file
257
bin/v-add-web-domain
Executable file
@@ -0,0 +1,257 @@
|
||||
#!/bin/bash
|
||||
# info: add web domain
|
||||
# options: USER DOMAIN [IP] [RESTART] [ALIASES] [PROXY_EXTENSIONS]
|
||||
#
|
||||
# example: v-add-web-domain admin wonderland.com 192.18.22.43 yes www.wonderland.com
|
||||
#
|
||||
# This function adds virtual host to a server. In cases when ip is
|
||||
# undefined in the script, "default" template will be used. The alias of
|
||||
# www.domain.tld type will be automatically assigned to the domain unless
|
||||
# "none" is transmited as argument. If ip have associated dns name, this
|
||||
# domain will also get the alias domain-tpl.$ipname. An alias with the ip
|
||||
# name is useful during the site testing while dns isn't moved to server yet.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
domain_idn=$2
|
||||
ip=$3
|
||||
restart=$4 # will be moved to the end soon
|
||||
aliases=$5
|
||||
proxy_ext=$6
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# shellcheck source=/usr/local/hestia/func/ip.sh
|
||||
source $HESTIA/func/ip.sh
|
||||
# shellcheck source=/usr/local/hestia/func/syshealth.sh
|
||||
source $HESTIA/func/syshealth.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# Additional argument formatting
|
||||
format_domain
|
||||
format_domain_idn
|
||||
format_aliases
|
||||
domain_utf=$(idn2 --quiet -d "$domain_idn")
|
||||
|
||||
|
||||
WWW_USER="www-data"
|
||||
if [ -f /etc/redhat-release ]; then
|
||||
WWW_USER="apache"
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
is_system_enabled "$WEB_SYSTEM" 'WEB_SYSTEM'
|
||||
check_args '2' "$#" 'USER DOMAIN [IP] [RESTART] [ALIASES] [PROXY_EXTENSIONS]'
|
||||
is_format_valid 'user' 'domain' 'aliases' 'ip' 'proxy_ext'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_package_full 'WEB_DOMAINS'
|
||||
|
||||
if [ "$aliases" != "none" ]; then
|
||||
ALIAS="$aliases"
|
||||
is_package_full 'WEB_ALIASES'
|
||||
fi
|
||||
|
||||
if [ "$($BIN/v-list-web-domain $user $domain_utf plain | cut -f 1) " != "$domain" ]; then
|
||||
is_domain_new 'web' "$domain_utf,$aliases"
|
||||
fi
|
||||
if [ "$($BIN/v-list-web-domain $user $domain_idn plain | cut -f 1) " != "$domain" ]; then
|
||||
is_domain_new 'web' "$domain_idn,$aliases"
|
||||
else
|
||||
is_domain_new 'web' "$domain,$aliases"
|
||||
fi
|
||||
if [ -z "$(is_ip_format_valid $domain)" ]; then
|
||||
echo "Error: Invalid domain format. IP address detected as input."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
is_dir_symlink "$HOMEDIR/$user/web"
|
||||
is_dir_symlink "$HOMEDIR/$user/web/$domain"
|
||||
|
||||
is_base_domain_owner "$domain,$aliases"
|
||||
|
||||
if [ -n "$ip" ]; then
|
||||
is_ip_valid "$ip" "$user"
|
||||
else
|
||||
get_user_ip
|
||||
fi
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Reading user values
|
||||
source_conf "$USER_DATA/user.conf"
|
||||
|
||||
[[ -e "$HOMEDIR/$user/web/$domain" ]] && check_result "$E_EXISTS" "Web domain folder for $domain should not exist"
|
||||
|
||||
# Creating domain directories
|
||||
mkdir $HOMEDIR/$user/web/$domain
|
||||
chown $user:$user $HOMEDIR/$user/web/$domain
|
||||
$BIN/v-add-fs-directory "$user" "$HOMEDIR/$user/web/$domain/public_html"
|
||||
$BIN/v-add-fs-directory "$user" "$HOMEDIR/$user/web/$domain/document_errors"
|
||||
$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
|
||||
touch /var/log/$WEB_SYSTEM/domains/$domain.bytes \
|
||||
/var/log/$WEB_SYSTEM/domains/$domain.log \
|
||||
/var/log/$WEB_SYSTEM/domains/$domain.error.log
|
||||
ln -f -s /var/log/$WEB_SYSTEM/domains/$domain.*log \
|
||||
$HOMEDIR/$user/web/$domain/logs/
|
||||
|
||||
# Adding domain skeleton
|
||||
user_exec cp -r $WEBTPL/skel/* "$HOMEDIR/$user/web/$domain/" > /dev/null 2>&1
|
||||
for file in $(find "$HOMEDIR/$user/web/$domain/" -type f); do
|
||||
sed -i "s/%domain%/$domain/g" $file
|
||||
done
|
||||
|
||||
# Changing file owner & permission
|
||||
chown -R $user:$user $HOMEDIR/$user/web/$domain
|
||||
chown root:$user /var/log/$WEB_SYSTEM/domains/$domain.* $conf
|
||||
chmod 640 /var/log/$WEB_SYSTEM/domains/$domain.*
|
||||
user_exec chmod 751 $HOMEDIR/$user/web/$domain/*
|
||||
user_exec chmod 551 $HOMEDIR/$user/web/$domain/stats $HOMEDIR/$user/web/$domain/logs
|
||||
user_exec chmod 644 $HOMEDIR/$user/web/$domain/public_*html/*
|
||||
user_exec chmod 551 $HOMEDIR/$user/web/$domain
|
||||
chown --no-dereference $user:$WWW_USER $HOMEDIR/$user/web/$domain/public_*html
|
||||
|
||||
# Adding PHP-FPM backend
|
||||
if [ -n "$WEB_BACKEND" ]; then
|
||||
if [ -z "$BACKEND_TEMPLATE" ]; then
|
||||
BACKEND_TEMPLATE='default'
|
||||
if [ -z "$(grep BACKEND_TEMPLATE $USER_DATA/user.conf)" ]; then
|
||||
sed -i "s/^DNS_TEMPL/BACKEND_TEMPLATE='default'\nDNS_TEMPL/g" \
|
||||
$USER_DATA/user.conf
|
||||
else
|
||||
update_user_value "$user" '$BACKEND_TEMPLATE' "default"
|
||||
fi
|
||||
fi
|
||||
export BACKEND="$BACKEND_TEMPLATE"
|
||||
$BIN/v-add-web-domain-backend "$user" "$domain" "$BACKEND_TEMPLATE" "$restart"
|
||||
check_result $? "Backend error" > /dev/null
|
||||
fi
|
||||
|
||||
# Preparing domain aliases
|
||||
if [ "$aliases" = 'none' ]; then
|
||||
ALIAS=''
|
||||
else
|
||||
ALIAS="www.$domain"
|
||||
if [ -z "$aliases" ]; then
|
||||
# Check and skip www alias for subdomains.
|
||||
IFS='.' read -r -a domain_elements <<< "$domain"
|
||||
if [ "${#domain_elements[@]}" -gt 2 ]; then
|
||||
is_valid_2_part_extension $domain
|
||||
if [ $? -ne 0 ]; then
|
||||
ALIAS=""
|
||||
else
|
||||
ALIAS="www.$domain"
|
||||
fi
|
||||
else
|
||||
ALIAS="www.$domain"
|
||||
fi
|
||||
else
|
||||
ALIAS="$aliases"
|
||||
fi
|
||||
|
||||
ip_alias=$(get_ip_alias "$domain")
|
||||
if [ -n "$ip_alias" ]; then
|
||||
ALIAS="$ALIAS,$ip_alias"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Preparing domain variables
|
||||
prepare_web_domain_values
|
||||
|
||||
if [ -z "$WEB_TEMPLATE" ]; then
|
||||
WEB_TEMPLATE='default'
|
||||
update_user_value "$user" '$WEB_TEMPLATE' "default"
|
||||
fi
|
||||
|
||||
# Adding web server config
|
||||
add_web_config "$WEB_SYSTEM" "$WEB_TEMPLATE.tpl"
|
||||
|
||||
# Adding proxy config
|
||||
if [ -n "$PROXY_SYSTEM" ]; then
|
||||
PROXY_EXT="$proxy_ext"
|
||||
if [ -z "$proxy_ext" ]; then
|
||||
# Code
|
||||
PROXY_EXT="css,htm,html,js,json,xml"
|
||||
# Image (from https://developer.mozilla.org/en-US/docs/Web/Media/Formats/Image_types)
|
||||
PROXY_EXT="$PROXY_EXT,apng,avif,bmp,cur,gif,ico,jfif,jpg,jpeg,pjp,pjpeg,png,svg,tif,tiff,webp"
|
||||
# Audio from (https://developer.mozilla.org/en-US/docs/Web/Media/Formats/Audio_codecs)
|
||||
PROXY_EXT="$PROXY_EXT,aac,caf,flac,m4a,midi,mp3,ogg,opus,wav"
|
||||
# Video (from https://developer.mozilla.org/en-US/docs/Web/Media/Formats/Video_codecs)
|
||||
PROXY_EXT="$PROXY_EXT,3gp,av1,avi,m4v,mkv,mov,mpg,mpeg,mp4,mp4v,webm"
|
||||
# Fonts
|
||||
PROXY_EXT="$PROXY_EXT,otf,ttf,woff,woff2"
|
||||
# Productivity
|
||||
PROXY_EXT="$PROXY_EXT,doc,docx,odf,odp,ods,odt,pdf,ppt,pptx,rtf,txt,xls,xlsx"
|
||||
# Archive
|
||||
PROXY_EXT="$PROXY_EXT,7z,bz2,gz,rar,tar,tgz,zip"
|
||||
# Binaries
|
||||
PROXY_EXT="$PROXY_EXT,apk,appx,bin,dmg,exe,img,iso,jar,msi"
|
||||
fi
|
||||
if [ -z "$PROXY_TEMPLATE" ]; then
|
||||
PROXY_TEMPLATE='default'
|
||||
update_user_value "$user" '$PROXY_TEMPLATE' "default"
|
||||
fi
|
||||
|
||||
add_web_config "$PROXY_SYSTEM" "$PROXY_TEMPLATE.tpl"
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Increasing counters
|
||||
increase_ip_value "$local_ip"
|
||||
increase_user_value "$user" '$U_WEB_DOMAINS'
|
||||
increase_user_value "$user" '$U_WEB_ALIASES' "$alias_number"
|
||||
|
||||
# Generating timestamp
|
||||
time_n_date=$(date +'%T %F')
|
||||
time=$(echo "$time_n_date" | cut -f 1 -d \ )
|
||||
date=$(echo "$time_n_date" | cut -f 2 -d \ )
|
||||
|
||||
# Adding domain in web.conf
|
||||
echo "DOMAIN='$domain' IP='$ip' IP6='' CUSTOM_DOCROOT='' ALIAS='$ALIAS' TPL='$WEB_TEMPLATE'\
|
||||
SSL='no' SSL_FORCE='no' SSL_HOME='same' LETSENCRYPT='no' FTP_USER='' FTP_MD5=''\
|
||||
BACKEND='$BACKEND_TEMPLATE' PROXY='$PROXY_TEMPLATE' PROXY_EXT='$PROXY_EXT'\
|
||||
STATS='' STATS_USER='' STATS_CRYPT='' U_DISK='0' U_BANDWIDTH='0'\
|
||||
SUSPENDED='no' TIME='$time' DATE='$date'" >> $USER_DATA/web.conf
|
||||
|
||||
syshealth_repair_web_config
|
||||
|
||||
# Restarting web server
|
||||
$BIN/v-restart-web "$restart"
|
||||
check_result $? "Web restart failed" > /dev/null
|
||||
|
||||
# Restarting proxy server
|
||||
$BIN/v-restart-proxy "$restart"
|
||||
check_result $? "Proxy restart failed" > /dev/null
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "Web" "Added new web domain (Name: $domain)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
114
bin/v-add-web-domain-alias
Executable file
114
bin/v-add-web-domain-alias
Executable file
@@ -0,0 +1,114 @@
|
||||
#!/bin/bash
|
||||
# info: add web domain alias
|
||||
# options: USER DOMAIN ALIASES [RESTART]
|
||||
#
|
||||
# example: v-add-web-domain-alias admin acme.com www.acme.com yes
|
||||
#
|
||||
# This function adds one or more aliases to a domain (it is also called
|
||||
# "domain parking"). This function supports wildcards *.domain.tpl.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
domain_idn=$2
|
||||
aliases=$3
|
||||
restart="$4"
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# shellcheck source=/usr/local/hestia/func/ip.sh
|
||||
source $HESTIA/func/ip.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# Additional argument formatting
|
||||
format_domain
|
||||
format_domain_idn
|
||||
# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ?
|
||||
format_aliases
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
if [ -z "$aliases" ]; then
|
||||
check_result "$E_INVALID" "Invalid alias format: empty"
|
||||
fi
|
||||
|
||||
check_args '3' "$#" 'USER DOMAIN ALIASES [RESTART]'
|
||||
is_format_valid 'user' 'domain' 'aliases'
|
||||
is_system_enabled "$WEB_SYSTEM" 'WEB_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'web' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'web' 'DOMAIN' "$domain"
|
||||
is_domain_new 'web' "$aliases"
|
||||
is_base_domain_owner "$aliases"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
get_domain_values 'web'
|
||||
|
||||
# Preparing domain values for the template substitution
|
||||
local_ip=$(get_real_ip $IP)
|
||||
if [ -z "$ALIAS" ]; then
|
||||
ALIAS="$aliases"
|
||||
else
|
||||
ALIAS="$ALIAS,$aliases"
|
||||
fi
|
||||
prepare_web_domain_values
|
||||
|
||||
is_package_full 'WEB_ALIASES'
|
||||
|
||||
# Rebuilding vhost
|
||||
del_web_config "$WEB_SYSTEM" "$TPL.tpl"
|
||||
add_web_config "$WEB_SYSTEM" "$TPL.tpl"
|
||||
if [ "$SSL" = 'yes' ]; then
|
||||
del_web_config "$WEB_SYSTEM" "$TPL.stpl"
|
||||
add_web_config "$WEB_SYSTEM" "$TPL.stpl"
|
||||
fi
|
||||
|
||||
# Rebuilding proxy configuration
|
||||
if [ -n "$PROXY_SYSTEM" ] && [ -n "$PROXY" ]; then
|
||||
del_web_config "$PROXY_SYSTEM" "$PROXY.tpl"
|
||||
add_web_config "$PROXY_SYSTEM" "$PROXY.tpl"
|
||||
if [ "$SSL" = 'yes' ]; then
|
||||
del_web_config "$PROXY_SYSTEM" "$PROXY.stpl"
|
||||
add_web_config "$PROXY_SYSTEM" "$PROXY.stpl"
|
||||
fi
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Adding new alias
|
||||
update_object_value 'web' 'DOMAIN' "$domain" '$ALIAS' "$ALIAS"
|
||||
increase_user_value "$user" '$U_WEB_ALIASES'
|
||||
|
||||
# Restarting web server
|
||||
$BIN/v-restart-web "$restart"
|
||||
check_result $? "Web restart failed" > /dev/null
|
||||
|
||||
# Restarting proxy server
|
||||
$BIN/v-restart-proxy "$restart"
|
||||
check_result $? "Proxy restart failed" > /dev/null
|
||||
|
||||
$BIN/v-log-action "$user" "Info" "Web" "Added new web domain alias (Alias: $aliases, Domain: $domain)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
71
bin/v-add-web-domain-allow-users
Executable file
71
bin/v-add-web-domain-allow-users
Executable file
@@ -0,0 +1,71 @@
|
||||
#!/bin/bash
|
||||
# info: Allow other users create subdomains
|
||||
# options: USER DOMAIN
|
||||
#
|
||||
# example: v-add-web-domain-allow-users admin admin.com
|
||||
#
|
||||
# Bypass the rule check for Enforce subdomain ownership for a specific domain.
|
||||
# Enforce subdomain ownership setting in /edit/server/ set to no will always overwrite this behaviour
|
||||
# eg: admin adds admin.com
|
||||
# user can create user.admin.com
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
domain_idn=$2
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# shellcheck source=/usr/local/hestia/func/ip.sh
|
||||
source $HESTIA/func/ip.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# Additional argument formatting
|
||||
format_domain
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '2' "$#" 'USER DOMAIN'
|
||||
is_format_valid 'user' 'domain'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'web' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'web' 'DOMAIN' "$domain"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Load domain data
|
||||
parse_object_kv_list $(grep "DOMAIN='$domain'" $USER_DATA/web.conf)
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
if [ -z "$ALLOW_USERS" ]; then
|
||||
add_object_key "web" 'DOMAIN' "$domain" 'ALLOW_USERS' 'TIME'
|
||||
fi
|
||||
|
||||
# Adding new alias
|
||||
update_object_value 'web' 'DOMAIN' "$domain" '$ALLOW_USERS' "yes"
|
||||
|
||||
$BIN/v-log-action "$user" "Warning" "Web" "Subdomain ownership enforcement disabled (Domain: $domain)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
97
bin/v-add-web-domain-backend
Executable file
97
bin/v-add-web-domain-backend
Executable file
@@ -0,0 +1,97 @@
|
||||
#!/bin/bash
|
||||
# info: add web domain backend
|
||||
# options: USER DOMAIN [TEMPLATE] [RESTART]
|
||||
#
|
||||
# example: v-add-web-domain-backend admin example.com default yes
|
||||
#
|
||||
# This function is used to add the web backend configuration.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
template=${3-default}
|
||||
restart=$4
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# shellcheck source=/usr/local/hestia/conf/hestia.conf
|
||||
source $HESTIA/conf/hestia.conf
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '2' "$#" 'USER DOMAIN [TEMPLATE] [RESTART]'
|
||||
is_format_valid 'user' 'domain'
|
||||
is_system_enabled "$WEB_BACKEND" 'WEB_BACKEND'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_backend_template_valid "$template"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Defining pool directory
|
||||
prepare_web_backend
|
||||
get_domain_values 'web'
|
||||
|
||||
if [[ -n "$BACKEND" && "$BACKEND" != "$template" ]]; then
|
||||
check_result "$E_EXISTS" "Pool already exists"
|
||||
fi
|
||||
|
||||
# Allocating backend port
|
||||
backend_port=9000
|
||||
ports=$(grep -v '^;' $pool/* 2> /dev/null | grep listen | grep -o :[0-9].*)
|
||||
ports=$(echo "$ports" | sed "s/://" | sort -n)
|
||||
for port in $ports; do
|
||||
if [ "$backend_port" -eq "$port" ]; then
|
||||
backend_port=$((backend_port + 1))
|
||||
fi
|
||||
done
|
||||
|
||||
# Adding backend config
|
||||
cat $WEBTPL/$WEB_BACKEND/$template.tpl \
|
||||
| sed -e "s|%backend_port%|$backend_port|" \
|
||||
-e "s|%user%|$user|g" \
|
||||
-e "s|%domain%|$domain|g" \
|
||||
-e "s|%backend%|$backend_type|g" \
|
||||
-e "s|%backend_version%|$backend_version|g" > $pool/$backend_type.conf
|
||||
|
||||
# Set correct document root path
|
||||
if [ -n "$CUSTOM_DOCROOT" ]; then
|
||||
docroot="$CUSTOM_DOCROOT"
|
||||
if [ -n "$CUSTOM_PHPROOT" ]; then
|
||||
docroot="$CUSTOM_PHPROOT"
|
||||
fi
|
||||
sed -i "s|/home\/$user\/web\/$domain\/public_html|$docroot|g" $pool/$backend_type.conf
|
||||
else
|
||||
docroot="$HOMEDIR/$user/web/$domain/public_html/"
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Restart php interpreter
|
||||
$BIN/v-restart-web-backend "$restart" "$backend_version"
|
||||
check_result $? "PHP restart failed" > /dev/null
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "Web" "Web domain configuration applied (Domain: $domain, Backend: $WEB_BACKEND)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
140
bin/v-add-web-domain-ftp
Executable file
140
bin/v-add-web-domain-ftp
Executable file
@@ -0,0 +1,140 @@
|
||||
#!/bin/bash
|
||||
# info: add ftp account for web domain.
|
||||
# options: USER DOMAIN FTP_USER FTP_PASSWORD [FTP_PATH]
|
||||
#
|
||||
# example: v-add-web-domain-ftp alice wonderland.com alice_ftp p4$$vvOrD
|
||||
#
|
||||
# This function creates additional ftp account for web domain.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
domain_idn=$2
|
||||
ftp_user=${1}_${3}
|
||||
password=$4
|
||||
HIDE=4
|
||||
ftp_path=$5
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# Additional argument formatting
|
||||
format_domain
|
||||
format_domain_idn
|
||||
# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ?
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '4' "$#" 'USER DOMAIN FTP_USER FTP_PASSWORD [FTP_PATH]'
|
||||
is_format_valid 'user' 'domain' 'ftp_user'
|
||||
is_system_enabled "$WEB_SYSTEM" 'WEB_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'web' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'web' 'DOMAIN' "$domain"
|
||||
check_ftp_user=$(grep "^$ftp_user:" /etc/passwd)
|
||||
if [ -n "$check_ftp_user" ] && [ "$FTP_USER" != "$ftp_user" ]; then
|
||||
echo "Error: ftp user $ftp_user already exists"
|
||||
log_event "$E_EXISTS" "$ARGUMENTS"
|
||||
exit "$E_EXISTS"
|
||||
fi
|
||||
is_password_valid
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Get domain values
|
||||
get_domain_values 'web'
|
||||
|
||||
# Defining ftp user shell
|
||||
shell=$(which nologin)
|
||||
if [ -n "$FTP_SHELL" ]; then
|
||||
shell=$FTP_SHELL
|
||||
fi
|
||||
|
||||
# Defining path
|
||||
if [ -z "$ftp_path" ]; then
|
||||
ftp_path_a="$HOMEDIR/$user/web/$domain"
|
||||
else
|
||||
# Validating absolute path
|
||||
ftp_path_a=$(readlink -f "$HOMEDIR/$user/web/$domain/$ftp_path")
|
||||
if [ -z "$(echo $ftp_path_a | grep $HOMEDIR/$user/web/$domain)" ]; then
|
||||
echo "Error: absolute path $ftp_path_a is invalid"
|
||||
log_event "$E_INVALID" "$ARGUMENTS"
|
||||
exit "$E_INVALID"
|
||||
fi
|
||||
# Creating ftp user home directory
|
||||
if [ ! -e "$ftp_path_a" ]; then
|
||||
$BIN/v-add-fs-directory "$user" "$ftp_path_a"
|
||||
chown $user:$user "$ftp_path_a"
|
||||
chmod 751 "$ftp_path_a"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Adding ftp user
|
||||
/usr/sbin/useradd $ftp_user \
|
||||
-s $shell \
|
||||
-o -u $(id -u $user) \
|
||||
-g $(id -g $user) \
|
||||
-G hestia-users \
|
||||
-M -d "$ftp_path_a" > /dev/null 2>&1
|
||||
|
||||
# Set ftp user password
|
||||
echo "$ftp_user:$password" | /usr/sbin/chpasswd
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
# Delete user on failure again
|
||||
/usr/sbin/deluser "$ftp_user" > /dev/null 2>&1
|
||||
echo "Error: Password not accepted due to PAM restrictions"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
ftp_md5=$(awk -v user=$ftp_user -F : 'user == $1 {print $2}' /etc/shadow)
|
||||
|
||||
# Adding jailed sftp env
|
||||
$BIN/v-add-user-sftp-jail "$ftp_user"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Transforming absolute path to relative
|
||||
ftp_path_r=$(echo $ftp_path_a | sed "s%$HOMEDIR/$user/web/$domain%%")
|
||||
|
||||
# Concatenating ftp variables
|
||||
if [ ! -z "$FTP_USER" ]; then
|
||||
ftp_user="$FTP_USER:$ftp_user"
|
||||
ftp_md5="$FTP_MD5:$ftp_md5"
|
||||
ftp_path="$FTP_PATH:$ftp_path_r"
|
||||
fi
|
||||
|
||||
# Adding new key into web.conf
|
||||
add_object_key "web" 'DOMAIN' "$domain" 'FTP_PATH' 'PROXY'
|
||||
|
||||
# Updating config
|
||||
update_object_value 'web' 'DOMAIN' "$domain" '$FTP_USER' "$ftp_user"
|
||||
update_object_value 'web' 'DOMAIN' "$domain" '$FTP_MD5' "$ftp_md5"
|
||||
update_object_value 'web' 'DOMAIN' "$domain" '$FTP_PATH' "$ftp_path"
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "Web" "Added new FTP account (Name: ${1}_${3}@$domain)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
125
bin/v-add-web-domain-httpauth
Executable file
125
bin/v-add-web-domain-httpauth
Executable file
@@ -0,0 +1,125 @@
|
||||
#!/bin/bash
|
||||
# info: add password protection for web domain
|
||||
# options: USER DOMAIN AUTH_USER AUTH_PASSWORD [RESTART]
|
||||
#
|
||||
# example: v-add-web-domain-httpauth admin acme.com user02 super_pass
|
||||
#
|
||||
# This function is used for securing web domain with http auth
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
auth_user=$3
|
||||
password=$4
|
||||
HIDE=4
|
||||
restart=${5-yes}
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# Defining htpasswd file
|
||||
htpasswd="$HOMEDIR/$user/conf/web/$domain/htpasswd"
|
||||
docroot="$HOMEDIR/$user/web/$domain/public_html"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '4' "$#" 'USER DOMAIN AUTH_USER AUTH_PASSWORD [RESTART]'
|
||||
is_format_valid 'user' 'domain'
|
||||
is_system_enabled "$WEB_SYSTEM" 'WEB_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'web' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'web' 'DOMAIN' "$domain"
|
||||
is_password_valid
|
||||
get_domain_values 'web'
|
||||
is_user_format_valid "$auth_user" "Auth user"
|
||||
if [ -n "$(echo "$AUTH_USER" | tr : '\n' | grep ^$auth_user$)" ]; then
|
||||
echo "Error: auth user $auth_user already exists"
|
||||
log_event "$E_EXISTS" "$ARGUMENTS"
|
||||
exit "$E_EXISTS"
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# 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
|
||||
|
||||
# Adding httpasswd user
|
||||
auth_hash=$($BIN/v-generate-password-hash htpasswd htpasswd $password)
|
||||
touch $htpasswd
|
||||
chmod 644 $htpasswd $htaccess
|
||||
chgrp $user $htpasswd $htaccess
|
||||
sed -i "/^$auth_user:/d" $htpasswd
|
||||
echo "$auth_user:$auth_hash" >> $htpasswd
|
||||
|
||||
# Restarting web server
|
||||
if [ "$restart" != 'no' ] && [ "$restart_required" = 'yes' ]; then
|
||||
$BIN/v-restart-web
|
||||
if [ -n "$PROXY_SYSTEM" ]; then
|
||||
$BIN/v-restart-proxy
|
||||
fi
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Preparing web.conf keys
|
||||
if [ -n "$AUTH_USER" ]; then
|
||||
auth_user="$AUTH_USER:$auth_user"
|
||||
auth_hash="$AUTH_HASH:$auth_hash"
|
||||
else
|
||||
# Adding new key into web.conf
|
||||
add_object_key "web" 'DOMAIN' "$domain" 'AUTH_USER' 'U_DISK'
|
||||
add_object_key "web" 'DOMAIN' "$domain" 'AUTH_HASH' 'U_DISK'
|
||||
fi
|
||||
|
||||
# Updating config
|
||||
update_object_value 'web' 'DOMAIN' "$domain" '$AUTH_USER' "$auth_user"
|
||||
update_object_value 'web' 'DOMAIN' "$domain" '$AUTH_HASH' "$auth_hash"
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "Web" "Password protection enabled (Domain: $domain, Username: $httpauth_user)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
88
bin/v-add-web-domain-proxy
Executable file
88
bin/v-add-web-domain-proxy
Executable file
@@ -0,0 +1,88 @@
|
||||
#!/bin/bash
|
||||
# info: add webdomain proxy support
|
||||
# options: USER DOMAIN [TEMPLATE] [EXTENTIONS] [RESTART]
|
||||
#
|
||||
# example: v-add-web-domain-proxy admin example.com
|
||||
#
|
||||
# This function enables proxy support for a domain. This can significantly
|
||||
# improve website speed.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
template=$3
|
||||
default_extentions="jpg,jpeg,gif,png,webp,ico,svg,css,zip,tgz,gz,rar,bz2,doc,xls,\
|
||||
exe,pdf,ppt,txt,odt,ods,odp,odf,tar,wav,bmp,rtf,js,mp3,avi,mpeg,flv,html,htm"
|
||||
extentions=${4-$default_extentions}
|
||||
restart="$5"
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# shellcheck source=/usr/local/hestia/func/ip.sh
|
||||
source $HESTIA/func/ip.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '2' "$#" 'USER DOMAIN [TEMPLATE] [EXTENTIONS] [RESTART]'
|
||||
is_format_valid 'user' 'domain' 'extentions'
|
||||
is_system_enabled "$PROXY_SYSTEM" 'PROXY_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'web' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'web' 'DOMAIN' "$domain"
|
||||
is_object_value_empty 'web' 'DOMAIN' "$domain" '$PROXY'
|
||||
if [ -z $template ]; then
|
||||
template=$(get_user_value '$PROXY_TEMPLATE')
|
||||
fi
|
||||
is_proxy_template_valid $template
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Defining domain parameters
|
||||
get_domain_values 'web'
|
||||
prepare_web_domain_values
|
||||
local_ip=$(get_real_ip "$IP")
|
||||
|
||||
# Preparing domain values for the template substitution
|
||||
PROXY_EXT="$extentions"
|
||||
add_web_config "$PROXY_SYSTEM" "$template.tpl"
|
||||
|
||||
# Adding proxy for ssl
|
||||
if [ "$SSL" = 'yes' ]; then
|
||||
add_web_config "$PROXY_SYSTEM" "$template.stpl"
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Update config
|
||||
update_object_value 'web' 'DOMAIN' "$domain" '$PROXY' "$template"
|
||||
update_object_value 'web' 'DOMAIN' "$domain" '$PROXY_EXT' "$extentions"
|
||||
|
||||
# Restarting web server
|
||||
$BIN/v-restart-proxy "$restart"
|
||||
check_result $? "Proxy restart failed" > /dev/null
|
||||
|
||||
$BIN/v-log-action "$user" "Info" "Web" "Proxy enabled (Domain: $domain)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
162
bin/v-add-web-domain-redirect
Executable file
162
bin/v-add-web-domain-redirect
Executable file
@@ -0,0 +1,162 @@
|
||||
#!/bin/bash
|
||||
# info: Adding force redirect to domain
|
||||
# options: USER DOMAIN REDIRECT HTTPCODE [RESTART]
|
||||
#
|
||||
# example: v-add-web-domain-redirect user domain.tld domain.tld
|
||||
# example: v-add-web-domain-redirect user domain.tld www.domain.tld
|
||||
# example: v-add-web-domain-redirect user domain.tld shop.domain.tld
|
||||
# example: v-add-web-domain-redirect user domain.tld different-domain.com
|
||||
# example: v-add-web-domain-redirect user domain.tld shop.different-domain.com
|
||||
# example: v-add-web-domain-redirect user domain.tld different-domain.com 302
|
||||
#
|
||||
# Function creates a forced redirect to a domain
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
redirect=$3
|
||||
code=${4-301}
|
||||
restart=${5-no}
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '3' "$#" 'USER DOMAIN REDIRECT [HTTP-CODE] [RESTART]'
|
||||
is_format_valid 'user' 'domain'
|
||||
is_number_format_valid "$code" "code"
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'web' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'web' 'DOMAIN' "$domain"
|
||||
|
||||
requesturi=0
|
||||
if [[ "$3" =~ http://|https:// ]]; then
|
||||
scheme_check=1
|
||||
scheme=$($HESTIA_PHP -r '$url=parse_url($argv[1]); echo $url["scheme"];' "$redirect")
|
||||
host=$($HESTIA_PHP -r '$url=parse_url($argv[1]); echo $url["host"];' "$redirect")
|
||||
path=$($HESTIA_PHP -r '$url=parse_url($argv[1]); if(!empty($url["path"])){echo $url["path"];}' "$redirect")
|
||||
port=$($HESTIA_PHP -r '$url=parse_url($argv[1]); if(!empty($url["port"])){echo $url["port"];}' "$redirect")
|
||||
|
||||
host=$(idn2 --quiet "$host")
|
||||
redirect="$scheme://$host$path"
|
||||
if [ -n "$port" ]; then
|
||||
redirect="$scheme://$host:$port$path"
|
||||
fi
|
||||
|
||||
isValidUrl=$(php -r '$url=$argv[1]; $url=filter_var($url,FILTER_VALIDATE_URL); echo $url;' "$redirect")
|
||||
if [ -z "$isValidUrl" ]; then
|
||||
check_result $E_INVALID "Invalid redirect"
|
||||
fi
|
||||
else
|
||||
host=$($HESTIA_PHP -r '$url=parse_url($argv[1]); echo $url["host"];' "http://$redirect")
|
||||
path=$($HESTIA_PHP -r '$url=parse_url($argv[1]); if(!empty($url["path"])){echo $url["path"];}' "http://$redirect")
|
||||
port=$($HESTIA_PHP -r '$url=parse_url($argv[1]); if(!empty($url["port"])){echo $url["port"];}' "$redirect")
|
||||
|
||||
host=$(idn2 --quiet "$host")
|
||||
|
||||
redirect="$host$path"
|
||||
if [ -n "$port" ]; then
|
||||
redirect="$host:$port$path"
|
||||
fi
|
||||
|
||||
isValidUrl=$(php -r '$url=$argv[1]; $url=filter_var($url,FILTER_VALIDATE_URL); echo $url;' "http://$redirect")
|
||||
if [ -z "$isValidUrl" ]; then
|
||||
check_result $E_INVALID "Invalid redirect"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Check if proxy is active
|
||||
if [ "$WEB_SYSTEM" = 'nginx' ] || [ "$PROXY_SYSTEM" = 'nginx' ]; then
|
||||
conf="$HOMEDIR/$user/conf/web/$domain/nginx.conf_redirect"
|
||||
sconf="$HOMEDIR/$user/conf/web/$domain/nginx.ssl.conf_redirect"
|
||||
fi
|
||||
|
||||
# Prevent $request_uri being added if ends in .html
|
||||
requesturi=0
|
||||
if [ -n "$path" ]; then
|
||||
lastchr=${path#${path%?}}
|
||||
if [ "$lastchr" = "/" ]; then
|
||||
requesturi=1
|
||||
redirect=${redirect:0:-1}
|
||||
fi
|
||||
else
|
||||
requesturi=1
|
||||
fi
|
||||
|
||||
# Insert redirect commands
|
||||
if [ -n "$PROXY_SYSTEM" ] || [ "$WEB_SYSTEM" = 'nginx' ]; then
|
||||
if [ "$scheme_check" = 1 ]; then
|
||||
if [ "$requesturi" = 1 ]; then
|
||||
echo " return $code $redirect\$request_uri;" > $conf
|
||||
else
|
||||
echo " return $code $redirect;" > $conf
|
||||
fi
|
||||
if [ ! -e "$sconf" ]; then
|
||||
ln -s "$conf" "$sconf"
|
||||
fi
|
||||
else
|
||||
echo "if (\$host != \"$redirect\") {" > $conf
|
||||
if [ "$requesturi" = 1 ]; then
|
||||
echo " return $code \$scheme://$redirect\$request_uri;" >> $conf
|
||||
else
|
||||
echo " return $code \$scheme://$redirect;" >> $conf
|
||||
fi
|
||||
echo "}" >> $conf
|
||||
|
||||
if [ ! -e "$sconf" ]; then
|
||||
ln -s "$conf" "$sconf"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
echo "Non supported please use .htaccess instead"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Update object keys
|
||||
if [ -z "$REDIRECT" ]; then
|
||||
add_object_key "web" 'DOMAIN' "$domain" 'REDIRECT' 'U_DISK'
|
||||
add_object_key "web" 'DOMAIN' "$domain" 'REDIRECT_CODE' 'U_DISK'
|
||||
fi
|
||||
|
||||
# Update values for domain
|
||||
update_object_value 'web' 'DOMAIN' "$domain" '$REDIRECT' "$redirect"
|
||||
update_object_value 'web' 'DOMAIN' "$domain" '$REDIRECT_CODE' "$code"
|
||||
|
||||
if [ "$restart" = "yes" ]; then
|
||||
# Restarting web server
|
||||
$BIN/v-restart-web "$restart"
|
||||
check_result $? "Web restart failed" > /dev/null
|
||||
|
||||
$BIN/v-restart-proxy "$restart"
|
||||
check_result $? "Proxy restart failed" > /dev/null
|
||||
fi
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "Web" "Domain redirection enabled (Domain: $domain, Redirect to: $redirect)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
143
bin/v-add-web-domain-ssl
Executable file
143
bin/v-add-web-domain-ssl
Executable file
@@ -0,0 +1,143 @@
|
||||
#!/bin/bash
|
||||
# info: adding ssl for domain
|
||||
# options: USER DOMAIN SSL_DIR [SSL_HOME] [RESTART]
|
||||
#
|
||||
# example: v-add-web-domain-ssl admin example.com /home/admin/conf/example.com/web
|
||||
#
|
||||
# This function turns on SSL support for a domain. Parameter ssl_dir is a path
|
||||
# to directory where 2 or 3 ssl files can be found. Certificate file
|
||||
# domain.tld.crt and its key domain.tld.key are mandatory. Certificate
|
||||
# authority domain.tld.ca file is optional. If home directory parameter
|
||||
# (ssl_home) is not set, https domain uses public_shtml as separate
|
||||
# documentroot directory.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
ssl_dir=$3
|
||||
ssl_home=${4-same}
|
||||
restart="$5"
|
||||
|
||||
domain=$domain
|
||||
domain_idn=$(idn2 --quiet "$domain")
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# shellcheck source=/usr/local/hestia/func/ip.sh
|
||||
source $HESTIA/func/ip.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# Additional argument formatting
|
||||
format_domain
|
||||
format_domain_idn
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '3' "$#" 'USER DOMAIN SSL_DIR [SSL_HOME] [RESTART]'
|
||||
is_format_valid 'user' 'domain' 'ssl_dir'
|
||||
is_system_enabled "$WEB_SYSTEM" 'WEB_SYSTEM'
|
||||
is_system_enabled "$WEB_SSL" 'SSL_SUPPORT'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'web' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'web' 'DOMAIN' "$domain"
|
||||
is_object_value_empty 'web' 'DOMAIN' "$domain" '$SSL'
|
||||
is_web_domain_cert_valid
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Adding certificate to user data directory
|
||||
cp -f $ssl_dir/$domain.crt $USER_DATA/ssl/$domain.crt
|
||||
cp -f $ssl_dir/$domain.key $USER_DATA/ssl/$domain.key
|
||||
cp -f $ssl_dir/$domain.crt $USER_DATA/ssl/$domain.pem
|
||||
if [ -e "$ssl_dir/$domain.ca" ]; then
|
||||
cp -f $ssl_dir/$domain.ca $USER_DATA/ssl/$domain.ca
|
||||
echo >> $USER_DATA/ssl/$domain.pem
|
||||
cat $USER_DATA/ssl/$domain.ca >> $USER_DATA/ssl/$domain.pem
|
||||
fi
|
||||
chmod 660 $USER_DATA/ssl/$domain.*
|
||||
|
||||
# Ensure SSL directory exists
|
||||
if [ ! -d "$HOMEDIR/$user/conf/web/$domain/ssl" ]; then
|
||||
mkdir -p $HOMEDIR/$user/conf/web/$domain/ssl/
|
||||
fi
|
||||
|
||||
# Adding certificate to user dir
|
||||
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
|
||||
|
||||
if [ "$SSL_FORCE" == "yes" ]; then
|
||||
# Enabling SSL redirection on demand
|
||||
$BIN/v-add-web-domain-ssl-force "$user" "$domain"
|
||||
fi
|
||||
# Parsing domain values
|
||||
get_domain_values 'web'
|
||||
local_ip=$(get_real_ip "$IP")
|
||||
|
||||
# Preparing domain values for the template substitution
|
||||
SSL_HOME="$ssl_home"
|
||||
prepare_web_domain_values
|
||||
|
||||
# Adding domain to the web config
|
||||
add_web_config "$WEB_SYSTEM" "$TPL.stpl"
|
||||
|
||||
# Checking proxy config
|
||||
if [ -n "$PROXY_SYSTEM" ] && [ -n "$PROXY" ]; then
|
||||
add_web_config "$PROXY_SYSTEM" "$PROXY.stpl"
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Increasing domain value
|
||||
increase_user_value "$user" '$U_WEB_SSL'
|
||||
|
||||
# Adding ssl values
|
||||
update_object_value 'web' 'DOMAIN' "$domain" '$SSL_HOME' "$SSL_HOME"
|
||||
update_object_value 'web' 'DOMAIN' "$domain" '$SSL' "yes"
|
||||
|
||||
# Restarting web server
|
||||
$BIN/v-restart-web "$restart"
|
||||
check_result $? "Web restart failed" > /dev/null
|
||||
|
||||
$BIN/v-restart-proxy "$restart"
|
||||
check_result $? "Proxy restart failed" > /dev/null
|
||||
|
||||
if [ -n "$UPDATE_HOSTNAME_SSL" ] && [ "$UPDATE_HOSTNAME_SSL" = "yes" ]; then
|
||||
hostname=$(hostname -f)
|
||||
if [ "$hostname" = "$domain" ]; then
|
||||
$BIN/v-update-host-certificate "$user" "$domain"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -n "$UPDATE_SSL_SCRIPT" ]; then
|
||||
eval "$UPDATE_SSL_SCRIPT $user $domain"
|
||||
fi
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "Web" "Added certificate and enabled SSL (Domain: $domain)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
97
bin/v-add-web-domain-ssl-force
Executable file
97
bin/v-add-web-domain-ssl-force
Executable file
@@ -0,0 +1,97 @@
|
||||
#!/bin/bash
|
||||
# info: Adding force SSL for a domain
|
||||
# options: USER DOMAIN [RESTART] [QUIET]
|
||||
#
|
||||
# example: v-add-web-domain-ssl-force admin acme.com
|
||||
#
|
||||
# This function forces SSL for the requested domain.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
restart="$3"
|
||||
quiet="$4"
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '2' "$#" 'USER DOMAIN'
|
||||
is_format_valid 'user' 'domain'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'web' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'web' 'DOMAIN' "$domain"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Load domain data
|
||||
parse_object_kv_list $(grep "DOMAIN='$domain'" $USER_DATA/web.conf)
|
||||
|
||||
# Check if SSL is enabled
|
||||
if [ "$SSL" != 'yes' ]; then
|
||||
echo "Error: SSL is not enabled"
|
||||
exit "$E_NOTEXIST"
|
||||
fi
|
||||
|
||||
# Check if proxy is active
|
||||
if [ -n "$PROXY_SYSTEM" ]; then
|
||||
forcessl="$HOMEDIR/$user/conf/web/$domain/$PROXY_SYSTEM.forcessl.conf"
|
||||
else
|
||||
forcessl="$HOMEDIR/$user/conf/web/$domain/$WEB_SYSTEM.forcessl.conf"
|
||||
fi
|
||||
|
||||
# Insert redirect commands
|
||||
if [ -n "$PROXY_SYSTEM" ] || [ "$WEB_SYSTEM" = 'nginx' ]; then
|
||||
echo 'return 301 https://$host$request_uri;' > $forcessl
|
||||
else
|
||||
echo 'RewriteEngine On' > $forcessl
|
||||
echo 'RewriteRule ^(.*)$ https://%{HTTP_HOST}$1 [R=301,L]' >> $forcessl
|
||||
fi
|
||||
|
||||
chown root:$user $forcessl
|
||||
chmod 640 $forcessl
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
if [ -z "$SSL_FORCE" ]; then
|
||||
add_object_key "web" 'DOMAIN' "$domain" 'SSL_FORCE' 'SSL_HOME'
|
||||
fi
|
||||
|
||||
# Set forcessl flag to enabled
|
||||
update_object_value 'web' 'DOMAIN' "$domain" '$SSL_FORCE' 'yes'
|
||||
|
||||
# Restart web server
|
||||
$BIN/v-restart-web "$restart"
|
||||
check_result $? "Web restart failed" > /dev/null
|
||||
|
||||
# Restart proxy
|
||||
$BIN/v-restart-proxy "$restart"
|
||||
check_result $? "Proxy restart failed" > /dev/null
|
||||
|
||||
# Logging
|
||||
if [ "$quiet" != "yes" ]; then
|
||||
$BIN/v-log-action "$user" "Info" "Web" "Automatic HTTPS redirection enabled (Domain: $domain)."
|
||||
fi
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
89
bin/v-add-web-domain-ssl-hsts
Executable file
89
bin/v-add-web-domain-ssl-hsts
Executable file
@@ -0,0 +1,89 @@
|
||||
#!/bin/bash
|
||||
# info: Adding hsts to a domain
|
||||
# options: USER DOMAIN [RESTART] [QUIET]
|
||||
#
|
||||
# This function enables HSTS for the requested domain.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
restart="$3"
|
||||
quiet="$4"
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '2' "$#" 'USER DOMAIN'
|
||||
is_format_valid 'user' 'domain'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'web' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'web' 'DOMAIN' "$domain"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Load domain data
|
||||
parse_object_kv_list $(grep "DOMAIN='$domain'" $USER_DATA/web.conf)
|
||||
|
||||
# Check if SSL is enabled
|
||||
if [ "$SSL" != 'yes' ]; then
|
||||
echo "Error: SSL is not enabled"
|
||||
exit "$E_NOTEXIST"
|
||||
fi
|
||||
|
||||
# Check for Apache/Nginx or Nginx/PHP-FPM configuration
|
||||
if [ -z "$PROXY_SYSTEM" ]; then
|
||||
hstsconf="$HOMEDIR/$user/conf/web/$domain/$WEB_SYSTEM.hsts.conf"
|
||||
else
|
||||
hstsconf="$HOMEDIR/$user/conf/web/$domain/$PROXY_SYSTEM.hsts.conf"
|
||||
fi
|
||||
|
||||
echo 'add_header Strict-Transport-Security "max-age=31536000;" always;' > $hstsconf
|
||||
|
||||
chown root:$user $hstsconf
|
||||
chmod 640 $hstsconf
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
if [ -z "$SSL_HSTS" ]; then
|
||||
add_object_key "web" 'DOMAIN' "$domain" 'SSL_HSTS' 'SSL_FORCE'
|
||||
fi
|
||||
|
||||
# Set forcessl flag to enabled
|
||||
update_object_value 'web' 'DOMAIN' "$domain" '$SSL_HSTS' 'yes'
|
||||
|
||||
# Restart web server
|
||||
$BIN/v-restart-web "$restart"
|
||||
check_result $? "Web restart failed" > /dev/null
|
||||
|
||||
# Restart proxy
|
||||
$BIN/v-restart-proxy "$restart"
|
||||
check_result $? "Proxy restart failed" > /dev/null
|
||||
|
||||
# Logging
|
||||
if [ "$quiet" != "yes" ]; then
|
||||
$BIN/v-log-action "$user" "Info" "Web" "HTTP Strict Transport Security (HSTS) enabled (Domain: $domain)."
|
||||
fi
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
60
bin/v-add-web-domain-ssl-preset
Executable file
60
bin/v-add-web-domain-ssl-preset
Executable file
@@ -0,0 +1,60 @@
|
||||
#!/bin/bash
|
||||
# info: Adding force SSL for a domain
|
||||
# options: USER DOMAIN [SSL]
|
||||
#
|
||||
# example: v-add-web-domain-ssl-preset
|
||||
#
|
||||
# Up on creating an web domain set the SSL Force values due to the delay of LE due to DNS propergation over DNS cluster
|
||||
# When LE has been activated it will set the actions
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
ssl=$3
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '2' "$#" 'USER DOMAIN [SSL]'
|
||||
is_format_valid 'user' 'domain' 'ssl'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'web' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'web' 'DOMAIN' "$domain"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Load domain data
|
||||
parse_object_kv_list $(grep "DOMAIN='$domain'" $USER_DATA/web.conf)
|
||||
|
||||
if [ "$ssl" = "yes" ]; then
|
||||
if [ -z "$SSL_FORCE" ]; then
|
||||
add_object_key "web" 'DOMAIN' "$domain" 'SSL_FORCE' 'SSL_HOME'
|
||||
fi
|
||||
|
||||
# Set forcessl flag to enabled
|
||||
update_object_value 'web' 'DOMAIN' "$domain" '$SSL_FORCE' 'yes'
|
||||
fi
|
||||
|
||||
# Logging
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
109
bin/v-add-web-domain-stats
Executable file
109
bin/v-add-web-domain-stats
Executable file
@@ -0,0 +1,109 @@
|
||||
#!/bin/bash
|
||||
# info: add log analyser to generate domain statistics
|
||||
# options: USER DOMAIN TYPE
|
||||
#
|
||||
# example: v-add-web-domain-stats admin example.com awstats
|
||||
#
|
||||
# This function is used for enabling log analyser system to a domain. For viewing
|
||||
# the domain statistics use <http://domain.tld/vstats/> link. Access this page
|
||||
# is not protected by default. If you want to secure it with passwords you
|
||||
# should use v-add-web-domain_stat_auth script.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
domain_idn=$2
|
||||
type=$3
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# Additional argument formatting
|
||||
format_domain
|
||||
format_domain_idn
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '3' "$#" 'USER DOMAIN TYPE'
|
||||
is_format_valid 'user' 'domain'
|
||||
is_system_enabled "$WEB_SYSTEM" 'WEB_SYSTEM'
|
||||
is_type_valid "$STATS_SYSTEM" "$type"
|
||||
is_object_valid 'user' 'USER' "$user" "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'web' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'web' 'DOMAIN' "$domain"
|
||||
is_object_value_empty 'web' 'DOMAIN' "$domain" '$STATS'
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Parse aliases
|
||||
get_domain_values 'web'
|
||||
|
||||
# Adding statistic config
|
||||
prepare_web_domain_values
|
||||
|
||||
if [ -z "${aliases//,/ }" ]; then
|
||||
stats_alias="localhost"
|
||||
else
|
||||
stats_alias=${aliases_idn//,/ }
|
||||
fi
|
||||
|
||||
cat $WEBTPL/$type/$type.tpl \
|
||||
| sed -e "s|%ip%|$ip|g" \
|
||||
-e "s|%web_port%|$WEB_PORT|g" \
|
||||
-e "s|%web_system%|$WEB_SYSTEM|g" \
|
||||
-e "s|%web_ssl_port%|$WEB_SSL_PORT|g" \
|
||||
-e "s|%rgroups%|$WEB_RGROUPs|g" \
|
||||
-e "s|%proxy_system%|$PROXY_SYSTEM|g" \
|
||||
-e "s|%proxy_port%|$PROXY_PORT|g" \
|
||||
-e "s|%proxy_ssl_port%|$PROXY_SSL_PORT|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%|$stats_alias|g" \
|
||||
-e "s|%alias_idn%|$stats_alias|g" \
|
||||
> $HOMEDIR/$user/conf/web/$domain/$type.conf
|
||||
|
||||
if [ "$type" == 'awstats' ]; then
|
||||
rm -f /etc/awstats/$type.$domain_idn.conf
|
||||
ln -s $HOMEDIR/$user/conf/web/$domain/$type.conf \
|
||||
/etc/awstats/$type.$domain_idn.conf
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Schedule statistic processing
|
||||
echo "$BIN/v-update-web-domain-stat $user $domain" >> $HESTIA/data/queue/webstats.pipe
|
||||
|
||||
# Update config
|
||||
update_object_value 'web' 'DOMAIN' "$domain" '$STATS' "$type"
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "Web" "Web traffic analyzer enabled (Domain: $domain)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
# Build stats
|
||||
exec $BIN/v-update-web-domain-stat "$user" "$domain"
|
||||
|
||||
exit
|
||||
89
bin/v-add-web-domain-stats-user
Executable file
89
bin/v-add-web-domain-stats-user
Executable file
@@ -0,0 +1,89 @@
|
||||
#!/bin/bash
|
||||
# info: add password protection to web domain statistics
|
||||
# options: USER DOMAIN STATS_USER STATS_PASSWORD [RESTART]
|
||||
#
|
||||
# example: v-add-web-domain-stats-user admin example.com watchdog your_password
|
||||
#
|
||||
# This function is used for securing the web statistics page.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
stats_user=$3
|
||||
password=$4
|
||||
HIDE=4
|
||||
restart=$5
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '4' "$#" 'USER DOMAIN STATS_USER STATS_PASS [RESTART]'
|
||||
is_format_valid 'user' 'domain' 'stats_user'
|
||||
is_system_enabled "$WEB_SYSTEM" 'WEB_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'web' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'web' 'DOMAIN' "$domain"
|
||||
is_password_valid
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Defining statistic dir
|
||||
stats_dir="$HOMEDIR/$user/web/$domain/stats"
|
||||
conf_dir="$HOMEDIR/$user/conf/web"
|
||||
|
||||
# Adding htaccess file
|
||||
if [ "$WEB_SYSTEM" = 'nginx' ]; then
|
||||
echo "auth_basic \"Web Statistics\";" > $stats_dir/auth.conf
|
||||
echo "auth_basic_user_file $stats_dir/.htpasswd;" >> $stats_dir/auth.conf
|
||||
else
|
||||
echo "AuthUserFile $stats_dir/.htpasswd" > $stats_dir/.htaccess
|
||||
echo "AuthName \"Web Statistics\"" >> $stats_dir/.htaccess
|
||||
echo "AuthType Basic" >> $stats_dir/.htaccess
|
||||
echo "Require valid-user" >> $stats_dir/.htaccess
|
||||
fi
|
||||
|
||||
# Generating htaccess user and password
|
||||
salt=$(generate_password "$PW_MATRIX" "8")
|
||||
stats_pass=$($BIN/v-generate-password-hash md5 $salt $password)
|
||||
echo "$stats_user:$stats_pass" > $stats_dir/.htpasswd
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Adding stats user in config
|
||||
update_object_value 'web' 'DOMAIN' "$domain" '$STATS_USER' "$stats_user"
|
||||
update_object_value 'web' 'DOMAIN' "$domain" '$STATS_CRYPT' "$stats_pass"
|
||||
|
||||
# Restarting web server
|
||||
if [ "$WEB_SYSTEM" = 'nginx' ]; then
|
||||
$BIN/v-restart-web "$restart"
|
||||
check_result $? "Web restart failed" > /dev/null
|
||||
fi
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "Web" "Web traffic analyzer password enabled (Username: $stats_user, Domain: $domain)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
194
bin/v-add-web-php
Executable file
194
bin/v-add-web-php
Executable file
@@ -0,0 +1,194 @@
|
||||
#!/bin/bash
|
||||
# info: add php fpm version
|
||||
# options: VERSION
|
||||
#
|
||||
# example: v-add-web-php 8.0
|
||||
#
|
||||
# Install php-fpm for provided version.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
version=$1
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
source_conf "$HESTIA/install/upgrade/upgrade.conf"
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '1' "$#" 'VERSION'
|
||||
|
||||
if [ -z "$WEB_BACKEND" ]; then
|
||||
echo "Multiple php versions are not supported for modphp"
|
||||
fi
|
||||
|
||||
# Set file locations
|
||||
php_fpm="/etc/init.d/php$version-fpm"
|
||||
|
||||
# Verify php version format
|
||||
if [ -f /etc/redhat-release ]; then
|
||||
if [[ ! $version =~ ^[0-9][0-9]+ ]]; then
|
||||
echo "The specified PHP version format is invalid, it should look like [0-9][0-9]."
|
||||
echo "Example: 70, 74, 80"
|
||||
exit "$E_INVALID"
|
||||
fi
|
||||
else
|
||||
if [[ ! $version =~ ^[0-9].[0-9]+ ]]; then
|
||||
echo "The specified PHP version format is invalid, it should look like [0-9].[0-9]."
|
||||
echo "Example: 7.0, 7.4, 8.0"
|
||||
exit "$E_INVALID"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check if php version already exists
|
||||
if [ -f "$php_fpm" ] && [ -f "$HESTIA/data/templates/web/php-fpm/PHP-${version/\./_}.tpl" ]; then
|
||||
echo "ERROR: Specified PHP version is already installed."
|
||||
exit "$E_INVALID"
|
||||
fi
|
||||
|
||||
# Check if php version is supported
|
||||
if [[ ! "$multiphp_v" =~ $version ]]; then
|
||||
echo "ERROR: Specified PHP version is not supported or does not exist."
|
||||
exit "$E_INVALID"
|
||||
fi
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
mph="php$version-common php$version-mbstring php$version-bcmath php$version-cli php$version-curl
|
||||
php$version-fpm php$version-gd php$version-intl php$version-mysql
|
||||
php$version-soap php$version-xml php$version-zip php$version-json php$version-bz2
|
||||
php$version-pspell php$version-imagick php$version-pgsql php$version-imap php$version-ldap"
|
||||
if [ -f /etc/redhat-release ]; then
|
||||
# Packages in Remi repo have names with php$version-php- prefixes
|
||||
mph="php$version-php-fpm php$version-php-cgi php$version-php-mysqlnd php$version-php-pgsql
|
||||
php$version-php-pdo php$version-php-common php$version-php-pecl-imagick php$version-php-imap
|
||||
php$version-php-ldap php$version-php-pecl-apcu php$version-php-pecl-zip php$version-php-cli
|
||||
php$version-php-opcache php$version-php-xml php$version-php-gd php$version-php-intl
|
||||
php$version-php-mbstring php$version-php-pspell php$version-php-readline"
|
||||
if [ "$version" = "56" ]; then
|
||||
mph=$(sed -e "s/php$version-php-pecl-apcu//")
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check is version is 7.1 or below to add mcrypt
|
||||
if [[ $(echo "$version 7.2" | awk '{print ($1 < $2)}') == 1 ]]; then
|
||||
mph="$mph php$version-mcrypt"
|
||||
fi
|
||||
|
||||
# Check if version is 8.0 or higher and drop php json.
|
||||
if [[ ${version:0:1} == "8" ]]; then
|
||||
mph=$(echo "$mph" | sed -e "s/php$version\(-php\)\{0,1\}-json//")
|
||||
fi
|
||||
|
||||
if ! echo "$DB_SYSTEM" | grep -w 'mysql' > /dev/null; then
|
||||
mph=$(echo "$mph" | sed -e "s/php$version\(-php\)\{0,1\}-mysql//")
|
||||
fi
|
||||
|
||||
if ! echo "$DB_SYSTEM" | grep -w 'pgsql' > /dev/null; then
|
||||
mph=$(echo "$mph" | sed -e "s/php$version\(-php\)\{0,1\}-pgsql//")
|
||||
fi
|
||||
|
||||
# Install php packages
|
||||
if [ -f '/etc/redhat-release' ]; then
|
||||
dnf install -q -y $mph > /dev/null 2>&1 &
|
||||
else
|
||||
apt-get -qq update
|
||||
apt-get -y -qq -o Dpkg::Options::="--force-confold" install $mph > /dev/null 2>&1 &
|
||||
fi
|
||||
BACK_PID=$!
|
||||
|
||||
# Check if package installation is done, print a spinner
|
||||
echo "Installing PHP-$version, please wait..."
|
||||
spinner="/-\|"
|
||||
spin_i=1
|
||||
while kill -0 $BACK_PID > /dev/null 2>&1; do
|
||||
printf "\b${spinner:spin_i++%${#spinner}:1}"
|
||||
sleep 0.5
|
||||
done
|
||||
|
||||
# Do a blank echo to get the \n back
|
||||
echo
|
||||
|
||||
# Check if installation was successful
|
||||
if [ ! -f "$php_fpm" ]; then
|
||||
echo "ERROR: Installation failed, please run the following command manually for debugging:"
|
||||
if [ -f '/etc/redhat-release' ]; then
|
||||
echo "dnf install $mph"
|
||||
else
|
||||
echo "apt-get install $mph"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check if required modules for apache2 are enabled
|
||||
if [ "$WEB_SYSTEM" = "apache2" ]; then
|
||||
if [ -f /etc/redhat-release ]; then
|
||||
if ! httpd -M | grep 'proxy_fcgi_module' ; then
|
||||
sed 's/#LoadModule proxy_fcgi_module/LoadModule proxy_fcgi_module/' -i /etc/httpd/conf.modules.d/00-proxy.conf
|
||||
sed 's/#LoadModule proxy_module/LoadModule proxy_module/' -i /etc/httpd/conf.modules.d/00-proxy.conf
|
||||
fi
|
||||
if ! httpd -M | grep 'setenvif_module' ; then
|
||||
sed 's/#LoadModule setenvif_module/LoadModule setenvif_module/' -i /etc/httpd/conf.modules.d/00-base.conf
|
||||
fi
|
||||
else
|
||||
if ! a2query -q -m proxy_fcgi; then
|
||||
a2enmod -q proxy_fcgi
|
||||
fi
|
||||
if ! a2query -q -m setenvif; then
|
||||
a2enmod -q setenvif
|
||||
fi
|
||||
fi
|
||||
$BIN/v-restart-web "yes"
|
||||
fi
|
||||
|
||||
# Configure fpm
|
||||
v_tpl=${version//./}
|
||||
if [ -f /etc/redhat-release ]; then
|
||||
systemctl enable php${version}-php-fpm
|
||||
rm -f /etc/opt/remi/php${version}/php-fpm.d/*
|
||||
cp -f $HESTIA_INSTALL_DIR/php-fpm/dummy.conf /etc/opt/remi/php${version}/php-fpm.d/
|
||||
sed -i "s/9999/99$v_tpl/g" /etc/opt/remi/php${version}/php-fpm.d/dummy.conf
|
||||
|
||||
# Increase max upload and max post size
|
||||
sed -i "s/upload_max_filesize = 2M/upload_max_filesize = 100M/g" /etc/opt/remi/php${version}/php.ini
|
||||
sed -i "s/post_max_size = 8M/post_max_size = 100M/g" /etc/opt/remi/php${version}/php.ini
|
||||
sed -i "s/max_execution_time = 30/max_execution_time = 60/g" /etc/opt/remi/php${version}/php.ini
|
||||
else
|
||||
update-rc.d php$version-fpm defaults > /dev/null 2>&1
|
||||
rm -f /etc/php/$version/fpm/pool.d/*
|
||||
cp -f $HESTIA_INSTALL_DIR/php-fpm/dummy.conf /etc/php/$version/fpm/pool.d/
|
||||
sed -i "s/9999/99$v_tpl/g" /etc/php/$version/fpm/pool.d/dummy.conf
|
||||
cp -f $HESTIA_INSTALL_DIR/php-fpm/php-fpm.conf /etc/php/$version/fpm/
|
||||
sed -i "s/fpm_v/$version/g" /etc/php/$version/fpm/php-fpm.conf
|
||||
|
||||
# Increase max upload and max post size
|
||||
sed -i "s/upload_max_filesize = 2M/upload_max_filesize = 100M/g" /etc/php/$version/fpm/php.ini
|
||||
sed -i "s/post_max_size = 8M/post_max_size = 100M/g" /etc/php/$version/fpm/php.ini
|
||||
sed -i "s/max_execution_time = 30/max_execution_time = 60/g" /etc/php/$version/fpm/php.ini
|
||||
fi
|
||||
# Install backend template
|
||||
cp -f $HESTIA_INSTALL_DIR/php-fpm/multiphp.tpl \
|
||||
$HESTIA/data/templates/web/php-fpm/PHP-${version/\./_}.tpl
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "system" "Info" "System" "Installed PHP $version."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
800
bin/v-backup-user
Executable file
800
bin/v-backup-user
Executable file
@@ -0,0 +1,800 @@
|
||||
#!/bin/bash
|
||||
# info: backup system user with all its objects
|
||||
# options: USER NOTIFY
|
||||
#
|
||||
# example: v-backup-user admin yes
|
||||
#
|
||||
# This function is used for backing up user with all its domains and databases.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
notify=${2-no}
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# shellcheck source=/usr/local/hestia/func/db.sh
|
||||
source $HESTIA/func/db.sh
|
||||
# shellcheck source=/usr/local/hestia/func/backup.sh
|
||||
source $HESTIA/func/backup.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# Return Disk Usage
|
||||
get_user_disk_usage() {
|
||||
u_usage=0
|
||||
web_exclusions=''
|
||||
mail_exclusions=''
|
||||
db_exclusions=''
|
||||
user_exclusions=''
|
||||
|
||||
# Parsing excludes
|
||||
if [ -e "$USER_DATA/backup-excludes.conf" ]; then
|
||||
web_exclusions=$(grep 'WEB=' $USER_DATA/backup-excludes.conf \
|
||||
| awk -F "WEB='" '{print $2}' | cut -f 1 -d \')
|
||||
mail_exclusions=$(grep 'MAIL=' $USER_DATA/backup-excludes.conf \
|
||||
| awk -F "MAIL='" '{print $2}' | cut -f 1 -d \')
|
||||
db_exclusions=$(grep 'DB=' $USER_DATA/backup-excludes.conf \
|
||||
| awk -F "DB='" '{print $2}' | cut -f 1 -d \')
|
||||
user_exclusions=$(grep 'USER=' $USER_DATA/backup-excludes.conf \
|
||||
| awk -F "USER='" '{print $2}' | cut -f 1 -d \')
|
||||
fi
|
||||
|
||||
if [ -f "$USER_DATA/web.conf" ] && [ "$web_exclusions" != '*' ]; then
|
||||
usage=0
|
||||
domains=$(grep 'DOMAIN=' $USER_DATA/web.conf \
|
||||
| awk -F "DOMAIN='" '{print $2}' | cut -f 1 -d \')
|
||||
|
||||
for domain in $domains; do
|
||||
exclusion=$(echo -e "$web_exclusions" | tr ',' '\n' | grep "^$domain\|\*$")
|
||||
if [ -z "$exclusion" ]; then
|
||||
# Defining home directory
|
||||
home_dir="$HOMEDIR/$user/web/$domain/"
|
||||
exclusion=$(echo -e "$web_exclusions" | tr ',' '\n' | grep "^$domain\|\*:")
|
||||
fargs=()
|
||||
|
||||
if [ -n "$exclusion" ]; then
|
||||
xdirs=$(echo -e "$exclusion" | tr ':' '\n' | grep -v "$domain\|\*")
|
||||
for xpath in $xdirs; do
|
||||
fargs+=(--exclude="$xpath")
|
||||
done
|
||||
fi
|
||||
|
||||
# Checking home directory exist
|
||||
if [ -e "$home_dir" ]; then
|
||||
disk_usage=$(nice -n 19 du -shm "$home_dir" "${fargs[@]}" | cut -f 1)
|
||||
u_usage=$((u_usage + disk_usage))
|
||||
fi
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
if [ -f "$USER_DATA/mail.conf" ] && [ "$mail_exclusions" != '*' ]; then
|
||||
usage=0
|
||||
domains=$(grep 'DOMAIN=' "$USER_DATA/mail.conf" \
|
||||
| awk -F "DOMAIN='" '{print $2}' | cut -f 1 -d \')
|
||||
|
||||
for domain in $domains; do
|
||||
check_exl=$(echo "$mail_exclusions" | tr ',' '\n' | grep "^$domain$")
|
||||
if [ -f "$USER_DATA/mail/$domain.conf" ] && [ -z "$check_exl" ]; then
|
||||
accounts=$(grep 'ACCOUNT=' "$USER_DATA/mail/$domain.conf" \
|
||||
| awk -F "ACCOUNT='" '{print $2}' | cut -f 1 -d \')
|
||||
|
||||
for account in $accounts; do
|
||||
home_dir=$HOMEDIR/$user/mail/$domain/$account
|
||||
exclusion=$(echo "$mail_exclusions" | tr ',' '\n' | grep "$domain:")
|
||||
exclusion=$(echo "$exclusion" | tr ':' '\n' | grep -E "^$account|\*")
|
||||
|
||||
if [ -z "$exclusion" ] && [ -e "$home_dir" ]; then
|
||||
disk_usage=$(nice -n 19 du -shm "$home_dir" | cut -f 1)
|
||||
u_usage=$((u_usage + disk_usage))
|
||||
fi
|
||||
done
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
if [ -f "$USER_DATA/db.conf" ] && [ "$db_exclusions" != '*' ]; then
|
||||
usage=0
|
||||
databases=$(grep 'DB=' "$USER_DATA/db.conf" \
|
||||
| awk -F "DB='" '{print $2}' | cut -f 1 -d \')
|
||||
for database in $databases; do
|
||||
exclusion=$(echo "$db_exclusions" | tr ',' '\n' | grep "^$database$")
|
||||
if [ -z "$exclusion" ]; then
|
||||
# Get database values
|
||||
get_database_values
|
||||
|
||||
# Switching on db type
|
||||
case $DB_SYSTEM in
|
||||
mysql) get_mysql_disk_usage ;;
|
||||
pgsql) get_pgsql_disk_usage ;;
|
||||
esac
|
||||
u_usage=$((u_usage + usage))
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
if [ "$user_exclusions" != '*' ]; then
|
||||
fargs=()
|
||||
for xpath in $(echo "$user_exclusions" | tr ',' '\n'); do
|
||||
fargs+=(--exclude="$xpath")
|
||||
done
|
||||
usage=$(du -shm "$HOMEDIR/$user" --exclude "$HOMEDIR/$user/web" --exclude "$HOMEDIR/$user/mail" --exclude "$HOMEDIR/$user/conf" "${fargs[@]}" | cut -f 1)
|
||||
u_usage=$((u_usage + usage))
|
||||
fi
|
||||
|
||||
echo ${u_usage}
|
||||
}
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '1' "$#" 'USER [NOTIFY]'
|
||||
is_format_valid 'user'
|
||||
is_system_enabled "$BACKUP_SYSTEM" 'BACKUP_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
if [ "$POLICY_BACKUP_SUSPENDED_USERS" != "yes" ]; then
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
fi
|
||||
is_backup_enabled
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_backup_conditions
|
||||
|
||||
# Set backup directory if undefined
|
||||
if [ -z "$BACKUP" ]; then
|
||||
BACKUP=/backup
|
||||
fi
|
||||
|
||||
# Check if backup folder exists and have the correct permission
|
||||
if [[ ! -d "$BACKUP" ]]; then
|
||||
mkdir -p $BACKUP
|
||||
fi
|
||||
if [ "$(stat -c %a "$BACKUP")" != 755 ]; then
|
||||
chmod 755 $BACKUP
|
||||
fi
|
||||
|
||||
# Get current time
|
||||
start_time=$(date '+%s')
|
||||
|
||||
# Set notification email and subject
|
||||
subj="$user → backup failed"
|
||||
email=$(grep CONTACT "$HESTIA/data/users/admin/user.conf" | cut -f 2 -d \')
|
||||
|
||||
# Validate available disk space (take usage * 2, due to the backup handling)
|
||||
let u_disk=$(($(get_user_disk_usage) * 2))
|
||||
let v_disk=$(($(stat -f --format="%a*%S" $BACKUP)))/1024/1024
|
||||
|
||||
if [ "$u_disk" -gt "$v_disk" ]; then
|
||||
let u_disk_original=$(get_user_disk_usage)
|
||||
# Always notify on failure
|
||||
echo "Not enough disk space available ($v_disk mb) to perform the backup of $user. ( $u_disk_original mb * 2 = $u_disk mb). https://hestiacp.com/docs/server-administration/backup-restore.html" | $SENDMAIL -s "$subj" "$email" "yes"
|
||||
# Deleting task from queue
|
||||
sed -i "/v-backup-user $user /d" $HESTIA/data/queue/backup.pipe
|
||||
check_result "$E_LIMIT" "not enough disk space available ($v_disk mb) to perform the backup of $user. ( $u_disk_original mb * 2 = $u_disk mb)."
|
||||
fi
|
||||
|
||||
if [ -z "$BACKUP_TEMP" ]; then
|
||||
BACKUP_TEMP=$BACKUP
|
||||
fi
|
||||
|
||||
# Creating temporary directory
|
||||
tmpdir=$(mktemp -p $BACKUP_TEMP -d)
|
||||
|
||||
if [ "$?" -ne 0 ]; then
|
||||
echo "Can't create tmp dir $tmpdir" | $SENDMAIL -s "$subj" "$email" "yes"
|
||||
# Deleting task from queue
|
||||
sed -i "/v-backup-user $user /d" $HESTIA/data/queue/backup.pipe
|
||||
check_result "$E_NOTEXIST" "can't create tmp dir"
|
||||
fi
|
||||
|
||||
# Backup sys configs
|
||||
echo "-- SYSTEM --" | tee $BACKUP/$user.log
|
||||
mkdir $tmpdir/hestia
|
||||
|
||||
echo -e "$(date "+%F %T") $user.conf" | tee -a $BACKUP/$user.log
|
||||
cp -r $USER_DATA/user.conf $tmpdir/hestia/
|
||||
cp -r $USER_DATA/ssl $tmpdir/hestia/
|
||||
|
||||
if [ -e "$USER_DATA/stats.log" ]; then
|
||||
echo -e "$(date "+%F %T") stats.log" | tee -a $BACKUP/$user.log
|
||||
cp -r $USER_DATA/stats.log $tmpdir/hestia/
|
||||
fi
|
||||
|
||||
if [ -e "$USER_DATA/history.log" ]; then
|
||||
echo -e "$(date "+%F %T") history.log" | tee -a $BACKUP/$user.log
|
||||
cp -r $USER_DATA/history.log $tmpdir/hestia/
|
||||
fi
|
||||
|
||||
if [ -e "$USER_DATA/backup-excludes.conf" ]; then
|
||||
echo -e "$(date "+%F %T") backup-excludes.conf" | tee -a $BACKUP/$user.log
|
||||
cp -r $USER_DATA/backup-excludes.conf $tmpdir/hestia/
|
||||
fi
|
||||
|
||||
# Backup PAM
|
||||
mkdir $tmpdir/pam
|
||||
echo -e "$(date "+%F %T") pam" | tee -a $BACKUP/$user.log
|
||||
grep "^$user:" /etc/passwd > $tmpdir/pam/passwd
|
||||
grep "^$user:" /etc/shadow > $tmpdir/pam/shadow
|
||||
grep "^$user:" /etc/group > $tmpdir/pam/group
|
||||
echo
|
||||
|
||||
# Parsing excludes
|
||||
if [ -e "$USER_DATA/backup-excludes.conf" ]; then
|
||||
source $USER_DATA/backup-excludes.conf
|
||||
fi
|
||||
|
||||
# WEB domains
|
||||
if [ -n "$WEB_SYSTEM" ] && [ "$WEB" != '*' ]; then
|
||||
echo -e "\n-- WEB --" | tee -a $BACKUP/$user.log
|
||||
mkdir $tmpdir/web/
|
||||
|
||||
# Parsing domain exclusions
|
||||
conf="$USER_DATA/web.conf"
|
||||
for domain in $(search_objects 'web' 'SUSPENDED' "*" 'DOMAIN'); do
|
||||
exclusion=$(echo -e "$WEB" | tr ',' '\n' | grep "^$domain$\|^\*$")
|
||||
if [ -z "$exclusion" ]; then
|
||||
web_list="$web_list $domain"
|
||||
else
|
||||
echo "$(date "+%F %T") excluding $domain" | tee -a $BACKUP/$user.log
|
||||
fi
|
||||
done
|
||||
web_list=$(echo "$web_list" | sed -e "s/ */\ /g" -e "s/^ //")
|
||||
|
||||
i=0
|
||||
|
||||
for domain in $web_list; do
|
||||
check_backup_conditions
|
||||
((i++))
|
||||
echo -e "$(date "+%F %T") $domain" | tee -a $BACKUP/$user.log
|
||||
mkdir -p $tmpdir/web/$domain/conf
|
||||
mkdir -p $tmpdir/web/$domain/hestia
|
||||
|
||||
# Get domain variables
|
||||
domain_idn=$domain
|
||||
format_domain_idn
|
||||
get_domain_values 'web'
|
||||
|
||||
# Backup web.conf
|
||||
cd $tmpdir/web/$domain/
|
||||
conf="$USER_DATA/web.conf"
|
||||
grep "DOMAIN='$domain'" $conf > hestia/web.conf
|
||||
|
||||
# Backup vhost config
|
||||
if [ -e "$HOMEDIR/$user/conf/web/$domain/$WEB_SYSTEM.conf" ]; then
|
||||
cp $HOMEDIR/$user/conf/web/$domain/$WEB_SYSTEM.conf* conf/
|
||||
elif [ -e "$HOMEDIR/$user/conf/web/$domain.$WEB_SYSTEM.conf" ]; then
|
||||
cp $HOMEDIR/$user/conf/web/$domain.$WEB_SYSTEM.conf* conf/
|
||||
else
|
||||
# legacy format: all domain configs in single file
|
||||
tpl_file="$WEBTPL/$WEB_SYSTEM/$WEB_BACKEND/$TPL.tpl"
|
||||
conf="$HOMEDIR/$user/conf/web/$WEB_SYSTEM.conf"
|
||||
get_web_config_lines "$tpl_file" "$conf"
|
||||
sed -n "$top_line,$bottom_line p" $conf > conf/$WEB_SYSTEM.conf
|
||||
fi
|
||||
|
||||
# Backup ssl vhost
|
||||
if [ "$SSL" = 'yes' ]; then
|
||||
if [ -e "$HOMEDIR/$user/conf/web/$domain/$WEB_SYSTEM.ssl.conf" ]; then
|
||||
cp $HOMEDIR/$user/conf/web/$domain/$WEB_SYSTEM.ssl.conf* conf/
|
||||
elif [ -e "$HOMEDIR/$user/conf/web/$domain.$WEB_SYSTEM.ssl.conf" ]; then
|
||||
cp $HOMEDIR/$user/conf/web/$domain.$WEB_SYSTEM.ssl.conf* conf/
|
||||
else
|
||||
# legacy format: all domain configs in single file
|
||||
tpl_file="$WEBTPL/$WEB_SYSTEM/$WEB_BACKEND/$TPL.stpl"
|
||||
conf="$HOMEDIR/$user/conf/web/s$WEB_SYSTEM.conf"
|
||||
get_web_config_lines "$tpl_file" "$conf"
|
||||
sed -n "$top_line,$bottom_line p" $conf > conf/s$WEB_SYSTEM.conf
|
||||
fi
|
||||
fi
|
||||
|
||||
# Backup proxy config
|
||||
if [ -n "$PROXY_SYSTEM" ] && [ -n "$PROXY" ]; then
|
||||
if [ -e "$HOMEDIR/$user/conf/web/$domain/$PROXY_SYSTEM.conf" ]; then
|
||||
cp $HOMEDIR/$user/conf/web/$domain/$PROXY_SYSTEM.conf* conf/
|
||||
elif [ -e "$HOMEDIR/$user/conf/web/$domain.$PROXY_SYSTEM.conf" ]; then
|
||||
cp $HOMEDIR/$user/conf/web/$domain.$PROXY_SYSTEM.conf* conf/
|
||||
else
|
||||
# legacy format: all domain configs in single file
|
||||
tpl_file="$WEBTPL/$PROXY_SYSTEM/$PROXY.tpl"
|
||||
conf="$HOMEDIR/$user/conf/web/$PROXY_SYSTEM.conf"
|
||||
get_web_config_lines "$tpl_file" "$conf"
|
||||
sed -n "$top_line,$bottom_line p" $conf > conf/$PROXY_SYSTEM.conf
|
||||
fi
|
||||
fi
|
||||
|
||||
# Backup ssl proxy config
|
||||
if [ -n "$PROXY_SYSTEM" ] && [ -n "$PROXY" ] && [ "$SSL" = 'yes' ]; then
|
||||
if [ -e "$HOMEDIR/$user/conf/web/$domain/$PROXY_SYSTEM.ssl.conf" ]; then
|
||||
cp $HOMEDIR/$user/conf/web/$domain/$PROXY_SYSTEM.ssl.conf* conf/
|
||||
elif [ -e "$HOMEDIR/$user/conf/web/$domain.$PROXY_SYSTEM.ssl.conf" ]; then
|
||||
cp $HOMEDIR/$user/conf/web/$domain.$PROXY_SYSTEM.ssl.conf* conf/
|
||||
else
|
||||
# legacy format: all domain configs in single file
|
||||
tpl_file="$WEBTPL/$PROXY_SYSTEM/$PROXY.stpl"
|
||||
conf="$HOMEDIR/$user/conf/web/s$PROXY_SYSTEM.conf"
|
||||
get_web_config_lines "$tpl_file" "$conf"
|
||||
sed -n "$top_line,$bottom_line p" $conf > conf/s$PROXY_SYSTEM.conf
|
||||
fi
|
||||
fi
|
||||
|
||||
domain_conf=$(grep "DOMAIN='$domain'" $conf)
|
||||
parse_object_kv_list_non_eval domain_conf
|
||||
|
||||
mkdir -p template/$WEB_SYSTEM/
|
||||
mkdir template/php-fpm/
|
||||
|
||||
if [ $WEB_BACKEND == 'php-fpm' ]; then
|
||||
cp $HESTIA/data/templates/web/$WEB_SYSTEM/php-fpm/$TPL.tpl template/$WEB_SYSTEM/
|
||||
cp $HESTIA/data/templates/web/$WEB_SYSTEM/php-fpm/$TPL.stpl template/$WEB_SYSTEM/
|
||||
cp $HESTIA/data/templates/web/php-fpm/$BACKEND.tpl template/php-fpm/
|
||||
else
|
||||
cp $HESTIA/data/templates/web/$WEB_SYSTEM/$TPL.tpl template/$WEB_SYSTEM/
|
||||
cp $HESTIA/data/templates/web/$WEB_SYSTEM/$TPL.stpl template/$WEB_SYSTEM/
|
||||
fi
|
||||
if [ -n "$PROXY_SYSTEM" ] && [ -n "$PROXY" ]; then
|
||||
mkdir template/$PROXY_SYSTEM
|
||||
cp $HESTIA/data/templates/web/$PROXY_SYSTEM/$PROXY.tpl template/$PROXY_SYSTEM/
|
||||
cp $HESTIA/data/templates/web/$PROXY_SYSTEM/$PROXY.stpl template/$PROXY_SYSTEM/
|
||||
fi
|
||||
|
||||
# Backup ssl certificates
|
||||
if [ "$SSL" = 'yes' ]; then
|
||||
cp $HOMEDIR/$user/conf/web/$domain/ssl/$domain.* conf/
|
||||
cp $USER_DATA/ssl/$domain.* hestia/
|
||||
fi
|
||||
|
||||
# Changin dir to documentroot
|
||||
cd $HOMEDIR/$user/web/$domain
|
||||
|
||||
# Define exclude arguments
|
||||
exclusion=$(echo -e "$WEB" | tr ',' '\n' | grep "^$domain\|\*:")
|
||||
set -f
|
||||
fargs=()
|
||||
fargs+=(--exclude='./logs/*')
|
||||
if [ -n "$exclusion" ]; then
|
||||
|
||||
if [[ "$exclusion" =~ '*' ]]; then
|
||||
exclusion="${exclusion/\*/$domain}"
|
||||
fi
|
||||
|
||||
xdirs="$(echo -e "$exclusion" | tr ':' '\n' | grep -v $domain)"
|
||||
for xpath in $xdirs; do
|
||||
if [ -d "$xpath" ]; then
|
||||
fargs+=(--exclude=$xpath/*)
|
||||
echo "$(date "+%F %T") excluding directory $xpath"
|
||||
msg="$msg\n$(date "+%F %T") excluding directory $xpath"
|
||||
else
|
||||
echo "$(date "+%F %T") excluding file $xpath"
|
||||
msg="$msg\n$(date "+%F %T") excluding file $xpath"
|
||||
fargs+=(--exclude=$xpath)
|
||||
fi
|
||||
done
|
||||
fi
|
||||
set +f
|
||||
|
||||
# Backup files
|
||||
if [ "$BACKUP_MODE" = 'zstd' ]; then
|
||||
tar "${fargs[@]}" -cpf- * | pzstd -"$BACKUP_GZIP" - > $tmpdir/web/$domain/domain_data.tar.zst
|
||||
else
|
||||
tar "${fargs[@]}" -cpf- * | gzip -"$BACKUP_GZIP" - > $tmpdir/web/$domain/domain_data.tar.gz
|
||||
fi
|
||||
done
|
||||
|
||||
# Print total
|
||||
if [ "$i" -eq 1 ]; then
|
||||
echo -e "$(date "+%F %T") *** $i domain ***" | tee -a $BACKUP/$user.log
|
||||
else
|
||||
echo -e "$(date "+%F %T") *** $i domains ***" | tee -a $BACKUP/$user.log
|
||||
fi
|
||||
fi
|
||||
|
||||
# DNS domains
|
||||
if [ -n "$DNS_SYSTEM" ] && [ "$DNS" != '*' ]; then
|
||||
echo -e "\n-- DNS --" | tee -a $BACKUP/$user.log
|
||||
mkdir $tmpdir/dns/
|
||||
|
||||
# Parsing domain exclusions
|
||||
for domain in $(search_objects 'dns' 'SUSPENDED' "*" 'DOMAIN'); do
|
||||
exclusion=$(echo "$DNS" | tr ',' '\n' | grep "^$domain$")
|
||||
if [ -z "$exclusion" ]; then
|
||||
dns_list="$dns_list $domain"
|
||||
else
|
||||
echo "$(date "+%F %T") excluding $domain"
|
||||
msg="$msg\n$(date "+%F %T") excluding $domain"
|
||||
fi
|
||||
done
|
||||
dns_list=$(echo "$dns_list" | sed -e "s/ */\ /g" -e "s/^ //")
|
||||
|
||||
i=0
|
||||
for domain in $dns_list; do
|
||||
((i++))
|
||||
echo -e "$(date "+%F %T") $domain" | tee -a $BACKUP/$user.log
|
||||
domain_idn="$domain"
|
||||
# Building directory tree
|
||||
mkdir -p $tmpdir/dns/$domain/conf
|
||||
mkdir -p $tmpdir/dns/$domain/conf/keys
|
||||
mkdir -p $tmpdir/dns/$domain/hestia
|
||||
|
||||
# Backup dns.conf
|
||||
cd $tmpdir/dns/$domain/
|
||||
conf="$USER_DATA/dns.conf"
|
||||
grep "DOMAIN='$domain'" $conf > hestia/dns.conf
|
||||
|
||||
# Backup dns recods
|
||||
cp $USER_DATA/dns/$domain.conf hestia/$domain.conf
|
||||
if [ "$DNS_SYSTEM" != 'remote' ]; then
|
||||
cp $HOMEDIR/$user/conf/dns/$domain.db conf/$domain.db
|
||||
fi
|
||||
# Backup DNSSEC public and private key if enabled
|
||||
dnssec=$(grep "DOMAIN='$domain'" $USER_DATA/dns.conf | grep "DNSSEC='yes'")
|
||||
if [ -n "$dnssec" ]; then
|
||||
format_domain_idn
|
||||
cp $USER_DATA/keys/K$domain_idn*.* $tmpdir/dns/$domain/conf/keys
|
||||
fi
|
||||
done
|
||||
|
||||
# Print total
|
||||
if [ "$i" -eq 1 ]; then
|
||||
echo -e "$(date "+%F %T") *** $i domain ***" | tee -a $BACKUP/$user.log
|
||||
else
|
||||
echo -e "$(date "+%F %T") *** $i domains ***" | tee -a $BACKUP/$user.log
|
||||
fi
|
||||
fi
|
||||
|
||||
# Mail domains
|
||||
if [ -n "$MAIL_SYSTEM" ] && [ "$MAIL" != '*' ]; then
|
||||
echo -e "\n-- MAIL --" | tee -a $BACKUP/$user.log
|
||||
mkdir $tmpdir/mail/
|
||||
|
||||
# Parsing domain exclusions
|
||||
conf="$USER_DATA/mail.conf"
|
||||
for domain in $(search_objects 'mail' 'SUSPENDED' "*" 'DOMAIN'); do
|
||||
check_exl=$(echo "$MAIL" | tr ',' '\n' | grep "^$domain$")
|
||||
if [ -z "$check_exl" ]; then
|
||||
mail_list="$mail_list $domain"
|
||||
else
|
||||
echo "$(date "+%F %T") excluding $domain" | tee -a $BACKUP/$user.log
|
||||
fi
|
||||
done
|
||||
mail_list=$(echo "$mail_list" | sed -e "s/ */\ /g" -e "s/^ //")
|
||||
|
||||
i=0
|
||||
for domain in $mail_list; do
|
||||
check_backup_conditions
|
||||
((i++))
|
||||
echo -e "$(date "+%F %T") $domain" | tee -a $BACKUP/$user.log
|
||||
mkdir -p $tmpdir/mail/$domain/conf
|
||||
mkdir -p $tmpdir/mail/$domain/hestia
|
||||
domain_idn=$domain
|
||||
format_domain_idn
|
||||
|
||||
# Backup exim config
|
||||
if [[ "$MAIL_SYSTEM" =~ exim ]]; then
|
||||
cd $tmpdir/mail/$domain/
|
||||
cp -r $HOMEDIR/$user/conf/mail/$domain/* conf/
|
||||
fi
|
||||
|
||||
# Backup mail.conf
|
||||
conf="$USER_DATA/mail.conf"
|
||||
grep "DOMAIN='$domain'" $conf > hestia/mail.conf
|
||||
cp $USER_DATA/mail/$domain.* hestia/
|
||||
if [ -n "$(ls $USER_DATA/mail/ | grep *@$domain)" ]; then
|
||||
cp $USER_DATA/mail/*@$domain.* hestia/
|
||||
fi
|
||||
|
||||
# Backup emails
|
||||
cd $HOMEDIR/$user/mail/$domain_idn
|
||||
accounts=()
|
||||
for account in *; do
|
||||
exclusion=$(echo "$MAIL" | tr ',' '\n' | grep "$domain:")
|
||||
exclusion=$(echo "$exclusion" | tr ':' '\n' | grep -E "^$account|\*")
|
||||
|
||||
# Checking exclusions
|
||||
if [ -z "$exclusion" ] && [[ "$MAIL_SYSTEM" =~ exim ]]; then
|
||||
accounts+=($account)
|
||||
else
|
||||
echo "$(date "+%F %T") excluding mail account $account" \
|
||||
| tee -a $BACKUP/$user.log
|
||||
fi
|
||||
done
|
||||
# Compress archive
|
||||
if [ ${#accounts[@]} -gt 0 ]; then
|
||||
if [ "$BACKUP_MODE" = 'zstd' ]; then
|
||||
tar -cpf- "${accounts[@]}" | pzstd -"$BACKUP_GZIP" - > $tmpdir/mail/$domain/accounts.tar.zst
|
||||
else
|
||||
tar -cpf- "${accounts[@]}" | gzip -"$BACKUP_GZIP" - > $tmpdir/mail/$domain/accounts.tar.gz
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
# Print total
|
||||
if [ "$i" -eq 1 ]; then
|
||||
echo -e "$(date "+%F %T") *** $i domain ***" | tee -a $BACKUP/$user.log
|
||||
else
|
||||
echo -e "$(date "+%F %T") *** $i domains ***" | tee -a $BACKUP/$user.log
|
||||
fi
|
||||
fi
|
||||
|
||||
# Databases
|
||||
if [ -n "$DB_SYSTEM" ] && [ "$DB" != '*' ]; then
|
||||
echo -e "\n-- DB --" | tee -a $BACKUP/$user.log
|
||||
mkdir $tmpdir/db/
|
||||
|
||||
# Parsing database exclusions
|
||||
for database in $(search_objects 'db' 'SUSPENDED' "*" 'DB'); do
|
||||
exclusion=$(echo "$DB" | tr ',' '\n' | grep "^$database$")
|
||||
if [ -z "$exclusion" ]; then
|
||||
db_list="$db_list $database"
|
||||
else
|
||||
echo "$(date "+%F %T") excluding $database" \
|
||||
| tee -a $BACKUP/$user.log
|
||||
fi
|
||||
done
|
||||
|
||||
i=0
|
||||
conf="$USER_DATA/db.conf"
|
||||
db_list=$(echo "$db_list" | sed -e "s/ */\ /g" -e "s/^ //")
|
||||
for database in $db_list; do
|
||||
check_backup_conditions
|
||||
((i++))
|
||||
get_database_values
|
||||
|
||||
echo -e "$(date "+%F %T") $database ($TYPE)" | tee -a $BACKUP/$user.log
|
||||
mkdir -p $tmpdir/db/$database/conf
|
||||
mkdir -p $tmpdir/db/$database/hestia
|
||||
|
||||
cd $tmpdir/db/$database/
|
||||
grep "DB='$database'" $conf > hestia/db.conf
|
||||
|
||||
dump="$tmpdir/db/$database/$database.$TYPE.sql"
|
||||
if [ "$BACKUP_MODE" = 'zstd' ]; then
|
||||
dumpgz="$tmpdir/db/$database/$database.$TYPE.sql.zst"
|
||||
else
|
||||
dumpgz="$tmpdir/db/$database/$database.$TYPE.sql.gz"
|
||||
fi
|
||||
|
||||
grants="$tmpdir/db/$database/conf/$database.$TYPE.$DBUSER"
|
||||
if [ ! -f "$dumpgz" ]; then
|
||||
|
||||
WAIT_LOOP_ENTERED=0
|
||||
while true; do
|
||||
if pgrep -x "mysqldump" > /dev/null; then
|
||||
WAIT_LOOP_ENTERED=1
|
||||
echo "Wait other mysqldump to finish"
|
||||
sleep 1
|
||||
else
|
||||
if [ "$WAIT_LOOP_ENTERED" -eq 1 ]; then
|
||||
echo "We can use mysqldump now"
|
||||
fi
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
case $TYPE in
|
||||
mysql) dump_mysql_database ;;
|
||||
pgsql) dump_pgsql_database ;;
|
||||
esac
|
||||
|
||||
# Compress dump
|
||||
if [ "$BACKUP_MODE" = 'zstd' ]; then
|
||||
pzstd -$BACKUP_GZIP $dump
|
||||
rm $dump
|
||||
else
|
||||
gzip -$BACKUP_GZIP $dump
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
# Print total
|
||||
if [ "$i" -eq 1 ]; then
|
||||
echo -e "$(date "+%F %T") *** $i database ***" \
|
||||
| tee -a $BACKUP/$user.log
|
||||
else
|
||||
echo -e "$(date "+%F %T") *** $i databases ***" \
|
||||
| tee -a $BACKUP/$user.log
|
||||
fi
|
||||
fi
|
||||
|
||||
# Cron jobs
|
||||
if [ -n "$CRON_SYSTEM" ] && [ "$CRON" != '*' ]; then
|
||||
echo -e "\n-- CRON --" | tee -a $BACKUP/$user.log
|
||||
mkdir $tmpdir/cron/
|
||||
|
||||
# Backup cron.conf
|
||||
cp $USER_DATA/cron.conf $tmpdir/cron/
|
||||
cron_record=$(wc -l $USER_DATA/cron.conf | cut -f 1 -d ' ')
|
||||
|
||||
if [ -e "/var/spool/cron/$user" ]; then
|
||||
cron_list="$cron_record"
|
||||
cp /var/spool/cron/$user $tmpdir/cron/
|
||||
fi
|
||||
|
||||
# Print total
|
||||
if [ "$cron_record" -eq 1 ]; then
|
||||
echo -e "$(date "+%F %T") *** $cron_record job ***" \
|
||||
| tee -a $BACKUP/$user.log
|
||||
else
|
||||
echo -e "$(date "+%F %T") *** $cron_record jobs ***" \
|
||||
| tee -a $BACKUP/$user.log
|
||||
fi
|
||||
fi
|
||||
|
||||
# User Directories
|
||||
if [ "$USER" != '*' ]; then
|
||||
echo -e "\n-- User Dir --" | tee -a $BACKUP/$user.log
|
||||
mkdir $tmpdir/user_dir
|
||||
cd $HOMEDIR/$user
|
||||
|
||||
# Parsing directory exclusions
|
||||
USER=''
|
||||
if [ -e "$USER_DATA/backup-excludes.conf" ]; then
|
||||
source $USER_DATA/backup-excludes.conf
|
||||
fi
|
||||
fargs=()
|
||||
for xpath in $(echo "$USER" | tr ',' '\n'); do
|
||||
if [ -d "$xpath" ]; then
|
||||
fargs+=(--exclude="$xpath"/*)
|
||||
echo "$(date "+%F %T") excluding directory $xpath" \
|
||||
| tee -a $BACKUP/$user.log
|
||||
else
|
||||
echo "$(date "+%F %T") excluding file $xpath" \
|
||||
| tee -a $BACKUP/$user.log
|
||||
fargs+=(--exclude="$xpath")
|
||||
fi
|
||||
done
|
||||
|
||||
IFS=$'\n'
|
||||
set -f
|
||||
i=0
|
||||
|
||||
for udir in $(ls -a | egrep -v "^conf$|^web$|^dns$|^tmp$|^mail$|^\.\.$|^\.$"); do
|
||||
exclusion=$(echo "$USER" | tr ',' '\n' | grep "^$udir$")
|
||||
if [ -z "$exclusion" ]; then
|
||||
((i++))
|
||||
udir_list="$udir_list $udir"
|
||||
echo -e "$(date "+%F %T") adding $udir" | tee -a $BACKUP/$user.log
|
||||
|
||||
check_backup_conditions
|
||||
|
||||
# Backup files and dirs
|
||||
if [ "$BACKUP_MODE" = 'zstd' ]; then
|
||||
tar --anchored -cpf- "${fargs[@]}" $udir | pzstd -"$BACKUP_GZIP" - > $tmpdir/user_dir/$udir.tar.zst
|
||||
else
|
||||
tar --anchored -cpf- "${fargs[@]}" $udir | gzip -"$BACKUP_GZIP" - > $tmpdir/user_dir/$udir.tar.gz
|
||||
fi
|
||||
|
||||
fi
|
||||
done
|
||||
set +f
|
||||
udir_list=$(echo "$udir_list" | sed -e "s/ */\ /g" -e "s/^ //")
|
||||
|
||||
# Print total
|
||||
if [ "$i" -eq 1 ]; then
|
||||
echo -e "$(date "+%F %T") *** $i user directory ***" \
|
||||
| tee -a $BACKUP/$user.log
|
||||
else
|
||||
echo -e "$(date "+%F %T") *** $i directories ***" \
|
||||
| tee -a $BACKUP/$user.log
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$BACKUP_MODE" = 'zstd' ]; then
|
||||
touch $tmpdir/.zstd
|
||||
fi
|
||||
|
||||
# Get backup size
|
||||
size="$(du -shm $tmpdir | cut -f 1)"
|
||||
|
||||
# Get current time
|
||||
end_time=$(date '+%s')
|
||||
time_n_date=$(date +'%T %F')
|
||||
time=$(echo "$time_n_date" | cut -f 1 -d \ )
|
||||
date=$(echo "$time_n_date" | cut -f 2 -d \ )
|
||||
backup_new_date=$(date +"%Y-%m-%d_%H-%M-%S")
|
||||
|
||||
echo -e "\n-- SUMMARY --" | tee -a $BACKUP/$user.log
|
||||
|
||||
errorcode="0"
|
||||
# Switching on backup system types
|
||||
for backup_type in $(echo -e "${BACKUP_SYSTEM//,/\\n}"); do
|
||||
case $backup_type in
|
||||
local) local_backup ;;
|
||||
ftp) ftp_backup ;;
|
||||
sftp) sftp_backup ;;
|
||||
b2) b2_backup ;;
|
||||
rclone) rclone_backup ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Removing tmpdir
|
||||
rm -rf $tmpdir
|
||||
if [[ "$errorcode" != "0" ]]; then
|
||||
if [[ "$BACKUP_SYSTEM" =~ "local" ]]; then
|
||||
echo -e "$(date "+%F %T") *** Local backup was successfully executed. Remote backup failed ***" \
|
||||
| tee -a $BACKUP/$user.log
|
||||
BACKUP_SYSTEM="local"
|
||||
else
|
||||
echo -e "$(date "+%F %T") *** Remote backup failed ***" \
|
||||
| tee -a $BACKUP/$user.log
|
||||
|
||||
exit $error_code
|
||||
fi
|
||||
fi
|
||||
# Calculation run time
|
||||
run_time=$((end_time - start_time))
|
||||
run_time=$((run_time / 60))
|
||||
current_time=$(date "+%T")
|
||||
if [ "$run_time" -lt 1 ]; then
|
||||
run_time=1
|
||||
fi
|
||||
min=minutes
|
||||
if [ "$run_time" -eq 1 ]; then
|
||||
min=minute
|
||||
fi
|
||||
|
||||
echo "$(date "+%F %T") Size: $size MB" | tee -a $BACKUP/$user.log
|
||||
echo "$(date "+%F %T") Runtime: $run_time $min" | tee -a $BACKUP/$user.log
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Removing duplicate
|
||||
touch $USER_DATA/backup.conf
|
||||
sed -i "/$user.$backup_new_date.tar/d" $USER_DATA/backup.conf
|
||||
|
||||
# Registering new backup
|
||||
backup_str="BACKUP='$user.$backup_new_date.tar'"
|
||||
backup_str="$backup_str TYPE='$BACKUP_SYSTEM' SIZE='$size'"
|
||||
backup_str="$backup_str WEB='${web_list// /,}'"
|
||||
backup_str="$backup_str DNS='${dns_list// /,}'"
|
||||
backup_str="$backup_str MAIL='${mail_list// /,}'"
|
||||
backup_str="$backup_str DB='${db_list// /,}'"
|
||||
backup_str="$backup_str CRON='$cron_list'"
|
||||
backup_str="$backup_str UDIR='${udir_list// /,}'"
|
||||
backup_str="$backup_str RUNTIME='$run_time' TIME='$time' DATE='$date'"
|
||||
echo "$backup_str" >> $USER_DATA/backup.conf
|
||||
|
||||
# Removing old backups
|
||||
tail -n $BACKUPS $USER_DATA/backup.conf > $USER_DATA/backup.conf_
|
||||
mv -f $USER_DATA/backup.conf_ $USER_DATA/backup.conf
|
||||
chmod 660 $USER_DATA/backup.conf
|
||||
chmod 660 $BACKUP/$user.log
|
||||
|
||||
# Deleting task from queue
|
||||
sed -i "/v-backup-user $user /d" $HESTIA/data/queue/backup.pipe
|
||||
|
||||
U_BACKUPS=$(grep BACKUP $USER_DATA/backup.conf | wc -l)
|
||||
update_user_value "$user" '$U_BACKUPS' "$U_BACKUPS"
|
||||
cd $BACKUP
|
||||
|
||||
# Send notification
|
||||
if [ -e "$BACKUP/$user.log" ] && [ "$notify" = "yes" ]; then
|
||||
subj="$user → backup has been completed"
|
||||
email=$(get_user_value '$CONTACT')
|
||||
cat $BACKUP/$user.log | $SENDMAIL -s "$subj" "$email" "$notify"
|
||||
$BIN/v-add-user-notification "$user" "Backup created successfully" "<p><span class='u-text-bold'>Archive:</span> <code>$user.$backup_new_date.tar</code></p>"
|
||||
fi
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "Backup" "Backup created (Archive: $backup_new_date.tar)."
|
||||
$BIN/v-log-action "system" "Info" "Backup" "Backup created (User: $user, Archive: $backup_new_date.tar)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
56
bin/v-backup-users
Executable file
56
bin/v-backup-users
Executable file
@@ -0,0 +1,56 @@
|
||||
#!/bin/bash
|
||||
# info: backup all users
|
||||
# options: NONE
|
||||
#
|
||||
# example: v-backup-users
|
||||
#
|
||||
# This function backups all system users.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Auto-repair all databases before backuping all accounts
|
||||
mysqlrepair --all-databases --check --auto-repair > /dev/null 2>&1
|
||||
|
||||
if [ -z "$BACKUP_SYSTEM" ]; then
|
||||
exit
|
||||
fi
|
||||
for user in $($BIN/v-list-sys-users plain); do
|
||||
check_suspend=$(grep "SUSPENDED='no'" $HESTIA/data/users/$user/user.conf)
|
||||
log=$HESTIA/log/backup.log
|
||||
if [ ! -f "$HESTIA/data/users/$user/user.conf" ]; then
|
||||
continue
|
||||
fi
|
||||
check_backup_conditions
|
||||
check_suspend=$(grep "SUSPENDED='no'" $HESTIA/data/users/$user/user.conf)
|
||||
log=$HESTIA/log/backup.log
|
||||
if [ -n "$check_suspend" ]; then
|
||||
echo -e "================================" >> $log
|
||||
echo -e "$user" >> $log
|
||||
echo -e "--------------------------------\n" >> $log
|
||||
nice -n 19 ionice -c2 -n7 $BIN/v-backup-user $user >> $log 2>&1
|
||||
echo -e "\n--------------------------------\n\n" >> $log
|
||||
fi
|
||||
done
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
exit
|
||||
85
bin/v-change-cron-job
Executable file
85
bin/v-change-cron-job
Executable file
@@ -0,0 +1,85 @@
|
||||
#!/bin/bash
|
||||
# info: change cron job
|
||||
# options: USER JOB MIN HOUR DAY MONTH WDAY COMMAND
|
||||
#
|
||||
# example: v-change-cron-job admin 7 * * * * * * /usr/bin/uptime
|
||||
#
|
||||
# This function is used for changing existing job. It fully replace job
|
||||
# parameters with new one but with same id.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
job=$2
|
||||
min=$3
|
||||
hour=$4
|
||||
day=$5
|
||||
month=$6
|
||||
wday=$7
|
||||
command=$8
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '7' "$#" 'USER JOB MIN HOUR DAY MONTH WDAY COMMAND'
|
||||
is_format_valid 'user' 'job' 'min' 'hour' 'day' 'month' 'wday' 'command'
|
||||
is_system_enabled "$CRON_SYSTEM" 'CRON_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'cron' 'JOB' "$job"
|
||||
is_object_unsuspended 'cron' 'JOB' "$job"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Generating timestamp
|
||||
time_n_date=$(date +'%T %F')
|
||||
time=$(echo "$time_n_date" | cut -f 1 -d \ )
|
||||
date=$(echo "$time_n_date" | cut -f 2 -d \ )
|
||||
|
||||
# Concatenating cron string
|
||||
command=$(echo $command | sed -e "s/'/%quote%/g")
|
||||
str="JOB='$job' MIN='$min' HOUR='$hour' DAY='$day' MONTH='$month' WDAY='$wday'"
|
||||
str="$str CMD='$command' SUSPENDED='no' TIME='$time' DATE='$date'"
|
||||
|
||||
# Deleting old job
|
||||
sed -i "/JOB='$job' /d" $USER_DATA/cron.conf
|
||||
|
||||
# Adding new
|
||||
echo "$str" >> $USER_DATA/cron.conf
|
||||
|
||||
# Sorting jobs by id
|
||||
sort_cron_jobs
|
||||
|
||||
# Sync system cron with user
|
||||
sync_cron_jobs
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Restarting crond
|
||||
$BIN/v-restart-cron
|
||||
check_result $? "Cron restart failed" > /dev/null
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "Cron Jobs" "Cron job updated (Job: $job, Command: $command)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
78
bin/v-change-database-host-password
Executable file
78
bin/v-change-database-host-password
Executable file
@@ -0,0 +1,78 @@
|
||||
#!/bin/bash
|
||||
# info: change database server password
|
||||
# options: TYPE HOST USER PASSWORD
|
||||
#
|
||||
# example: v-change-database-host-password mysql localhost wp_user pA$$w@rD
|
||||
#
|
||||
# This function changes database server password.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
type=$1
|
||||
host=$2
|
||||
dbuser=$3
|
||||
password=$4
|
||||
HIDE=4
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/db.sh
|
||||
source $HESTIA/func/db.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
args_usage='TYPE HOST DBUSER DBPASS'
|
||||
check_args '4' "$#" "$args_usage"
|
||||
is_format_valid 'host' 'dbuser'
|
||||
is_object_valid "../../conf/$type" 'HOST' "$host"
|
||||
dbpass="$password"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Define email
|
||||
email=$(grep CONTACT $HESTIA/data/users/admin/user.conf | cut -f2 -d \')
|
||||
subj="v-change-database-host-password $*"
|
||||
|
||||
case $type in
|
||||
mysql)
|
||||
mysql_connect "$host"
|
||||
query="USE mysql; UPDATE user SET"
|
||||
query="$query password=PASSWORD('$dbpass')"
|
||||
query="$query WHERE User='$dbuser';"
|
||||
query="$query FLUSH PRIVILEGES;"
|
||||
mysql_query "$query"
|
||||
if [ "$dbuser" == "root" ]; then
|
||||
echo -e "[client]\npassword='$dbpass'\n" > /root/.my.cnf
|
||||
chmod 600 /root/.my.cnf
|
||||
fi
|
||||
;;
|
||||
pgsql) echo "TBD" > /dev/null ;;
|
||||
esac
|
||||
|
||||
update_object_value "../../conf/$type" 'HOST' "$host" '$USER' "$dbuser"
|
||||
update_object_value "../../conf/$type" 'HOST' "$host" '$PASSWORD' "$dbpass"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "system" "Warning" "Database" "Password changed for remote database host (Host: $host)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
133
bin/v-change-database-owner
Executable file
133
bin/v-change-database-owner
Executable file
@@ -0,0 +1,133 @@
|
||||
#!/bin/bash
|
||||
# info: change database owner
|
||||
# options: DATABASE USER
|
||||
#
|
||||
# example: v-change-database-owner mydb alice
|
||||
#
|
||||
# This function for changing database owner.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
database=$1
|
||||
user=$2
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/db.sh
|
||||
source $HESTIA/func/db.sh
|
||||
# shellcheck source=/usr/local/hestia/func/rebuild.sh
|
||||
source $HESTIA/func/rebuild.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '2' "$#" 'DATABASE USER'
|
||||
is_format_valid 'database' 'user'
|
||||
is_system_enabled "$DB_SYSTEM" 'DB_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
|
||||
# Check owner existence
|
||||
owner=$(echo $database | cut -f 1 -d '_')
|
||||
if [ ! -d "$HESTIA/data/users/$owner" ]; then
|
||||
echo "Error: database owner doesn't exist"
|
||||
log_event "$E_NOTEXIST" "$ARGUMENTS"
|
||||
exit "$E_NOTEXIST"
|
||||
fi
|
||||
|
||||
# Check if owner is the same as the dst user
|
||||
if [ "$owner" = "$user" ]; then
|
||||
exit
|
||||
fi
|
||||
|
||||
# Check db existence
|
||||
db_data=$(grep "DB='$database'" $HESTIA/data/users/$owner/db.conf)
|
||||
if [ -z "$db_data" ]; then
|
||||
echo "Error: database $database doesn't exist"
|
||||
log_event "$E_NOTEXIST" "$ARGUMENTS"
|
||||
exit "$E_NOTEXIST"
|
||||
fi
|
||||
|
||||
parse_object_kv_list "$db_data"
|
||||
#Fix issue #1084 with "Upper case not allowed with PGSQL"
|
||||
if [ "$TYPE" == "pgsql" ]; then
|
||||
usersmall=$(echo "$user" | tr '[:upper:]' '[:lower:]')
|
||||
else
|
||||
usersmall=$user
|
||||
fi
|
||||
|
||||
# Check if database name is uniqe
|
||||
new_db=$(echo $database | sed "s/^${owner}_/${usersmall}_/")
|
||||
check_db=$(grep "DB='$new_db'" $HESTIA/data/users/$user/db.conf)
|
||||
if [ -n "$check_db" ]; then
|
||||
echo "Error: $new_db database exists"
|
||||
log_event "$E_EXISTS" "$ARGUMENTS"
|
||||
exit "$E_EXISTS"
|
||||
fi
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Creating temporary directory
|
||||
tmpdir=$(mktemp -p $BACKUP -d "tmp.$database.XXXXXXXXXX")
|
||||
|
||||
# Suspend database
|
||||
$BIN/v-suspend-database $owner $database > /dev/null 2>&1
|
||||
|
||||
# Dump database
|
||||
dump="$tmpdir/$database.$TYPE.sql"
|
||||
grants="$tmpdir/$database.$TYPE.$DBUSER"
|
||||
case $TYPE in
|
||||
mysql) dump_mysql_database ;;
|
||||
pgsql) dump_pgsql_database ;;
|
||||
esac
|
||||
|
||||
# Import configuration
|
||||
db_data=$(echo "$db_data" | sed "s/'${owner}_/'${usersmall}_/g")
|
||||
echo "$db_data" >> $HESTIA/data/users/$user/db.conf
|
||||
parse_object_kv_list "$db_data"
|
||||
|
||||
# Unsuspend db
|
||||
$BIN/v-unsuspend-database "$user" "$new_db" > /dev/null 2>&1
|
||||
|
||||
# Rebuild databases
|
||||
$BIN/v-rebuild-databases "$user"
|
||||
|
||||
# Import dump
|
||||
case $TYPE in
|
||||
mysql) import_mysql_database "$dump" ;;
|
||||
pgsql) import_pgsql_database "$dump" ;;
|
||||
esac
|
||||
|
||||
# Deleting tmpdir
|
||||
rm -rf $tmpdir
|
||||
|
||||
# Remove old database
|
||||
$BIN/v-unsuspend-database "$owner" "$database" > /dev/null 2>&1
|
||||
$BIN/v-delete-database "$owner" "$database" > /dev/null 2>&1
|
||||
|
||||
# Update counters
|
||||
$BIN/v-update-user-counters "$owner"
|
||||
$BIN/v-update-user-counters "$user"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Logging
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
69
bin/v-change-database-password
Executable file
69
bin/v-change-database-password
Executable file
@@ -0,0 +1,69 @@
|
||||
#!/bin/bash
|
||||
# info: change database password
|
||||
# options: USER DATABASE DBPASS
|
||||
#
|
||||
# example: v-change-database-password admin wp_db neW_pAssWorD
|
||||
#
|
||||
# This function for changing database user password to a database. It uses the
|
||||
# full name of database as argument.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
database=$2
|
||||
password=$3
|
||||
HIDE=3
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/db.sh
|
||||
source $HESTIA/func/db.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '3' "$#" 'USER DATABASE DBPASS'
|
||||
is_format_valid 'user' 'database'
|
||||
is_system_enabled "$DB_SYSTEM" 'DB_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'db' 'DB' "$database"
|
||||
is_object_unsuspended 'db' 'DB' "$database"
|
||||
is_password_valid
|
||||
dbpass="$password"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
# Get database values
|
||||
get_database_values
|
||||
|
||||
case $TYPE in
|
||||
mysql) change_mysql_password ;;
|
||||
pgsql) change_pgsql_password ;;
|
||||
esac
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Update config value
|
||||
update_object_value 'db' 'DB' "$database" '$MD5' "$md5"
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "Database" "Database password changed (Database: $database)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
109
bin/v-change-database-user
Executable file
109
bin/v-change-database-user
Executable file
@@ -0,0 +1,109 @@
|
||||
#!/bin/bash
|
||||
# info: change database username
|
||||
# options: USER DATABASE DBUSER [DBPASS]
|
||||
#
|
||||
# example: v-change-database-user admin my_db joe_user
|
||||
#
|
||||
# This function for changing database user. It uses the
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
database=$2
|
||||
dbuser="$user"_"$3"
|
||||
password=$4
|
||||
HIDE=4
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/db.sh
|
||||
source $HESTIA/func/db.sh
|
||||
# shellcheck source=/usr/local/hestia/func/rebuild.sh
|
||||
source $HESTIA/func/rebuild.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '3' "$#" 'USER DATABASE DBUSER [DBPASS]'
|
||||
is_format_valid 'user' 'database' 'dbuser'
|
||||
is_system_enabled "$DB_SYSTEM" 'DB_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'db' 'DB' "$database"
|
||||
is_object_new 'db' 'DBUSER' "$dbuser"
|
||||
is_object_unsuspended 'db' 'DB' "$database"
|
||||
is_password_valid
|
||||
dbpass="$password"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Compare old and new user
|
||||
old_dbuser=$(get_object_value 'db' 'DB' "$database" '$DBUSER')
|
||||
if [ "$old_dbuser" = "$dbuser" ]; then
|
||||
exit
|
||||
fi
|
||||
|
||||
# Set new dbuser
|
||||
update_object_value 'db' 'DB' "$database" '$DBUSER' "$dbuser"
|
||||
|
||||
# Get database values
|
||||
get_database_values
|
||||
|
||||
#Fix issue #1084 with "Upper case not allowed with PGSQL"
|
||||
if [ "$TYPE" = "pgsql" ]; then
|
||||
dbuser=$(echo $dbuser | tr '[:upper:]' '[:lower:]')
|
||||
exclude="-"
|
||||
if [[ "$dbuser" =~ $exclude ]]; then
|
||||
check_result "$E_INVALID" "invalid database user format"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Rebuild database
|
||||
case $TYPE in
|
||||
mysql) rebuild_mysql_database ;;
|
||||
pgsql) rebuild_pgsql_database ;;
|
||||
esac
|
||||
|
||||
# Change password
|
||||
if [ -n "$dbpass" ]; then
|
||||
case $TYPE in
|
||||
mysql) change_mysql_password ;;
|
||||
pgsql) change_pgsql_password ;;
|
||||
esac
|
||||
|
||||
# Update config value
|
||||
update_object_value 'db' 'DB' "$database" '$MD5' "$md5"
|
||||
fi
|
||||
|
||||
# Remove old user
|
||||
check_old_dbuser=$(grep "DBUSER='$old_dbuser'" $USER_DATA/db.conf)
|
||||
if [ -z "$check_old_dbuser" ]; then
|
||||
case $TYPE in
|
||||
mysql) delete_mysql_user ;;
|
||||
pgsql) delete_pgsql_user ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "Database" "Database user changed (Database: $database, User: $dbuser)"
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
107
bin/v-change-dns-domain-dnssec
Executable file
107
bin/v-change-dns-domain-dnssec
Executable file
@@ -0,0 +1,107 @@
|
||||
#!/bin/bash
|
||||
# info: change dns domain dnssec status
|
||||
# options: USER DOMAIN STATUS
|
||||
#
|
||||
# example: v-change-dns-domain-dnssec admin domain.pp.ua yes
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
domain_idn=$2
|
||||
status=$3
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/rebuild.sh
|
||||
source $HESTIA/func/rebuild.sh
|
||||
# shellcheck source=/usr/local/hestia/func/syshealth.sh
|
||||
source $HESTIA/func/syshealth.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# Additional argument formatting
|
||||
format_domain
|
||||
format_domain_idn
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '3' "$#" 'USER DOMAIN STATUS'
|
||||
is_format_valid 'user' 'domain' ''
|
||||
is_system_enabled "$DNS_SYSTEM" 'DNS_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'dns' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'dns' 'DOMAIN' "$domain"
|
||||
|
||||
if [ -n "$status" ]; then
|
||||
is_boolean_format_valid "$status" 'status'
|
||||
fi
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
if [ "$DNS_CLUSTER_SYSTEM" != 'hestia-zone' ]; then
|
||||
check_result "$E_DISABLED" "DNSSEC is not supported when DNS_CLUSTER_SYSTEM is not set to hestia-zone"
|
||||
fi
|
||||
|
||||
version=$(named -v | awk 'NR==1{print $2}')
|
||||
if version_ge '9.16.18' $version; then
|
||||
check_result "$E_DISABLED" "DNSSEC is not supported when bind / named version <= 9.16.18"
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
if [ -f "$HESTIA/data/queue/dns-cluster.pipe" ]; then
|
||||
bash $HESTIA/data/queue/dns-cluster.pipe
|
||||
fi
|
||||
|
||||
syshealth_repair_dns_config
|
||||
|
||||
# Changing exp
|
||||
update_object_value 'dns' 'DOMAIN' "$domain" '$DNSSEC' "$status"
|
||||
|
||||
# Update serial
|
||||
update_domain_serial
|
||||
# Rebuild DNS config
|
||||
rebuild_dns_domain_conf
|
||||
|
||||
if [ $status = "no" ]; then
|
||||
update_object_value 'dns' 'DOMAIN' "$domain" '$KEY' ""
|
||||
# Delete existing keys
|
||||
rm -fr $HOMEDIR/$user/conf/dns/$domain.db.*
|
||||
rm -fr /var/cache/bind/K$domain_idn.*
|
||||
rm -fr $USER_DATA/keys/K$domain_idn.*
|
||||
fi
|
||||
|
||||
# Updating dns-cluster queue
|
||||
if [ "$DNS_CLUSTER" = "yes" ]; then
|
||||
# Check for first sync
|
||||
dlock=$(grep "domain $user $domain" $HESTIA/data/queue/dns-cluster.pipe)
|
||||
if [ -z "$dlock" ]; then
|
||||
cmd="$BIN/v-add-remote-dns-domain $user $domain yes"
|
||||
echo "$cmd" >> $HESTIA/data/queue/dns-cluster.pipe
|
||||
fi
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "DNS" "Updated DNS SOA expiration date (Domain: $domain, Value: $exp)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
73
bin/v-change-dns-domain-exp
Executable file
73
bin/v-change-dns-domain-exp
Executable file
@@ -0,0 +1,73 @@
|
||||
#!/bin/bash
|
||||
# info: change dns domain expiration date
|
||||
# options: USER DOMAIN EXP
|
||||
#
|
||||
# example: v-change-dns-domain-exp admin domain.pp.ua 2020-11-20
|
||||
#
|
||||
# This function of changing the term of expiration domain's registration. The
|
||||
# serial number will be refreshed automatically during update.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
domain_idn=$2
|
||||
exp=$3
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# Additional argument formatting
|
||||
format_domain
|
||||
format_domain_idn
|
||||
# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ?
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '3' "$#" 'USER DOMAIN EXP'
|
||||
is_format_valid 'user' 'domain' 'exp'
|
||||
is_system_enabled "$DNS_SYSTEM" 'DNS_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'dns' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'dns' 'DOMAIN' "$domain"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Changing exp
|
||||
update_object_value 'dns' 'DOMAIN' "$domain" '$EXP' "$exp"
|
||||
|
||||
# Updating dns-cluster queue
|
||||
if [ "$DNS_CLUSTER" = "yes" ]; then
|
||||
# Check for first sync
|
||||
dlock=$(grep "domain $user $domain" $HESTIA/data/queue/dns-cluster.pipe)
|
||||
if [ -z "$dlock" ]; then
|
||||
cmd="$BIN/v-change-remote-dns-domain-exp $user $domain $exp"
|
||||
echo "$cmd" >> $HESTIA/data/queue/dns-cluster.pipe
|
||||
fi
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "DNS" "Updated DNS SOA expiration date (Domain: $domain, Value: $exp)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
95
bin/v-change-dns-domain-ip
Executable file
95
bin/v-change-dns-domain-ip
Executable file
@@ -0,0 +1,95 @@
|
||||
#!/bin/bash
|
||||
# info: change dns domain ip address
|
||||
# options: USER DOMAIN IP [RESTART]
|
||||
#
|
||||
# example: v-change-dns-domain-ip admin domain.com 123.212.111.222
|
||||
#
|
||||
# This function for changing the main ip of DNS zone.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
domain_idn=$2
|
||||
ip=$3
|
||||
restart=$4
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# shellcheck source=/usr/local/hestia/func/rebuild.sh
|
||||
source $HESTIA/func/rebuild.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# Additional argument formatting
|
||||
format_domain
|
||||
format_domain_idn
|
||||
# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ?
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '3' "$#" 'USER DOMAIN IP [RESTART]'
|
||||
is_format_valid 'user' 'domain' 'ip'
|
||||
is_system_enabled "$DNS_SYSTEM" 'DNS_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'dns' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'dns' 'DOMAIN' "$domain"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Get old ip
|
||||
get_domain_values 'dns'
|
||||
old=$IP
|
||||
|
||||
# Changing ip
|
||||
update_object_value 'dns' 'DOMAIN' "$domain" '$IP' "$ip"
|
||||
|
||||
# Changing records
|
||||
sed -i "s/$old/$ip/g" $USER_DATA/dns/$domain.conf
|
||||
|
||||
# Update serial
|
||||
update_domain_serial
|
||||
# Updating zone
|
||||
if [[ "$DNS_SYSTEM" =~ named|bind ]]; then
|
||||
rebuild_dns_domain_conf
|
||||
fi
|
||||
|
||||
# Updating dns-cluster queue
|
||||
if [ "$DNS_CLUSTER" = "yes" ]; then
|
||||
# Check for first sync
|
||||
dlock=$(grep "domain $user $domain" $HESTIA/data/queue/dns-cluster.pipe)
|
||||
if [ -z "$dlock" ]; then
|
||||
cmd="$BIN/v-add-remote-dns-domain $user $domain yes"
|
||||
echo "$cmd" >> $HESTIA/data/queue/dns-cluster.pipe
|
||||
fi
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Restarting named
|
||||
$BIN/v-restart-dns "$restart"
|
||||
check_result $? "DNS restart failed" > /dev/null
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "DNS" "IP address for DNS domain changed (IP: $ip, Domain: $domain)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
89
bin/v-change-dns-domain-soa
Executable file
89
bin/v-change-dns-domain-soa
Executable file
@@ -0,0 +1,89 @@
|
||||
#!/bin/bash
|
||||
# info: change dns domain soa record
|
||||
# options: USER DOMAIN SOA [RESTART]
|
||||
#
|
||||
# example: v-change-dns-domain-soa admin acme.com d.ns.domain.tld
|
||||
#
|
||||
# This function for changing SOA record. This type of records can not be
|
||||
# modified by v-change-dns-record call.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
domain_idn=$2
|
||||
soa=$(echo $3 | sed -e 's/\.*$//g' -e 's/^\.*//g')
|
||||
restart=$4
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# shellcheck source=/usr/local/hestia/func/rebuild.sh
|
||||
source $HESTIA/func/rebuild.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# Additional argument formatting
|
||||
format_domain
|
||||
format_domain_idn
|
||||
# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ?
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '3' "$#" 'USER DOMAIN SOA [RESTART]'
|
||||
is_format_valid 'user' 'domain' 'soa'
|
||||
is_system_enabled "$DNS_SYSTEM" 'DNS_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'dns' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'dns' 'DOMAIN' "$domain"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Changing soa
|
||||
update_object_value 'dns' 'DOMAIN' "$domain" '$SOA' "$soa"
|
||||
|
||||
# Update serial
|
||||
update_domain_serial
|
||||
# Updating zone
|
||||
if [[ "$DNS_SYSTEM" =~ named|bind ]]; then
|
||||
rebuild_dns_domain_conf
|
||||
fi
|
||||
|
||||
# Updating dns-cluster queue
|
||||
if [ "$DNS_CLUSTER" = "yes" ]; then
|
||||
# Check for first sync
|
||||
dlock=$(grep "domain $user $domain" $HESTIA/data/queue/dns-cluster.pipe)
|
||||
if [ -z "$dlock" ]; then
|
||||
cmd="$BIN/v-change-remote-dns-domain-soa $user $domain $soa"
|
||||
echo "$cmd" >> $HESTIA/data/queue/dns-cluster.pipe
|
||||
fi
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Restarting named
|
||||
$BIN/v-restart-dns "$restart"
|
||||
check_result $? "DNS restart failed" > /dev/null
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "DNS" "SOA record for DNS domain changed (SOA: $soa, Domain: $domain)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
172
bin/v-change-dns-domain-tpl
Executable file
172
bin/v-change-dns-domain-tpl
Executable file
@@ -0,0 +1,172 @@
|
||||
#!/bin/bash
|
||||
# info: change dns domain template
|
||||
# options: USER DOMAIN TEMPLATE [RESTART]
|
||||
#
|
||||
# example: v-change-dns-domain-tpl admin example.com child-ns yes
|
||||
#
|
||||
# This function for changing the template of records. By updating old records
|
||||
# will be removed and new records will be generated in accordance with
|
||||
# parameters of new template.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
domain_idn=$2
|
||||
template=$3
|
||||
restart=$4
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# shellcheck source=/usr/local/hestia/func/rebuild.sh
|
||||
source $HESTIA/func/rebuild.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# Additional argument formatting
|
||||
format_domain
|
||||
format_domain_idn
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '3' "$#" 'USER DOMAIN TEMPLATE [RESTART]'
|
||||
is_format_valid 'user' 'domain' 'template'
|
||||
is_system_enabled "$DNS_SYSTEM" 'DNS_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'dns' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'dns' 'DOMAIN' "$domain"
|
||||
is_dns_template_valid "$template"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Defining variables
|
||||
get_domain_values 'dns'
|
||||
i=1
|
||||
ns=$(get_user_value '$NS')
|
||||
for nameserver in ${ns//,/ }; do
|
||||
eval ns$i=$nameserver
|
||||
((++i))
|
||||
done
|
||||
|
||||
# Reading template
|
||||
template_data=$(cat "$DNSTPL/$template.tpl")
|
||||
|
||||
# Deleting unused nameservers
|
||||
if [ -z "$ns3" ]; then
|
||||
template_data=$(echo "$template_data" | grep -v %ns3%)
|
||||
fi
|
||||
if [ -z "$ns4" ]; then
|
||||
template_data=$(echo "$template_data" | grep -v %ns4%)
|
||||
fi
|
||||
if [ -z "$ns5" ]; then
|
||||
template_data=$(echo "$template_data" | grep -v %ns5%)
|
||||
fi
|
||||
if [ -z "$ns6" ]; then
|
||||
template_data=$(echo "$template_data" | grep -v %ns6%)
|
||||
fi
|
||||
if [ -z "$ns7" ]; then
|
||||
template_data=$(echo "$template_data" | grep -v %ns7%)
|
||||
fi
|
||||
if [ -z "$ns8" ]; then
|
||||
template_data=$(echo "$template_data" | grep -v %ns8%)
|
||||
fi
|
||||
|
||||
# Changing tpl
|
||||
echo "$template_data" \
|
||||
| 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/%ns5%/$ns5/g" \
|
||||
-e "s/%ns6%/$ns6/g" \
|
||||
-e "s/%ns7%/$ns7/g" \
|
||||
-e "s/%ns8%/$ns8/g" \
|
||||
-e "s/%time%/$TIME/g" \
|
||||
-e "s/%date%/$DATE/g" > $USER_DATA/dns/$domain.conf
|
||||
records="$(wc -l $USER_DATA/dns/$domain.conf | cut -f 1 -d ' ')"
|
||||
|
||||
# Refresh DKIM records in DNS if signing key exists for domain
|
||||
if [ "$template" = "default" ] || [ "$template" = "child-ns" ]; then
|
||||
if [ -n "$MAIL_SYSTEM" ] && [ -f "$HOMEDIR/$user/conf/mail/$domain/dkim.pem" ]; then
|
||||
check_dns_domain=$(is_object_valid 'dns' 'DOMAIN' "$domain")
|
||||
if [ "$?" -eq 0 ]; then
|
||||
p=$(cat "$USER_DATA/mail/$domain.pub" | grep -v ' KEY---' | tr -d '\n')
|
||||
record='_domainkey'
|
||||
policy="\"t=y; o=~;\""
|
||||
$BIN/v-add-dns-record "$user" "$domain" "$record" TXT "$policy" '' '' 'no'
|
||||
|
||||
record='mail._domainkey'
|
||||
selector="\"v=DKIM1\; k=rsa\; p=$p\""
|
||||
$BIN/v-add-dns-record "$user" "$domain" "$record" TXT "$selector"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Set correct domain name formatting for Office 365/Microsoft 365 MX records
|
||||
if [ "$template" = "office365" ]; then
|
||||
check_dns_domain=$(is_object_valid 'dns' 'DOMAIN' "$domain")
|
||||
if [ "$?" -eq 0 ]; then
|
||||
record='@'
|
||||
formatted_domain=$(echo "$domain" | sed 's/\./-/g')
|
||||
$BIN/v-add-dns-record "$user" "$domain" "$record" MX "${formatted_domain}.mail.protection.outlook.com." '0' '' "$restart"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Update serial
|
||||
update_domain_serial
|
||||
# Updating zone
|
||||
if [[ "$DNS_SYSTEM" =~ named|bind ]]; then
|
||||
rebuild_dns_domain_conf
|
||||
fi
|
||||
|
||||
# Updating dns-cluster queue
|
||||
if [ "$DNS_CLUSTER" = "yes" ]; then
|
||||
# Check for first sync
|
||||
dlock=$(grep "domain $user $domain" $HESTIA/data/queue/dns-cluster.pipe)
|
||||
if [ -z "$dlock" ]; then
|
||||
cmd="$BIN/v-add-remote-dns-domain $user $domain domain"
|
||||
echo "$cmd" >> $HESTIA/data/queue/dns-cluster.pipe
|
||||
fi
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Updating hestia config
|
||||
update_object_value 'dns' 'DOMAIN' "$domain" '$TPL' "$template"
|
||||
update_object_value 'dns' 'DOMAIN' "$domain" '$RECORDS' "$records"
|
||||
|
||||
# Rebuild DNS zone and update counters to ensure that it has updated correctly
|
||||
$BIN/v-rebuild-dns-domain "$user" "$domain" no
|
||||
$BIN/v-update-user-stats "$user"
|
||||
$BIN/v-update-user-counters "$user"
|
||||
|
||||
# Restarting named
|
||||
$BIN/v-restart-dns "$restart"
|
||||
check_result $? "DNS restart failed" > /dev/null
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "system" "Info" "DNS" "Template for DNS domain changed (Template: $template, Domain: $domain)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
88
bin/v-change-dns-domain-ttl
Executable file
88
bin/v-change-dns-domain-ttl
Executable file
@@ -0,0 +1,88 @@
|
||||
#!/bin/bash
|
||||
# info: change dns domain ttl
|
||||
# options: USER DOMAIN TTL [RESTART]
|
||||
#
|
||||
# example: v-change-dns-domain-ttl alice example.com 14400
|
||||
#
|
||||
# This function for changing the time to live TTL parameter for all records.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
domain_idn=$2
|
||||
ttl=$3
|
||||
restart=$4
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# shellcheck source=/usr/local/hestia/func/rebuild.sh
|
||||
source $HESTIA/func/rebuild.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# Additional argument formatting
|
||||
format_domain
|
||||
format_domain_idn
|
||||
# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ?
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '3' "$#" 'USER DOMAIN TTL [RESTART]'
|
||||
is_format_valid 'user' 'domain' 'ttl'
|
||||
is_system_enabled "$DNS_SYSTEM" 'DNS_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'dns' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'dns' 'DOMAIN' "$domain"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Changing ttl
|
||||
update_object_value 'dns' 'DOMAIN' "$domain" '$TTL' "$ttl"
|
||||
|
||||
# Update serial
|
||||
update_domain_serial
|
||||
# Updating zone
|
||||
if [[ "$DNS_SYSTEM" =~ named|bind ]]; then
|
||||
rebuild_dns_domain_conf
|
||||
fi
|
||||
|
||||
# Updating dns-cluster queue
|
||||
if [ "$DNS_CLUSTER" = "yes" ]; then
|
||||
# Check for first sync
|
||||
dlock=$(grep "domain $user $domain" $HESTIA/data/queue/dns-cluster.pipe)
|
||||
if [ -z "$dlock" ]; then
|
||||
cmd="$BIN/v-change-remote-dns-domain-ttl $user $domain $ttl"
|
||||
echo "$cmd" >> $HESTIA/data/queue/dns-cluster.pipe
|
||||
fi
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Restarting named
|
||||
$BIN/v-restart-dns "$restart"
|
||||
check_result $? "DNS restart failed" > /dev/null
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "DNS" "TTL for DNS domain changed (TTL: $ttl, Domain: $domain)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
168
bin/v-change-dns-record
Executable file
168
bin/v-change-dns-record
Executable file
@@ -0,0 +1,168 @@
|
||||
#!/bin/bash
|
||||
# info: change dns domain record
|
||||
# options: USER DOMAIN ID RECORD TYPE VALUE [PRIORITY] [RESTART] [TTL]
|
||||
#
|
||||
# example: v-change-dns-record admin domain.ua 42 192.18.22.43
|
||||
#
|
||||
# This function for changing DNS record.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
domain_idn=$2
|
||||
id=$3
|
||||
record=$4
|
||||
rtype=$5
|
||||
dvalue=$6
|
||||
priority=$7
|
||||
restart=$8
|
||||
ttl=$9
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# shellcheck source=/usr/local/hestia/func/rebuild.sh
|
||||
source $HESTIA/func/rebuild.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# Additional argument formatting
|
||||
format_domain
|
||||
format_domain_idn
|
||||
# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ?
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '6' "$#" 'USER DOMAIN ID RECORD TYPE VALUE [PRIORITY] [RESTART] [TTL]'
|
||||
is_format_valid 'user' 'domain' 'id' 'record'
|
||||
is_system_enabled "$DNS_SYSTEM" 'DNS_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'dns' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'dns' 'DOMAIN' "$domain"
|
||||
is_object_valid "dns/$domain" 'ID' "$id"
|
||||
is_format_valid 'ttl'
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
if [ "$record" = "@" ] && [ "$rtype" = "CNAME" ]; then
|
||||
check_result $E_INVALID "CNAME on root is not allowed"
|
||||
fi
|
||||
|
||||
# Make sure the variable for the optional parameter TTL is empty before parsing
|
||||
# We depend on that later on
|
||||
unset TTL
|
||||
|
||||
# Parsing domain config
|
||||
line=$(grep "ID='$id'" $USER_DATA/dns/$domain.conf)
|
||||
parse_object_kv_list "$line"
|
||||
|
||||
if [ -z "$rtype" ]; then
|
||||
rtype=$TYPE
|
||||
fi
|
||||
|
||||
if [ -z "$priority" ]; then
|
||||
priority=$PRIORITY
|
||||
fi
|
||||
|
||||
# Null priority for none MX/SRV records
|
||||
if [ "$rtype" != 'MX' ] && [ "$rtype" != 'SRV' ]; then
|
||||
priority=''
|
||||
fi
|
||||
|
||||
# Add trailing dot at the end of NS/CNAME/MX/PTR/SRV record
|
||||
if [[ $rtype =~ ^NS|CNAME|MX|PTR|SRV ]]; then
|
||||
trailing_dot=$(echo "$dvalue" | grep "\.$")
|
||||
if [ -z "$trailing_dot" ]; then
|
||||
dvalue="$dvalue."
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ $rtype =~ NS|CNAME|MX|PTR|SRV ]]; then
|
||||
dvalue=$(idn2 --quiet "$dvalue")
|
||||
record=$(idn2 --quiet "$record")
|
||||
fi
|
||||
|
||||
if [ "$rtype" != "CAA" ]; then
|
||||
dvalue=${dvalue//\"/}
|
||||
|
||||
if [ "$rtype" != 'SRV' ] && [[ "$dvalue" =~ [\;[:space:]] ]]; then
|
||||
dvalue='"'"$dvalue"'"'
|
||||
fi
|
||||
fi
|
||||
|
||||
#RTYPE wasn't checked make sure to do it now correctly
|
||||
is_format_valid 'user' 'domain' 'id' 'record' 'rtype' 'dvalue'
|
||||
|
||||
# Additional verifications
|
||||
is_dns_fqnd "$TYPE" "$dvalue"
|
||||
is_dns_nameserver_valid "$domain" "$TYPE" "$dvalue"
|
||||
|
||||
if [[ "$RECORD" == "$record" ]] && [[ "$TYPE" == "$rtype" ]] && [[ "$PRIORITY" -eq "$priority" ]] \
|
||||
&& [[ "$VALUE" == "$dvalue" ]] && [[ "$SUSPENDED" == 'no' ]] && [[ "$TTL" -eq "$ttl" ]]; then
|
||||
echo "No pending changes in DNS entry."
|
||||
exit "$E_EXISTS"
|
||||
fi
|
||||
|
||||
# Generating timestamp
|
||||
time_n_date=$(date +'%T %F')
|
||||
time=$(echo "$time_n_date" | cut -f 1 -d \ )
|
||||
date=$(echo "$time_n_date" | cut -f 2 -d \ )
|
||||
|
||||
# Adding record
|
||||
dns_rec="ID='$id' RECORD='$record' TYPE='$rtype' PRIORITY='$priority'"
|
||||
dns_rec="$dns_rec VALUE='$dvalue' SUSPENDED='no' TIME='$time' DATE='$date'"
|
||||
[ -n "$ttl" ] && dns_rec="$dns_rec TTL='$ttl'"
|
||||
# Deleting old record
|
||||
sed -i "/^ID='$id'/d" $USER_DATA/dns/$domain.conf
|
||||
# Add new entry
|
||||
echo "$dns_rec" >> $USER_DATA/dns/$domain.conf
|
||||
|
||||
# Sorting records
|
||||
sort_dns_records
|
||||
|
||||
# Update serial
|
||||
update_domain_serial
|
||||
# Updating zone
|
||||
if [[ "$DNS_SYSTEM" =~ named|bind ]]; then
|
||||
rebuild_dns_domain_conf
|
||||
fi
|
||||
|
||||
# Updating dns-cluster queue
|
||||
if [ "$DNS_CLUSTER" = "yes" ]; then
|
||||
# Check for first sync
|
||||
dlock=$(grep "domain $user $domain" $HESTIA/data/queue/dns-cluster.pipe)
|
||||
if [ -z "$dlock" ]; then
|
||||
cmd="$BIN/v-add-remote-dns-domain $user $domain records"
|
||||
echo "$cmd" >> $HESTIA/data/queue/dns-cluster.pipe
|
||||
fi
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Restarting named
|
||||
$BIN/v-restart-dns "$restart"
|
||||
check_result $? "DNS restart failed" > /dev/null
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "DNS" "DNS record value changed (Type: $rtype, Record: $record, Value: $dvalue, Domain: $domain)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
93
bin/v-change-dns-record-id
Executable file
93
bin/v-change-dns-record-id
Executable file
@@ -0,0 +1,93 @@
|
||||
#!/bin/bash
|
||||
# info: change dns domain record id
|
||||
# options: USER DOMAIN ID NEWID [RESTART]
|
||||
#
|
||||
# example: v-change-dns-record-id admin acme.com 24 42 yes
|
||||
#
|
||||
# This function for changing internal record id.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
domain_idn=$2
|
||||
id=$3
|
||||
newid=$4
|
||||
restart=$5
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# shellcheck source=/usr/local/hestia/func/rebuild.sh
|
||||
source $HESTIA/func/rebuild.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# Additional argument formatting
|
||||
format_domain
|
||||
format_domain_idn
|
||||
# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ?
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '4' "$#" 'USER DOMAIN ID NEWID [RESTART]'
|
||||
is_format_valid 'user' 'domain' 'id' 'newid'
|
||||
is_system_enabled "$DNS_SYSTEM" 'DNS_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'dns' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'dns' 'DOMAIN' "$domain"
|
||||
is_object_valid "dns/$domain" 'ID' "$id"
|
||||
is_object_new "dns/$domain" 'ID' "$newid"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Change id
|
||||
sed -i "s/^ID='$id'/ID='$newid'/" $USER_DATA/dns/$domain.conf
|
||||
|
||||
# Sorting records
|
||||
sort_dns_records
|
||||
|
||||
# Update serial
|
||||
update_domain_serial
|
||||
# Updating zone
|
||||
if [[ "$DNS_SYSTEM" =~ named|bind ]]; then
|
||||
rebuild_dns_domain_conf
|
||||
fi
|
||||
|
||||
# Updating dns-cluster queue
|
||||
if [ "$DNS_CLUSTER" = "yes" ]; then
|
||||
# Check for first sync
|
||||
dlock=$(grep "domain $user $domain" $HESTIA/data/queue/dns-cluster.pipe)
|
||||
if [ -z "$dlock" ]; then
|
||||
cmd="$BIN/v-add-remote-dns-domain $user $domain records"
|
||||
echo "$cmd" >> $HESTIA/data/queue/dns-cluster.pipe
|
||||
fi
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Restarting named
|
||||
$BIN/v-restart-dns "$restart"
|
||||
check_result $? "DNS restart failed" > /dev/null
|
||||
|
||||
# Logging
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
317
bin/v-change-domain-owner
Executable file
317
bin/v-change-domain-owner
Executable file
@@ -0,0 +1,317 @@
|
||||
#!/bin/bash
|
||||
# info: change domain owner
|
||||
# options: DOMAIN USER
|
||||
#
|
||||
# example: v-change-domain-owner www.example.com bob
|
||||
#
|
||||
# This function of changing domain ownership.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
domain=$1
|
||||
user=$2
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/ip.sh
|
||||
source $HESTIA/func/ip.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '2' "$#" 'DOMAIN USER'
|
||||
is_format_valid 'domain' 'user'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
owner=$($BIN/v-search-domain-owner "$domain")
|
||||
if [ -z "$owner" ]; then
|
||||
check_result "$E_NOTEXIST" "domain $domain doesn't exist"
|
||||
fi
|
||||
if [ "$owner" = "$user" ]; then
|
||||
echo "ERROR: $domain is already owned by $user."
|
||||
exit
|
||||
fi
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
echo "Moving $domain from $owner to $user, please wait..."
|
||||
|
||||
# WEB domain
|
||||
web_data=$(grep "DOMAIN='$domain'" $HESTIA/data/users/$owner/web.conf)
|
||||
if [ -n "$web_data" ]; then
|
||||
echo "[*] Moving web domain..."
|
||||
$BIN/v-suspend-web-domain "$owner" "$domain" >> /dev/null 2>&1
|
||||
parse_object_kv_list "$web_data"
|
||||
|
||||
if [ -n "$CUSTOM_DOCROOT" ]; then
|
||||
if [ -z $(echo $CUSTOM_DOCROOT | grep -i "/home/$owner/web/$domain") ]; then
|
||||
docdomain=$(echo "$CUSTOM_DOCROOT" | cut -d'/' -f5)
|
||||
$BIN/v-list-web-domain $user $docdomain > /dev/null
|
||||
if [ "$?" != 0 ]; then
|
||||
echo "Error: Target domain doesn't belong to the new user"
|
||||
exit $E_NOTEXIST
|
||||
fi
|
||||
new_docroot=$(echo $CUSTOM_DOCROOT | sed "s/\/home\/$owner/\/home\/$user/")
|
||||
new_php_docroot=$(echo $CUSTOM_PHPROOT | sed "s/\/home\/$owner/\/home\/$user/")
|
||||
|
||||
else
|
||||
new_docroot=$(echo $CUSTOM_DOCROOT | sed "s/\/home\/$owner/\/home\/$user/")
|
||||
new_php_docroot=$(echo $CUSTOM_PHPROOT | sed "s/\/home\/$owner/\/home\/$user/")
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$(echo $(get_user_ips) | grep $IP)" ]; then
|
||||
echo "[*] IP dedicated to $owner select new ip address..."
|
||||
get_user_ip
|
||||
fi
|
||||
old_ip=$IP
|
||||
new_ip=$ip
|
||||
echo $ip
|
||||
|
||||
# Change IP
|
||||
if [ -n "$ip" ]; then
|
||||
web_data=$(echo "$web_data" | sed "s/IP='$IP'/IP='$ip'/")
|
||||
fi
|
||||
if [ -n "$new_docroot" ]; then
|
||||
web_data=$(echo "$web_data" | sed "s|CUSTOM_DOCROOT='$CUSTOM_DOCROOT'|CUSTOM_DOCROOT='$new_docroot'|")
|
||||
web_data=$(echo "$web_data" | sed "s|CUSTOM_PHPROOT='$CUSTOM_PHPROOT'|CUSTOM_PHPROOT='$new_php_docroot'|")
|
||||
fi
|
||||
web_data=$(echo "$web_data" | sed "s/SUSPENDED='no'/SUSPENDED='yes'/")
|
||||
|
||||
# Check SSL
|
||||
if [ "$SSL" = 'yes' ]; then
|
||||
ssl_crt=$HESTIA/data/users/$owner/ssl/$domain.crt
|
||||
ssl_key=$HESTIA/data/users/$owner/ssl/$domain.key
|
||||
ssl_ca=$HESTIA/data/users/$owner/ssl/$domain.ca
|
||||
ssl_pem=$HESTIA/data/users/$owner/ssl/$domain.pem
|
||||
mv $ssl_crt $HESTIA/data/users/$user/ssl/
|
||||
mv $ssl_key $HESTIA/data/users/$user/ssl/
|
||||
mv $ssl_ca $HESTIA/data/users/$user/ssl/ >> /dev/null 2>&1
|
||||
mv $ssl_pem $HESTIA/data/users/$user/ssl/ >> /dev/null 2>&1
|
||||
rm -f $HOMEDIR/$owner/conf/web/ssl.$domain.*
|
||||
fi
|
||||
|
||||
# Check ftp user account
|
||||
if [ -n "$FTP_USER" ]; then
|
||||
/usr/sbin/userdel -f "$FTP_USER" >> /dev/null 2>&1
|
||||
old_str="FTP_USER='$FTP_USER'"
|
||||
new_str=$(echo "$old_str" | sed "s/${owner}_/${user}_/")
|
||||
web_data=$(echo "$web_data" | sed "s/$old_str/$new_str/")
|
||||
fi
|
||||
|
||||
# Move config
|
||||
sed -i "/DOMAIN='$domain'/d" $HESTIA/data/users/$owner/web.conf
|
||||
echo "$web_data" >> $HESTIA/data/users/$user/web.conf
|
||||
|
||||
# Move data
|
||||
mv $HOMEDIR/$owner/web/$domain $HOMEDIR/$user/web/
|
||||
|
||||
# Change ownership
|
||||
find "$HOMEDIR/$user/web/$domain" -user "$owner" \
|
||||
-exec chown -h $user:$user {} \;
|
||||
|
||||
# Rebuild config
|
||||
$BIN/v-unsuspend-web-domain "$user" "$domain" no >> /dev/null 2>&1
|
||||
$BIN/v-rebuild-web-domains "$owner" no
|
||||
$BIN/v-rebuild-web-domains "$user"
|
||||
|
||||
# Cleanup old config
|
||||
rm -rf "$HOMEDIR/$owner/conf/web/$domain/"
|
||||
fi
|
||||
|
||||
# DNS domain
|
||||
dns_data=$(grep "DOMAIN='$domain'" $HESTIA/data/users/$owner/dns.conf)
|
||||
if [ -n "$dns_data" ]; then
|
||||
echo "[*] Moving DNS zone and records..."
|
||||
parse_object_kv_list "$dns_data"
|
||||
|
||||
# Change IP
|
||||
if [ -n "$ip" ]; then
|
||||
dns_data=$(echo "$dns_data" | sed "s/IP='$IP'/IP='$ip'/")
|
||||
sed -i "s/$IP/$ip/g" $HESTIA/data/users/$owner/dns/$domain.conf
|
||||
fi
|
||||
|
||||
# Move config
|
||||
sed -i "/DOMAIN='$domain'/d" $HESTIA/data/users/$owner/dns.conf
|
||||
echo "$dns_data" >> $HESTIA/data/users/$user/dns.conf
|
||||
|
||||
# Move dns records
|
||||
mv $HESTIA/data/users/$owner/dns/$domain.conf \
|
||||
$HESTIA/data/users/$user/dns/
|
||||
|
||||
# Rebuild config
|
||||
$BIN/v-unsuspend-dns-domain "$user" "$domain" no >> /dev/null 2>&1
|
||||
$BIN/v-rebuild-dns-domains "$owner" no
|
||||
$BIN/v-rebuild-dns-domains "$user"
|
||||
|
||||
# Cleanup old config
|
||||
rm -f $HOMEDIR/$owner/conf/dns/$domain.db
|
||||
|
||||
# Resync dns cluster
|
||||
if [ "$DNS_CLUSTER" = "yes" ]; then
|
||||
$BIN/v-sync-dns-cluster
|
||||
fi
|
||||
fi
|
||||
|
||||
# MAIL domain
|
||||
mail_data=$(grep "DOMAIN='$domain'" $HESTIA/data/users/$owner/mail.conf)
|
||||
if [ -n "$mail_data" ]; then
|
||||
$BIN/v-suspend-mail-domain "$owner" "$domain" >> /dev/null 2>&1
|
||||
echo "[*] Moving mail domain and accounts..."
|
||||
|
||||
parse_object_kv_list "$mail_data"
|
||||
|
||||
# Ensure mail configuration directory exists for receiving user
|
||||
if [ ! -e "$HOMEDIR/$user/conf/mail/$domain/" ]; then
|
||||
mkdir -p $HOMEDIR/$user/conf/mail/$domain/
|
||||
fi
|
||||
|
||||
# Move config
|
||||
sed -i "/DOMAIN='$domain'/d" $HESTIA/data/users/$owner/mail.conf
|
||||
mail_data=$(echo "$mail_data" | sed "s/SUSPENDED='no'/SUSPENDED='yes'/")
|
||||
echo "$mail_data" >> $HESTIA/data/users/$user/mail.conf
|
||||
mv -f $HESTIA/data/users/$owner/mail/$domain.conf \
|
||||
$HESTIA/data/users/$user/mail/
|
||||
|
||||
# Move DKIM
|
||||
if [ -e "$HESTIA/data/users/$owner/mail/$domain.pem" ]; then
|
||||
mv -f $HESTIA/data/users/$owner/mail/$domain.pem \
|
||||
$HESTIA/data/users/$user/mail/
|
||||
mv -f $HESTIA/data/users/$owner/mail/$domain.pub \
|
||||
$HESTIA/data/users/$user/mail/
|
||||
fi
|
||||
|
||||
# Move SSL certificates
|
||||
if [ "$SSL" = 'yes' ]; then
|
||||
# Ensure that SSL directory exists and move certificates
|
||||
mkdir -p $HESTIA/data/users/$user/ssl/
|
||||
mkdir -p $HOMEDIR/$user/conf/mail/$domain/ssl/
|
||||
|
||||
ssl_crt=$HESTIA/data/users/$owner/ssl/mail.$domain.crt
|
||||
ssl_key=$HESTIA/data/users/$owner/ssl/mail.$domain.key
|
||||
ssl_ca=$HESTIA/data/users/$owner/ssl/mail.$domain.ca
|
||||
ssl_pem=$HESTIA/data/users/$owner/ssl/mail.$domain.pem
|
||||
mv $ssl_crt $HESTIA/data/users/$user/ssl/
|
||||
mv $ssl_key $HESTIA/data/users/$user/ssl/
|
||||
mv $ssl_ca $HESTIA/data/users/$user/ssl/ >> /dev/null 2>&1
|
||||
mv $ssl_pem $HESTIA/data/users/$user/ssl/ >> /dev/null 2>&1
|
||||
|
||||
# Add certificate to user home directory
|
||||
cp -f $HESTIA/data/users/$user/ssl/mail.$domain.crt $HOMEDIR/$user/conf/mail/$domain/ssl/$domain.crt
|
||||
cp -f $HESTIA/data/users/$user/ssl/mail.$domain.key $HOMEDIR/$user/conf/mail/$domain/ssl/$domain.key
|
||||
cp -f $HESTIA/data/users/$user/ssl/mail.$domain.pem $HOMEDIR/$user/conf/mail/$domain/ssl/$domain.pem
|
||||
if [ -e "$HESTIA/data/users/$user/ssl/mail.$domain.ca" ]; then
|
||||
cp -f $HESTIA/data/users/$user/ssl/mail.$domain.ca $HOMEDIR/$user/conf/mail/$domain/ssl/$domain.ca
|
||||
fi
|
||||
|
||||
# Add domain SSL configuration to dovecot
|
||||
if [ -f "/etc/dovecot/conf.d/domains/$domain.conf" ]; then
|
||||
rm -f /etc/dovecot/conf.d/domains/$domain.conf
|
||||
fi
|
||||
|
||||
echo "" >> /etc/dovecot/conf.d/domains/$domain.conf
|
||||
echo "local_name mail.$domain {" >> /etc/dovecot/conf.d/domains/$domain.conf
|
||||
echo " ssl_cert = <$HOMEDIR/$user/conf/mail/$domain/ssl/$domain.pem" >> /etc/dovecot/conf.d/domains/$domain.conf
|
||||
echo " ssl_key = <$HOMEDIR/$user/conf/mail/$domain/ssl/$domain.key" >> /etc/dovecot/conf.d/domains/$domain.conf
|
||||
echo "}" >> /etc/dovecot/conf.d/domains/$domain.conf
|
||||
|
||||
# Add domain SSL configuration to exim4
|
||||
# Cleanup symlinks
|
||||
find /usr/local/hestia/ssl/mail -xtype l -delete
|
||||
|
||||
ln -s -f $HOMEDIR/$user/conf/mail/$domain/ssl/$domain.pem /usr/local/hestia/ssl/mail/mail.$domain.crt
|
||||
ln -s -f $HOMEDIR/$user/conf/mail/$domain/ssl/$domain.key /usr/local/hestia/ssl/mail/mail.$domain.key
|
||||
|
||||
# Set correct permissions on certificates
|
||||
chmod 750 $HOMEDIR/$user/conf/mail/$domain/ssl
|
||||
chown -R $MAIL_USER:mail $HOMEDIR/$user/conf/mail/$domain/ssl
|
||||
chmod 0644 $HOMEDIR/$user/conf/mail/$domain/ssl/*
|
||||
chown -h $user:mail $HOMEDIR/$user/conf/mail/$domain/ssl/*
|
||||
chmod -R 0644 /usr/local/hestia/ssl/mail/*
|
||||
chown -h $user:mail /usr/local/hestia/ssl/mail/*
|
||||
fi
|
||||
|
||||
# Move data
|
||||
mv $HOMEDIR/$owner/mail/$domain $HOMEDIR/$user/mail/
|
||||
|
||||
# Change ownership
|
||||
find $HOMEDIR/$user/mail/$domain -user $owner \
|
||||
-exec chown -h $user {} \;
|
||||
|
||||
# Checking exim username for later chowning
|
||||
exim_user="exim"
|
||||
check_exim_username=$(grep -c '^Debian-exim:' /etc/passwd)
|
||||
if [ "$check_exim_username" -eq 1 ]; then
|
||||
exim_user="Debian-exim"
|
||||
fi
|
||||
# Chowning mail conf files to exim user
|
||||
if [ -d "$HOMEDIR/$user/conf/mail/$domain" ]; then
|
||||
find $HOMEDIR/$user/conf/mail/$domain -user root \
|
||||
-exec chown $exim_user {} \;
|
||||
fi
|
||||
|
||||
# Remove old mail directory from original owner
|
||||
if [ -e "$HOMEDIR/$owner/mail/$domain" ]; then
|
||||
rm -rf "$HOMEDIR/$owner/mail/$domain"
|
||||
fi
|
||||
|
||||
# Remove old mail configuration directory from original owner
|
||||
if [ -e "$HOMEDIR/$owner/conf/mail/$domain" ]; then
|
||||
rm -rf "$HOMEDIR/$owner/conf/mail/$domain"
|
||||
fi
|
||||
if [ -e "$HESTIA/data/users/$owner/mail/$domain.conf" ]; then
|
||||
rm -f "$HESTIA/data/users/$owner/mail/$domain.conf"
|
||||
fi
|
||||
|
||||
# Rebuild config
|
||||
$BIN/v-unsuspend-mail-domain "$user" "$domain" no
|
||||
$BIN/v-rebuild-mail-domains "$owner" no
|
||||
$BIN/v-rebuild-mail-domains "$user"
|
||||
fi
|
||||
|
||||
# Update counters
|
||||
$BIN/v-update-user-counters "$owner"
|
||||
$BIN/v-update-user-counters "$user"
|
||||
|
||||
# Mail domains currently don't have the IP variable set see #2306
|
||||
if [ -n "$old_ip" ]; then
|
||||
# Recalculate ip usage
|
||||
if [ -n "$ip" ]; then
|
||||
decrease_ip_value $old_ip $owner
|
||||
increase_ip_value $new_ip
|
||||
else
|
||||
# recalculate ip
|
||||
decrease_ip_value $old_ip $owner
|
||||
increase_ip_value $old_ip
|
||||
fi
|
||||
fi
|
||||
# Send notification to panel
|
||||
if [ -n "$web_data" ] || [ -n "$dns_data" ] || [ -n "$mail_data" ]; then
|
||||
$BIN/v-add-user-notification "$user" "$domain has been added to your account" ''
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "system" "Info" "System" "Domain moved between users (Domain: $domain, Old user: $owner, New User: $user)."
|
||||
$BIN/v-log-action "$user" "Info" "System" "New domain added to account (Domain: $domain)."
|
||||
$BIN/v-log-action "$owner" "Info" "System" "Domain removed from account (Domain: $domain)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
95
bin/v-change-firewall-rule
Executable file
95
bin/v-change-firewall-rule
Executable file
@@ -0,0 +1,95 @@
|
||||
#!/bin/bash
|
||||
# info: change firewall rule
|
||||
# options: RULE ACTION IP PORT [PROTOCOL] [COMMENT]
|
||||
#
|
||||
# example: v-change-firewall-rule 3 ACCEPT 5.188.123.17 443
|
||||
#
|
||||
# This function is used for changing existing firewall rule.
|
||||
# It fully replace rule with new one but keeps same id.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
rule=$1
|
||||
action=$(echo $2 | tr '[:lower:]' '[:upper:]')
|
||||
ip=$3
|
||||
port_ext=$4
|
||||
protocol=${5-TCP}
|
||||
protocol=$(echo $protocol | tr '[:lower:]' '[:upper:]')
|
||||
comment=$6
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# Sort function
|
||||
sort_fw_rules() {
|
||||
cat $HESTIA/data/firewall/rules.conf \
|
||||
| sort -n -k 2 -t \' > $HESTIA/data/firewall/rules.conf.tmp
|
||||
mv -f $HESTIA/data/firewall/rules.conf.tmp \
|
||||
$HESTIA/data/firewall/rules.conf
|
||||
}
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '4' "$#" 'RULE ACTION IP PORT [PROTOCOL] [COMMENT]'
|
||||
is_format_valid 'rule' 'action' 'protocol' 'port_ext'
|
||||
if [ ! -z "$comment" ]; then
|
||||
is_format_valid 'comment'
|
||||
fi
|
||||
is_system_enabled "$FIREWALL_SYSTEM" 'FIREWALL_SYSTEM'
|
||||
is_object_valid '../../data/firewall/rules' 'RULE' "$rule"
|
||||
|
||||
if [[ "$ip" =~ ^ipset: ]]; then
|
||||
ipset_name="${ip#ipset:}"
|
||||
$BIN/v-list-firewall-ipset plain | grep "^$ipset_name\s" > /dev/null
|
||||
check_result $? 'ipset object not found' "$E_NOTEXIST"
|
||||
else
|
||||
is_format_valid 'ip'
|
||||
fi
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Generating timestamp
|
||||
time_n_date=$(date +'%T %F')
|
||||
time=$(echo "$time_n_date" | cut -f 1 -d \ )
|
||||
date=$(echo "$time_n_date" | cut -f 2 -d \ )
|
||||
|
||||
# Concatenating firewall rule
|
||||
str="RULE='$rule' ACTION='$action' PROTOCOL='$protocol' PORT='$port_ext'"
|
||||
str="$str IP='$ip' COMMENT='$comment' SUSPENDED='no'"
|
||||
str="$str TIME='$time' DATE='$date'"
|
||||
|
||||
# Deleting old rule
|
||||
sed -i "/RULE='$rule' /d" $HESTIA/data/firewall/rules.conf
|
||||
|
||||
# Adding new
|
||||
echo "$str" >> $HESTIA/data/firewall/rules.conf
|
||||
|
||||
# Sorting firewall rules by id number
|
||||
sort_fw_rules
|
||||
|
||||
# Updating system firewall
|
||||
$BIN/v-update-firewall
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "system" "Info" "Firewall" "Firewall rule changed (Rule: $rule, Action: $action, Protocol: $protocol, Port: $port_ext)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
exit
|
||||
62
bin/v-change-fs-file-permission
Executable file
62
bin/v-change-fs-file-permission
Executable file
@@ -0,0 +1,62 @@
|
||||
#!/bin/bash
|
||||
# info: change file permission
|
||||
# options: USER FILE PERMISSIONS
|
||||
#
|
||||
# example: v-change-fs-file-permission admin readme.txt 0777
|
||||
#
|
||||
# This function changes file access permissions on the file system
|
||||
|
||||
user=$1
|
||||
src_file=$2
|
||||
permissions=$3
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '3' "$#" 'USER FILE PERMISSIONS'
|
||||
is_format_valid 'user'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
# Checking user homedir
|
||||
homedir=$(grep "^$user:" /etc/passwd | cut -f 6 -d :)
|
||||
if [ -z "$homedir" ]; then
|
||||
echo "Error: user home directory doesn't exist"
|
||||
exit 12
|
||||
fi
|
||||
|
||||
# Checking source file
|
||||
if [ ! -f "$src_file" ]; then
|
||||
echo "Error: source file doesn't exist $src_file"
|
||||
exit 3
|
||||
fi
|
||||
|
||||
# Checking source path
|
||||
rpath=$(readlink -f "$src_file")
|
||||
if [ -z "$(echo $rpath | egrep "^/tmp|^$homedir")" ]; then
|
||||
echo "Error: invalid source path $src_file"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# Changing file permissions
|
||||
user_exec chmod -R $permissions "$src_file" > /dev/null 2>&1
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Error: access permission on $src_file was not changed"
|
||||
exit 3
|
||||
fi
|
||||
|
||||
$BIN/v-log-action "system" "Info" "System" "File system permissions changed (User: $user, File: $src_file, Permissions: $permissions)."
|
||||
|
||||
# Exiting
|
||||
exit
|
||||
94
bin/v-change-mail-account-password
Executable file
94
bin/v-change-mail-account-password
Executable file
@@ -0,0 +1,94 @@
|
||||
#!/bin/bash
|
||||
# info: change mail account password
|
||||
# options: USER DOMAIN ACCOUNT PASSWORD
|
||||
#
|
||||
# example: v-change-mail-account-password admin mydomain.tld user p4$$vvOrD
|
||||
#
|
||||
# This function changes email account password.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
domain_idn=$2
|
||||
account=$3
|
||||
password=$4
|
||||
HIDE=4
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hest
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# Additional argument formatting
|
||||
format_domain
|
||||
format_domain_idn
|
||||
# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ?
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '4' "$#" 'USER DOMAIN ACCOUNT PASSWORD'
|
||||
is_format_valid 'user' 'domain' 'account'
|
||||
is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'mail' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'mail' 'DOMAIN' "$domain"
|
||||
is_object_valid "mail/$domain" 'ACCOUNT' "$account"
|
||||
is_object_unsuspended "mail/$domain" 'ACCOUNT' "$account"
|
||||
is_password_valid
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Generating hashed password
|
||||
if [ -n "$(doveadm pw -l | grep BLF-CRYPT)" ]; then
|
||||
set +H # disable ! style history substitution
|
||||
md5="$(doveadm pw -s BLF-CRYPT -p "$password")"
|
||||
elif [ -n "$(doveadm pw -l | grep ARGON2ID)" ]; then
|
||||
# Fall back on Argon2id if bcrypt is not available
|
||||
set +H # disable ! style history substitution
|
||||
md5="$(doveadm pw -s ARGON2ID -p "$password")"
|
||||
else
|
||||
# Fall back on MD5 if neither bcrypt nor argon2id is available
|
||||
salt=$(generate_password "$PW_MATRIX" "8")
|
||||
md5="{MD5}$($BIN/v-generate-password-hash md5 $salt <<< $password)"
|
||||
fi
|
||||
|
||||
if [[ "$MAIL_SYSTEM" =~ exim ]]; then
|
||||
quota=$(get_object_value "mail/$domain" 'ACCOUNT' "$account" '$QUOTA')
|
||||
if [ "$quota" = 'unlimited' ]; then
|
||||
quota=0
|
||||
fi
|
||||
sed -i "/^$account:/d" $HOMEDIR/$user/conf/mail/$domain/passwd
|
||||
str="$account:$md5:$user:mail::$HOMEDIR/$user:${quota}:userdb_quota_rule=*:storage=${quota}M"
|
||||
echo "$str" >> $HOMEDIR/$user/conf/mail/$domain/passwd
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Update md5
|
||||
update_object_value "mail/$domain" 'ACCOUNT' "$account" '$MD5' "$md5"
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "Mail" "Mail account password changed (Account: $account@$domain)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
84
bin/v-change-mail-account-quota
Executable file
84
bin/v-change-mail-account-quota
Executable file
@@ -0,0 +1,84 @@
|
||||
#!/bin/bash
|
||||
# info: change mail account quota
|
||||
# options: USER DOMAIN ACCOUNT QUOTA
|
||||
#
|
||||
# example: v-change-mail-account-quota admin mydomain.tld user01 unlimited
|
||||
#
|
||||
# This function changes email account disk quota.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
domain_idn=$2
|
||||
account=$3
|
||||
quota=$4
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# Additional argument formatting
|
||||
format_domain
|
||||
format_domain_idn
|
||||
# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ?
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '4' "$#" 'USER DOMAIN ACCOUNT QUOTA'
|
||||
is_format_valid 'user' 'domain' 'account'
|
||||
if [ "$quota" != 'unlimited' ]; then
|
||||
is_format_valid 'quota'
|
||||
fi
|
||||
is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'mail' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'mail' 'DOMAIN' "$domain"
|
||||
is_object_valid "mail/$domain" 'ACCOUNT' "$account"
|
||||
is_object_unsuspended "mail/$domain" 'ACCOUNT' "$account"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
md5=$(get_object_value "mail/$domain" 'ACCOUNT' "$account" '$MD5')
|
||||
if [[ "$MAIL_SYSTEM" =~ exim ]]; then
|
||||
if [ "$quota" = 'unlimited' ]; then
|
||||
quota=0
|
||||
fi
|
||||
sed -i "/^$account:/d" "$HOMEDIR/$user/conf/mail/$domain/passwd"
|
||||
str="$account:$md5:$user:mail::$HOMEDIR/$user:${quota}:userdb_quota_rule=*:storage=${quota}M"
|
||||
echo "$str" >> "$HOMEDIR/$user/conf/mail/$domain/passwd"
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
if [[ "$quota" -eq 0 ]]; then
|
||||
quota='unlimited'
|
||||
fi
|
||||
|
||||
# Update quota
|
||||
update_object_value "mail/$domain" 'ACCOUNT' "$account" '$QUOTA' "$quota"
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "Mail" "Mail account quota changed (Quota: $quota, Account: $account@$domain)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
96
bin/v-change-mail-account-rate-limit
Executable file
96
bin/v-change-mail-account-rate-limit
Executable file
@@ -0,0 +1,96 @@
|
||||
#!/bin/bash
|
||||
# info: change mail account rate limit
|
||||
# options: USER DOMAIN ACCOUNT RATE
|
||||
#
|
||||
# example: v-change-mail-account-rate-limit admin mydomain.tld user01 100
|
||||
#
|
||||
# This function changes email account rate limit. Use system to use domain or "server" setting
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
user=$1
|
||||
domain=$2
|
||||
domain_idn=$2
|
||||
account=$3
|
||||
rate=$4
|
||||
|
||||
# Includes
|
||||
# shellcheck source=/etc/hestiacp/hestia.conf
|
||||
source /etc/hestiacp/hestia.conf
|
||||
# shellcheck source=/usr/local/hestia/func/main.sh
|
||||
source $HESTIA/func/main.sh
|
||||
# shellcheck source=/usr/local/hestia/func/domain.sh
|
||||
source $HESTIA/func/domain.sh
|
||||
# shellcheck source=/usr/local/hestia/func/syshealth.sh
|
||||
source $HESTIA/func/syshealth.sh
|
||||
# load config file
|
||||
source_conf "$HESTIA/conf/hestia.conf"
|
||||
|
||||
# Additional argument formatting
|
||||
format_domain
|
||||
format_domain_idn
|
||||
# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ?
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Verifications #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
check_args '4' "$#" 'USER DOMAIN ACCOUNT RATE'
|
||||
is_format_valid 'user' 'domain' 'account'
|
||||
if [ "$rate" != 'system' ]; then
|
||||
is_format_valid 'rate'
|
||||
fi
|
||||
is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM'
|
||||
is_object_valid 'user' 'USER' "$user"
|
||||
is_object_unsuspended 'user' 'USER' "$user"
|
||||
is_object_valid 'mail' 'DOMAIN' "$domain"
|
||||
is_object_unsuspended 'mail' 'DOMAIN' "$domain"
|
||||
is_object_valid "mail/$domain" 'ACCOUNT' "$account"
|
||||
is_object_unsuspended "mail/$domain" 'ACCOUNT' "$account"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
md5=$(get_object_value "mail/$domain" 'ACCOUNT' "$account" '$MD5')
|
||||
if [[ "$MAIL_SYSTEM" =~ exim ]]; then
|
||||
if [ "$rate" = "system" ]; then
|
||||
user_rate_limit=$(get_object_value 'mail' 'DOMAIN' "$domain" '$RATE_LIMIT')
|
||||
if [ -n "$user_rate_limit" ]; then
|
||||
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
|
||||
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
|
||||
else
|
||||
sed -i "/^$account@$domain_idn:/ d" $HOMEDIR/$user/conf/mail/$domain/limits
|
||||
echo "$account@$domain_idn:$rate" >> $HOMEDIR/$user/conf/mail/$domain/limits
|
||||
fi
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
if [[ "$rate" = "system" ]]; then
|
||||
rate=''
|
||||
fi
|
||||
|
||||
syshealth_repair_mail_account_config
|
||||
|
||||
# Update quota
|
||||
update_object_value "mail/$domain" 'ACCOUNT' "$account" '$RATE_LIMIT' "$rate"
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "Mail" "Mail account rate limit changed (Rate: $rate, Account: $account@$domain)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
exit
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user