77# Credits: Maks Usmanov (skamasle), Jaap Marcus (jaapmarcus) and contributors:
88# Thanks to <https://github.com/Skamasle/sk_da_importer/graphs/contributors>
99
10- # This script is provided whitout any warranty
10+ # This script is provided without any warranty
1111# Run at your own risk
1212# Version 0.1
1313# This script restore backups from DA to Hestiacp
1414
1515# shellcheck source=/usr/local/hestia/func/main.sh
16- source $HESTIA /func/main.sh
16+ source " $HESTIA " /func/main.sh
1717# shellcheck source=/etc/hestiacp/hestia.conf
1818source /etc/hestiacp/hestia.conf
1919# load config file
2020source_conf " $HESTIA /conf/hestia.conf"
2121
22- # Check required binaries
2322if [ ! -e /usr/bin/rsync ] || [ ! -e /usr/bin/file ]; then
2423 echo " #######################################"
2524 echo " rsync not installed, try install it"
@@ -32,10 +31,11 @@ if [ ! -e /usr/bin/rsync ] || [ ! -e /usr/bin/file ]; then
3231 fi
3332 exit 3
3433fi
35-
3634# Put this to 0 if you want use bash -x to debug it
3735debug=1
3836hestia_package=default
37+ letsencrypt_enable=0
38+ addusertext=" IMPORTED"
3939tmp_dir=' tmp_dir_da_backup'
4040time=$( echo " $time_n_date " | cut -f 1 -d \ )
4141date=$( echo " $time_n_date " | cut -f 2 -d \ )
@@ -56,6 +56,12 @@ delete_tmp() {
5656 rm -rf /backup/${tmp_dir}
5757}
5858
59+ # URL decoding function
60+ urldecode () {
61+ local url_encoded=" ${1// +/ } "
62+ printf ' %b' " ${url_encoded//%/ \\ x} "
63+ }
64+
5965tput setaf 3
6066echo " #######################################"
6167echo " # START WITH IMPORT "
@@ -138,13 +144,13 @@ else
138144 exit 3
139145fi
140146
141- cd /backup/${tmp_dir} /
147+ cd /backup/${tmp_dir} / || exit
142148main_dir=$( pwd)
143149echo " Access tmp directory $main_dir "
144150directadmin_user=$( grep username backup/user.conf | cut -d " =" -f 2)
145151directadmin_usermail=$( grep email backup/user.conf | cut -d " =" -f 2 | grep @)
146152echo " Get User: $directadmin_user "
147- if [ -z $directadmin_usermail ]; then
153+ if [ -z " $directadmin_usermail " ]; then
148154 directadmin_usermail=$( grep domain backup/user.conf | cut -d " =" -f 2 | head -n 1)
149155fi
150156
156162
157163echo " Generate random password for $directadmin_user and create Hestiacp Account ..."
158164new_password=$( generate_password)
159- $BIN /v-add-user $directadmin_user $new_password $directadmin_usermail $hestia_package
165+ " $BIN " /v-add-user " $directadmin_user " " $new_password " " $directadmin_usermail " $hestia_package $addusertext
160166if [ " $? " -ne 0 ]; then
161167 tput setaf 1
162168 echo " Error: Unable to create user"
@@ -184,32 +190,33 @@ function run_da_db() {
184190 for da_db in $da_db_list ; do
185191
186192 database_name=${da_db::- 5}
187- grep -w $database_name server_dbs
193+ grep -w " $database_name " server_dbs
188194 if [ $? == " 1" ]; then
189195 if [ -e " backup/${database_name} .sql" ]; then
190196
191197 # Get the database name
192- db=$( grep db_collation backup/${da_db} | tr ' &' ' \n ' | grep SCHEMA_NAME | cut -d " =" -f 2)
198+ db=$( grep db_collation backup/" ${da_db} " | tr ' &' ' \n ' | grep SCHEMA_NAME | cut -d " =" -f 2)
193199
194200 tput setaf 2
195201 echo " Create and restore ${db} "
196202 tput sgr0
197203 mysql -e " CREATE DATABASE $db "
198- mysql ${db} < backup/${db} .sql
204+ mysql " ${db} " < backup/" ${db} " .sql
199205 # Get all the users of the database
200206 while IFS= read -r line; do
201207
202- selectdb_line=$( echo $line | grep passwd)
208+ selectdb_line=$( echo " $line " | grep passwd)
203209 if [ ! -z " $selectdb_line " ]; then
204210
205- db_user=$( echo $selectdb_line | tr ' &' ' \n ' | grep ${directadmin_user} | cut -d " =" -f 1)
206- md5=$( echo $selectdb_line | tr ' &' ' \n ' | grep passwd | cut -d " =" -f 2)
211+ db_user=$( echo " $selectdb_line " | tr ' &' ' \n ' | grep " ${directadmin_user} " | cut -d " =" -f 1)
212+ encoded_md5=$( echo " $selectdb_line " | tr ' &' ' \n ' | grep passwd | cut -d " =" -f 2)
213+ md5=$( urldecode " $encoded_md5 " )
207214
208215 echo " DB: $db "
209216 echo " udb: $db_user "
210217 echo " Password: ${md5} "
211218
212- echo " DB='$db ' DBUSER='$db_user ' MD5='$md5 ' HOST='localhost' TYPE='mysql' CHARSET='UTF8' U_DISK='0' SUSPENDED='no' TIME='$time ' DATE='$data '" >> /usr/local/hestia/data/users/$directadmin_user /db.conf
219+ echo " DB='$db ' DBUSER='$db_user ' MD5='$md5 ' HOST='localhost' TYPE='mysql' CHARSET='UTF8' U_DISK='0' SUSPENDED='no' TIME='$time ' DATE='$date '" >> /usr/local/hestia/data/users/" $directadmin_user " /db.conf
213220 fi
214221
215222 done < " backup/${da_db} "
@@ -218,11 +225,11 @@ function run_da_db() {
218225 tput setaf 2
219226 echo " Rebuild databases files for $directadmin_user "
220227 tput sgr0
221- $BIN /v-rebuild-databases $directadmin_user
228+ " $BIN " /v-rebuild-databases " $directadmin_user "
222229 fi
223230 else
224231 tput setaf 1
225- echo " Error: Cant restore database $db alredy exists in mysql server"
232+ echo " Error: Cant restore database $db already exists in mysql server"
226233 tput sgr0
227234 fi
228235 done
@@ -250,39 +257,39 @@ for directadmin_domain in $directadmin_domain_list; do
250257 tput setaf 2
251258 echo " Add $directadmin_domain if not exists"
252259 tput sgr0
253- $BIN /v-add-domain ${directadmin_user} $directadmin_domain
260+ " $BIN " /v-add-domain " ${directadmin_user} " " $directadmin_domain "
254261 if [ $? -ne 0 ]; then
255262 tput setaf 4
256263 echo " Domain $directadmin_domain already added in some account, skip..."
257264 tput sgr0
258- elif [ -d /home/${directadmin_user} /web/${directadmin_domain} ]; then
265+ elif [ -d /home/" ${directadmin_user} " /web/" ${directadmin_domain} " ]; then
259266 echo " Domain $directadmin_domain added, restoring files"
260- echo $directadmin_domain >> restored_domains
261- rm -f /home/$directadmin_user /web/$directadmin_domain /public_html/index.html
262- rm -f /home/$directadmin_user /web/$directadmin_domain /public_html/robots.txt
267+ echo " $directadmin_domain " >> restored_domains
268+ rm -f /home/" $directadmin_user " /web/" $directadmin_domain " /public_html/index.html
269+ rm -f /home/" $directadmin_user " /web/" $directadmin_domain " /public_html/robots.txt
263270
264271 public_sync_count=0
265- rsync -av domains/${directadmin_domain} /public_html/ /home/$directadmin_user /web/$directadmin_domain /public_html 2>&1 \
272+ rsync -av domains/" ${directadmin_domain} " /public_html/ /home/" $directadmin_user " /web/" $directadmin_domain " /public_html 2>&1 \
266273 | while read file_dm; do
267274 public_sync_count=$(( $public_sync_count + 1 ))
268275 echo -en " -- $public_sync_count restored files\r"
269276 done
270277
271- chown ${directadmin_user} : ${directadmin_user} -R /home/${directadmin_user} /web/${directadmin_domain} /public_html
272- chmod 751 /home/${directadmin_user} /web/${directadmin_domain} /public_html
278+ chown " ${directadmin_user} " : " ${directadmin_user} " -R /home/" ${directadmin_user} " /web/" ${directadmin_domain} " /public_html
279+ chmod 751 /home/" ${directadmin_user} " /web/" ${directadmin_domain} " /public_html
273280
274281 if [[ -L " domains/${directadmin_domain} /private_html" && -d " domains/${directadmin_domain} /private_html" ]]; then
275282 echo " private_html is a symlink to public_html so we don't need to copy it."
276283 else
277284 private_sync_count=0
278285
279- rsync -av domains/${directadmin_domain} /private_html/ /home/$directadmin_user /web/$directadmin_domain /private 2>&1 \
286+ rsync -av domains/" ${directadmin_domain} " /private_html/ /home/" $directadmin_user " /web/" $directadmin_domain " /private 2>&1 \
280287 | while read file_dm; do
281288 private_sync_count=$(( $private_sync_count + 1 ))
282289 echo -en " -- $private_sync_count restored files\r"
283290 done
284- chown ${directadmin_user} : ${directadmin_user} -R /home/${directadmin_user} /web/${directadmin_domain} /private
285- chmod 751 /home/${directadmin_user} /web/${directadmin_domain} /private
291+ chown " ${directadmin_user} " : " ${directadmin_user} " -R /home/" ${directadmin_user} " /web/" ${directadmin_domain} " /private
292+ chmod 751 /home/" ${directadmin_user} " /web/" ${directadmin_domain} " /private
286293 fi
287294 else
288295 echo " Ups.. cant restore or add domain: $directadmin_domain "
@@ -300,41 +307,145 @@ echo "Start restoring mails"
300307tput sgr0
301308function da_restore_imap_pass() {
302309 # DirectAdmin passw is SHA512-CRYPT
303- da_orig_pass=$( grep -w $1 backup/$2 /email/passwd | tr ' :' ' ' | cut -d " " -f2)
304- echo ${da_orig_pass}
310+ da_orig_pass=$( grep -w " $1 " backup/" $2 " /email/passwd | tr ' :' ' ' | cut -d " " -f2)
311+ echo " ${da_orig_pass} "
305312 USER_DATA=$HESTIA /data/users/${3} /
306313 update_object_value " mail/${2} " ' ACCOUNT' " ${1} " ' $MD5' " {SHA512-CRYPT}$da_orig_pass "
307314 echo " Password for $1 @$2 restored"
308315}
309316echo cat restored_domains
310317if [ -e restored_domains ]; then
311318 cat restored_domains | while read da_mail_domain; do
312- if [ " $( ls -A imap/${da_mail_domain} /) " ]; then
319+ if [ " $( ls -A imap/" ${da_mail_domain} " /) " ]; then
313320 tput setaf 2
314321 echo " Found Imap for ${da_mail_domain} "
315322 tput sgr0
316- ls -1 imap/${da_mail_domain} / | while read da_imap; do
323+ ls -1 imap/" ${da_mail_domain} " / | while read da_imap; do
317324 tmp_pass=$( generate_password)
318- $BIN /v-add-mail-account $directadmin_user $da_mail_domain $da_imap tmp_pass
325+ " $BIN " /v-add-mail-account " $directadmin_user " " $da_mail_domain " " $da_imap " " $ tmp_pass"
319326 if [ " $debug " != 0 ]; then
320- rsync -av imap/${da_mail_domain} / ${da_imap} /Maildir/ /home/${directadmin_user} /mail/${da_mail_domain} / ${da_imap} 2>&1 \
327+ rsync -av imap/" ${da_mail_domain} " / " ${da_imap} " /Maildir/ /home/" ${directadmin_user} " /mail/" ${da_mail_domain} " / " ${da_imap} " 2>&1 \
321328 | while read backup_file_dm; do
322329 sk_sync=$(( sk_sync + 1 ))
323330 echo -en " -- $sk_sync restored files\r"
324331 done
325332 echo " "
326333 else
327- rsync imap/${da_mail_domain} / ${da_imap} /Maildir/ /home/${directadmin_user} /mail/${da_mail_domain} / ${da_imap}
334+ rsync imap/" ${da_mail_domain} " / " ${da_imap} " /Maildir/ /home/" ${directadmin_user} " /mail/" ${da_mail_domain} " / " ${da_imap} "
328335 fi
329- chown ${directadmin_user} :mail -R /home/${directadmin_user} /mail/${da_mail_domain} / ${da_imap}
330- find /home/$directadmin_user /mail/$da_mail_domain -type f -name ' dovecot*' -delete
331- da_restore_imap_pass $da_imap $da_mail_domain $directadmin_user
336+ chown " ${directadmin_user} " :mail -R /home/" ${directadmin_user} " /mail/" ${da_mail_domain} " / " ${da_imap} "
337+ find /home/" $directadmin_user " /mail/" $da_mail_domain " -type f -name ' dovecot*' -delete
338+ da_restore_imap_pass " $da_imap " " $da_mail_domain " " $directadmin_user "
332339 done
333340
334- $BIN /v-rebuild-mail-domain $directadmin_user $da_mail_domain
341+ " $BIN " /v-rebuild-mail-domain " $directadmin_user " " $da_mail_domain "
335342 fi
336343 done
337344fi
345+
346+ tput setaf 3
347+ echo " #######################################"
348+ echo " # CRON JOBS "
349+ echo " #######################################"
350+ tput sgr0
351+
352+ # Restore cron jobs
353+ if [ -f " backup/crontab.conf" ]; then
354+ while IFS= read -r cron_line; do
355+ # Skip empty lines and comments
356+ [[ -z " $cron_line " || " $cron_line " =~ ^# .*$ ]] && continue
357+
358+ # Check if the line is an environment variable
359+ if [[ " $cron_line " =~ ^[A-Z]+= ]]; then
360+ # Export environment variable
361+ # echo "Setting environment variable: $cron_line"
362+ export " $cron_line "
363+ continue
364+ fi
365+
366+ # Remove the cron job identifier and extract cron job details
367+ if [[ " $cron_line " =~ ^[0-9]+= ]]; then
368+ cron_line=${cron_line#* =}
369+ fi
370+
371+ # Extract cron job details (handle cases where command contains spaces)
372+ IFS= ' ' read -r min hour day month wday command <<< " $cron_line "
373+
374+ # Ensure it is a valid cron job line (i.e., min, hour, day, month, wday should be numeric or valid cron symbols)
375+ if ! [[ " $min " =~ ^[\* 0-9,-/]+$ && " $hour " =~ ^[\* 0-9,-/]+$ && " $day " =~ ^[\* 0-9,-/]+$ && " $month " =~ ^[\* 0-9,-/]+$ && " $wday " =~ ^[\* 0-9,-/]+$ ]]; then
376+ echo " Invalid cron job format: $cron_line "
377+ continue
378+ fi
379+
380+ # Reconstruct the command part
381+ command= " ${cron_line# " ${min} " " ${hour} " " ${day} " " ${month} " " ${wday} " } "
382+
383+ echo " Adding cron job for user $directadmin_user : $cron_line "
384+ " $BIN " /v-add-cron-job " $directadmin_user " " $min " " $hour " " $day " " $month " " $wday " " $command "
385+ done < " backup/crontab.conf"
386+ else
387+ echo " No cron jobs found to restore."
388+ fi
389+
390+ tput setaf 3
391+ echo " #######################################"
392+ echo " # DOMAIN ALIASES "
393+ echo " #######################################"
394+ tput sgr0
395+
396+ # Restore domain aliases
397+ domain_base_dir= " backup"
398+
399+ if [ -d " $domain_base_dir " ]; then
400+ for domain_subdir in " $domain_base_dir " /* /; do
401+ domain_pointers_file=" $domain_subdir /domain.pointers"
402+ if [ -f " $domain_pointers_file " ]; then
403+ while IFS= read -r pointer_line; do
404+ # Skip empty lines and comments
405+ [[ -z " $pointer_line " || " $pointer_line " =~ ^# .*$ ]] && continue
406+
407+ # Extract alias and type
408+ alias_domain= $( echo " $pointer_line " | cut -d' =' -f1)
409+ alias_type= $( echo " $pointer_line " | awk -F' type=' ' {print $2}' )
410+
411+ if [[ " $alias_type " == " alias" || " $alias_type " == " pointer" ]]; then
412+ domain_name=$( basename " $domain_subdir " )
413+ echo " Adding domain alias $alias_domain for user $directadmin_user on domain $domain_name "
414+ " $BIN " /v-add-web-domain-alias " $directadmin_user " " $domain_name " " $alias_domain " no
415+ else
416+ echo " Skipping non-alias type for $alias_domain : $alias_type "
417+ fi
418+ done < " $domain_pointers_file "
419+ fi
420+ done
421+ else
422+ echo " No domain directories found to restore."
423+ fi
424+
425+ tput setaf 3
426+ echo " #######################################"
427+ echo " # ENABLE LETSENCRYPT "
428+ echo " #######################################"
429+ tput sgr0
430+
431+ # Enable Let's Encrypt for each domain
432+ if [ " $letsencrypt_enable " = 1 ]; then
433+ for directadmin_domain in $directadmin_domain_list ; do
434+ echo " Enabling Let's Encrypt for $directadmin_domain "
435+ letsencrypt_output=$( " $BIN " /v-add-letsencrypt-domain " $directadmin_user " " $directadmin_domain " ' ' yes 2>&1 )
436+ echo " $letsencrypt_output "
437+ if echo " $letsencrypt_output " | grep -q " Error: mail domain" ; then
438+ echo " Error with Let's Encrypt: $letsencrypt_output "
439+ echo " Retrying Let's Encrypt without mail domain for $directadmin_domain "
440+ " $BIN " /v-add-letsencrypt-domain " $directadmin_user " " $directadmin_domain " ' ' no
441+ else
442+ echo " Let's Encrypt enabled for $directadmin_domain "
443+ fi
444+ done
445+ else
446+ echo " Let's Encrypt is not enabled for any domain."
447+ fi
448+
338449delete_tmp
339450tput sgr0
340451tput setaf 2
0 commit comments