rebuild.sh 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867
  1. #!/bin/bash
  2. #===========================================================================#
  3. # #
  4. # Hestia Control Panel - Rebuild Function Library #
  5. # #
  6. #===========================================================================#
  7. # User account rebuild
  8. rebuild_user_conf() {
  9. sanitize_config_file "user"
  10. # Get user variables
  11. source_conf "$USER_DATA/user.conf"
  12. # Creating user data files
  13. chmod 770 $USER_DATA
  14. chmod 660 $USER_DATA/user.conf
  15. touch $USER_DATA/backup.conf
  16. chmod 660 $USER_DATA/backup.conf
  17. touch $USER_DATA/history.log
  18. chmod 660 $USER_DATA/history.log
  19. touch $USER_DATA/stats.log
  20. chmod 660 $USER_DATA/stats.log
  21. # Update FNAME LNAME to NAME
  22. if [ -z "$NAME" ]; then
  23. NAME="$FNAME $LNAME"
  24. if [ -z $FNAME ]; then NAME=""; fi
  25. sed -i "s/FNAME='$FNAME'/NAME='$NAME'/g" $USER_DATA/user.conf
  26. sed -i "/LNAME='$LNAME'/d" $USER_DATA/user.conf
  27. fi
  28. if [ -z "${TWOFA+x}" ]; then
  29. sed -i "/RKEY/a TWOFA=''" $USER_DATA/user.conf
  30. fi
  31. if [ -z "${QRCODE+x}" ]; then
  32. sed -i "/TWOFA/a QRCODE=''" $USER_DATA/user.conf
  33. fi
  34. if [ -z "${PHPCLI+x}" ]; then
  35. sed -i "/QRCODE/a PHPCLI=''" $USER_DATA/user.conf
  36. fi
  37. if [ -z "${ROLE+x}" ]; then
  38. sed -i "/PHPCLI/a ROLE='user'" $USER_DATA/user.conf
  39. fi
  40. if [ -z "${THEME+x}" ]; then
  41. sed -i "/LANGUAGE/a THEME=''" $USER_DATA/user.conf
  42. fi
  43. if [ -z "${PREF_UI_SORT+x}" ]; then
  44. sed -i "/NOTIFICATIONS/a PREF_UI_SORT='name'" $USER_DATA/user.conf
  45. fi
  46. if [ -z "${LOGIN_DISABLED+x}" ]; then
  47. sed -i "/PREF_UI_SORT/a LOGIN_DISABLED=''" $USER_DATA/user.conf
  48. fi
  49. if [ -z "${LOGIN_USE_IPLIST+x}" ]; then
  50. sed -i "/LOGIN_DISABLED/a LOGIN_USE_IPLIST=''" $USER_DATA/user.conf
  51. fi
  52. if [ -z "${LOGIN_ALLOW_IPS+x}" ]; then
  53. sed -i "/LOGIN_USE_IPLIST/a LOGIN_ALLOW_IPS=''" $USER_DATA/user.conf
  54. fi
  55. # Run template trigger
  56. if [ -x "$HESTIA/data/packages/$PACKAGE.sh" ]; then
  57. $HESTIA/data/packages/$PACKAGE.sh "$user" "$CONTACT" "$NAME"
  58. fi
  59. # Rebuild user
  60. shell=$(grep -w "$SHELL" /etc/shells |head -n1)
  61. /usr/sbin/useradd "$user" -s "$shell" -c "$CONTACT" \
  62. -m -d "$HOMEDIR/$user" > /dev/null 2>&1
  63. # Add a general group for normal users created by Hestia
  64. if [ -z "$(grep "^hestia-users:" /etc/group)" ]; then
  65. groupadd --system "hestia-users"
  66. fi
  67. # Add membership to hestia-users group to non-admin users
  68. if [ "$user" = "admin" ]; then
  69. setfacl -m "g:admin:r-x" "$HOMEDIR/$user"
  70. else
  71. usermod -a -G "hestia-users" "$user"
  72. setfacl -m "u:$user:r-x" "$HOMEDIR/$user"
  73. fi
  74. setfacl -m "g:hestia-users:---" "$HOMEDIR/$user"
  75. # Update user shell
  76. /usr/bin/chsh -s "$shell" "$user" &>/dev/null
  77. # Update password
  78. chmod u+w /etc/shadow
  79. sed -i "s|^$user:[^:]*:|$user:$MD5:|" /etc/shadow
  80. chmod u-w /etc/shadow
  81. # Building directory tree
  82. if [ -e "$HOMEDIR/$user/conf" ]; then
  83. chattr -i $HOMEDIR/$user/conf > /dev/null 2>&1
  84. fi
  85. # Create default writeable folders
  86. mkdir -p \
  87. $HOMEDIR/$user/conf \
  88. $HOMEDIR/$user/.config \
  89. $HOMEDIR/$user/.cache \
  90. $HOMEDIR/$user/.local \
  91. $HOMEDIR/$user/.composer \
  92. $HOMEDIR/$user/.vscode-server \
  93. $HOMEDIR/$user/.ssh \
  94. $HOMEDIR/$user/.npm
  95. chmod a+x $HOMEDIR/$user
  96. chmod a+x $HOMEDIR/$user/conf
  97. chown --no-dereference $user:$user \
  98. $HOMEDIR/$user \
  99. $HOMEDIR/$user/.config \
  100. $HOMEDIR/$user/.cache \
  101. $HOMEDIR/$user/.local \
  102. $HOMEDIR/$user/.composer \
  103. $HOMEDIR/$user/.vscode-server \
  104. $HOMEDIR/$user/.ssh \
  105. $HOMEDIR/$user/.npm
  106. chown root:root $HOMEDIR/$user/conf
  107. $BIN/v-add-user-sftp-jail "$user"
  108. # Update disk pipe
  109. sed -i "/ $user$/d" $HESTIA/data/queue/disk.pipe
  110. echo "$BIN/v-update-user-disk $user" >> $HESTIA/data/queue/disk.pipe
  111. # WEB
  112. if [ -n "$WEB_SYSTEM" ] && [ "$WEB_SYSTEM" != 'no' ]; then
  113. mkdir -p $USER_DATA/ssl
  114. chmod 770 $USER_DATA/ssl
  115. touch $USER_DATA/web.conf
  116. chmod 660 $USER_DATA/web.conf
  117. if [ "$(grep -w $user $HESTIA/data/queue/traffic.pipe)" ]; then
  118. echo "$BIN/v-update-web-domains-traff $user" \
  119. >> $HESTIA/data/queue/traffic.pipe
  120. fi
  121. echo "$BIN/v-update-web-domains-disk $user" \
  122. >> $HESTIA/data/queue/disk.pipe
  123. if [[ -L "$HOMEDIR/$user/web" ]]; then
  124. rm $HOMEDIR/$user/web
  125. fi
  126. mkdir -p $HOMEDIR/$user/conf/web/$domain
  127. mkdir -p $HOMEDIR/$user/web
  128. mkdir -p $HOMEDIR/$user/tmp
  129. chmod 751 $HOMEDIR/$user/conf/web
  130. chmod 751 $HOMEDIR/$user/web
  131. chmod 771 $HOMEDIR/$user/tmp
  132. chown --no-dereference $user:$user $HOMEDIR/$user/web
  133. if [ "$create_user" = "yes" ]; then
  134. $BIN/v-rebuild-web-domains $user $restart
  135. fi
  136. fi
  137. # DNS
  138. if [ -n "$DNS_SYSTEM" ] && [ "$DNS_SYSTEM" != 'no' ]; then
  139. mkdir -p $USER_DATA/dns
  140. chmod 770 $USER_DATA/dns
  141. touch $USER_DATA/dns.conf
  142. chmod 660 $USER_DATA/dns.conf
  143. mkdir -p $HOMEDIR/$user/conf/dns
  144. chmod 751 $HOMEDIR/$user/conf/dns
  145. if [ "$create_user" = "yes" ]; then
  146. $BIN/v-rebuild-dns-domains $user $restart
  147. fi
  148. fi
  149. if [ -n "$MAIL_SYSTEM" ] && [ "$MAIL_SYSTEM" != 'no' ]; then
  150. mkdir -p $USER_DATA/mail
  151. chmod 770 $USER_DATA/mail
  152. touch $USER_DATA/mail.conf
  153. chmod 660 $USER_DATA/mail.conf
  154. echo "$BIN/v-update-mail-domains-disk $user" \
  155. >> $HESTIA/data/queue/disk.pipe
  156. if [[ -L "$HOMEDIR/$user/mail" ]]; then
  157. rm $HOMEDIR/$user/mail
  158. fi
  159. mkdir -p $HOMEDIR/$user/conf/mail/$domain
  160. mkdir -p $HOMEDIR/$user/mail
  161. chmod 751 $HOMEDIR/$user/mail
  162. chmod 751 $HOMEDIR/$user/conf/mail
  163. if [ "$create_user" = "yes" ]; then
  164. $BIN/v-rebuild-mail-domains $user
  165. fi
  166. fi
  167. if [ -n "$DB_SYSTEM" ] && [ "$DB_SYSTEM" != 'no' ]; then
  168. touch $USER_DATA/db.conf
  169. chmod 660 $USER_DATA/db.conf
  170. echo "$BIN/v-update-databases-disk $user" >> $HESTIA/data/queue/disk.pipe
  171. if [ "$create_user" = "yes" ]; then
  172. $BIN/v-rebuild-databases $user
  173. fi
  174. fi
  175. if [ -n "$CRON_SYSTEM" ] && [ "$CRON_SYSTEM" != 'no' ]; then
  176. touch $USER_DATA/cron.conf
  177. chmod 660 $USER_DATA/cron.conf
  178. if [ "$create_user" = "yes" ]; then
  179. $BIN/v-rebuild-cron-jobs $user $restart
  180. fi
  181. fi
  182. # Set immutable flag
  183. chattr +i $HOMEDIR/$user/conf > /dev/null 2>&1
  184. }
  185. # WEB domain rebuild
  186. rebuild_web_domain_conf() {
  187. # Ensure that global domain folders are available
  188. if [ ! -d /etc/$WEB_SYSTEM/conf.d/domains ]; then
  189. mkdir -p /etc/$WEB_SYSTEM/conf.d/domains
  190. fi
  191. if [ ! -d /etc/$PROXY_SYSTEM/conf.d/domains ]; then
  192. mkdir -p /etc/$PROXY_SYSTEM/conf.d/domains
  193. fi
  194. syshealth_repair_web_config
  195. get_domain_values 'web'
  196. is_ip_valid $IP
  197. prepare_web_domain_values
  198. # Remove old web configuration files
  199. if [ -f /etc/$WEB_SYSTEM/conf.d/$domain.conf ]; then
  200. rm -f /etc/$WEB_SYSTEM/conf.d/$domain*.conf
  201. fi
  202. if [ -f /etc/$PROXY_SYSTEM/conf.d/$domain.conf ]; then
  203. rm -f /etc/$PROXY_SYSTEM/conf.d/$domain*.conf
  204. fi
  205. # Temporary allow write permissions to owner
  206. [ -d "$HOMEDIR/$user/web/$domain" ] && chmod 751 "$HOMEDIR/$user/web/$domain"
  207. # Rebuilding domain directories
  208. if [ -d "$HOMEDIR/$user/web/$domain/document_errors" ]; then
  209. $BIN/v-delete-fs-directory "$user" "$HOMEDIR/$user/web/$domain/document_errors"
  210. fi
  211. $BIN/v-add-fs-directory "$user" "$HOMEDIR/$user/web/$domain"
  212. $BIN/v-add-fs-directory "$user" "$HOMEDIR/$user/web/$domain/public_html"
  213. $BIN/v-add-fs-directory "$user" "$HOMEDIR/$user/web/$domain/document_errors"
  214. $BIN/v-add-fs-directory "$user" "$HOMEDIR/$user/web/$domain/cgi-bin"
  215. $BIN/v-add-fs-directory "$user" "$HOMEDIR/$user/web/$domain/private"
  216. $BIN/v-add-fs-directory "$user" "$HOMEDIR/$user/web/$domain/stats"
  217. $BIN/v-add-fs-directory "$user" "$HOMEDIR/$user/web/$domain/logs"
  218. # Creating domain logs
  219. if [ ! -e "/var/log/$WEB_SYSTEM/domains" ]; then
  220. mkdir -p /var/log/$WEB_SYSTEM/domains
  221. chmod 771 /var/log/$WEB_SYSTEM/domains
  222. fi
  223. touch /var/log/$WEB_SYSTEM/domains/$domain.bytes \
  224. /var/log/$WEB_SYSTEM/domains/$domain.log \
  225. /var/log/$WEB_SYSTEM/domains/$domain.error.log
  226. # Creating symlinks
  227. cd $HOMEDIR/$user/web/$domain/logs/
  228. ln -f -s /var/log/$WEB_SYSTEM/domains/$domain.log .
  229. ln -f -s /var/log/$WEB_SYSTEM/domains/$domain.error.log .
  230. cd /
  231. # Propagating html skeleton
  232. if [ -d "$WEBTPL/skel/document_errors/" ]; then
  233. user_exec cp -r "$WEBTPL/skel/document_errors/" "$HOMEDIR/$user/web/$domain/"
  234. fi
  235. # Set ownership
  236. chown --no-dereference $user:$user \
  237. $HOMEDIR/$user/web/$domain \
  238. $HOMEDIR/$user/web/$domain/private \
  239. $HOMEDIR/$user/web/$domain/cgi-bin \
  240. $HOMEDIR/$user/web/$domain/public_*html
  241. chown -R $user:$user $HOMEDIR/$user/web/$domain/document_errors
  242. chown root:$user /var/log/$WEB_SYSTEM/domains/$domain.*
  243. # Adding vhost configuration
  244. conf="$HOMEDIR/$user/conf/web/$domain/$WEB_SYSTEM.conf"
  245. add_web_config "$WEB_SYSTEM" "$TPL.tpl"
  246. # Adding SSL vhost configuration
  247. if [ "$SSL" = 'yes' ]; then
  248. ssl_file_dir="$HOMEDIR/$user/conf/web/$domain/ssl"
  249. conf="$HOMEDIR/$user/conf/web/$domain/$WEB_SYSTEM.ssl.conf"
  250. if [ ! -d "$ssl_file_dir" ]; then
  251. mkdir -p $ssl_file_dir
  252. fi
  253. add_web_config "$WEB_SYSTEM" "$TPL.stpl"
  254. cp -f $USER_DATA/ssl/$domain.crt \
  255. $HOMEDIR/$user/conf/web/$domain/ssl/$domain.crt
  256. cp -f $USER_DATA/ssl/$domain.key \
  257. $HOMEDIR/$user/conf/web/$domain/ssl/$domain.key
  258. cp -f $USER_DATA/ssl/$domain.pem \
  259. $HOMEDIR/$user/conf/web/$domain/ssl/$domain.pem
  260. if [ -e "$USER_DATA/ssl/$domain.ca" ]; then
  261. cp -f $USER_DATA/ssl/$domain.ca \
  262. $HOMEDIR/$user/conf/web/$domain/ssl/$domain.ca
  263. fi
  264. fi
  265. # Refresh HTTPS redirection if previously enabled
  266. if [ "$SSL_FORCE" = 'yes' ]; then
  267. $BIN/v-delete-web-domain-ssl-force $user $domain no yes
  268. $BIN/v-add-web-domain-ssl-force $user $domain no yes
  269. fi
  270. if [ "$SSL_HSTS" = 'yes' ]; then
  271. $BIN/v-delete-web-domain-ssl-hsts $user $domain no yes
  272. $BIN/v-add-web-domain-ssl-hsts $user $domain no yes
  273. fi
  274. if [ "$FASTCGI_CACHE" = 'yes' ]; then
  275. $BIN/v-delete-fastcgi-cache $user $domain
  276. $BIN/v-add-fastcgi-cache $user $domain "$FASTCGI_DURATION"
  277. fi
  278. # Adding proxy configuration
  279. if [ -n "$PROXY_SYSTEM" ] && [ -n "$PROXY" ]; then
  280. conf="$HOMEDIR/$user/conf/web/$domain/$PROXY_SYSTEM.conf"
  281. add_web_config "$PROXY_SYSTEM" "$PROXY.tpl"
  282. if [ "$SSL" = 'yes' ]; then
  283. conf="$HOMEDIR/$user/conf/web/$domain/$PROXY_SYSTEM.ssl.conf"
  284. add_web_config "$PROXY_SYSTEM" "$PROXY.stpl"
  285. fi
  286. fi
  287. # Adding web stats parser
  288. if [ -n "$STATS" ]; then
  289. domain_idn=$domain
  290. format_domain_idn
  291. cat $WEBTPL/$STATS/$STATS.tpl |\
  292. sed -e "s|%ip%|$local_ip|g" \
  293. -e "s|%web_system%|$WEB_SYSTEM|g" \
  294. -e "s|%domain_idn%|$domain_idn|g" \
  295. -e "s|%domain%|$domain|g" \
  296. -e "s|%user%|$user|g" \
  297. -e "s|%home%|$HOMEDIR|g" \
  298. -e "s|%alias%|${aliases//,/ }|g" \
  299. -e "s|%alias_idn%|${aliases_idn//,/ }|g" \
  300. > $HOMEDIR/$user/conf/web/$domain/$STATS.conf
  301. if [ "$STATS" == 'awstats' ]; then
  302. if [ -e "/etc/awstats/$STATS.$domain_idn.conf" ]; then
  303. rm -f "/etc/awstats/$STATS.$domain_idn.conf"
  304. fi
  305. ln -f -s $HOMEDIR/$user/conf/web/$domain/$STATS.conf \
  306. /etc/awstats/$STATS.$domain_idn.conf
  307. fi
  308. webstats="$BIN/v-update-web-domain-stat $user $domain"
  309. check_webstats=$(grep "$webstats" $HESTIA/data/queue/webstats.pipe)
  310. if [ -z "$check_webstats" ]; then
  311. echo "$webstats" >> $HESTIA/data/queue/webstats.pipe
  312. fi
  313. if [ -n "$STATS_USER" ]; then
  314. stats_dir="$HOMEDIR/$user/web/$domain/stats"
  315. if [ "$WEB_SYSTEM" = 'nginx' ]; then
  316. echo "auth_basic \"Web Statistics\";" |user_exec tee $stats_dir/auth.conf > /dev/null
  317. echo "auth_basic_user_file $stats_dir/.htpasswd;" |user_exec tee -a $stats_dir/auth.conf > /dev/null
  318. else
  319. echo "AuthUserFile $stats_dir/.htpasswd" |user_exec tee $stats_dir/.htaccess > /dev/null
  320. echo "AuthName \"Web Statistics\"" |user_exec tee -a $stats_dir/.htaccess > /dev/null
  321. echo "AuthType Basic" |user_exec tee -a $stats_dir/.htaccess > /dev/null
  322. echo "Require valid-user" |user_exec tee -a $stats_dir/.htaccess > /dev/null
  323. fi
  324. echo "$STATS_USER:$STATS_CRYPT" |user_exec tee $stats_dir/.htpasswd > /dev/null
  325. fi
  326. fi
  327. # Adding ftp users
  328. if [ -z "$FTP_SHELL" ]; then
  329. shell=$(which nologin)
  330. if [ -e "/usr/bin/rssh" ]; then
  331. shell='/usr/bin/rssh'
  332. fi
  333. else
  334. shell=$FTP_SHELL
  335. fi
  336. for ftp_user in ${FTP_USER//:/ }; do
  337. if [ -z "$(grep ^$ftp_user: /etc/passwd)" ]; then
  338. position=$(echo $FTP_USER |tr ':' '\n' |grep -n '' |\
  339. grep ":$ftp_user$" |cut -f 1 -d:)
  340. ftp_path=$(echo $FTP_PATH |tr ':' '\n' |grep -n '' |\
  341. grep "^$position:" |cut -f 2 -d :)
  342. ftp_md5=$(echo $FTP_MD5 | tr ':' '\n' |grep -n '' |\
  343. grep "^$position:" |cut -f 2 -d :)
  344. # rebuild S/FTP users
  345. $BIN/v-delete-web-domain-ftp "$user" "$domain" "$ftp_user"
  346. # Generate temporary password to add user but update afterwards
  347. temp_password=$(generate_password);
  348. $BIN/v-add-web-domain-ftp "$user" "$domain" "${ftp_user#*_}" "$temp_password" "$ftp_path"
  349. # Updating ftp user password
  350. chmod u+w /etc/shadow
  351. sed -i "s|^$ftp_user:[^:]*:|$ftp_user:$ftp_md5:|" /etc/shadow
  352. chmod u-w /etc/shadow
  353. #Update web.conf for next rebuild or move
  354. update_object_value 'web' 'DOMAIN' "$domain" '$FTP_MD5' "$ftp_md5"
  355. fi
  356. done
  357. # Adding http auth protection
  358. htaccess="$HOMEDIR/$user/conf/web/$domain/htaccess"
  359. htpasswd="$HOMEDIR/$user/conf/web/$domain/htpasswd"
  360. docroot="$HOMEDIR/$user/web/$domain/public_html"
  361. for auth_user in ${AUTH_USER//:/ }; do
  362. # Parsing auth user variables
  363. position=$(echo $AUTH_USER |tr ':' '\n' |grep -n '' |\
  364. grep ":$auth_user$" |cut -f 1 -d:)
  365. auth_hash=$(echo $AUTH_HASH |tr ':' '\n' |grep -n '' |\
  366. grep "^$position:" |cut -f 2 -d :)
  367. # Adding http auth user
  368. touch $htpasswd
  369. sed -i "/^$auth_user:/d" $htpasswd
  370. echo "$auth_user:$auth_hash" >> $htpasswd
  371. # Adding htaccess password protection
  372. if [ "$WEB_SYSTEM" = "nginx" ] || [ "$PROXY_SYSTEM" = "nginx" ]; then
  373. htaccess="$HOMEDIR/$user/conf/web/$domain/nginx.conf_htaccess"
  374. shtaccess="$HOMEDIR/$user/conf/web/$domain/nginx.ssl.conf_htaccess"
  375. if [ ! -f "$htaccess" ]; then
  376. echo "auth_basic \"$domain password access\";" > $htaccess
  377. echo "auth_basic_user_file $htpasswd;" >> $htaccess
  378. ln -s $htaccess $shtaccess
  379. restart_required='yes'
  380. fi
  381. else
  382. htaccess="$HOMEDIR/$user/conf/web/$domain/apache2.conf_htaccess"
  383. shtaccess="$HOMEDIR/$user/conf/web/$domain/apache2.ssl.conf_htaccess"
  384. if [ ! -f "$htaccess" ]; then
  385. echo "<Directory $docroot>" > $htaccess
  386. echo " AuthUserFile $htpasswd" >> $htaccess
  387. echo " AuthName \"$domain access\"" >> $htaccess
  388. echo " AuthType Basic" >> $htaccess
  389. echo " Require valid-user" >> $htaccess
  390. echo "</Directory>" >> $htaccess
  391. ln -s $htaccess $shtaccess
  392. restart_required='yes'
  393. fi
  394. fi
  395. chmod 644 $htpasswd $htaccess
  396. chgrp $user $htpasswd $htaccess
  397. done
  398. # Set folder permissions
  399. no_symlink_chmod 551 $HOMEDIR/$user/web/$domain \
  400. $HOMEDIR/$user/web/$domain/stats \
  401. $HOMEDIR/$user/web/$domain/logs
  402. no_symlink_chmod 751 $HOMEDIR/$user/web/$domain/private \
  403. $HOMEDIR/$user/web/$domain/cgi-bin \
  404. $HOMEDIR/$user/web/$domain/public_*html \
  405. $HOMEDIR/$user/web/$domain/document_errors
  406. chmod 640 /var/log/$WEB_SYSTEM/domains/$domain.*
  407. chown --no-dereference $user:www-data $HOMEDIR/$user/web/$domain/public_*html
  408. }
  409. # DNS domain rebuild
  410. rebuild_dns_domain_conf() {
  411. # Get domain values
  412. get_domain_values 'dns'
  413. domain_idn=$(idn2 --quiet "$domain")
  414. # Checking zone file
  415. if [ ! -e "$USER_DATA/dns/$domain.conf" ]; then
  416. cat $DNSTPL/$TPL.tpl |\
  417. sed -e "s/%ip%/$IP/g" \
  418. -e "s/%domain_idn%/$domain_idn/g" \
  419. -e "s/%domain%/$domain/g" \
  420. -e "s/%ns1%/$ns1/g" \
  421. -e "s/%ns2%/$ns2/g" \
  422. -e "s/%ns3%/$ns3/g" \
  423. -e "s/%ns4%/$ns4/g" \
  424. -e "s/%time%/$TIME/g" \
  425. -e "s/%date%/$DATE/g" > $USER_DATA/dns/$domain.conf
  426. fi
  427. # Sorting records
  428. sort_dns_records
  429. # Updating zone
  430. update_domain_zone
  431. # Set permissions
  432. if [ "$DNS_SYSTEM" = 'named' ]; then
  433. dns_group='named'
  434. else
  435. dns_group='bind'
  436. fi
  437. # Set file permissions
  438. chmod 640 $HOMEDIR/$user/conf/dns/$domain.db
  439. chown root:$dns_group $HOMEDIR/$user/conf/dns/$domain.db
  440. # Get dns config path
  441. if [ -e '/etc/named.conf' ]; then
  442. dns_conf='/etc/named.conf'
  443. fi
  444. if [ -e '/etc/bind/named.conf' ]; then
  445. dns_conf='/etc/bind/named.conf'
  446. fi
  447. # Bind config check
  448. if [ "$SUSPENDED" = 'yes' ]; then
  449. rm_string=$(grep -n /etc/namedb/$domain.db $dns_conf | cut -d : -f 1)
  450. if [ -n "$rm_string" ]; then
  451. sed -i "$rm_string d" $dns_conf
  452. fi
  453. suspended_dns=$((suspended_dns + 1))
  454. else
  455. if [ -z "$(grep /$domain.db $dns_conf)" ]; then
  456. named="zone \"$domain_idn\" {type master; file"
  457. named="$named \"$HOMEDIR/$user/conf/dns/$domain.db\";};"
  458. echo "$named" >> $dns_conf
  459. fi
  460. fi
  461. user_domains=$((user_domains + 1))
  462. records=$(wc -l $USER_DATA/dns/$domain.conf | cut -f 1 -d ' ')
  463. user_records=$((user_records + records))
  464. update_object_value 'dns' 'DOMAIN' "$domain" '$RECORDS' "$records"
  465. }
  466. # MAIL domain rebuild
  467. rebuild_mail_domain_conf() {
  468. syshealth_repair_mail_config
  469. get_domain_values 'mail'
  470. if [[ "$domain" = *[![:ascii:]]* ]]; then
  471. domain_idn=$(idn2 --quiet $domain)
  472. else
  473. domain_idn=$domain
  474. fi
  475. # Inherit web domain local ip address
  476. unset -v nat ip local_ip domain_ip
  477. local domain_ip=$(get_object_value 'web' 'DOMAIN' "$domain" '$IP')
  478. if [ -n "$domain_ip" ]; then
  479. local local_ip=$(get_real_ip "$domain_ip")
  480. is_ip_valid "$local_ip" "$user"
  481. else
  482. get_user_ip
  483. fi
  484. if [ "$SUSPENDED" = 'yes' ]; then
  485. SUSPENDED_MAIL=$((SUSPENDED_MAIL +1))
  486. fi
  487. if [ ! -d "$USER_DATA/mail" ]; then
  488. rm -f $USER_DATA/mail
  489. mkdir $USER_DATA/mail
  490. fi
  491. # Rebuilding exim config structure
  492. if [[ "$MAIL_SYSTEM" =~ exim ]]; then
  493. rm -f /etc/$MAIL_SYSTEM/domains/$domain_idn
  494. mkdir -p $HOMEDIR/$user/conf/mail/$domain
  495. ln -s $HOMEDIR/$user/conf/mail/$domain \
  496. /etc/$MAIL_SYSTEM/domains/$domain_idn
  497. rm -f $HOMEDIR/$user/conf/mail/$domain/accounts
  498. rm -f $HOMEDIR/$user/conf/mail/$domain/aliases
  499. rm -f $HOMEDIR/$user/conf/mail/$domain/antispam
  500. rm -f $HOMEDIR/$user/conf/mail/$domain/reject_spam
  501. rm -f $HOMEDIR/$user/conf/mail/$domain/antivirus
  502. rm -f $HOMEDIR/$user/conf/mail/$domain/protection
  503. rm -f $HOMEDIR/$user/conf/mail/$domain/passwd
  504. rm -f $HOMEDIR/$user/conf/mail/$domain/fwd_only
  505. rm -f $HOMEDIR/$user/conf/mail/$domain/ip
  506. rm -fr $HOMEDIR/$user/conf/mail/$domain/limits
  507. touch $HOMEDIR/$user/conf/mail/$domain/accounts
  508. touch $HOMEDIR/$user/conf/mail/$domain/aliases
  509. touch $HOMEDIR/$user/conf/mail/$domain/passwd
  510. touch $HOMEDIR/$user/conf/mail/$domain/fwd_only
  511. touch $HOMEDIR/$user/conf/mail/$domain/limits
  512. # Setting outgoing ip address
  513. if [ -n "$local_ip" ]; then
  514. echo "$local_ip" > $HOMEDIR/$user/conf/mail/$domain/ip
  515. fi
  516. # Adding antispam protection
  517. if [ "$ANTISPAM" = 'yes' ]; then
  518. touch $HOMEDIR/$user/conf/mail/$domain/antispam
  519. fi
  520. # Adding antivirus protection
  521. if [ "$ANTIVIRUS" = 'yes' ]; then
  522. touch $HOMEDIR/$user/conf/mail/$domain/antivirus
  523. fi
  524. # Adding reject spam protection
  525. if [ "$REJECT" = 'yes' ]; then
  526. touch $HOMEDIR/$user/conf/mail/$domain/reject_spam
  527. fi
  528. # Adding dkim
  529. if [ "$DKIM" = 'yes' ]; then
  530. cp $USER_DATA/mail/$domain.pem \
  531. $HOMEDIR/$user/conf/mail/$domain/dkim.pem
  532. fi
  533. # Rebuild SMTP Relay configuration
  534. if [ "$U_SMTP_RELAY" = 'true' ]; then
  535. $BIN/v-add-mail-domain-smtp-relay $user $domain "$U_SMTP_RELAY_HOST" "$U_SMTP_RELAY_USERNAME" "$U_SMTP_RELAY_PASSWORD" "$U_SMTP_RELAY_PORT"
  536. fi
  537. # Removing configuration files if domain is suspended
  538. if [ "$SUSPENDED" = 'yes' ]; then
  539. rm -f /etc/$MAIL_SYSTEM/domains/$domain_idn
  540. rm -f /etc/dovecot/conf.d/domains/$domain_idn.conf
  541. fi
  542. # Adding mail directory
  543. if [ ! -e $HOMEDIR/$user/mail/$domain_idn ]; then
  544. mkdir "$HOMEDIR/$user/mail/$domain_idn"
  545. fi
  546. # Webamil client
  547. if [ "$WEBMAIL" = '' ]; then
  548. $HESTIA/bin/v-add-mail-domain-webmail $user $domain 'roundcube' 'no'
  549. fi
  550. # Adding catchall email
  551. dom_aliases=$HOMEDIR/$user/conf/mail/$domain/aliases
  552. if [ -n "$CATCHALL" ]; then
  553. echo "*@$domain_idn:$CATCHALL" >> $dom_aliases
  554. fi
  555. fi
  556. # Rebuild domain accounts
  557. accs=0
  558. dom_disk=0
  559. if [ -e "$USER_DATA/mail/$domain.conf" ]; then
  560. accounts=$(search_objects "mail/$domain" 'SUSPENDED' "no" 'ACCOUNT')
  561. else
  562. accounts=''
  563. fi
  564. for account in $accounts; do
  565. (( ++accs))
  566. object=$(grep "ACCOUNT='$account'" $USER_DATA/mail/$domain.conf)
  567. FWD_ONLY='no'
  568. parse_object_kv_list "$object"
  569. if [ "$SUSPENDED" = 'yes' ]; then
  570. MD5='SUSPENDED'
  571. fi
  572. if [[ "$MAIL_SYSTEM" =~ exim ]]; then
  573. if [ "$QUOTA" = 'unlimited' ]; then
  574. QUOTA=0
  575. fi
  576. str="$account:$MD5:$user:mail::$HOMEDIR/$user:${QUOTA}:userdb_quota_rule=*:storage=${QUOTA}M"
  577. echo $str >> $HOMEDIR/$user/conf/mail/$domain/passwd
  578. userstr="$account:$account:$user:mail:$HOMEDIR/$user"
  579. echo $userstr >> $HOMEDIR/$user/conf/mail/$domain/accounts
  580. for malias in ${ALIAS//,/ }; do
  581. echo "$malias@$domain_idn:$account@$domain_idn" >> $dom_aliases
  582. done
  583. if [ -n "$FWD" ]; then
  584. echo "$account@$domain_idn:$FWD" >> $dom_aliases
  585. fi
  586. if [ "$FWD_ONLY" = 'yes' ]; then
  587. echo "$account" >> $HOMEDIR/$user/conf/mail/$domain/fwd_only
  588. fi
  589. user_rate_limit=$(get_object_value 'mail' 'DOMAIN' "$domain" '$RATE_LIMIT');
  590. if [ -n "$RATE_LIMIT" ]; then
  591. #user value
  592. sed -i "/^$account@$domain_idn:/ d" $HOMEDIR/$user/conf/mail/$domain/limits
  593. echo "$account@$domain_idn:$RATE_LIMIT" >> $HOMEDIR/$user/conf/mail/$domain/limits
  594. elif [ -n "$user_rate_limit" ]; then
  595. #revert to account value
  596. sed -i "/^$account@$domain_idn:/ d" $HOMEDIR/$user/conf/mail/$domain/limits
  597. echo "$account@$domain_idn:$user_rate_limit" >> $HOMEDIR/$user/conf/mail/$domain/limits
  598. else
  599. #revert to system value
  600. system=$(cat /etc/exim4/limit.conf)
  601. sed -i "/^$account@$domain_idn:/ d" $HOMEDIR/$user/conf/mail/$domain/limits
  602. echo "$account@$domain_idn:$system" >> $HOMEDIR/$user/conf/mail/$domain/limits
  603. fi
  604. fi
  605. done
  606. # Set permissions and ownership
  607. if [[ "$MAIL_SYSTEM" =~ exim ]]; then
  608. chmod 660 $USER_DATA/mail/$domain.*
  609. chmod 771 $HOMEDIR/$user/conf/mail/$domain
  610. chmod 660 $HOMEDIR/$user/conf/mail/$domain/*
  611. chmod 771 /etc/$MAIL_SYSTEM/domains/$domain_idn
  612. chmod 770 $HOMEDIR/$user/mail/$domain_idn
  613. chown -R $MAIL_USER:mail $HOMEDIR/$user/conf/mail/$domain
  614. if [ "$IMAP_SYSTEM" = "dovecot" ]; then
  615. chown -R dovecot:mail $HOMEDIR/$user/conf/mail/$domain/passwd
  616. fi
  617. chown $MAIL_USER:mail $HOMEDIR/$user/conf/mail/$domain/accounts
  618. chown $user:mail $HOMEDIR/$user/mail/$domain_idn
  619. fi
  620. # Add missing SSL configuration flags to existing domains
  621. # for per-domain SSL migration
  622. sslcheck=$(grep "DOMAIN='$domain'" $USER_DATA/mail.conf | grep SSL)
  623. if [ -z "$sslcheck" ]; then
  624. sed -i "s|$domain'|$domain' SSL='no' LETSENCRYPT='no'|g" $USER_DATA/mail.conf
  625. fi
  626. # Remove and recreate SSL configuration
  627. if [ -f "$HOMEDIR/$user/conf/mail/$domain/ssl/$domain.crt" ]; then
  628. del_mail_ssl_config
  629. add_mail_ssl_config
  630. update_object_value 'mail' 'DOMAIN' "$domain" '$SSL' "yes"
  631. else
  632. update_object_value 'mail' 'DOMAIN' "$domain" '$SSL' "no"
  633. fi
  634. dom_disk=0
  635. for account in $(search_objects "mail/$domain" 'SUSPENDED' "no" 'ACCOUNT'); do
  636. home_dir=$HOMEDIR/$user/mail/$domain/$account
  637. if [ -e "$home_dir" ]; then
  638. udisk=$(nice -n 19 du -shm $home_dir | cut -f 1 )
  639. else
  640. udisk=0
  641. fi
  642. update_object_value "mail/$domain" 'ACCOUNT' "$account" '$U_DISK' "$udisk"
  643. dom_disk=$((dom_disk + udisk))
  644. done
  645. update_object_value 'mail' 'DOMAIN' "$domain" '$ACCOUNTS' "$accs"
  646. update_object_value 'mail' 'DOMAIN' "$domain" '$U_DISK' "$dom_disk"
  647. # Update usage counters
  648. U_MAIL_ACCOUNTS=$((U_MAIL_ACCOUNTS + accs))
  649. U_MAIL_DOMAINS=$((U_MAIL_DOMAINS + 1))
  650. recalc_user_disk_usage
  651. }
  652. # Rebuild MySQL
  653. rebuild_mysql_database() {
  654. mysql_connect $HOST
  655. mysql_query "CREATE DATABASE \`$DB\` CHARACTER SET $CHARSET" >/dev/null
  656. if [ "$mysql_fork" = "mysql" ]; then
  657. # mysql
  658. mysql_ver_sub=$(echo $mysql_ver |cut -d '.' -f1)
  659. mysql_ver_sub_sub=$(echo $mysql_ver |cut -d '.' -f2)
  660. if [ "$mysql_ver_sub" -ge 8 ] || { [ "$mysql_ver_sub" -eq 5 ] && [ "$mysql_ver_sub_sub" -ge 7 ]; } then
  661. # mysql >= 5.7
  662. mysql_query "CREATE USER IF NOT EXISTS \`$DBUSER\`" > /dev/null
  663. mysql_query "CREATE USER IF NOT EXISTS \`$DBUSER\`@localhost" > /dev/null
  664. query="UPDATE mysql.user SET authentication_string='$MD5'"
  665. query="$query WHERE User='$DBUSER'"
  666. else
  667. # mysql < 5.7
  668. query="UPDATE mysql.user SET Password='$MD5' WHERE User='$DBUSER'"
  669. fi
  670. else
  671. # mariadb
  672. mysql_ver_sub=$(echo $mysql_ver |cut -d '.' -f1)
  673. mysql_ver_sub_sub=$(echo $mysql_ver |cut -d '.' -f2)
  674. if [ "$mysql_ver_sub" -eq 5 ]; then
  675. # mariadb = 5
  676. mysql_query "CREATE USER \`$DBUSER\`" > /dev/null
  677. mysql_query "CREATE USER \`$DBUSER\`@localhost" > /dev/null
  678. query="UPDATE mysql.user SET Password='$MD5' WHERE User='$DBUSER'"
  679. else
  680. # mariadb = 10
  681. mysql_query "CREATE USER IF NOT EXISTS \`$DBUSER\` IDENTIFIED BY PASSWORD '$MD5'" > /dev/null
  682. mysql_query "CREATE USER IF NOT EXISTS \`$DBUSER\`@localhost IDENTIFIED BY PASSWORD '$MD5'" > /dev/null
  683. if [ "$mysql_ver_sub_sub" -ge 4 ]; then
  684. #mariadb >= 10.4
  685. query="SET PASSWORD FOR '$DBUSER'@'%' = '$MD5';"
  686. query2="SET PASSWORD FOR '$DBUSER'@'localhost' = '$MD5';"
  687. else
  688. #mariadb < 10.4
  689. query="UPDATE mysql.user SET Password='$MD5' WHERE User='$DBUSER'"
  690. fi
  691. fi
  692. fi
  693. mysql_query "GRANT ALL ON \`$DB\`.* TO \`$DBUSER\`@\`%\`" >/dev/null
  694. mysql_query "GRANT ALL ON \`$DB\`.* TO \`$DBUSER\`@localhost" >/dev/null
  695. mysql_query "$query" >/dev/null
  696. if [ ! -z "$query2" ]; then
  697. mysql_query "$query2" >/dev/null
  698. fi
  699. mysql_query "FLUSH PRIVILEGES" >/dev/null
  700. }
  701. # Rebuild PostgreSQL
  702. rebuild_pgsql_database() {
  703. host_str=$(grep "HOST='$HOST'" $HESTIA/conf/pgsql.conf)
  704. parse_object_kv_list "$host_str"
  705. export PGPASSWORD="$PASSWORD"
  706. if [ -z $HOST ] || [ -z $USER ] || [ -z $PASSWORD ] || [ -z $TPL ]; then
  707. echo "Error: postgresql config parsing failed"
  708. if [ -n "$SENDMAIL" ]; then
  709. echo "Can't parse PostgreSQL config" | $SENDMAIL -s "$subj" $email
  710. fi
  711. log_event "$E_PARSING" "$ARGUMENTS"
  712. exit "$E_PARSING"
  713. fi
  714. query='SELECT VERSION()'
  715. psql -h $HOST -U $USER -c "$query" > /dev/null 2>&1
  716. if [ '0' -ne "$?" ]; then
  717. echo "Error: Connection failed"
  718. if [ -n "$SENDMAIL" ]; then
  719. echo "Database connection to PostgreSQL host $HOST failed" |\
  720. $SENDMAIL -s "$subj" $email
  721. fi
  722. log_event "$E_CONNECT" "$ARGUMENTS"
  723. exit "$E_CONNECT"
  724. fi
  725. query="CREATE ROLE $DBUSER"
  726. psql -h $HOST -U $USER -c "$query" > /dev/null 2>&1
  727. query="UPDATE pg_authid SET rolpassword='$MD5' WHERE rolname='$DBUSER'"
  728. psql -h $HOST -U $USER -c "$query" > /dev/null 2>&1
  729. query="CREATE DATABASE $DB OWNER $DBUSER"
  730. if [ "$TPL" = 'template0' ]; then
  731. query="$query ENCODING '$CHARSET' TEMPLATE $TPL"
  732. else
  733. query="$query TEMPLATE $TPL"
  734. fi
  735. psql -h $HOST -U $USER -c "$query" > /dev/null 2>&1
  736. query="GRANT ALL PRIVILEGES ON DATABASE $DB TO $DBUSER"
  737. psql -h $HOST -U $USER -c "$query" > /dev/null 2>&1
  738. query="GRANT CONNECT ON DATABASE template1 to $DBUSER"
  739. psql -h $HOST -U $USER -c "$query" > /dev/null 2>&1
  740. }
  741. # Import MySQL dump
  742. import_mysql_database() {
  743. host_str=$(grep "HOST='$HOST'" $HESTIA/conf/mysql.conf)
  744. parse_object_kv_list "$host_str"
  745. if [ -z $HOST ] || [ -z $USER ] || [ -z $PASSWORD ]; then
  746. echo "Error: mysql config parsing failed"
  747. log_event "$E_PARSING" "$ARGUMENTS"
  748. exit "$E_PARSING"
  749. fi
  750. mysql -h $HOST -u $USER -p$PASSWORD $DB < $1 > /dev/null 2>&1
  751. }
  752. # Import PostgreSQL dump
  753. import_pgsql_database() {
  754. host_str=$(grep "HOST='$HOST'" $HESTIA/conf/pgsql.conf)
  755. parse_object_kv_list "$host_str"
  756. export PGPASSWORD="$PASSWORD"
  757. if [ -z $HOST ] || [ -z $USER ] || [ -z $PASSWORD ] || [ -z $TPL ]; then
  758. echo "Error: postgresql config parsing failed"
  759. log_event "$E_PARSING" "$ARGUMENTS"
  760. exit "$E_PARSING"
  761. fi
  762. psql -h $HOST -U $USER $DB < $1 > /dev/null 2>&1
  763. }