hst-install-debian.sh 81 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296
  1. #!/bin/bash
  2. # ======================================================== #
  3. #
  4. # Hestia Control Panel Installer for Debian
  5. # https://www.hestiacp.com/
  6. #
  7. # Currently Supported Versions:
  8. # Debian 10, 11
  9. #
  10. # ======================================================== #
  11. #----------------------------------------------------------#
  12. # Variables&Functions #
  13. #----------------------------------------------------------#
  14. export PATH=$PATH:/sbin
  15. export DEBIAN_FRONTEND=noninteractive
  16. RHOST='apt.hestiacp.com'
  17. GPG='gpg.hestiacp.com'
  18. VERSION='debian'
  19. HESTIA='/usr/local/hestia'
  20. LOG="/root/hst_install_backups/hst_install-$(date +%d%m%Y%H%M).log"
  21. memory=$(grep 'MemTotal' /proc/meminfo | tr ' ' '\n' | grep [0-9])
  22. hst_backups="/root/hst_install_backups/$(date +%d%m%Y%H%M)"
  23. spinner="/-\|"
  24. os='debian'
  25. release="$(cat /etc/debian_version | tr "." "\n" | head -n1)"
  26. codename="$(cat /etc/os-release | grep VERSION= | cut -f 2 -d \( | cut -f 1 -d \))"
  27. architecture="$(arch)"
  28. HESTIA_INSTALL_DIR="$HESTIA/install/deb"
  29. HESTIA_COMMON_DIR="$HESTIA/install/common"
  30. VERBOSE='no'
  31. # Define software versions
  32. HESTIA_INSTALL_VER='1.8.0~alpha'
  33. # Dependencies
  34. multiphp_v=("5.6" "7.0" "7.1" "7.2" "7.3" "7.4" "8.0" "8.1" "8.2")
  35. fpm_v="8.1"
  36. mariadb_v="10.11"
  37. # Defining software pack for all distros
  38. software="acl apache2 apache2-suexec-custom apache2-suexec-pristine apache2-utils awstats bc bind9 bsdmainutils bsdutils
  39. clamav-daemon cron curl dnsutils dovecot-imapd dovecot-managesieved dovecot-pop3d dovecot-sieve e2fslibs e2fsprogs
  40. exim4 exim4-daemon-heavy expect fail2ban flex ftp git hestia=${HESTIA_INSTALL_VER} hestia-nginx hestia-php idn2
  41. imagemagick ipset jq libapache2-mod-fcgid libapache2-mod-php$fpm_v libapache2-mpm-itk libmail-dkim-perl lsb-release
  42. lsof mariadb-client mariadb-common mariadb-server mc mysql-client mysql-common mysql-server net-tools nginx openssh-server
  43. php$fpm_v php$fpm_v-apcu php$fpm_v-bz2 php$fpm_v-cgi php$fpm_v-cli php$fpm_v-common php$fpm_v-curl php$fpm_v-gd
  44. php$fpm_v-imagick php$fpm_v-imap php$fpm_v-intl php$fpm_v-ldap php$fpm_v-mbstring php$fpm_v-mysql php$fpm_v-opcache
  45. php$fpm_v-pgsql php$fpm_v-pspell php$fpm_v-readline php$fpm_v-xml php$fpm_v-zip postgresql postgresql-contrib
  46. proftpd-basic quota rrdtool rsyslog spamassassin sudo sysstat unrar-free unzip util-linux vim-common vsftpd whois zip zstd"
  47. installer_dependencies="apt-transport-https ca-certificates curl dirmngr gnupg openssl wget"
  48. # Defining help function
  49. help() {
  50. echo "Usage: $0 [OPTIONS]
  51. -a, --apache Install Apache [yes|no] default: yes
  52. -w, --phpfpm Install PHP-FPM [yes|no] default: yes
  53. -o, --multiphp Install Multi-PHP [yes|no] default: no
  54. -v, --vsftpd Install Vsftpd [yes|no] default: yes
  55. -j, --proftpd Install ProFTPD [yes|no] default: no
  56. -k, --named Install Bind [yes|no] default: yes
  57. -m, --mysql Install MariaDB [yes|no] default: yes
  58. -M, --mysql8 Install MySQL [yes|no] default: no
  59. -g, --postgresql Install PostgreSQL [yes|no] default: no
  60. -x, --exim Install Exim [yes|no] default: yes
  61. -z, --dovecot Install Dovecot [yes|no] default: yes
  62. -Z, --sieve Install Sieve [yes|no] default: no
  63. -c, --clamav Install ClamAV [yes|no] default: yes
  64. -t, --spamassassin Install SpamAssassin [yes|no] default: yes
  65. -i, --iptables Install Iptables [yes|no] default: yes
  66. -b, --fail2ban Install Fail2ban [yes|no] default: yes
  67. -q, --quota Filesystem Quota [yes|no] default: no
  68. -d, --api Activate API [yes|no] default: yes
  69. -r, --port Change Backend Port default: 8083
  70. -l, --lang Default language default: en
  71. -y, --interactive Interactive install [yes|no] default: yes
  72. -6, --ipv6 Enable IPv6 Support [yes|no] default: no
  73. -s, --hostname Set hostname
  74. -e, --email Set admin email
  75. -p, --password Set admin password
  76. -D, --with-debs Path to Hestia debs
  77. -f, --force Force installation
  78. -O, --override Override checks (dangerous!)
  79. -h, --help Print this help
  80. Example: bash $0 -e demo@hestiacp.com -p p4ssw0rd --multiphp yes"
  81. exit 1
  82. }
  83. # Defining file download function
  84. download_file() {
  85. wget $1 -q --show-progress --progress=bar:force
  86. }
  87. # Defining password-gen function
  88. gen_pass() {
  89. matrix=$1
  90. length=$2
  91. if [ -z "$matrix" ]; then
  92. matrix="A-Za-z0-9"
  93. fi
  94. if [ -z "$length" ]; then
  95. length=16
  96. fi
  97. head /dev/urandom | tr -dc $matrix | head -c$length
  98. }
  99. # Defining return code check function
  100. check_result() {
  101. if [ $1 -ne 0 ]; then
  102. echo "Error: $2"
  103. exit $1
  104. fi
  105. }
  106. # Defining function to set default value
  107. set_default_value() {
  108. eval variable=\$$1
  109. if [ -z "$variable" ]; then
  110. eval $1=$2
  111. fi
  112. if [ "$variable" != 'yes' ] && [ "$variable" != 'no' ]; then
  113. eval $1=$2
  114. fi
  115. }
  116. # Defining function to set default language value
  117. set_default_lang() {
  118. if [ -z "$lang" ]; then
  119. eval lang=$1
  120. fi
  121. lang_list="ar az bg bn bs ckb cs da de el en es fa fi fr hr hu id it ja ka ko nl no pl pt pt-br ro ru sk sr sv th tr uk ur vi zh-cn zh-tw"
  122. if ! (echo $lang_list | grep -w $lang > /dev/null 2>&1); then
  123. eval lang=$1
  124. fi
  125. }
  126. # Define the default backend port
  127. set_default_port() {
  128. if [ -z "$port" ]; then
  129. eval port=$1
  130. fi
  131. }
  132. # Write configuration KEY/VALUE pair to $HESTIA/conf/hestia.conf
  133. write_config_value() {
  134. local key="$1"
  135. local value="$2"
  136. echo "$key='$value'" >> ${HESTIA}/conf/hestia.conf
  137. }
  138. # Sort configuration file values
  139. # Write final copy to $HESTIA/conf/hestia.conf for active usage
  140. # Duplicate file to $HESTIA/conf/defaults/hestia.conf to restore known good installation values
  141. sort_config_file() {
  142. sort ${HESTIA}/conf/hestia.conf -o /tmp/updconf
  143. mv ${HESTIA}/conf/hestia.conf ${HESTIA}/conf/hestia.conf.bak
  144. mv /tmp/updconf ${HESTIA}/conf/hestia.conf
  145. rm -f ${HESTIA}/conf/hestia.conf.bak
  146. if [ ! -d "$HESTIA/conf/defaults/" ]; then
  147. mkdir -p "${HESTIA}/conf/defaults/"
  148. fi
  149. cp ${HESTIA}/conf/hestia.conf ${HESTIA}/conf/defaults/hestia.conf
  150. }
  151. # Validate hostname according to RFC1178
  152. validate_hostname() {
  153. # remove extra .
  154. servername=$(echo "$servername" | sed -e "s/[.]*$//g")
  155. servername=$(echo "$servername" | sed -e "s/^[.]*//")
  156. if [[ $(echo "$servername" | grep -o "\." | wc -l) -gt 1 ]] && [[ ! $servername =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
  157. # Hostname valid
  158. return 1
  159. else
  160. # Hostname invalid
  161. return 0
  162. fi
  163. }
  164. validate_email() {
  165. if [[ ! "$email" =~ ^[A-Za-z0-9._%+-]+@[[:alnum:].-]+\.[A-Za-z]{2,63}$ ]]; then
  166. # Email invalid
  167. return 0
  168. else
  169. # Email valid
  170. return 1
  171. fi
  172. }
  173. #----------------------------------------------------------#
  174. # Verifications #
  175. #----------------------------------------------------------#
  176. # Creating temporary file
  177. tmpfile=$(mktemp -p /tmp)
  178. # Translating argument to --gnu-long-options
  179. for arg; do
  180. delim=""
  181. case "$arg" in
  182. --apache) args="${args}-a " ;;
  183. --phpfpm) args="${args}-w " ;;
  184. --vsftpd) args="${args}-v " ;;
  185. --proftpd) args="${args}-j " ;;
  186. --named) args="${args}-k " ;;
  187. --mysql) args="${args}-m " ;;
  188. --mariadb) args="${args}-m " ;;
  189. --mysql-classic) args="${args}-M " ;;
  190. --mysql8) args="${args}-M " ;;
  191. --postgresql) args="${args}-g " ;;
  192. --exim) args="${args}-x " ;;
  193. --dovecot) args="${args}-z " ;;
  194. --sieve) args="${args}-Z " ;;
  195. --clamav) args="${args}-c " ;;
  196. --spamassassin) args="${args}-t " ;;
  197. --iptables) args="${args}-i " ;;
  198. --fail2ban) args="${args}-b " ;;
  199. --multiphp) args="${args}-o " ;;
  200. --quota) args="${args}-q " ;;
  201. --port) args="${args}-r " ;;
  202. --lang) args="${args}-l " ;;
  203. --interactive) args="${args}-y " ;;
  204. --ipv6) args="${args}-6 " ;;
  205. --api) args="${args}-d " ;;
  206. --hostname) args="${args}-s " ;;
  207. --email) args="${args}-e " ;;
  208. --password) args="${args}-p " ;;
  209. --force) args="${args}-f " ;;
  210. --override) args="${args}-O " ;;
  211. --with-debs) args="${args}-D " ;;
  212. --help) args="${args}-h " ;;
  213. *)
  214. [[ "${arg:0:1}" == "-" ]] || delim="\""
  215. args="${args}${delim}${arg}${delim} "
  216. ;;
  217. esac
  218. done
  219. eval set -- "$args"
  220. # Parsing arguments
  221. while getopts "a:w:v:j:k:m:M:g:d:x:z:Z:c:t:i:b:r:o:q:l:y:6:s:e:p:D:fOh" Option; do
  222. case $Option in
  223. a) apache=$OPTARG ;; # Apache
  224. w) phpfpm=$OPTARG ;; # PHP-FPM
  225. o) multiphp=$OPTARG ;; # Multi-PHP
  226. v) vsftpd=$OPTARG ;; # Vsftpd
  227. j) proftpd=$OPTARG ;; # Proftpd
  228. k) named=$OPTARG ;; # Named
  229. m) mysql=$OPTARG ;; # MariaDB
  230. M) mysql8=$OPTARG ;; # MySQL
  231. g) postgresql=$OPTARG ;; # PostgreSQL
  232. x) exim=$OPTARG ;; # Exim
  233. z) dovecot=$OPTARG ;; # Dovecot
  234. Z) sieve=$OPTARG ;; # Sieve
  235. c) clamd=$OPTARG ;; # ClamAV
  236. t) spamd=$OPTARG ;; # SpamAssassin
  237. i) iptables=$OPTARG ;; # Iptables
  238. b) fail2ban=$OPTARG ;; # Fail2ban
  239. q) quota=$OPTARG ;; # FS Quota
  240. r) port=$OPTARG ;; # Backend Port
  241. l) lang=$OPTARG ;; # Language
  242. d) api=$OPTARG ;; # Activate API
  243. y) interactive=$OPTARG ;; # Interactive install
  244. 6) ipv6_support=$OPTARG ;; # IPv6
  245. s) servername=$OPTARG ;; # Hostname
  246. e) email=$OPTARG ;; # Admin email
  247. p) vpass=$OPTARG ;; # Admin password
  248. D) withdebs=$OPTARG ;; # Hestia debs path
  249. f) force='yes' ;; # Force install
  250. O) override='yes' ;; # Override checks
  251. h) help ;; # Help
  252. *) help ;; # Print help (default)
  253. esac
  254. done
  255. # Defining default software stack
  256. set_default_value 'nginx' 'yes'
  257. set_default_value 'apache' 'yes'
  258. set_default_value 'phpfpm' 'yes'
  259. set_default_value 'multiphp' 'no'
  260. set_default_value 'vsftpd' 'yes'
  261. set_default_value 'proftpd' 'no'
  262. set_default_value 'named' 'yes'
  263. set_default_value 'mysql' 'yes'
  264. set_default_value 'mysql8' 'no'
  265. set_default_value 'postgresql' 'no'
  266. set_default_value 'exim' 'yes'
  267. set_default_value 'dovecot' 'yes'
  268. set_default_value 'sieve' 'no'
  269. if [ $memory -lt 1500000 ]; then
  270. set_default_value 'clamd' 'no'
  271. set_default_value 'spamd' 'no'
  272. elif [ $memory -lt 3000000 ]; then
  273. set_default_value 'clamd' 'no'
  274. set_default_value 'spamd' 'yes'
  275. else
  276. set_default_value 'clamd' 'yes'
  277. set_default_value 'spamd' 'yes'
  278. fi
  279. set_default_value 'iptables' 'yes'
  280. set_default_value 'fail2ban' 'yes'
  281. set_default_value 'quota' 'no'
  282. set_default_value 'interactive' 'yes'
  283. set_default_value 'ipv6_support' 'no'
  284. set_default_value 'api' 'yes'
  285. set_default_port '8083'
  286. set_default_lang 'en'
  287. # Checking software conflicts
  288. if [ "$proftpd" = 'yes' ]; then
  289. vsftpd='no'
  290. fi
  291. if [ "$exim" = 'no' ]; then
  292. clamd='no'
  293. spamd='no'
  294. dovecot='no'
  295. fi
  296. if [ "$dovecot" = 'no' ]; then
  297. sieve='no'
  298. fi
  299. if [ "$iptables" = 'no' ]; then
  300. fail2ban='no'
  301. fi
  302. if [ "$apache" = 'no' ]; then
  303. phpfpm='yes'
  304. fi
  305. if [ "$mysql" = 'yes' ] && [ "$mysql8" = 'yes' ]; then
  306. mysql='no'
  307. fi
  308. if [ "$mysqlclassic" = 'yes' ] && [ "$architecture" = 'aarch64' ]; then
  309. check_result 1 "Mysql 8 does not support ARM64 yet for Debian please use Ubuntu. Unable to continue"
  310. fi
  311. # Checking root permissions
  312. if [ "x$(id -u)" != 'x0' ]; then
  313. check_result 1 "Script can be run executed only by root"
  314. fi
  315. if [ -d "/usr/local/hestia" -a -z "$override" ]; then
  316. check_result 1 "Hestia install detected. Unable to continue"
  317. fi
  318. # Checking admin user account
  319. if [ -n "$(grep ^admin: /etc/passwd /etc/group)" ] && [ -z "$force" ]; then
  320. echo 'Please remove admin user account before proceeding.'
  321. echo 'If you want to do it automatically run installer with -f option:'
  322. echo -e "Example: bash $0 --force\n"
  323. check_result 1 "User admin exists"
  324. fi
  325. # Clear the screen once launch permissions have been verified
  326. clear
  327. # Configure apt to retry downloading on error
  328. if [ ! -f /etc/apt/apt.conf.d/80-retries ]; then
  329. echo "APT::Acquire::Retries \"3\";" > /etc/apt/apt.conf.d/80-retries
  330. fi
  331. # Welcome message
  332. echo "Welcome to the Hestia Control Panel installer!"
  333. echo
  334. echo "Please wait, the installer is now checking for missing dependencies..."
  335. echo
  336. # Update apt repository
  337. apt-get -qq update
  338. # Creating backup directory
  339. mkdir -p "$hst_backups"
  340. # Pre-install packages
  341. echo "[ * ] Installing dependencies..."
  342. apt-get -y install $installer_dependencies >> $LOG
  343. check_result $? "Package installation failed, check log file for more details."
  344. # Check if apparmor is installed
  345. if [ $(dpkg-query -W -f='${Status}' apparmor 2> /dev/null | grep -c "ok installed") -eq 0 ]; then
  346. apparmor='no'
  347. else
  348. apparmor='yes'
  349. fi
  350. # Check repository availability
  351. wget --quiet "https://$GPG/deb_signing.key" -O /dev/null
  352. check_result $? "Unable to connect to the Hestia APT repository"
  353. # Check installed packages
  354. tmpfile=$(mktemp -p /tmp)
  355. dpkg --get-selections > $tmpfile
  356. conflicts_pkg="exim4 mariadb-server apache2 nginx hestia postfix"
  357. # Drop postfix from the list if exim should not be installed
  358. if [ "$exim" = 'no' ]; then
  359. conflicts_pkg=$(echo $conflicts_pkg | sed 's/postfix//g' | xargs)
  360. fi
  361. for pkg in $conflicts_pkg; do
  362. if [ -n "$(grep $pkg $tmpfile)" ]; then
  363. conflicts="$pkg* $conflicts"
  364. fi
  365. done
  366. rm -f $tmpfile
  367. if [ -n "$conflicts" ] && [ -z "$force" ]; then
  368. echo '!!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!!'
  369. echo
  370. echo 'WARNING: The following packages are already installed'
  371. echo "$conflicts"
  372. echo
  373. echo 'It is highly recommended that you remove them before proceeding.'
  374. echo
  375. echo '!!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!!'
  376. echo
  377. read -p 'Would you like to remove the conflicting packages? [y/n] ' answer
  378. if [ "$answer" = 'y' ] || [ "$answer" = 'Y' ]; then
  379. apt-get -qq purge $conflicts -y
  380. check_result $? 'apt-get remove failed'
  381. unset $answer
  382. else
  383. check_result 1 "Hestia Control Panel should be installed on a clean server."
  384. fi
  385. fi
  386. # Check network configuration
  387. if [ -d /etc/netplan ] && [ -z "$force" ]; then
  388. if [ -z "$(ls -A /etc/netplan)" ]; then
  389. echo '!!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!!'
  390. echo
  391. echo 'WARNING: Your network configuration may not be set up correctly.'
  392. echo 'Details: The netplan configuration directory is empty.'
  393. echo ''
  394. echo 'You may have a network configuration file that was created using'
  395. echo 'systemd-networkd.'
  396. echo ''
  397. echo 'It is strongly recommended to migrate to netplan, which is now the'
  398. echo 'default network configuration system in newer releases of Ubuntu.'
  399. echo ''
  400. echo 'While you can leave your configuration as-is, please note that you'
  401. echo 'will not be able to use additional IPs properly.'
  402. echo ''
  403. echo 'If you wish to continue and force the installation,'
  404. echo 'run this script with -f option:'
  405. echo "Example: bash $0 --force"
  406. echo
  407. echo '!!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!!'
  408. echo
  409. check_result 1 "Unable to detect netplan configuration."
  410. fi
  411. fi
  412. # Validate whether installation script matches release version before continuing with install
  413. if [ -z "$withdebs" ] || [ ! -d "$withdebs" ]; then
  414. release_branch_ver=$(curl -s https://raw.githubusercontent.com/hestiacp/hestiacp/release/src/deb/hestia/control | grep "Version:" | awk '{print $2}')
  415. if [ "$HESTIA_INSTALL_VER" != "$release_branch_ver" ]; then
  416. echo
  417. echo -e "\e[91mInstallation aborted\e[0m"
  418. echo "===================================================================="
  419. echo -e "\e[33mERROR: Install script version does not match package version!\e[0m"
  420. echo -e "\e[33mPlease download the installer from the release branch in order to continue:\e[0m"
  421. echo ""
  422. echo -e "\e[33mhttps://raw.githubusercontent.com/hestiacp/hestiacp/release/install/hst-install.sh\e[0m"
  423. echo ""
  424. echo -e "\e[33mTo test pre-release versions, build the .deb packages and re-run the installer:\e[0m"
  425. echo -e " \e[33m./hst_autocompile.sh \e[1m--hestia branchname no\e[21m\e[0m"
  426. echo -e " \e[33m./hst-install.sh .. \e[1m--with-debs /tmp/hestiacp-src/debs\e[21m\e[0m"
  427. echo ""
  428. check_result 1 "Installation aborted"
  429. fi
  430. fi
  431. case $architecture in
  432. x86_64)
  433. ARCH="amd64"
  434. ;;
  435. aarch64)
  436. ARCH="arm64"
  437. ;;
  438. *)
  439. echo
  440. echo -e "\e[91mInstallation aborted\e[0m"
  441. echo "===================================================================="
  442. echo -e "\e[33mERROR: $architecture is currently not supported!\e[0m"
  443. echo -e "\e[33mPlease verify the achitecture used is currenlty supported\e[0m"
  444. echo ""
  445. echo -e "\e[33mhttps://github.com/hestiacp/hestiacp/blob/main/README.md\e[0m"
  446. echo ""
  447. check_result 1 "Installation aborted"
  448. ;;
  449. esac
  450. #----------------------------------------------------------#
  451. # Brief Info #
  452. #----------------------------------------------------------#
  453. install_welcome_message() {
  454. DISPLAY_VER=$(echo $HESTIA_INSTALL_VER | sed "s|~alpha||g" | sed "s|~beta||g")
  455. echo
  456. echo ' _ _ _ _ ____ ____ '
  457. echo ' | | | | ___ ___| |_(_) __ _ / ___| _ \ '
  458. echo ' | |_| |/ _ \/ __| __| |/ _` | | | |_) | '
  459. echo ' | _ | __/\__ \ |_| | (_| | |___| __/ '
  460. echo ' |_| |_|\___||___/\__|_|\__,_|\____|_| '
  461. echo " "
  462. echo " Hestia Control Panel "
  463. if [[ "$HESTIA_INSTALL_VER" =~ "beta" ]]; then
  464. echo " BETA RELEASE "
  465. fi
  466. if [[ "$HESTIA_INSTALL_VER" =~ "alpha" ]]; then
  467. echo " DEVELOPMENT SNAPSHOT "
  468. echo " NOT INTENDED FOR PRODUCTION USE "
  469. echo " USE AT YOUR OWN RISK "
  470. fi
  471. echo " ${DISPLAY_VER} "
  472. echo " www.hestiacp.com "
  473. echo
  474. echo "========================================================================"
  475. echo
  476. echo "Thank you for downloading Hestia Control Panel! In a few moments,"
  477. echo "we will begin installing the following components on your server:"
  478. echo
  479. }
  480. # Printing nice ASCII logo
  481. clear
  482. install_welcome_message
  483. # Web stack
  484. echo ' - NGINX Web / Proxy Server'
  485. if [ "$apache" = 'yes' ]; then
  486. echo ' - Apache Web Server (as backend)'
  487. fi
  488. if [ "$phpfpm" = 'yes' ] && [ "$multiphp" = 'no' ]; then
  489. echo ' - PHP-FPM Application Server'
  490. fi
  491. if [ "$multiphp" = 'yes' ]; then
  492. phpfpm='yes'
  493. echo ' - Multi-PHP Environment'
  494. fi
  495. # DNS stack
  496. if [ "$named" = 'yes' ]; then
  497. echo ' - Bind DNS Server'
  498. fi
  499. # Mail stack
  500. if [ "$exim" = 'yes' ]; then
  501. echo -n ' - Exim Mail Server'
  502. if [ "$clamd" = 'yes' ] || [ "$spamd" = 'yes' ]; then
  503. echo -n ' + '
  504. if [ "$clamd" = 'yes' ]; then
  505. echo -n 'ClamAV '
  506. fi
  507. if [ "$spamd" = 'yes' ]; then
  508. if [ "$clamd" = 'yes' ]; then
  509. echo -n '+ '
  510. fi
  511. echo -n 'SpamAssassin'
  512. fi
  513. fi
  514. echo
  515. if [ "$dovecot" = 'yes' ]; then
  516. echo -n ' - Dovecot POP3/IMAP Server'
  517. if [ "$sieve" = 'yes' ]; then
  518. echo -n '+ Sieve'
  519. fi
  520. fi
  521. fi
  522. echo
  523. # Database stack
  524. if [ "$mysql" = 'yes' ]; then
  525. echo ' - MariaDB Database Server'
  526. fi
  527. if [ "$mysql8" = 'yes' ]; then
  528. echo ' - MySQL8 Database Server'
  529. fi
  530. if [ "$postgresql" = 'yes' ]; then
  531. echo ' - PostgreSQL Database Server'
  532. fi
  533. # FTP stack
  534. if [ "$vsftpd" = 'yes' ]; then
  535. echo ' - Vsftpd FTP Server'
  536. fi
  537. if [ "$proftpd" = 'yes' ]; then
  538. echo ' - ProFTPD FTP Server'
  539. fi
  540. # Firewall stack
  541. if [ "$iptables" = 'yes' ]; then
  542. echo -n ' - Firewall (iptables)'
  543. fi
  544. if [ "$iptables" = 'yes' ] && [ "$fail2ban" = 'yes' ]; then
  545. echo -n ' + Fail2Ban Access Monitor'
  546. fi
  547. echo -e "\n"
  548. echo "========================================================================"
  549. echo -e "\n"
  550. # Asking for confirmation to proceed
  551. if [ "$interactive" = 'yes' ]; then
  552. read -p 'Would you like to continue with the installation? [Y/N]: ' answer
  553. if [ "$answer" != 'y' ] && [ "$answer" != 'Y' ]; then
  554. echo 'Goodbye'
  555. exit 1
  556. fi
  557. fi
  558. # Validate Email / Hostname even when interactive = no
  559. # Asking for contact email
  560. if [ -z "$email" ]; then
  561. while validate_email; do
  562. echo -e "\nPlease use a valid emailadress (ex. info@domain.tld)."
  563. read -p 'Please enter admin email address: ' email
  564. done
  565. else
  566. if validate_email; then
  567. echo "Please use a valid emailadress (ex. info@domain.tld)."
  568. exit 1
  569. fi
  570. fi
  571. # Asking to set FQDN hostname
  572. if [ -z "$servername" ]; then
  573. # Ask and validate FQDN hostname.
  574. read -p "Please enter FQDN hostname [$(hostname -f)]: " servername
  575. # Set hostname if it wasn't set
  576. if [ -z "$servername" ]; then
  577. servername=$(hostname -f)
  578. fi
  579. # Validate Hostname, go to loop if the validation fails.
  580. while validate_hostname; do
  581. echo -e "\nPlease use a valid hostname according to RFC1178 (ex. hostname.domain.tld)."
  582. read -p "Please enter FQDN hostname [$(hostname -f)]: " servername
  583. done
  584. else
  585. # Validate FQDN hostname if it is preset
  586. if validate_hostname; then
  587. echo "Please use a valid hostname according to RFC1178 (ex. hostname.domain.tld)."
  588. exit 1
  589. fi
  590. fi
  591. # Generating admin password if it wasn't set
  592. displaypass="The password you chose during installation."
  593. if [ -z "$vpass" ]; then
  594. vpass=$(gen_pass)
  595. displaypass=$vpass
  596. fi
  597. # Set FQDN if it wasn't set
  598. mask1='(([[:alnum:]](-?[[:alnum:]])*)\.)'
  599. mask2='*[[:alnum:]](-?[[:alnum:]])+\.[[:alnum:]]{2,}'
  600. if ! [[ "$servername" =~ ^${mask1}${mask2}$ ]]; then
  601. if [[ -n "$servername" ]]; then
  602. servername="$servername.example.com"
  603. else
  604. servername="example.com"
  605. fi
  606. echo "127.0.0.1 $servername" >> /etc/hosts
  607. if [ "$ipv6_support" = 'yes' ]; then
  608. echo "::1 $servername" >> /etc/hosts
  609. fi
  610. fi
  611. if [[ -z $(grep -i "$servername" /etc/hosts) ]]; then
  612. echo "127.0.0.1 $servername" >> /etc/hosts
  613. if [ "$ipv6_support" = 'yes' ]; then
  614. echo "::1 $servername" >> /etc/hosts
  615. fi
  616. fi
  617. # Set email if it wasn't set
  618. if [[ -z "$email" ]]; then
  619. email="admin@$servername"
  620. fi
  621. # Defining backup directory
  622. echo -e "Installation backup directory: $hst_backups"
  623. # Print Log File Path
  624. echo "Installation log file: $LOG"
  625. # Print new line
  626. echo
  627. #----------------------------------------------------------#
  628. # Checking swap #
  629. #----------------------------------------------------------#
  630. # Checking swap on small instances
  631. if [ -z "$(swapon -s)" ] && [ "$memory" -lt 1000000 ]; then
  632. fallocate -l 1G /swapfile
  633. chmod 600 /swapfile
  634. mkswap /swapfile
  635. swapon /swapfile
  636. echo "/swapfile none swap sw 0 0" >> /etc/fstab
  637. fi
  638. #----------------------------------------------------------#
  639. # Install repository #
  640. #----------------------------------------------------------#
  641. # Define apt conf location
  642. apt=/etc/apt/sources.list.d
  643. # Create new folder if not all-ready exists
  644. mkdir -p /root/.gnupg/ && chmod 700 /root/.gnupg/
  645. # Updating system
  646. echo "Adding required repositories to proceed with installation:"
  647. echo
  648. # Installing Nginx repo
  649. echo "[ * ] NGINX"
  650. echo "deb [arch=$ARCH signed-by=/usr/share/keyrings/nginx-keyring.gpg] https://nginx.org/packages/mainline/$VERSION/ $codename nginx" > $apt/nginx.list
  651. curl -s https://nginx.org/keys/nginx_signing.key | gpg --dearmor | tee /usr/share/keyrings/nginx-keyring.gpg > /dev/null 2>&1
  652. # Installing sury PHP repo
  653. echo "[ * ] PHP"
  654. echo "deb [arch=$ARCH signed-by=/usr/share/keyrings/sury-keyring.gpg] https://packages.sury.org/php/ $codename main" > $apt/php.list
  655. curl -s https://packages.sury.org/php/apt.gpg | gpg --dearmor | tee /usr/share/keyrings/sury-keyring.gpg > /dev/null 2>&1
  656. # Installing sury Apache2 repo
  657. if [ "$apache" = 'yes' ]; then
  658. echo "[ * ] Apache2"
  659. echo "deb [arch=$ARCH signed-by=/usr/share/keyrings/apache2-keyring.gpg] https://packages.sury.org/apache2/ $codename main" > $apt/apache2.list
  660. curl -s https://packages.sury.org/apache2/apt.gpg | gpg --dearmor | tee /usr/share/keyrings/apache2-keyring.gpg > /dev/null 2>&1
  661. fi
  662. # Installing MariaDB repo
  663. if [ "$mysql" = 'yes' ]; then
  664. echo "[ * ] MariaDB"
  665. echo "deb [arch=$ARCH signed-by=/usr/share/keyrings/mariadb-keyring.gpg] https://dlm.mariadb.com/repo/mariadb-server/$mariadb_v/repo/$VERSION $codename main" > $apt/mariadb.list
  666. curl -s https://mariadb.org/mariadb_release_signing_key.asc | gpg --dearmor | tee /usr/share/keyrings/mariadb-keyring.gpg > /dev/null 2>&1
  667. fi
  668. # Installing Mysql8 repo
  669. if [ "$mysql8" = 'yes' ]; then
  670. echo "[ * ] Mysql 8"
  671. echo "deb [arch=$ARCH signed-by=/usr/share/keyrings/mysql-keyring.gpg] http://repo.mysql.com/apt/debian/ $codename mysql-apt-config" >> /etc/apt/sources.list.d/mysql.list
  672. echo "deb [arch=$ARCH signed-by=/usr/share/keyrings/mysql-keyring.gpg] http://repo.mysql.com/apt/debian/ $codename mysql-8.0" >> /etc/apt/sources.list.d/mysql.list
  673. echo "deb [arch=$ARCH signed-by=/usr/share/keyrings/mysql-keyring.gpg] http://repo.mysql.com/apt/debian/ $codename mysql-tools" >> /etc/apt/sources.list.d/mysql.list
  674. echo "#deb [arch=$ARCH signed-by=/usr/share/keyrings/mysql-keyring.gpg] http://repo.mysql.com/apt/debian/ $codename mysql-tools-preview" >> /etc/apt/sources.list.d/mysql.list
  675. echo "deb-src [arch=$ARCH signed-by=/usr/share/keyrings/mysql-keyring.gpg] http://repo.mysql.com/apt/debian/ $codename mysql-8.0" >> /etc/apt/sources.list.d/mysql.list
  676. GNUPGHOME="$(mktemp -d)"
  677. export GNUPGHOME
  678. for keyserver in $(shuf -e ha.pool.sks-keyservers.net hkp://p80.pool.sks-keyservers.net:80 keyserver.ubuntu.com hkp://keyserver.ubuntu.com:80); do
  679. gpg --no-default-keyring --keyring /usr/share/keyrings/mysql-keyring.gpg --keyserver "${keyserver}" --recv-keys "467B942D3A79BD29" > /dev/null 2>&1 && break
  680. done
  681. fi
  682. # Installing HestiaCP repo
  683. echo "[ * ] Hestia Control Panel"
  684. echo "deb [arch=$ARCH signed-by=/usr/share/keyrings/hestia-keyring.gpg] https://$RHOST/ $codename main" > $apt/hestia.list
  685. gpg --no-default-keyring --keyring /usr/share/keyrings/hestia-keyring.gpg --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys A189E93654F0B0E5 > /dev/null 2>&1
  686. # Installing PostgreSQL repo
  687. if [ "$postgresql" = 'yes' ]; then
  688. echo "[ * ] PostgreSQL"
  689. echo "deb [arch=$ARCH signed-by=/usr/share/keyrings/postgresql-keyring.gpg] https://apt.postgresql.org/pub/repos/apt/ $codename-pgdg main" > $apt/postgresql.list
  690. curl -s https://www.postgresql.org/media/keys/ACCC4CF8.asc | gpg --dearmor | tee /usr/share/keyrings/postgresql-keyring.gpg > /dev/null 2>&1
  691. fi
  692. # Echo for a new line
  693. echo
  694. # Updating system
  695. echo -ne "Updating currently installed packages, please wait... "
  696. apt-get -qq update
  697. apt-get -y upgrade >> $LOG &
  698. BACK_PID=$!
  699. # Check if package installation is done, print a spinner
  700. spin_i=1
  701. while kill -0 $BACK_PID > /dev/null 2>&1; do
  702. printf "\b${spinner:spin_i++%${#spinner}:1}"
  703. sleep 0.5
  704. done
  705. # Do a blank echo to get the \n back
  706. echo
  707. # Check Installation result
  708. wait $BACK_PID
  709. check_result $? 'apt-get upgrade failed'
  710. #----------------------------------------------------------#
  711. # Backup #
  712. #----------------------------------------------------------#
  713. # Creating backup directory tree
  714. mkdir -p $hst_backups
  715. cd $hst_backups
  716. mkdir nginx apache2 php vsftpd proftpd bind exim4 dovecot clamd
  717. mkdir spamassassin mysql postgresql openssl hestia
  718. # Backup OpenSSL configuration
  719. cp /etc/ssl/openssl.cnf $hst_backups/openssl > /dev/null 2>&1
  720. # Backup nginx configuration
  721. systemctl stop nginx > /dev/null 2>&1
  722. cp -r /etc/nginx/* $hst_backups/nginx > /dev/null 2>&1
  723. # Backup Apache configuration
  724. systemctl stop apache2 > /dev/null 2>&1
  725. cp -r /etc/apache2/* $hst_backups/apache2 > /dev/null 2>&1
  726. rm -f /etc/apache2/conf.d/* > /dev/null 2>&1
  727. # Backup PHP-FPM configuration
  728. systemctl stop php*-fpm > /dev/null 2>&1
  729. cp -r /etc/php/* $hst_backups/php > /dev/null 2>&1
  730. # Backup Bind configuration
  731. systemctl stop bind9 > /dev/null 2>&1
  732. cp -r /etc/bind/* $hst_backups/bind > /dev/null 2>&1
  733. # Backup Vsftpd configuration
  734. systemctl stop vsftpd > /dev/null 2>&1
  735. cp /etc/vsftpd.conf $hst_backups/vsftpd > /dev/null 2>&1
  736. # Backup ProFTPD configuration
  737. systemctl stop proftpd > /dev/null 2>&1
  738. cp /etc/proftpd/* $hst_backups/proftpd > /dev/null 2>&1
  739. # Backup Exim configuration
  740. systemctl stop exim4 > /dev/null 2>&1
  741. cp -r /etc/exim4/* $hst_backups/exim4 > /dev/null 2>&1
  742. # Backup ClamAV configuration
  743. systemctl stop clamav-daemon > /dev/null 2>&1
  744. cp -r /etc/clamav/* $hst_backups/clamav > /dev/null 2>&1
  745. # Backup SpamAssassin configuration
  746. systemctl stop spamassassin > /dev/null 2>&1
  747. cp -r /etc/spamassassin/* $hst_backups/spamassassin > /dev/null 2>&1
  748. # Backup Dovecot configuration
  749. systemctl stop dovecot > /dev/null 2>&1
  750. cp /etc/dovecot.conf $hst_backups/dovecot > /dev/null 2>&1
  751. cp -r /etc/dovecot/* $hst_backups/dovecot > /dev/null 2>&1
  752. # Backup MySQL/MariaDB configuration and data
  753. systemctl stop mysql > /dev/null 2>&1
  754. killall -9 mysqld > /dev/null 2>&1
  755. mv /var/lib/mysql $hst_backups/mysql/mysql_datadir > /dev/null 2>&1
  756. cp -r /etc/mysql/* $hst_backups/mysql > /dev/null 2>&1
  757. mv -f /root/.my.cnf $hst_backups/mysql > /dev/null 2>&1
  758. # Backup Hestia
  759. systemctl stop hestia > /dev/null 2>&1
  760. cp -r ${HESTIA}/* $hst_backups/hestia > /dev/null 2>&1
  761. apt-get -y purge hestia hestia-nginx hestia-php > /dev/null 2>&1
  762. rm -rf ${HESTIA} > /dev/null 2>&1
  763. #----------------------------------------------------------#
  764. # Package Includes #
  765. #----------------------------------------------------------#
  766. if [ "$phpfpm" = 'yes' ]; then
  767. fpm="php$fpm_v php$fpm_v-common php$fpm_v-bcmath php$fpm_v-cli
  768. php$fpm_v-curl php$fpm_v-fpm php$fpm_v-gd php$fpm_v-intl
  769. php$fpm_v-mysql php$fpm_v-soap php$fpm_v-xml php$fpm_v-zip
  770. php$fpm_v-mbstring php$fpm_v-bz2 php$fpm_v-pspell
  771. php$fpm_v-imagick"
  772. software="$software $fpm"
  773. fi
  774. #----------------------------------------------------------#
  775. # Package Excludes #
  776. #----------------------------------------------------------#
  777. # Excluding packages
  778. software=$(echo "$software" | sed -e "s/apache2.2-common//")
  779. if [ "$apache" = 'no' ]; then
  780. software=$(echo "$software" | sed -e "s/apache2 //")
  781. software=$(echo "$software" | sed -e "s/apache2-bin//")
  782. software=$(echo "$software" | sed -e "s/apache2-utils//")
  783. software=$(echo "$software" | sed -e "s/apache2-suexec-custom//")
  784. software=$(echo "$software" | sed -e "s/apache2.2-common//")
  785. software=$(echo "$software" | sed -e "s/libapache2-mod-rpaf//")
  786. software=$(echo "$software" | sed -e "s/libapache2-mod-fcgid//")
  787. software=$(echo "$software" | sed -e "s/libapache2-mod-php$fpm_v//")
  788. fi
  789. if [ "$vsftpd" = 'no' ]; then
  790. software=$(echo "$software" | sed -e "s/vsftpd//")
  791. fi
  792. if [ "$proftpd" = 'no' ]; then
  793. software=$(echo "$software" | sed -e "s/proftpd-basic//")
  794. software=$(echo "$software" | sed -e "s/proftpd-mod-vroot//")
  795. fi
  796. if [ "$named" = 'no' ]; then
  797. software=$(echo "$software" | sed -e "s/bind9//")
  798. fi
  799. if [ "$exim" = 'no' ]; then
  800. software=$(echo "$software" | sed -e "s/exim4 //")
  801. software=$(echo "$software" | sed -e "s/exim4-daemon-heavy//")
  802. software=$(echo "$software" | sed -e "s/dovecot-imapd//")
  803. software=$(echo "$software" | sed -e "s/dovecot-pop3d//")
  804. software=$(echo "$software" | sed -e "s/clamav-daemon//")
  805. software=$(echo "$software" | sed -e "s/spamassassin//")
  806. software=$(echo "$software" | sed -e "s/dovecot-sieve//")
  807. software=$(echo "$software" | sed -e "s/dovecot-managesieved//")
  808. fi
  809. if [ "$clamd" = 'no' ]; then
  810. software=$(echo "$software" | sed -e "s/clamav-daemon//")
  811. fi
  812. if [ "$spamd" = 'no' ]; then
  813. software=$(echo "$software" | sed -e "s/spamassassin//")
  814. fi
  815. if [ "$dovecot" = 'no' ]; then
  816. software=$(echo "$software" | sed -e "s/dovecot-imapd//")
  817. software=$(echo "$software" | sed -e "s/dovecot-pop3d//")
  818. fi
  819. if [ "$sieve" = 'no' ]; then
  820. software=$(echo "$software" | sed -e "s/dovecot-sieve//")
  821. software=$(echo "$software" | sed -e "s/dovecot-managesieved//")
  822. fi
  823. if [ "$mysql" = 'no' ]; then
  824. software=$(echo "$software" | sed -e "s/mariadb-server//")
  825. software=$(echo "$software" | sed -e "s/mariadb-client//")
  826. software=$(echo "$software" | sed -e "s/mariadb-common//")
  827. fi
  828. if [ "$mysql8" = 'no' ]; then
  829. software=$(echo "$software" | sed -e "s/mysql-server//")
  830. software=$(echo "$software" | sed -e "s/mysql-client//")
  831. software=$(echo "$software" | sed -e "s/mysql-common//")
  832. fi
  833. if [ "$mysql" = 'no' ] && [ "$mysql8" = 'no' ]; then
  834. software=$(echo "$software" | sed -e "s/php$fpm_v-mysql//")
  835. fi
  836. if [ "$postgresql" = 'no' ]; then
  837. software=$(echo "$software" | sed -e "s/postgresql-contrib//")
  838. software=$(echo "$software" | sed -e "s/postgresql//")
  839. software=$(echo "$software" | sed -e "s/php$fpm_v-pgsql//")
  840. fi
  841. if [ "$fail2ban" = 'no' ]; then
  842. software=$(echo "$software" | sed -e "s/fail2ban//")
  843. fi
  844. if [ "$iptables" = 'no' ]; then
  845. software=$(echo "$software" | sed -e "s/ipset//")
  846. software=$(echo "$software" | sed -e "s/fail2ban//")
  847. fi
  848. if [ "$phpfpm" = 'yes' ]; then
  849. software=$(echo "$software" | sed -e "s/php$fpm_v-cgi//")
  850. software=$(echo "$software" | sed -e "s/libapache2-mpm-itk//")
  851. software=$(echo "$software" | sed -e "s/libapache2-mod-ruid2//")
  852. software=$(echo "$software" | sed -e "s/libapache2-mod-php$fpm_v//")
  853. fi
  854. if [ -d "$withdebs" ]; then
  855. software=$(echo "$software" | sed -e "s/hestia-nginx//")
  856. software=$(echo "$software" | sed -e "s/hestia-php//")
  857. software=$(echo "$software" | sed -e "s/hestia=${HESTIA_INSTALL_VER}//")
  858. fi
  859. #----------------------------------------------------------#
  860. # Install packages #
  861. #----------------------------------------------------------#
  862. # Disabling daemon autostart on apt-get install
  863. echo -e '#!/bin/sh\nexit 101' > /usr/sbin/policy-rc.d
  864. chmod a+x /usr/sbin/policy-rc.d
  865. # Installing apt packages
  866. echo "The installer is now downloading and installing all required packages."
  867. echo -ne "NOTE: This process may take 10 to 15 minutes to complete, please wait... "
  868. echo
  869. apt-get -y install $software > $LOG
  870. BACK_PID=$!
  871. # Check if package installation is done, print a spinner
  872. spin_i=1
  873. while kill -0 $BACK_PID > /dev/null 2>&1; do
  874. printf "\b${spinner:spin_i++%${#spinner}:1}"
  875. sleep 0.5
  876. done
  877. # Do a blank echo to get the \n back
  878. echo
  879. # Check Installation result
  880. wait $BACK_PID
  881. check_result $? "apt-get install failed"
  882. echo
  883. echo "========================================================================"
  884. echo
  885. # Install Hestia packages from local folder
  886. if [ -n "$withdebs" ] && [ -d "$withdebs" ]; then
  887. echo "[ * ] Installing local package files..."
  888. echo " - hestia core package"
  889. dpkg -i $withdebs/hestia_*.deb > /dev/null 2>&1
  890. if [ -z $(ls $withdebs/hestia-php_*.deb 2> /dev/null) ]; then
  891. echo " - hestia-php backend package (from apt)"
  892. apt-get -y install hestia-php > /dev/null 2>&1
  893. else
  894. echo " - hestia-php backend package"
  895. dpkg -i $withdebs/hestia-php_*.deb > /dev/null 2>&1
  896. fi
  897. if [ -z $(ls $withdebs/hestia-nginx_*.deb 2> /dev/null) ]; then
  898. echo " - hestia-nginx backend package (from apt)"
  899. apt-get -y install hestia-nginx > /dev/null 2>&1
  900. else
  901. echo " - hestia-nginx backend package"
  902. dpkg -i $withdebs/hestia-nginx_*.deb > /dev/null 2>&1
  903. fi
  904. fi
  905. # Restoring autostart policy
  906. rm -f /usr/sbin/policy-rc.d
  907. #----------------------------------------------------------#
  908. # Configure system #
  909. #----------------------------------------------------------#
  910. echo "[ * ] Configuring system settings..."
  911. # Enable SFTP subsystem for SSH
  912. sftp_subsys_enabled=$(grep -iE "^#?.*subsystem.+(sftp )?sftp-server" /etc/ssh/sshd_config)
  913. if [ -n "$sftp_subsys_enabled" ]; then
  914. sed -i -E "s/^#?.*Subsystem.+(sftp )?sftp-server/Subsystem sftp internal-sftp/g" /etc/ssh/sshd_config
  915. fi
  916. # Reduce SSH login grace time
  917. sed -i "s/[#]LoginGraceTime [[:digit:]]m/LoginGraceTime 1m/g" /etc/ssh/sshd_config
  918. # Disable SSH suffix broadcast
  919. if [ -z "$(grep "^DebianBanner no" /etc/ssh/sshd_config)" ]; then
  920. sed -i '/^[#]Banner .*/a DebianBanner no' /etc/ssh/sshd_config
  921. if [ -z "$(grep "^DebianBanner no" /etc/ssh/sshd_config)" ]; then
  922. # If first attempt fails just add it
  923. echo '' >> /etc/ssh/sshd_config
  924. echo 'DebianBanner no' >> /etc/ssh/sshd_config
  925. fi
  926. fi
  927. # Restart SSH daemon
  928. systemctl restart ssh
  929. # Disable AWStats cron
  930. rm -f /etc/cron.d/awstats
  931. # Replace awstatst function
  932. cp -f ${HESTIA_INSTALL_DIR}/logrotate/httpd-prerotate/* /etc/logrotate.d/httpd-prerotate/
  933. # Set directory color
  934. if [ -z "$(grep 'LS_COLORS="$LS_COLORS:di=00;33"' /etc/profile)" ]; then
  935. echo 'LS_COLORS="$LS_COLORS:di=00;33"' >> /etc/profile
  936. fi
  937. # Register /sbin/nologin and /usr/sbin/nologin
  938. if [ -z "$(grep ^/sbin/nologin /etc/shells)" ]; then
  939. echo "/sbin/nologin" >> /etc/shells
  940. fi
  941. if [ -z "$(grep ^/usr/sbin/nologin /etc/shells)" ]; then
  942. echo "/usr/sbin/nologin" >> /etc/shells
  943. fi
  944. # Configuring NTP
  945. sed -i 's/#NTP=/NTP=pool.ntp.org/' /etc/systemd/timesyncd.conf
  946. systemctl enable systemd-timesyncd
  947. systemctl start systemd-timesyncd
  948. # Restrict access to /proc fs
  949. # - Prevent unpriv users from seeing each other running processes
  950. mount -o remount,defaults,hidepid=2 /proc > /dev/null 2>&1
  951. if [ $? -ne 0 ]; then
  952. echo "Info: Cannot remount /proc (LXC containers require additional perm added to host apparmor profile)"
  953. else
  954. echo "@reboot root sleep 5 && mount -o remount,defaults,hidepid=2 /proc" > /etc/cron.d/hestia-proc
  955. fi
  956. #----------------------------------------------------------#
  957. # Configure Hestia #
  958. #----------------------------------------------------------#
  959. echo "[ * ] Configuring Hestia Control Panel..."
  960. # Installing sudo configuration
  961. mkdir -p /etc/sudoers.d
  962. cp -f ${HESTIA_INSTALL_DIR}/sudo/admin /etc/sudoers.d/
  963. chmod 440 /etc/sudoers.d/admin
  964. # Add Hestia global config
  965. if [[ ! -e /etc/hestiacp/hestia.conf ]]; then
  966. mkdir -p /etc/hestiacp
  967. echo -e "# Do not edit this file, will get overwritten on next upgrade, use /etc/hestiacp/local.conf instead\n\nexport HESTIA='/usr/local/hestia'\n\n[[ -f /etc/hestiacp/local.conf ]] && source /etc/hestiacp/local.conf" > /etc/hestiacp/hestia.conf
  968. fi
  969. # Configuring system env
  970. echo "export HESTIA='$HESTIA'" > /etc/profile.d/hestia.sh
  971. echo 'PATH=$PATH:'$HESTIA'/bin' >> /etc/profile.d/hestia.sh
  972. echo 'export PATH' >> /etc/profile.d/hestia.sh
  973. chmod 755 /etc/profile.d/hestia.sh
  974. source /etc/profile.d/hestia.sh
  975. # Configuring logrotate for Hestia logs
  976. cp -f ${HESTIA_INSTALL_DIR}/logrotate/hestia /etc/logrotate.d/hestia
  977. # Create log path and symbolic link
  978. rm -f /var/log/hestia
  979. mkdir -p /var/log/hestia
  980. ln -s /var/log/hestia ${HESTIA}/log
  981. # Building directory tree and creating some blank files for Hestia
  982. mkdir -p ${HESTIA}/conf ${HESTIA}/ssl ${HESTIA}/data/ips \
  983. ${HESTIA}/data/queue ${HESTIA}/data/users ${HESTIA}/data/firewall \
  984. ${HESTIA}/data/sessions
  985. touch ${HESTIA}/data/queue/backup.pipe ${HESTIA}/data/queue/disk.pipe \
  986. ${HESTIA}/data/queue/webstats.pipe ${HESTIA}/data/queue/restart.pipe \
  987. ${HESTIA}/data/queue/traffic.pipe ${HESTIA}/data/queue/daily.pipe ${HESTIA}/log/system.log \
  988. ${HESTIA}/log/nginx-error.log ${HESTIA}/log/auth.log ${HESTIA}/log/backup.log
  989. chmod 750 ${HESTIA}/conf ${HESTIA}/data/users ${HESTIA}/data/ips ${HESTIA}/log
  990. chmod -R 750 ${HESTIA}/data/queue
  991. chmod 660 /var/log/hestia/*
  992. chmod 770 ${HESTIA}/data/sessions
  993. # Generating Hestia configuration
  994. rm -f ${HESTIA}/conf/hestia.conf > /dev/null 2>&1
  995. touch ${HESTIA}/conf/hestia.conf
  996. chmod 660 ${HESTIA}/conf/hestia.conf
  997. # Write default port value to hestia.conf
  998. # If a custom port is specified it will be set at the end of the installation process.
  999. write_config_value "BACKEND_PORT" "8083"
  1000. # Web stack
  1001. if [ "$apache" = 'yes' ]; then
  1002. write_config_value "WEB_SYSTEM" "apache2"
  1003. write_config_value "WEB_RGROUPS" "www-data"
  1004. write_config_value "WEB_PORT" "8080"
  1005. write_config_value "WEB_SSL_PORT" "8443"
  1006. write_config_value "WEB_SSL" "mod_ssl"
  1007. write_config_value "PROXY_SYSTEM" "nginx"
  1008. write_config_value "PROXY_PORT" "80"
  1009. write_config_value "PROXY_SSL_PORT" "443"
  1010. write_config_value "STATS_SYSTEM" "awstats"
  1011. fi
  1012. if [ "$apache" = 'no' ]; then
  1013. write_config_value "WEB_SYSTEM" "nginx"
  1014. write_config_value "WEB_PORT" "80"
  1015. write_config_value "WEB_SSL_PORT" "443"
  1016. write_config_value "WEB_SSL" "openssl"
  1017. write_config_value "STATS_SYSTEM" "awstats"
  1018. fi
  1019. if [ "$phpfpm" = 'yes' ]; then
  1020. write_config_value "WEB_BACKEND" "php-fpm"
  1021. fi
  1022. # Database stack
  1023. if [ "$mysql" = 'yes' ] || [ "$mysql8" = 'yes' ]; then
  1024. installed_db_types='mysql'
  1025. fi
  1026. if [ "$postgresql" = 'yes' ]; then
  1027. installed_db_types="$installed_db_types,pgsql"
  1028. fi
  1029. if [ -n "$installed_db_types" ]; then
  1030. db=$(echo "$installed_db_types" \
  1031. | sed "s/,/\n/g" \
  1032. | sort -r -u \
  1033. | sed "/^$/d" \
  1034. | sed ':a;N;$!ba;s/\n/,/g')
  1035. write_config_value "DB_SYSTEM" "$db"
  1036. fi
  1037. # FTP stack
  1038. if [ "$vsftpd" = 'yes' ]; then
  1039. write_config_value "FTP_SYSTEM" "vsftpd"
  1040. fi
  1041. if [ "$proftpd" = 'yes' ]; then
  1042. write_config_value "FTP_SYSTEM" "proftpd"
  1043. fi
  1044. # DNS stack
  1045. if [ "$named" = 'yes' ]; then
  1046. write_config_value "DNS_SYSTEM" "bind9"
  1047. fi
  1048. # Mail stack
  1049. if [ "$exim" = 'yes' ]; then
  1050. write_config_value "MAIL_SYSTEM" "exim4"
  1051. if [ "$clamd" = 'yes' ]; then
  1052. write_config_value "ANTIVIRUS_SYSTEM" "clamav-daemon"
  1053. fi
  1054. if [ "$spamd" = 'yes' ]; then
  1055. write_config_value "ANTISPAM_SYSTEM" "spamassassin"
  1056. fi
  1057. if [ "$dovecot" = 'yes' ]; then
  1058. write_config_value "IMAP_SYSTEM" "dovecot"
  1059. fi
  1060. if [ "$sieve" = 'yes' ]; then
  1061. write_config_value "SIEVE_SYSTEM" "yes"
  1062. fi
  1063. fi
  1064. # Cron daemon
  1065. write_config_value "CRON_SYSTEM" "cron"
  1066. # Firewall stack
  1067. if [ "$iptables" = 'yes' ]; then
  1068. write_config_value "FIREWALL_SYSTEM" "iptables"
  1069. fi
  1070. if [ "$iptables" = 'yes' ] && [ "$fail2ban" = 'yes' ]; then
  1071. write_config_value "FIREWALL_EXTENSION" "fail2ban"
  1072. fi
  1073. # Disk quota
  1074. if [ "$quota" = 'yes' ]; then
  1075. write_config_value "DISK_QUOTA" "yes"
  1076. else
  1077. write_config_value "DISK_QUOTA" "no"
  1078. fi
  1079. # Backups
  1080. write_config_value "BACKUP_SYSTEM" "local"
  1081. write_config_value "BACKUP_GZIP" "4"
  1082. write_config_value "BACKUP_MODE" "zstd"
  1083. # Language
  1084. write_config_value "LANGUAGE" "$lang"
  1085. # Login in screen
  1086. write_config_value "LOGIN_STYLE" "default"
  1087. # Theme
  1088. write_config_value "THEME" "dark"
  1089. # Inactive session timeout
  1090. write_config_value "INACTIVE_SESSION_TIMEOUT" "60"
  1091. # Version & Release Branch
  1092. write_config_value "VERSION" "${HESTIA_INSTALL_VER}"
  1093. write_config_value "RELEASE_BRANCH" "release"
  1094. # Email notifications after upgrade
  1095. write_config_value "UPGRADE_SEND_EMAIL" "true"
  1096. write_config_value "UPGRADE_SEND_EMAIL_LOG" "false"
  1097. # Installing hosting packages
  1098. cp -rf ${HESTIA_COMMON_DIR}/packages ${HESTIA}/data/
  1099. # Update nameservers in hosting package
  1100. IFS='.' read -r -a domain_elements <<< "$servername"
  1101. if [ -n "${domain_elements[-2]}" ] && [ -n "${domain_elements[-1]}" ]; then
  1102. serverdomain="${domain_elements[-2]}.${domain_elements[-1]}"
  1103. sed -i s/"domain.tld"/"$serverdomain"/g ${HESTIA}/data/packages/*.pkg
  1104. fi
  1105. # Installing templates
  1106. cp -rf ${HESTIA_INSTALL_DIR}/templates ${HESTIA}/data/
  1107. cp -rf ${HESTIA_COMMON_DIR}/templates/web/ ${HESTIA}/data/templates
  1108. cp -rf ${HESTIA_COMMON_DIR}/templates/dns/ ${HESTIA}/data/templates
  1109. mkdir -p /var/www/html
  1110. mkdir -p /var/www/document_errors
  1111. # Install default success page
  1112. cp -rf ${HESTIA_COMMON_DIR}/templates/web/unassigned/index.html /var/www/html/
  1113. cp -rf ${HESTIA_COMMON_DIR}/templates/web/skel/document_errors/* /var/www/document_errors/
  1114. # Installing firewall rules
  1115. cp -rf ${HESTIA_COMMON_DIR}/firewall ${HESTIA}/data/
  1116. rm -f ${HESTIA}/data/firewall/ipset/blacklist.sh ${HESTIA}/data/firewall/ipset/blacklist.ipv6.sh
  1117. # Installing apis
  1118. cp -rf ${HESTIA_COMMON_DIR}/api ${HESTIA}/data/
  1119. # Configuring server hostname
  1120. ${HESTIA}/bin/v-change-sys-hostname $servername > /dev/null 2>&1
  1121. # Configuring global OpenSSL options
  1122. echo "[ * ] Configuring OpenSSL to improve TLS performance..."
  1123. tls13_ciphers="TLS_AES_128_GCM_SHA256:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_256_GCM_SHA384"
  1124. if [ "$release" = "10" ] || [ "$release" = "11" ]; then
  1125. sed -i '/^system_default = system_default_sect$/a system_default = hestia_openssl_sect\n\n[hestia_openssl_sect]\nCiphersuites = '"$tls13_ciphers"'\nOptions = PrioritizeChaCha' /etc/ssl/openssl.cnf
  1126. elif [ "$release" = "12" ]; then
  1127. if ! grep -qw "^ssl_conf = ssl_sect$" /etc/ssl/openssl.cnf 2> /dev/null; then
  1128. sed -i '/providers = provider_sect$/a ssl_conf = ssl_sect' /etc/ssl/openssl.cnf
  1129. fi
  1130. if ! grep -qw "^[ssl_sect]$" /etc/ssl/openssl.cnf 2> /dev/null; then
  1131. sed -i '$a \\n[ssl_sect]\nsystem_default = hestia_openssl_sect\n\n[hestia_openssl_sect]\nCiphersuites = '"$tls13_ciphers"'\nOptions = PrioritizeChaCha' /etc/ssl/openssl.cnf
  1132. elif grep -qw "^system_default = system_default_sect$" /etc/ssl/openssl.cnf 2> /dev/null; then
  1133. sed -i '/^system_default = system_default_sect$/a system_default = hestia_openssl_sect\n\n[hestia_openssl_sect]\nCiphersuites = '"$tls13_ciphers"'\nOptions = PrioritizeChaCha' /etc/ssl/openssl.cnf
  1134. fi
  1135. fi
  1136. # Generating SSL certificate
  1137. echo "[ * ] Generating default self-signed SSL certificate..."
  1138. ${HESTIA}/bin/v-generate-ssl-cert $(hostname) '' 'US' 'California' \
  1139. 'San Francisco' 'Hestia Control Panel' 'IT' > /tmp/hst.pem
  1140. # Parsing certificate file
  1141. crt_end=$(grep -n "END CERTIFICATE-" /tmp/hst.pem | cut -f 1 -d:)
  1142. key_start=$(grep -n "BEGIN RSA" /tmp/hst.pem | cut -f 1 -d:)
  1143. key_end=$(grep -n "END RSA" /tmp/hst.pem | cut -f 1 -d:)
  1144. # Adding SSL certificate
  1145. echo "[ * ] Adding SSL certificate to Hestia Control Panel..."
  1146. cd ${HESTIA}/ssl
  1147. sed -n "1,${crt_end}p" /tmp/hst.pem > certificate.crt
  1148. sed -n "$key_start,${key_end}p" /tmp/hst.pem > certificate.key
  1149. chown root:mail ${HESTIA}/ssl/*
  1150. chmod 660 ${HESTIA}/ssl/*
  1151. rm /tmp/hst.pem
  1152. # Install dhparam.pem
  1153. cp -f ${HESTIA_INSTALL_DIR}/ssl/dhparam.pem /etc/ssl
  1154. # Deleting old admin user
  1155. if [ -n "$(grep ^admin: /etc/passwd)" ] && [ "$force" = 'yes' ]; then
  1156. chattr -i /home/admin/conf > /dev/null 2>&1
  1157. userdel -f admin > /dev/null 2>&1
  1158. chattr -i /home/admin/conf > /dev/null 2>&1
  1159. mv -f /home/admin $hst_backups/home/ > /dev/null 2>&1
  1160. rm -f /tmp/sess_* > /dev/null 2>&1
  1161. fi
  1162. if [ -n "$(grep ^admin: /etc/group)" ] && [ "$force" = 'yes' ]; then
  1163. groupdel admin > /dev/null 2>&1
  1164. fi
  1165. # Enable sftp jail
  1166. echo "[ * ] Enable SFTP jail..."
  1167. ${HESTIA}/bin/v-add-sys-sftp-jail > /dev/null 2>&1
  1168. check_result $? "can't enable sftp jail"
  1169. # Adding Hestia admin account
  1170. echo "[ * ] Create admin account..."
  1171. ${HESTIA}/bin/v-add-user admin $vpass $email "system" "System Administrator"
  1172. check_result $? "can't create admin user"
  1173. ${HESTIA}/bin/v-change-user-shell admin nologin
  1174. ${HESTIA}/bin/v-change-user-role admin admin
  1175. ${HESTIA}/bin/v-change-user-language admin $lang
  1176. ${HESTIA}/bin/v-change-sys-config-value 'POLICY_SYSTEM_PROTECTED_ADMIN' 'yes'
  1177. locale-gen "en_US.utf8" > /dev/null 2>&1
  1178. #----------------------------------------------------------#
  1179. # Configure Nginx #
  1180. #----------------------------------------------------------#
  1181. echo "[ * ] Configuring NGINX..."
  1182. rm -f /etc/nginx/conf.d/*.conf
  1183. cp -f ${HESTIA_INSTALL_DIR}/nginx/nginx.conf /etc/nginx/
  1184. cp -f ${HESTIA_INSTALL_DIR}/nginx/status.conf /etc/nginx/conf.d/
  1185. cp -f ${HESTIA_INSTALL_DIR}/nginx/agents.conf /etc/nginx/conf.d/
  1186. cp -f ${HESTIA_INSTALL_DIR}/nginx/phpmyadmin.inc /etc/nginx/conf.d/
  1187. cp -f ${HESTIA_INSTALL_DIR}/nginx/phppgadmin.inc /etc/nginx/conf.d/
  1188. cp -f ${HESTIA_INSTALL_DIR}/logrotate/nginx /etc/logrotate.d/
  1189. if [ "$ipv6_support" = 'yes' ]; then
  1190. cp -f ${HESTIA_INSTALL_DIR}/nginx/nginx-ipv6.conf /etc/nginx/nginx.conf
  1191. cp -f ${HESTIA_INSTALL_DIR}/nginx/status-ipv6.conf /etc/nginx/conf.d/status.conf
  1192. fi
  1193. mkdir -p /etc/nginx/conf.d/domains
  1194. mkdir -p /etc/nginx/modules-enabled
  1195. mkdir -p /var/log/nginx/domains
  1196. # Update dns servers in nginx.conf
  1197. dns_resolver=$(cat /etc/resolv.conf | grep -i '^nameserver' | cut -d ' ' -f2 | tr '\r\n' ' ' | xargs)
  1198. for ip in $dns_resolver; do
  1199. if [[ $ip =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
  1200. resolver="$ip $resolver"
  1201. fi
  1202. if [ "$ipv6_support" = 'yes' ]; then
  1203. if [[ $ip =~ ^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$ ]]; then
  1204. resolver="[$ip] $resolver"
  1205. fi
  1206. fi
  1207. done
  1208. if [ -n "$resolver" ]; then
  1209. if [ "$ipv6_support" = 'yes' ]; then
  1210. sed -i "s/1.1.1.1 \[2606:4700:4700::1111\] 1.1.1.1 \[2606:4700:4700::1001\]/$resolver/g" /etc/nginx/nginx.conf
  1211. sed -i "s/1.1.1.1 \[2606:4700:4700::1111\] 1.1.1.1 \[2606:4700:4700::1001\]/$resolver/g" /usr/local/hestia/nginx/conf/nginx.conf
  1212. else
  1213. sed -i "s/1.1.1.1 8.8.8.8/$resolver/g" /etc/nginx/nginx.conf
  1214. sed -i "s/1.1.1.1 8.8.8.8/$resolver/g" /usr/local/hestia/nginx/conf/nginx.conf
  1215. fi
  1216. fi
  1217. # https://github.com/ergin/nginx-cloudflare-real-ip/
  1218. cf_ips="$(curl -fsLm5 --retry 2 https://api.cloudflare.com/client/v4/ips)"
  1219. if [ -n "$cf_ips" ] && [ "$(echo "$cf_ips" | jq -r '.success//""')" = "true" ]; then
  1220. cf_inc="/etc/nginx/conf.d/cloudflare.inc"
  1221. echo "[ * ] Updating Cloudflare IP Ranges for Nginx..."
  1222. echo "# Cloudflare IP Ranges" > $cf_inc
  1223. echo "" >> $cf_inc
  1224. echo "# IPv4" >> $cf_inc
  1225. for ipv4 in $(echo "$cf_ips" | jq -r '.result.ipv4_cidrs[]//""' | sort); do
  1226. echo "set_real_ip_from $ipv4;" >> $cf_inc
  1227. done
  1228. echo "" >> $cf_inc
  1229. echo "# IPv6" >> $cf_inc
  1230. for ipv6 in $(echo "$cf_ips" | jq -r '.result.ipv6_cidrs[]//""' | sort); do
  1231. echo "set_real_ip_from $ipv6;" >> $cf_inc
  1232. done
  1233. echo "" >> $cf_inc
  1234. echo "real_ip_header CF-Connecting-IP;" >> $cf_inc
  1235. fi
  1236. update-rc.d nginx defaults > /dev/null 2>&1
  1237. systemctl start nginx >> $LOG
  1238. check_result $? "nginx start failed"
  1239. #----------------------------------------------------------#
  1240. # Configure Apache #
  1241. #----------------------------------------------------------#
  1242. if [ "$apache" = 'yes' ]; then
  1243. echo "[ * ] Configuring Apache Web Server..."
  1244. mkdir -p /etc/apache2/conf.d
  1245. mkdir -p /etc/apache2/conf.d/domains
  1246. # Copy configuration files
  1247. cp -f ${HESTIA_INSTALL_DIR}/apache2/apache2.conf /etc/apache2/
  1248. cp -f ${HESTIA_INSTALL_DIR}/apache2/status.conf /etc/apache2/mods-available/hestia-status.conf
  1249. cp -f /etc/apache2/mods-available/status.load /etc/apache2/mods-available/hestia-status.load
  1250. cp -f ${HESTIA_INSTALL_DIR}/logrotate/apache2 /etc/logrotate.d/
  1251. if [ "$ipv6_support" = 'yes' ]; then
  1252. cp -f ${HESTIA_INSTALL_DIR}/apache2/status-ipv6.conf /etc/apache2/mods-available/hestia-status.conf
  1253. fi
  1254. # Enable needed modules
  1255. a2enmod rewrite > /dev/null 2>&1
  1256. a2enmod suexec > /dev/null 2>&1
  1257. a2enmod ssl > /dev/null 2>&1
  1258. a2enmod actions > /dev/null 2>&1
  1259. a2dismod --quiet status > /dev/null 2>&1
  1260. a2enmod --quiet hestia-status > /dev/null 2>&1
  1261. # Enable mod_ruid/mpm_itk or mpm_event
  1262. if [ "$phpfpm" = 'yes' ]; then
  1263. # Disable prefork and php, enable event
  1264. a2dismod php$fpm_v > /dev/null 2>&1
  1265. a2dismod mpm_prefork > /dev/null 2>&1
  1266. a2enmod mpm_event > /dev/null 2>&1
  1267. cp -f ${HESTIA_INSTALL_DIR}/apache2/hestia-event.conf /etc/apache2/conf.d/
  1268. else
  1269. a2enmod mpm_itk > /dev/null 2>&1
  1270. fi
  1271. echo "# Powered by hestia" > /etc/apache2/sites-available/default
  1272. echo "# Powered by hestia" > /etc/apache2/sites-available/default-ssl
  1273. echo "# Powered by hestia" > /etc/apache2/ports.conf
  1274. echo -e "/home\npublic_html/cgi-bin" > /etc/apache2/suexec/www-data
  1275. touch /var/log/apache2/access.log /var/log/apache2/error.log
  1276. mkdir -p /var/log/apache2/domains
  1277. chmod a+x /var/log/apache2
  1278. chmod 640 /var/log/apache2/access.log /var/log/apache2/error.log
  1279. chmod 751 /var/log/apache2/domains
  1280. # Prevent remote access to server-status page
  1281. sed -i '/Allow from all/d' /etc/apache2/mods-available/hestia-status.conf
  1282. update-rc.d apache2 defaults > /dev/null 2>&1
  1283. systemctl start apache2 >> $LOG
  1284. check_result $? "apache2 start failed"
  1285. else
  1286. update-rc.d apache2 disable > /dev/null 2>&1
  1287. systemctl stop apache2 > /dev/null 2>&1
  1288. fi
  1289. #----------------------------------------------------------#
  1290. # Configure PHP-FPM #
  1291. #----------------------------------------------------------#
  1292. if [ "$phpfpm" = "yes" ]; then
  1293. if [ "$multiphp" = 'yes' ]; then
  1294. for v in "${multiphp_v[@]}"; do
  1295. echo "[ * ] Install PHP $v..."
  1296. ${HESTIA}/bin/v-add-web-php "$v" > /dev/null 2>&1
  1297. done
  1298. else
  1299. echo "[ * ] Install PHP $fpm_v..."
  1300. ${HESTIA}/bin/v-add-web-php "$fpm_v" > /dev/null 2>&1
  1301. fi
  1302. echo "[ * ] Configuring PHP $fpm_v..."
  1303. # Create www.conf for webmail and php(*)admin
  1304. cp -f ${HESTIA_INSTALL_DIR}/php-fpm/www.conf /etc/php/$fpm_v/fpm/pool.d/www.conf
  1305. update-rc.d php$fpm_v-fpm defaults > /dev/null 2>&1
  1306. systemctl start php$fpm_v-fpm >> $LOG
  1307. check_result $? "php-fpm start failed"
  1308. # Set default php version to $fpm_v
  1309. update-alternatives --set php /usr/bin/php$fpm_v > /dev/null 2>&1
  1310. fi
  1311. #----------------------------------------------------------#
  1312. # Configure PHP #
  1313. #----------------------------------------------------------#
  1314. echo "[ * ] Configuring PHP..."
  1315. ZONE=$(timedatectl > /dev/null 2>&1 | grep Timezone | awk '{print $2}')
  1316. if [ -z "$ZONE" ]; then
  1317. ZONE='UTC'
  1318. fi
  1319. for pconf in $(find /etc/php* -name php.ini); do
  1320. sed -i "s%;date.timezone =%date.timezone = $ZONE%g" $pconf
  1321. sed -i 's%_open_tag = Off%_open_tag = On%g' $pconf
  1322. done
  1323. # Cleanup php session files not changed in the last 7 days (60*24*7 minutes)
  1324. echo '#!/bin/sh' > /etc/cron.daily/php-session-cleanup
  1325. echo "find -O3 /home/*/tmp/ -ignore_readdir_race -depth -mindepth 1 -name 'sess_*' -type f -cmin '+10080' -delete > /dev/null 2>&1" >> /etc/cron.daily/php-session-cleanup
  1326. echo "find -O3 $HESTIA/data/sessions/ -ignore_readdir_race -depth -mindepth 1 -name 'sess_*' -type f -cmin '+10080' -delete > /dev/null 2>&1" >> /etc/cron.daily/php-session-cleanup
  1327. chmod 755 /etc/cron.daily/php-session-cleanup
  1328. #----------------------------------------------------------#
  1329. # Configure Vsftpd #
  1330. #----------------------------------------------------------#
  1331. if [ "$vsftpd" = 'yes' ]; then
  1332. echo "[ * ] Configuring Vsftpd server..."
  1333. cp -f ${HESTIA_INSTALL_DIR}/vsftpd/vsftpd.conf /etc/
  1334. if [ "$ipv6_support" = 'yes' ]; then
  1335. cp -f ${HESTIA_INSTALL_DIR}/vsftpd/vsftpd-ipv6.conf /etc/vsftpd.conf
  1336. fi
  1337. touch /var/log/vsftpd.log
  1338. chown root:adm /var/log/vsftpd.log
  1339. chmod 640 /var/log/vsftpd.log
  1340. touch /var/log/xferlog
  1341. chown root:adm /var/log/xferlog
  1342. chmod 640 /var/log/xferlog
  1343. update-rc.d vsftpd defaults
  1344. systemctl start vsftpd >> $LOG
  1345. check_result $? "vsftpd start failed"
  1346. fi
  1347. #----------------------------------------------------------#
  1348. # Configure ProFTPD #
  1349. #----------------------------------------------------------#
  1350. if [ "$proftpd" = 'yes' ]; then
  1351. echo "[ * ] Configuring ProFTPD server..."
  1352. echo "127.0.0.1 $servername" >> /etc/hosts
  1353. cp -f ${HESTIA_INSTALL_DIR}/proftpd/proftpd.conf /etc/proftpd/
  1354. cp -f ${HESTIA_INSTALL_DIR}/proftpd/tls.conf /etc/proftpd/
  1355. if [ "$release" -eq 11 ]; then
  1356. sed -i 's|IdentLookups off|#IdentLookups off|g' /etc/proftpd/proftpd.conf
  1357. fi
  1358. update-rc.d proftpd defaults > /dev/null 2>&1
  1359. systemctl start proftpd >> $LOG
  1360. check_result $? "proftpd start failed"
  1361. if [ "$release" -eq 11 ]; then
  1362. unit_files="$(systemctl list-unit-files | grep proftpd)"
  1363. if [[ "$unit_files" =~ "disabled" ]]; then
  1364. systemctl enable proftpd
  1365. fi
  1366. fi
  1367. fi
  1368. #----------------------------------------------------------#
  1369. # Configure MariaDB / MySQL #
  1370. #----------------------------------------------------------#
  1371. if [ "$mysql" = 'yes' ] || [ "$mysql8" = 'yes' ]; then
  1372. [ "$mysql" = 'yes' ] && mysql_type="MariaDB" || mysql_type="MySQL"
  1373. echo "[ * ] Configuring $mysql_type database server..."
  1374. mycnf="my-small.cnf"
  1375. if [ $memory -gt 1200000 ]; then
  1376. mycnf="my-medium.cnf"
  1377. fi
  1378. if [ $memory -gt 3900000 ]; then
  1379. mycnf="my-large.cnf"
  1380. fi
  1381. if [ "$mysql_type" = 'MariaDB' ]; then
  1382. # Run mysql_install_db
  1383. mysql_install_db >> $LOG
  1384. fi
  1385. # Remove symbolic link
  1386. rm -f /etc/mysql/my.cnf
  1387. # Configuring MariaDB
  1388. cp -f ${HESTIA_INSTALL_DIR}/mysql/$mycnf /etc/mysql/my.cnf
  1389. # Switch MariaDB inclusions to the MySQL
  1390. if [ "$mysql_type" = 'MySQL' ]; then
  1391. sed -i '/query_cache_size/d' /etc/mysql/my.cnf
  1392. sed -i 's|mariadb.conf.d|mysql.conf.d|g' /etc/mysql/my.cnf
  1393. fi
  1394. if [ "$mysql_type" = 'MariaDB' ]; then
  1395. update-rc.d mariadb defaults > /dev/null 2>&1
  1396. systemctl -q enable mariadb 2> /dev/null
  1397. systemctl start mariadb >> $LOG
  1398. check_result $? "${mysql_type,,} start failed"
  1399. fi
  1400. if [ "$mysql_type" = 'MySQL' ]; then
  1401. update-rc.d mysql defaults > /dev/null 2>&1
  1402. systemctl -q enable mysql 2> /dev/null
  1403. systemctl start mysql >> $LOG
  1404. check_result $? "${mysql_type,,} start failed"
  1405. fi
  1406. # Securing MariaDB/MySQL installation
  1407. mpass=$(gen_pass)
  1408. echo -e "[client]\npassword='$mpass'\n" > /root/.my.cnf
  1409. chmod 600 /root/.my.cnf
  1410. if [ -f '/usr/bin/mariadb' ]; then
  1411. mysql_server="mariadb"
  1412. else
  1413. mysql_server="mysql"
  1414. fi
  1415. # Alter root password
  1416. $mysql_server -e "ALTER USER 'root'@'localhost' IDENTIFIED BY '$mpass'; FLUSH PRIVILEGES;"
  1417. if [ "$mysql_type" = 'MariaDB' ]; then
  1418. # Allow mysql access via socket for startup
  1419. $mysql_server -e "UPDATE mysql.global_priv SET priv=json_set(priv, '$.password_last_changed', UNIX_TIMESTAMP(), '$.plugin', 'mysql_native_password', '$.authentication_string', 'invalid', '$.auth_or', json_array(json_object(), json_object('plugin', 'unix_socket'))) WHERE User='root';"
  1420. # Disable anonymous users
  1421. $mysql_server -e "DELETE FROM mysql.global_priv WHERE User='';"
  1422. else
  1423. $mysql_server -e "ALTER USER 'root'@'localhost' IDENTIFIED WITH caching_sha2_password BY '$mpass';"
  1424. $mysql_server -e "DELETE FROM mysql.user WHERE User='';"
  1425. $mysql_server -e "DELETE FROM mysql.user WHERE User='root' AND Host NOT IN ('localhost', '127.0.0.1', '::1');"
  1426. fi
  1427. # Drop test database
  1428. $mysql_server -e "DROP DATABASE IF EXISTS test"
  1429. $mysql_server -e "DELETE FROM mysql.db WHERE Db='test' OR Db='test\\_%'"
  1430. # Flush privileges
  1431. $mysql_server -e "FLUSH PRIVILEGES;"
  1432. fi
  1433. #----------------------------------------------------------#
  1434. # Configure phpMyAdmin #
  1435. #----------------------------------------------------------#
  1436. # Source upgrade.conf with phpmyadmin versions
  1437. # shellcheck source=/usr/local/hestia/install/upgrade/upgrade.conf
  1438. source ${HESTIA}/install/upgrade/upgrade.conf
  1439. if [ "$mysql" = 'yes' ] || [ "$mysql8" = 'yes' ]; then
  1440. # Display upgrade information
  1441. echo "[ * ] Installing phpMyAdmin version v$pma_v..."
  1442. # Download latest phpmyadmin release
  1443. wget --quiet --retry-connrefused https://files.phpmyadmin.net/phpMyAdmin/$pma_v/phpMyAdmin-$pma_v-all-languages.tar.gz
  1444. # Unpack files
  1445. tar xzf phpMyAdmin-$pma_v-all-languages.tar.gz
  1446. # Create folders
  1447. mkdir -p /usr/share/phpmyadmin
  1448. mkdir -p /etc/phpmyadmin
  1449. mkdir -p /etc/phpmyadmin/conf.d/
  1450. mkdir /usr/share/phpmyadmin/tmp
  1451. # Configuring Apache2 for PHPMYADMIN
  1452. if [ "$apache" = 'yes' ]; then
  1453. touch /etc/apache2/conf.d/phpmyadmin.inc
  1454. fi
  1455. # Overwrite old files
  1456. cp -rf phpMyAdmin-$pma_v-all-languages/* /usr/share/phpmyadmin
  1457. # Create copy of config file
  1458. cp -f ${HESTIA_INSTALL_DIR}/phpmyadmin/config.inc.php /etc/phpmyadmin/
  1459. mkdir -p /var/lib/phpmyadmin/tmp
  1460. chmod 770 /var/lib/phpmyadmin/tmp
  1461. chown root:www-data /usr/share/phpmyadmin/tmp
  1462. # Set config and log directory
  1463. sed -i "s|'configFile' => ROOT_PATH . 'config.inc.php',|'configFile' => '/etc/phpmyadmin/config.inc.php',|g" /usr/share/phpmyadmin/libraries/vendor_config.php
  1464. # Create temporary folder and change permission
  1465. chmod 770 /usr/share/phpmyadmin/tmp
  1466. chown root:www-data /usr/share/phpmyadmin/tmp
  1467. # Generate blow fish
  1468. blowfish=$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 32)
  1469. sed -i "s|%blowfish_secret%|$blowfish|" /etc/phpmyadmin/config.inc.php
  1470. # Clean Up
  1471. rm -fr phpMyAdmin-$pma_v-all-languages
  1472. rm -f phpMyAdmin-$pma_v-all-languages.tar.gz
  1473. write_config_value "DB_PMA_ALIAS" "phpmyadmin"
  1474. ${HESTIA}/bin/v-change-sys-db-alias 'pma' "phpmyadmin"
  1475. # Special thanks to Pavel Galkin (https://skurudo.ru)
  1476. # https://github.com/skurudo/phpmyadmin-fixer
  1477. # shellcheck source=/usr/local/hestia/install/deb/phpmyadmin/pma.sh
  1478. source ${HESTIA_INSTALL_DIR}/phpmyadmin/pma.sh > /dev/null 2>&1
  1479. # limit access to /etc/phpmyadmin/
  1480. chown -R root:www-data /etc/phpmyadmin/
  1481. chmod -R 640 /etc/phpmyadmin/*
  1482. chmod 750 /etc/phpmyadmin/conf.d/
  1483. fi
  1484. #----------------------------------------------------------#
  1485. # Configure PostgreSQL #
  1486. #----------------------------------------------------------#
  1487. if [ "$postgresql" = 'yes' ]; then
  1488. echo "[ * ] Configuring PostgreSQL database server..."
  1489. ppass=$(gen_pass)
  1490. cp -f ${HESTIA_INSTALL_DIR}/postgresql/pg_hba.conf /etc/postgresql/*/main/
  1491. systemctl restart postgresql
  1492. sudo -iu postgres psql -c "ALTER USER postgres WITH PASSWORD '$ppass'" > /dev/null 2>&1
  1493. mkdir -p /etc/phppgadmin/
  1494. mkdir -p /usr/share/phppgadmin/
  1495. wget --retry-connrefused --quiet https://github.com/hestiacp/phppgadmin/releases/download/v$pga_v/phppgadmin-v$pga_v.tar.gz
  1496. tar xzf phppgadmin-v$pga_v.tar.gz -C /usr/share/phppgadmin/
  1497. cp -f ${HESTIA_INSTALL_DIR}/pga/config.inc.php /etc/phppgadmin/
  1498. ln -s /etc/phppgadmin/config.inc.php /usr/share/phppgadmin/conf/
  1499. # Configuring phpPgAdmin
  1500. if [ "$apache" = 'yes' ]; then
  1501. cp -f ${HESTIA_INSTALL_DIR}/pga/phppgadmin.conf /etc/apache2/conf.d/phppgadmin.inc
  1502. fi
  1503. rm phppgadmin-v$pga_v.tar.gz
  1504. write_config_value "DB_PGA_ALIAS" "phppgadmin"
  1505. ${HESTIA}/bin/v-change-sys-db-alias 'pga' "phppgadmin"
  1506. fi
  1507. #----------------------------------------------------------#
  1508. # Configure Bind #
  1509. #----------------------------------------------------------#
  1510. if [ "$named" = 'yes' ]; then
  1511. echo "[ * ] Configuring Bind DNS server..."
  1512. cp -f ${HESTIA_INSTALL_DIR}/bind/named.conf /etc/bind/
  1513. cp -f ${HESTIA_INSTALL_DIR}/bind/named.conf.options /etc/bind/
  1514. chown root:bind /etc/bind/named.conf
  1515. chown root:bind /etc/bind/named.conf.options
  1516. chown bind:bind /var/cache/bind
  1517. chmod 640 /etc/bind/named.conf
  1518. chmod 640 /etc/bind/named.conf.options
  1519. aa-complain /usr/sbin/named 2> /dev/null
  1520. if [ "$apparmor" = 'yes' ]; then
  1521. echo "/home/** rwm," >> /etc/apparmor.d/local/usr.sbin.named 2> /dev/null
  1522. systemctl status apparmor > /dev/null 2>&1
  1523. if [ $? -ne 0 ]; then
  1524. systemctl restart apparmor >> $LOG
  1525. fi
  1526. fi
  1527. update-rc.d bind9 defaults > /dev/null 2>&1
  1528. systemctl start bind9
  1529. check_result $? "bind9 start failed"
  1530. # Workaround for OpenVZ/Virtuozzo
  1531. if [ -e "/proc/vz/veinfo" ] && [ -e "/etc/rc.local" ]; then
  1532. sed -i "s/^exit 0/service bind9 restart\nexit 0/" /etc/rc.local
  1533. fi
  1534. fi
  1535. #----------------------------------------------------------#
  1536. # Configure Exim #
  1537. #----------------------------------------------------------#
  1538. if [ "$exim" = 'yes' ]; then
  1539. echo "[ * ] Configuring Exim mail server..."
  1540. gpasswd -a Debian-exim mail > /dev/null 2>&1
  1541. exim_version=$(exim4 --version | head -1 | awk '{print $3}' | cut -f -2 -d .)
  1542. if [ "$exim_version" = "4.94" ]; then
  1543. cp -f ${HESTIA_INSTALL_DIR}/exim/exim4.conf.4.94.template /etc/exim4/exim4.conf.template
  1544. else
  1545. cp -f ${HESTIA_INSTALL_DIR}/exim/exim4.conf.template /etc/exim4/
  1546. fi
  1547. cp -f ${HESTIA_INSTALL_DIR}/exim/dnsbl.conf /etc/exim4/
  1548. cp -f ${HESTIA_INSTALL_DIR}/exim/spam-blocks.conf /etc/exim4/
  1549. cp -f ${HESTIA_INSTALL_DIR}/exim/limit.conf /etc/exim4/
  1550. cp -f ${HESTIA_INSTALL_DIR}/exim/system.filter /etc/exim4/
  1551. touch /etc/exim4/white-blocks.conf
  1552. if [ "$spamd" = 'yes' ]; then
  1553. sed -i "s/#SPAM/SPAM/g" /etc/exim4/exim4.conf.template
  1554. fi
  1555. if [ "$clamd" = 'yes' ]; then
  1556. sed -i "s/#CLAMD/CLAMD/g" /etc/exim4/exim4.conf.template
  1557. fi
  1558. chmod 640 /etc/exim4/exim4.conf.template
  1559. rm -rf /etc/exim4/domains
  1560. mkdir -p /etc/exim4/domains
  1561. rm -f /etc/alternatives/mta
  1562. ln -s /usr/sbin/exim4 /etc/alternatives/mta
  1563. update-rc.d -f sendmail remove > /dev/null 2>&1
  1564. systemctl stop sendmail > /dev/null 2>&1
  1565. update-rc.d -f postfix remove > /dev/null 2>&1
  1566. systemctl stop postfix > /dev/null 2>&1
  1567. update-rc.d exim4 defaults
  1568. systemctl start exim4 >> $LOG
  1569. check_result $? "exim4 start failed"
  1570. fi
  1571. #----------------------------------------------------------#
  1572. # Configure Dovecot #
  1573. #----------------------------------------------------------#
  1574. if [ "$dovecot" = 'yes' ]; then
  1575. echo "[ * ] Configuring Dovecot POP/IMAP mail server..."
  1576. gpasswd -a dovecot mail > /dev/null 2>&1
  1577. cp -rf ${HESTIA_COMMON_DIR}/dovecot /etc/
  1578. cp -f ${HESTIA_INSTALL_DIR}/logrotate/dovecot /etc/logrotate.d/
  1579. rm -f /etc/dovecot/conf.d/15-mailboxes.conf
  1580. chown -R root:root /etc/dovecot*
  1581. #Alter config for 2.2
  1582. version=$(dovecot --version | cut -f -2 -d .)
  1583. if [ "$version" = "2.2" ]; then
  1584. echo "[ * ] Downgrade dovecot config to sync with 2.2 settings"
  1585. sed -i 's|#ssl_dh_parameters_length = 4096|ssl_dh_parameters_length = 4096|g' /etc/dovecot/conf.d/10-ssl.conf
  1586. sed -i 's|ssl_dh = </etc/ssl/dhparam.pem|#ssl_dh = </etc/ssl/dhparam.pem|g' /etc/dovecot/conf.d/10-ssl.conf
  1587. sed -i 's|ssl_min_protocol = TLSv1.2|ssl_protocols = !SSLv3 !TLSv1 !TLSv1.1|g' /etc/dovecot/conf.d/10-ssl.conf
  1588. fi
  1589. update-rc.d dovecot defaults
  1590. systemctl start dovecot >> $LOG
  1591. check_result $? "dovecot start failed"
  1592. fi
  1593. #----------------------------------------------------------#
  1594. # Configure ClamAV #
  1595. #----------------------------------------------------------#
  1596. if [ "$clamd" = 'yes' ]; then
  1597. gpasswd -a clamav mail > /dev/null 2>&1
  1598. gpasswd -a clamav Debian-exim > /dev/null 2>&1
  1599. cp -f ${HESTIA_INSTALL_DIR}/clamav/clamd.conf /etc/clamav/
  1600. update-rc.d clamav-daemon defaults
  1601. if [ ! -d "/run/clamav" ]; then
  1602. mkdir /run/clamav
  1603. fi
  1604. chown -R clamav:clamav /run/clamav
  1605. if [ -e "/lib/systemd/system/clamav-daemon.service" ]; then
  1606. exec_pre1='ExecStartPre=-/bin/mkdir -p /run/clamav'
  1607. exec_pre2='ExecStartPre=-/bin/chown -R clamav:clamav /run/clamav'
  1608. sed -i "s|\[Service\]/|[Service]\n$exec_pre1\n$exec_pre2|g" \
  1609. /lib/systemd/system/clamav-daemon.service
  1610. systemctl daemon-reload
  1611. fi
  1612. echo -ne "[ * ] Installing ClamAV anti-virus definitions... "
  1613. /usr/bin/freshclam >> $LOG &
  1614. BACK_PID=$!
  1615. spin_i=1
  1616. while kill -0 $BACK_PID > /dev/null 2>&1; do
  1617. printf "\b${spinner:spin_i++%${#spinner}:1}"
  1618. sleep 0.5
  1619. done
  1620. echo
  1621. systemctl start clamav-daemon >> $LOG
  1622. check_result $? "clamav-daemon start failed"
  1623. fi
  1624. #----------------------------------------------------------#
  1625. # Configure SpamAssassin #
  1626. #----------------------------------------------------------#
  1627. if [ "$spamd" = 'yes' ]; then
  1628. echo "[ * ] Configuring SpamAssassin..."
  1629. update-rc.d spamassassin defaults > /dev/null 2>&1
  1630. sed -i "s/ENABLED=0/ENABLED=1/" /etc/default/spamassassin
  1631. systemctl start spamassassin >> $LOG
  1632. check_result $? "spamassassin start failed"
  1633. unit_files="$(systemctl list-unit-files | grep spamassassin)"
  1634. if [[ "$unit_files" =~ "disabled" ]]; then
  1635. systemctl enable spamassassin > /dev/null 2>&1
  1636. fi
  1637. sed -i "s/#CRON=1/CRON=1/" /etc/default/spamassassin
  1638. fi
  1639. #----------------------------------------------------------#
  1640. # Configure Fail2Ban #
  1641. #----------------------------------------------------------#
  1642. if [ "$fail2ban" = 'yes' ]; then
  1643. echo "[ * ] Configuring fail2ban access monitor..."
  1644. cp -rf ${HESTIA_INSTALL_DIR}/fail2ban /etc/
  1645. if [ "$dovecot" = 'no' ]; then
  1646. fline=$(cat /etc/fail2ban/jail.local | grep -n dovecot-iptables -A 2)
  1647. fline=$(echo "$fline" | grep enabled | tail -n1 | cut -f 1 -d -)
  1648. sed -i "${fline}s/true/false/" /etc/fail2ban/jail.local
  1649. fi
  1650. if [ "$exim" = 'no' ]; then
  1651. fline=$(cat /etc/fail2ban/jail.local | grep -n exim-iptables -A 2)
  1652. fline=$(echo "$fline" | grep enabled | tail -n1 | cut -f 1 -d -)
  1653. sed -i "${fline}s/true/false/" /etc/fail2ban/jail.local
  1654. fi
  1655. if [ "$vsftpd" = 'yes' ]; then
  1656. # Create vsftpd Log File
  1657. if [ ! -f "/var/log/vsftpd.log" ]; then
  1658. touch /var/log/vsftpd.log
  1659. fi
  1660. fline=$(cat /etc/fail2ban/jail.local | grep -n vsftpd-iptables -A 2)
  1661. fline=$(echo "$fline" | grep enabled | tail -n1 | cut -f 1 -d -)
  1662. sed -i "${fline}s/false/true/" /etc/fail2ban/jail.local
  1663. fi
  1664. if [ ! -e /var/log/auth.log ]; then
  1665. # Debian workaround: auth logging was moved to systemd
  1666. touch /var/log/auth.log
  1667. chmod 640 /var/log/auth.log
  1668. chown root:adm /var/log/auth.log
  1669. fi
  1670. if [ -f /etc/fail2ban/jail.d/defaults-debian.conf ]; then
  1671. rm -f /etc/fail2ban/jail.d/defaults-debian.conf
  1672. fi
  1673. update-rc.d fail2ban defaults
  1674. systemctl start fail2ban >> $LOG
  1675. check_result $? "fail2ban start failed"
  1676. fi
  1677. # Configuring MariaDB/MySQL host
  1678. if [ "$mysql" = 'yes' ] || [ "$mysql8" = 'yes' ]; then
  1679. ${HESTIA}/bin/v-add-database-host mysql localhost root $mpass
  1680. fi
  1681. # Configuring PostgreSQL host
  1682. if [ "$postgresql" = 'yes' ]; then
  1683. ${HESTIA}/bin/v-add-database-host pgsql localhost postgres $ppass
  1684. fi
  1685. #----------------------------------------------------------#
  1686. # Install Roundcube #
  1687. #----------------------------------------------------------#
  1688. # Min requirements Dovecot + Exim + Mysql
  1689. if ([ "$mysql" == 'yes' ] || [ "$mysql8" == 'yes' ]) && [ "$dovecot" == "yes" ]; then
  1690. echo "[ * ] Install Roundcube..."
  1691. ${HESTIA}/bin/v-add-sys-roundcube
  1692. write_config_value "WEBMAIL_ALIAS" "webmail"
  1693. else
  1694. write_config_value "WEBMAIL_ALIAS" ""
  1695. write_config_value "WEBMAIL_SYSTEM" ""
  1696. fi
  1697. #----------------------------------------------------------#
  1698. # Install Sieve #
  1699. #----------------------------------------------------------#
  1700. # Min requirements Dovecot + Exim + Mysql + Roundcube
  1701. if [ "$sieve" = 'yes' ]; then
  1702. # Folder paths
  1703. RC_INSTALL_DIR="/var/lib/roundcube"
  1704. RC_CONFIG_DIR="/etc/roundcube"
  1705. echo "[ * ] Install Sieve..."
  1706. # dovecot.conf install
  1707. sed -i "s/namespace/service stats \{\n unix_listener stats-writer \{\n group = mail\n mode = 0660\n user = dovecot\n \}\n\}\n\nnamespace/g" /etc/dovecot/dovecot.conf
  1708. # Dovecot conf files
  1709. # 10-master.conf
  1710. sed -i -E -z "s/ }\n user = dovecot\n}/ \}\n unix_listener auth-master \{\n group = mail\n mode = 0660\n user = dovecot\n \}\n user = dovecot\n\}/g" /etc/dovecot/conf.d/10-master.conf
  1711. # 15-lda.conf
  1712. sed -i "s/\#mail_plugins = \\\$mail_plugins/mail_plugins = \$mail_plugins quota sieve\n auth_socket_path = \/var\/run\/dovecot\/auth-master/g" /etc/dovecot/conf.d/15-lda.conf
  1713. # 20-imap.conf
  1714. sed -i "s/mail_plugins = quota imap_quota/mail_plugins = quota imap_quota imap_sieve/g" /etc/dovecot/conf.d/20-imap.conf
  1715. # Replace dovecot-sieve config files
  1716. cp -f ${HESTIA_COMMON_DIR}/dovecot/sieve/* /etc/dovecot/conf.d
  1717. # Dovecot default file install
  1718. echo -e "require [\"fileinto\"];\n# rule:[SPAM]\nif header :contains \"X-Spam-Flag\" \"YES\" {\n fileinto \"INBOX.Spam\";\n}\n" > /etc/dovecot/sieve/default
  1719. # exim4 install
  1720. sed -i "s/\stransport = local_delivery/ transport = dovecot_virtual_delivery/" /etc/exim4/exim4.conf.template
  1721. sed -i "s/address_pipe:/dovecot_virtual_delivery:\n driver = pipe\n command = \/usr\/lib\/dovecot\/dovecot-lda -e -d \$local_part@\$domain -f \$sender_address -a \$original_local_part@\$original_domain\n delivery_date_add\n envelope_to_add\n return_path_add\n log_output = true\n log_defer_output = true\n user = \${extract{2}{:}{\${lookup{\$local_part}lsearch{\/etc\/exim4\/domains\/\${lookup{\$domain}dsearch{\/etc\/exim4\/domains\/}}\/passwd}}}}\n group = mail\n return_output\n\naddress_pipe:/g" /etc/exim4/exim4.conf.template
  1722. # Permission changes
  1723. chown -R dovecot:mail /var/log/dovecot.log
  1724. chmod 660 /var/log/dovecot.log
  1725. if [ -d "/var/lib/roundcube" ]; then
  1726. # Modify Roundcube config
  1727. mkdir -p $RC_CONFIG_DIR/plugins/managesieve
  1728. cp -f ${HESTIA_COMMON_DIR}/roundcube/plugins/config_managesieve.inc.php $RC_CONFIG_DIR/plugins/managesieve/config.inc.php
  1729. ln -s $RC_CONFIG_DIR/plugins/managesieve/config.inc.php $RC_INSTALL_DIR/plugins/managesieve/config.inc.php
  1730. chown -R root:www-data $RC_CONFIG_DIR/
  1731. chmod 751 -R $RC_CONFIG_DIR
  1732. chmod 644 $RC_CONFIG_DIR/*.php
  1733. chmod 644 $RC_CONFIG_DIR/plugins/managesieve/config.inc.php
  1734. sed -i "s/'archive'/'archive', 'managesieve'/g" $RC_CONFIG_DIR/config.inc.php
  1735. fi
  1736. # Restart Dovecot and exim4
  1737. systemctl restart dovecot > /dev/null 2>&1
  1738. systemctl restart exim4 > /dev/null 2>&1
  1739. fi
  1740. #----------------------------------------------------------#
  1741. # Configure API #
  1742. #----------------------------------------------------------#
  1743. if [ "$api" = "yes" ]; then
  1744. # Keep legacy api enabled until transition is complete
  1745. write_config_value "API" "yes"
  1746. write_config_value "API_SYSTEM" "1"
  1747. write_config_value "API_ALLOWED_IP" ""
  1748. else
  1749. write_config_value "API" "no"
  1750. write_config_value "API_SYSTEM" "0"
  1751. write_config_value "API_ALLOWED_IP" ""
  1752. ${HESTIA}/bin/v-change-sys-api disable
  1753. fi
  1754. #----------------------------------------------------------#
  1755. # Configure File Manager #
  1756. #----------------------------------------------------------#
  1757. echo "[ * ] Configuring File Manager..."
  1758. ${HESTIA}/bin/v-add-sys-filemanager quiet
  1759. #----------------------------------------------------------#
  1760. # Configure dependencies #
  1761. #----------------------------------------------------------#
  1762. echo "[ * ] Configuring PHP dependencies..."
  1763. ${HESTIA}/bin/v-add-sys-dependencies quiet
  1764. echo "[ * ] Install Rclone"
  1765. curl -s https://rclone.org/install.sh | bash > /dev/null 2>&1
  1766. #----------------------------------------------------------#
  1767. # Configure IP #
  1768. #----------------------------------------------------------#
  1769. # Configuring system IPs
  1770. echo "[ * ] Configuring System IP..."
  1771. ${HESTIA}/bin/v-update-sys-ip > /dev/null 2>&1
  1772. # Get primary IP
  1773. default_nic="$(ip -d -j route show | jq -r '.[] | if .dst == "default" then .dev else empty end')"
  1774. # IPv4
  1775. primary_ipv4="$(ip -4 -d -j addr show "$default_nic" | jq -r '.[].addr_info[] | if .scope == "global" then .local else empty end' | head -n1)"
  1776. ip=${primary_ipv4}
  1777. local_ip=${primary_ipv4}
  1778. # IPv6
  1779. if [ "$ipv6_support" = 'yes' ]; then
  1780. primary_ipv6="$(ip -6 -d -j addr show "$default_nic" | jq -r '.[].addr_info[] | if .scope == "global" then .local else empty end' | head -n1)"
  1781. ipv6=${primary_ipv6}
  1782. local_ipv6=${primary_ipv6}
  1783. else
  1784. primary_ipv6=""
  1785. ipv6=""
  1786. local_ipv6=""
  1787. fi
  1788. # Configuring firewall
  1789. if [ "$iptables" = 'yes' ]; then
  1790. ${HESTIA}/bin/v-update-firewall
  1791. fi
  1792. # Get public IP
  1793. pub_ipv4="$(curl -fsLm5 --retry 2 --ipv4 https://ip.hestiacp.com/)"
  1794. if [ "$ipv6_support" = 'yes' ]; then
  1795. pub_ipv6="$(curl -fsLm5 --retry 2 --ipv6 https://ip.hestiacp.com/)"
  1796. else
  1797. pub_ipv6=""
  1798. fi
  1799. if [ -n "$pub_ipv4" ] && [ "$pub_ipv4" != "$ip" ]; then
  1800. ${HESTIA}/bin/v-change-sys-ip-nat ${ip} ${pub_ipv4} > /dev/null 2>&1
  1801. ip=${pub_ipv4}
  1802. fi
  1803. # Configuring libapache2-mod-remoteip
  1804. if [ "$apache" = 'yes' ] && [ "$nginx" = 'yes' ]; then
  1805. cd /etc/apache2/mods-available
  1806. echo "<IfModule mod_remoteip.c>" > remoteip.conf
  1807. echo " RemoteIPHeader X-Real-IP" >> remoteip.conf
  1808. if [ "$local_ip" != "127.0.0.1" ] && [ "$pub_ipv4" != "127.0.0.1" ]; then
  1809. echo " RemoteIPInternalProxy 127.0.0.1" >> remoteip.conf
  1810. fi
  1811. if [ -n "$local_ip" ] && [ "$local_ip" != "$pub_ipv4" ]; then
  1812. echo " RemoteIPInternalProxy $local_ip" >> remoteip.conf
  1813. fi
  1814. if [ -n "$pub_ipv4" ]; then
  1815. echo " RemoteIPInternalProxy $pub_ipv4" >> remoteip.conf
  1816. fi
  1817. echo "</IfModule>" >> remoteip.conf
  1818. sed -i "s/LogFormat \"%h/LogFormat \"%a/g" /etc/apache2/apache2.conf
  1819. a2enmod remoteip >> $LOG
  1820. systemctl restart apache2
  1821. fi
  1822. # Adding default domain
  1823. if [ -n "$ip" ]; then
  1824. if [ -n "$ipv6" ]; then
  1825. ${HESTIA}/bin/v-add-web-domain-ipv46 admin ${servername} ${ip} ${ipv6}
  1826. else
  1827. ${HESTIA}/bin/v-add-web-domain-ipv46 admin ${servername} ${ip}
  1828. fi
  1829. else
  1830. if [ -n "$ipv6" ]; then
  1831. ${HESTIA}/bin/v-add-web-domain-ipv46 admin ${servername} "" ${ipv6}
  1832. fi
  1833. fi
  1834. check_result $? "can't create $servername domain"
  1835. # Adding cron jobs
  1836. export SCHEDULED_RESTART="yes"
  1837. command="sudo $HESTIA/bin/v-update-sys-queue restart"
  1838. ${HESTIA}/bin/v-add-cron-job 'admin' '*/2' '*' '*' '*' '*' "$command"
  1839. systemctl restart cron
  1840. command="sudo $HESTIA/bin/v-update-sys-queue daily"
  1841. ${HESTIA}/bin/v-add-cron-job 'admin' '10' '00' '*' '*' '*' "$command"
  1842. command="sudo $HESTIA/bin/v-update-sys-queue disk"
  1843. ${HESTIA}/bin/v-add-cron-job 'admin' '15' '02' '*' '*' '*' "$command"
  1844. command="sudo $HESTIA/bin/v-update-sys-queue traffic"
  1845. ${HESTIA}/bin/v-add-cron-job 'admin' '10' '00' '*' '*' '*' "$command"
  1846. command="sudo $HESTIA/bin/v-update-sys-queue webstats"
  1847. ${HESTIA}/bin/v-add-cron-job 'admin' '30' '03' '*' '*' '*' "$command"
  1848. command="sudo $HESTIA/bin/v-update-sys-queue backup"
  1849. ${HESTIA}/bin/v-add-cron-job 'admin' '*/5' '*' '*' '*' '*' "$command"
  1850. command="sudo $HESTIA/bin/v-backup-users"
  1851. ${HESTIA}/bin/v-add-cron-job 'admin' '10' '05' '*' '*' '*' "$command"
  1852. command="sudo $HESTIA/bin/v-update-user-stats"
  1853. ${HESTIA}/bin/v-add-cron-job 'admin' '20' '00' '*' '*' '*' "$command"
  1854. command="sudo $HESTIA/bin/v-update-sys-rrd"
  1855. ${HESTIA}/bin/v-add-cron-job 'admin' '*/5' '*' '*' '*' '*' "$command"
  1856. command="sudo $HESTIA/bin/v-update-letsencrypt-ssl"
  1857. min=$(gen_pass '012345' '2')
  1858. hour=$(gen_pass '1234567' '1')
  1859. ${HESTIA}/bin/v-add-cron-job 'admin' "$min" "$hour" '*' '*' '*' "$command"
  1860. # Enable automatic updates
  1861. ${HESTIA}/bin/v-add-cron-hestia-autoupdate apt
  1862. # Building initital rrd images
  1863. ${HESTIA}/bin/v-update-sys-rrd
  1864. # Enabling file system quota
  1865. if [ "$quota" = 'yes' ]; then
  1866. ${HESTIA}/bin/v-add-sys-quota
  1867. fi
  1868. # Set backend port
  1869. ${HESTIA}/bin/v-change-sys-port $port > /dev/null 2>&1
  1870. # Create default configuration files
  1871. ${HESTIA}/bin/v-update-sys-defaults
  1872. # Update remaining packages since repositories have changed
  1873. echo -ne "[ * ] Installing remaining software updates..."
  1874. apt-get -qq update
  1875. apt-get -y upgrade >> $LOG &
  1876. BACK_PID=$!
  1877. echo
  1878. # Starting Hestia service
  1879. update-rc.d hestia defaults
  1880. systemctl start hestia
  1881. check_result $? "hestia start failed"
  1882. chown admin:admin ${HESTIA}/data/sessions
  1883. # Create backup folder and set correct permission
  1884. mkdir -p /backup/
  1885. chmod 755 /backup/
  1886. # Create cronjob to generate ssl
  1887. echo "@reboot root sleep 10 && rm /etc/cron.d/hestia-ssl && PATH='/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:' && /usr/local/hestia/bin/v-add-letsencrypt-host" > /etc/cron.d/hestia-ssl
  1888. #----------------------------------------------------------#
  1889. # Set hestia.conf default values #
  1890. #----------------------------------------------------------#
  1891. echo "[ * ] Updating configuration files..."
  1892. BIN="${HESTIA}/bin"
  1893. source ${HESTIA}/func/syshealth.sh
  1894. syshealth_repair_system_config
  1895. # Add /usr/local/hestia/bin/ to path variable
  1896. echo 'if [ "${PATH#*/usr/local/hestia/bin*}" = "$PATH" ]; then
  1897. . /etc/profile.d/hestia.sh
  1898. fi' >> /root/.bashrc
  1899. #----------------------------------------------------------#
  1900. # Hestia Access Info #
  1901. #----------------------------------------------------------#
  1902. # Comparing hostname and IP
  1903. host_ipv4=$(host -t A ${servername})
  1904. if [ $? -eq 0 ]; then
  1905. host_ipv4=$(echo "$host_ipv4" | sed -e 's/[^ ]* .* \([^ ]*\)/\1/')
  1906. else
  1907. host_ipv4=""
  1908. fi
  1909. if [ "$ipv6_support" = 'yes' ]; then
  1910. host_ipv6=$(host -t AAAA ${servername})
  1911. if [ $? -eq 0 ]; then
  1912. host_ipv6=$(echo "$host_ipv6" | sed -e 's/[^ ]* .* \([^ ]*\)/\1/')
  1913. else
  1914. host_ipv6=""
  1915. fi
  1916. else
  1917. host_ipv6=""
  1918. fi
  1919. echo -e "\n"
  1920. echo "===================================================================="
  1921. echo -e "\n"
  1922. # Sending notification to admin email
  1923. echo -e "Congratulations!
  1924. You have successfully installed Hestia Control Panel on your server.
  1925. Ready to get started? Log in using the following credentials:
  1926. " > $tmpfile
  1927. if [ -n "$ip" -a "$host_ipv4" = "$ip" ]; then
  1928. ipv4_accessible=1
  1929. else
  1930. ipv4_accessible=0
  1931. fi
  1932. if [ -n "$ipv6" -a "$host_ipv6" = "$ipv6" ]; then
  1933. ipv6_accessible=1
  1934. else
  1935. ipv6_accessible=0
  1936. fi
  1937. if [ $ipv4_accessible -eq 1 -o $ipv6_accessible -eq 1 ]; then
  1938. echo -e " Admin URL: https://${servername}:$port" >> $tmpfile
  1939. else
  1940. echo -e " ${servername} is not accessible from internet!" >> $tmpfile
  1941. echo -e " Use Backup URL for Admin login:" >> $tmpfile
  1942. fi
  1943. if [ -n "$ip" ]; then
  1944. echo " Backup URL: https://$ip:$port" >> $tmpfile
  1945. fi
  1946. if [ -n "$ipv6" ]; then
  1947. echo " Backup URL: https://[$ipv6]:$port" >> $tmpfile
  1948. fi
  1949. echo -e -n " Username: admin
  1950. Password: $displaypass
  1951. Thank you for choosing Hestia Control Panel to power your full stack web server,
  1952. we hope that you enjoy using it as much as we do!
  1953. Please feel free to contact us at any time if you have any questions,
  1954. or if you encounter any bugs or problems:
  1955. Documentation: https://hestiacp.com/docs/
  1956. Forum: https://forum.hestiacp.com/
  1957. Discord: https://discord.gg/nXRUZch
  1958. GitHub: https://www.github.com/hestiacp/hestiacp
  1959. Note: Automatic updates are enabled by default. If you would like to disable them,
  1960. please log in and navigate to Server > Updates to turn them off.
  1961. Help support the Hestia Control Panel project by donating via PayPal:
  1962. https://www.hestiacp.com/donate
  1963. --
  1964. Sincerely yours,
  1965. The Hestia Control Panel development team
  1966. Made with love & pride by the open-source community around the world.
  1967. " >> $tmpfile
  1968. send_mail="$HESTIA/web/inc/mail-wrapper.php"
  1969. cat $tmpfile | $send_mail -s "Hestia Control Panel" $email
  1970. # Congrats
  1971. echo
  1972. cat $tmpfile
  1973. rm -f $tmpfile
  1974. # Add welcome message to notification panel
  1975. ${HESTIA}/bin/v-add-user-notification admin 'Welcome to Hestia Control Panel!' '<br>You are now ready to begin <a href="/add/user/">adding user accounts</a> and <a href="/add/web/">domains</a>. For help and assistance, <a href="https://hestiacp.com/docs/" target="_blank">view the documentation</a> or <a href="https://forum.hestiacp.com/" target="_blank">visit our forum</a>.<br><br>Please <a href="https://github.com/hestiacp/hestiacp/issues" target="_blank">report any issues via GitHub</a>.<br><br><b>Have a wonderful day!</b><br><br><i class="fas fa-heart icon-red"></i> The Hestia Control Panel development team'
  1976. # Clean-up
  1977. # Sort final configuration file
  1978. sort_config_file
  1979. if [ "$interactive" = 'yes' ]; then
  1980. echo "[ ! ] IMPORTANT: The system will now reboot to complete the installation process."
  1981. read -n 1 -s -r -p "Press any key to continue"
  1982. reboot
  1983. else
  1984. echo "[ ! ] IMPORTANT: You must restart the system before continuing!"
  1985. fi
  1986. # EOF