From 346a50856bf6f260554e8fa38f2f28bc3dca4f78 Mon Sep 17 00:00:00 2001 From: Alexey Berezhok Date: Tue, 19 Mar 2024 22:05:27 +0300 Subject: [PATCH] Initial --- CHANGELOG.md | 1794 +++++ CONTRIBUTING.md | 76 + LICENSE | 674 ++ README.md | 138 + SECURITY.md | 51 + bin/v-acknowledge-user-notification | 81 + bin/v-add-access-key | 106 + bin/v-add-backup-host | 344 + bin/v-add-cron-hestia-autoupdate | 99 + bin/v-add-cron-job | 93 + bin/v-add-cron-letsencrypt-job | 46 + bin/v-add-cron-reports | 60 + bin/v-add-cron-restart-job | 46 + bin/v-add-database | 113 + bin/v-add-database-host | 169 + bin/v-add-database-temp-user | 87 + bin/v-add-dns-domain | 222 + bin/v-add-dns-on-web-alias | 91 + bin/v-add-dns-record | 172 + bin/v-add-domain | 100 + bin/v-add-fastcgi-cache | 118 + bin/v-add-firewall-ban | 91 + bin/v-add-firewall-chain | 130 + bin/v-add-firewall-ipset | 205 + bin/v-add-firewall-rule | 109 + bin/v-add-fs-archive | 85 + bin/v-add-fs-directory | 55 + bin/v-add-fs-file | 55 + bin/v-add-letsencrypt-domain | 629 ++ bin/v-add-letsencrypt-host | 98 + bin/v-add-letsencrypt-user | 148 + bin/v-add-mail-account | 139 + bin/v-add-mail-account-alias | 80 + bin/v-add-mail-account-autoreply | 85 + bin/v-add-mail-account-forward | 88 + bin/v-add-mail-account-fwd-only | 86 + bin/v-add-mail-domain | 224 + bin/v-add-mail-domain-antispam | 69 + bin/v-add-mail-domain-antivirus | 69 + bin/v-add-mail-domain-catchall | 70 + bin/v-add-mail-domain-dkim | 98 + bin/v-add-mail-domain-reject | 71 + bin/v-add-mail-domain-smtp-relay | 81 + bin/v-add-mail-domain-ssl | 144 + bin/v-add-mail-domain-webmail | 190 + bin/v-add-remote-dns-domain | 124 + bin/v-add-remote-dns-host | 131 + bin/v-add-remote-dns-record | 98 + bin/v-add-sys-api-ip | 49 + bin/v-add-sys-dependencies | 109 + bin/v-add-sys-filemanager | 119 + bin/v-add-sys-firewall | 56 + bin/v-add-sys-ip | 234 + bin/v-add-sys-pma-sso | 120 + bin/v-add-sys-quota | 106 + bin/v-add-sys-roundcube | 216 + bin/v-add-sys-sftp-jail | 99 + bin/v-add-sys-smtp | 63 + bin/v-add-sys-smtp-relay | 64 + bin/v-add-sys-snappymail | 174 + bin/v-add-user | 286 + bin/v-add-user-2fa | 64 + bin/v-add-user-composer | 95 + bin/v-add-user-notification | 79 + bin/v-add-user-package | 154 + bin/v-add-user-sftp-jail | 94 + bin/v-add-user-sftp-key | 82 + bin/v-add-user-ssh-key | 73 + bin/v-add-user-wp-cli | 69 + bin/v-add-web-domain | 257 + bin/v-add-web-domain-alias | 114 + bin/v-add-web-domain-allow-users | 71 + bin/v-add-web-domain-backend | 97 + bin/v-add-web-domain-ftp | 140 + bin/v-add-web-domain-httpauth | 125 + bin/v-add-web-domain-proxy | 88 + bin/v-add-web-domain-redirect | 162 + bin/v-add-web-domain-ssl | 143 + bin/v-add-web-domain-ssl-force | 97 + bin/v-add-web-domain-ssl-hsts | 89 + bin/v-add-web-domain-ssl-preset | 60 + bin/v-add-web-domain-stats | 109 + bin/v-add-web-domain-stats-user | 89 + bin/v-add-web-php | 194 + bin/v-backup-user | 800 ++ bin/v-backup-users | 56 + bin/v-change-cron-job | 85 + bin/v-change-database-host-password | 78 + bin/v-change-database-owner | 133 + bin/v-change-database-password | 69 + bin/v-change-database-user | 109 + bin/v-change-dns-domain-dnssec | 107 + bin/v-change-dns-domain-exp | 73 + bin/v-change-dns-domain-ip | 95 + bin/v-change-dns-domain-soa | 89 + bin/v-change-dns-domain-tpl | 172 + bin/v-change-dns-domain-ttl | 88 + bin/v-change-dns-record | 168 + bin/v-change-dns-record-id | 93 + bin/v-change-domain-owner | 317 + bin/v-change-firewall-rule | 95 + bin/v-change-fs-file-permission | 62 + bin/v-change-mail-account-password | 94 + bin/v-change-mail-account-quota | 84 + bin/v-change-mail-account-rate-limit | 96 + bin/v-change-mail-domain-catchall | 69 + bin/v-change-mail-domain-rate-limit | 72 + bin/v-change-mail-domain-sslcert | 72 + bin/v-change-remote-dns-domain-exp | 83 + bin/v-change-remote-dns-domain-soa | 91 + bin/v-change-remote-dns-domain-ttl | 91 + bin/v-change-sys-api | 86 + bin/v-change-sys-config-value | 56 + bin/v-change-sys-db-alias | 108 + bin/v-change-sys-demo-mode | 68 + bin/v-change-sys-hestia-ssl | 76 + bin/v-change-sys-hostname | 79 + bin/v-change-sys-ip-name | 54 + bin/v-change-sys-ip-nat | 119 + bin/v-change-sys-ip-owner | 94 + bin/v-change-sys-ip-status | 65 + bin/v-change-sys-language | 78 + bin/v-change-sys-php | 67 + bin/v-change-sys-port | 107 + bin/v-change-sys-release | 71 + bin/v-change-sys-service-config | 129 + bin/v-change-sys-timezone | 78 + bin/v-change-sys-webmail | 70 + bin/v-change-user-config-value | 54 + bin/v-change-user-contact | 59 + bin/v-change-user-language | 73 + bin/v-change-user-name | 60 + bin/v-change-user-ns | 95 + bin/v-change-user-package | 195 + bin/v-change-user-password | 72 + bin/v-change-user-php-cli | 81 + bin/v-change-user-rkey | 67 + bin/v-change-user-role | 49 + bin/v-change-user-shell | 66 + bin/v-change-user-sort-order | 51 + bin/v-change-user-template | 72 + bin/v-change-user-theme | 66 + bin/v-change-web-domain-backend-tpl | 186 + bin/v-change-web-domain-dirlist | 88 + bin/v-change-web-domain-docroot | 137 + bin/v-change-web-domain-ftp-password | 90 + bin/v-change-web-domain-ftp-path | 100 + bin/v-change-web-domain-httpauth | 84 + bin/v-change-web-domain-ip | 103 + bin/v-change-web-domain-name | 130 + bin/v-change-web-domain-proxy-tpl | 97 + bin/v-change-web-domain-sslcert | 95 + bin/v-change-web-domain-sslhome | 104 + bin/v-change-web-domain-stats | 104 + bin/v-change-web-domain-tpl | 91 + bin/v-check-access-key | 114 + bin/v-check-api-key | 62 + bin/v-check-fs-permission | 59 + bin/v-check-mail-account-hash | 65 + bin/v-check-user-2fa | 57 + bin/v-check-user-hash | 102 + bin/v-check-user-password | 130 + bin/v-copy-fs-directory | 69 + bin/v-copy-fs-file | 69 + bin/v-copy-user-package | 68 + bin/v-delete-access-key | 57 + bin/v-delete-backup-host | 62 + bin/v-delete-cron-hestia-autoupdate | 68 + bin/v-delete-cron-job | 73 + bin/v-delete-cron-reports | 60 + bin/v-delete-cron-restart-job | 47 + bin/v-delete-database | 78 + bin/v-delete-database-host | 60 + bin/v-delete-database-temp-user | 69 + bin/v-delete-databases | 52 + bin/v-delete-dns-domain | 105 + bin/v-delete-dns-domains | 57 + bin/v-delete-dns-domains-src | 58 + bin/v-delete-dns-on-web-alias | 92 + bin/v-delete-dns-record | 95 + bin/v-delete-domain | 90 + bin/v-delete-fastcgi-cache | 90 + bin/v-delete-firewall-ban | 88 + bin/v-delete-firewall-chain | 71 + bin/v-delete-firewall-ipset | 80 + bin/v-delete-firewall-rule | 54 + bin/v-delete-fs-directory | 57 + bin/v-delete-fs-file | 55 + bin/v-delete-letsencrypt-domain | 117 + bin/v-delete-mail-account | 82 + bin/v-delete-mail-account-alias | 80 + bin/v-delete-mail-account-autoreply | 73 + bin/v-delete-mail-account-forward | 83 + bin/v-delete-mail-account-fwd-only | 68 + bin/v-delete-mail-domain | 111 + bin/v-delete-mail-domain-antispam | 68 + bin/v-delete-mail-domain-antivirus | 69 + bin/v-delete-mail-domain-catchall | 66 + bin/v-delete-mail-domain-dkim | 74 + bin/v-delete-mail-domain-reject | 70 + bin/v-delete-mail-domain-smtp-relay | 65 + bin/v-delete-mail-domain-ssl | 72 + bin/v-delete-mail-domain-webmail | 101 + bin/v-delete-mail-domains | 52 + bin/v-delete-remote-dns-domain | 74 + bin/v-delete-remote-dns-domains | 78 + bin/v-delete-remote-dns-host | 71 + bin/v-delete-remote-dns-record | 83 + bin/v-delete-sys-api-ip | 54 + bin/v-delete-sys-filemanager | 76 + bin/v-delete-sys-firewall | 50 + bin/v-delete-sys-ip | 171 + bin/v-delete-sys-mail-queue | 45 + bin/v-delete-sys-pma-sso | 78 + bin/v-delete-sys-quota | 74 + bin/v-delete-sys-sftp-jail | 88 + bin/v-delete-sys-smtp | 49 + bin/v-delete-sys-smtp-relay | 47 + bin/v-delete-user | 125 + bin/v-delete-user-2fa | 61 + bin/v-delete-user-auth-log | 44 + bin/v-delete-user-backup | 82 + bin/v-delete-user-backup-exclusions | 82 + bin/v-delete-user-ips | 69 + bin/v-delete-user-log | 61 + bin/v-delete-user-notification | 79 + bin/v-delete-user-package | 63 + bin/v-delete-user-sftp-jail | 82 + bin/v-delete-user-ssh-key | 61 + bin/v-delete-user-stats | 60 + bin/v-delete-web-domain | 163 + bin/v-delete-web-domain-alias | 99 + bin/v-delete-web-domain-allow-users | 69 + bin/v-delete-web-domain-backend | 99 + bin/v-delete-web-domain-ftp | 89 + bin/v-delete-web-domain-httpauth | 98 + bin/v-delete-web-domain-proxy | 77 + bin/v-delete-web-domain-redirect | 72 + bin/v-delete-web-domain-ssl | 97 + bin/v-delete-web-domain-ssl-force | 80 + bin/v-delete-web-domain-ssl-hsts | 78 + bin/v-delete-web-domain-stats | 75 + bin/v-delete-web-domain-stats-user | 73 + bin/v-delete-web-domains | 62 + bin/v-delete-web-php | 125 + bin/v-download-backup | 119 + bin/v-dump-database | 90 + bin/v-dump-site | 70 + bin/v-export-rrd | 201 + bin/v-extract-fs-archive | 171 + bin/v-generate-api-key | 56 + bin/v-generate-debug-report | 74 + bin/v-generate-password-hash | 49 + bin/v-generate-ssl-cert | 189 + bin/v-get-dns-domain-value | 57 + bin/v-get-fs-file-type | 46 + bin/v-get-mail-account-value | 59 + bin/v-get-mail-domain-value | 57 + bin/v-get-sys-timezone | 51 + bin/v-get-sys-timezones | 61 + bin/v-get-user-salt | 124 + bin/v-get-user-value | 47 + bin/v-import-cpanel | 304 + bin/v-insert-dns-domain | 92 + bin/v-insert-dns-record | 53 + bin/v-insert-dns-records | 55 + bin/v-list-access-key | 88 + bin/v-list-access-keys | 93 + bin/v-list-api | 70 + bin/v-list-apis | 65 + bin/v-list-backup-host | 142 + bin/v-list-cron-job | 108 + bin/v-list-cron-jobs | 115 + bin/v-list-database | 96 + bin/v-list-database-host | 115 + bin/v-list-database-hosts | 145 + bin/v-list-database-types | 78 + bin/v-list-databases | 109 + bin/v-list-default-php | 87 + bin/v-list-dns-domain | 103 + bin/v-list-dns-domains | 113 + bin/v-list-dns-records | 125 + bin/v-list-dns-template | 109 + bin/v-list-dns-templates | 83 + bin/v-list-dnssec-public-key | 99 + bin/v-list-firewall | 104 + bin/v-list-firewall-ban | 94 + bin/v-list-firewall-ipset | 108 + bin/v-list-firewall-rule | 91 + bin/v-list-fs-directory | 51 + bin/v-list-letsencrypt-user | 89 + bin/v-list-mail-account | 104 + bin/v-list-mail-account-autoreply | 86 + bin/v-list-mail-accounts | 127 + bin/v-list-mail-domain | 123 + bin/v-list-mail-domain-dkim | 86 + bin/v-list-mail-domain-dkim-dns | 93 + bin/v-list-mail-domain-ssl | 154 + bin/v-list-mail-domains | 118 + bin/v-list-remote-dns-hosts | 106 + bin/v-list-sys-clamd-config | 77 + bin/v-list-sys-config | 301 + bin/v-list-sys-cpu-status | 32 + bin/v-list-sys-db-status | 87 + bin/v-list-sys-disk-status | 35 + bin/v-list-sys-dns-status | 80 + bin/v-list-sys-dovecot-config | 107 + bin/v-list-sys-hestia-autoupdate | 84 + bin/v-list-sys-hestia-ssl | 128 + bin/v-list-sys-hestia-updates | 156 + bin/v-list-sys-info | 116 + bin/v-list-sys-interfaces | 88 + bin/v-list-sys-ip | 103 + bin/v-list-sys-ips | 104 + bin/v-list-sys-languages | 88 + bin/v-list-sys-mail-status | 57 + bin/v-list-sys-memory-status | 30 + bin/v-list-sys-mysql-config | 86 + bin/v-list-sys-network-status | 30 + bin/v-list-sys-nginx-config | 91 + bin/v-list-sys-pgsql-config | 73 + bin/v-list-sys-php | 94 + bin/v-list-sys-php-config | 97 + bin/v-list-sys-proftpd-config | 68 + bin/v-list-sys-rrd | 163 + bin/v-list-sys-services | 343 + bin/v-list-sys-shells | 83 + bin/v-list-sys-spamd-config | 68 + bin/v-list-sys-sshd-port | 83 + bin/v-list-sys-themes | 111 + bin/v-list-sys-users | 81 + bin/v-list-sys-vsftpd-config | 68 + bin/v-list-sys-web-status | 53 + bin/v-list-sys-webmail | 81 + bin/v-list-user | 197 + bin/v-list-user-auth-log | 137 + bin/v-list-user-backup | 106 + bin/v-list-user-backup-exclusions | 187 + bin/v-list-user-backups | 118 + bin/v-list-user-ips | 115 + bin/v-list-user-log | 133 + bin/v-list-user-notifications | 115 + bin/v-list-user-ns | 92 + bin/v-list-user-package | 124 + bin/v-list-user-packages | 122 + bin/v-list-user-ssh-key | 121 + bin/v-list-user-stats | 151 + bin/v-list-users | 194 + bin/v-list-users-stats | 147 + bin/v-list-web-domain | 160 + bin/v-list-web-domain-accesslog | 95 + bin/v-list-web-domain-errorlog | 95 + bin/v-list-web-domain-ssl | 157 + bin/v-list-web-domains | 148 + bin/v-list-web-stats | 84 + bin/v-list-web-templates | 84 + bin/v-list-web-templates-backend | 88 + bin/v-list-web-templates-proxy | 89 + bin/v-log-action | 62 + bin/v-log-user-login | 67 + bin/v-log-user-logout | 44 + bin/v-move-fs-directory | 68 + bin/v-move-fs-file | 66 + bin/v-open-fs-config | 63 + bin/v-open-fs-file | 55 + bin/v-purge-nginx-cache | 78 + bin/v-rebuild-all | 68 + bin/v-rebuild-cron-jobs | 56 + bin/v-rebuild-database | 75 + bin/v-rebuild-databases | 82 + bin/v-rebuild-dns-domain | 105 + bin/v-rebuild-dns-domains | 106 + bin/v-rebuild-mail-domain | 92 + bin/v-rebuild-mail-domains | 75 + bin/v-rebuild-user | 74 + bin/v-rebuild-users | 51 + bin/v-rebuild-web-domain | 118 + bin/v-rebuild-web-domains | 142 + bin/v-refresh-sys-theme | 30 + bin/v-rename-user-package | 89 + bin/v-repair-sys-config | 36 + bin/v-restart-cron | 68 + bin/v-restart-dns | 91 + bin/v-restart-ftp | 68 + bin/v-restart-mail | 78 + bin/v-restart-proxy | 133 + bin/v-restart-service | 103 + bin/v-restart-system | 51 + bin/v-restart-web | 115 + bin/v-restart-web-backend | 89 + bin/v-restore-cron-job | 51 + bin/v-restore-database | 51 + bin/v-restore-dns-domain | 51 + bin/v-restore-mail-domain | 51 + bin/v-restore-user | 947 +++ bin/v-restore-web-domain | 51 + bin/v-revoke-api-key | 56 + bin/v-run-cli-cmd | 93 + bin/v-schedule-letsencrypt-domain | 68 + bin/v-schedule-user-backup | 53 + bin/v-schedule-user-backup-download | 53 + bin/v-schedule-user-restore | 62 + bin/v-search-command | 58 + bin/v-search-domain-owner | 62 + bin/v-search-fs-object | 60 + bin/v-search-object | 269 + bin/v-search-user-object | 270 + bin/v-start-service | 65 + bin/v-stop-firewall | 104 + bin/v-stop-service | 69 + bin/v-suspend-cron-job | 62 + bin/v-suspend-cron-jobs | 56 + bin/v-suspend-database | 67 + bin/v-suspend-database-host | 52 + bin/v-suspend-databases | 52 + bin/v-suspend-dns-domain | 74 + bin/v-suspend-dns-domains | 53 + bin/v-suspend-dns-record | 83 + bin/v-suspend-domain | 93 + bin/v-suspend-firewall-rule | 55 + bin/v-suspend-mail-account | 76 + bin/v-suspend-mail-accounts | 59 + bin/v-suspend-mail-domain | 73 + bin/v-suspend-mail-domains | 54 + bin/v-suspend-remote-dns-host | 51 + bin/v-suspend-user | 105 + bin/v-suspend-web-domain | 104 + bin/v-suspend-web-domains | 62 + bin/v-sync-dns-cluster | 124 + bin/v-unsuspend-cron-job | 62 + bin/v-unsuspend-cron-jobs | 56 + bin/v-unsuspend-database | 66 + bin/v-unsuspend-database-host | 52 + bin/v-unsuspend-databases | 52 + bin/v-unsuspend-dns-domain | 78 + bin/v-unsuspend-dns-domains | 53 + bin/v-unsuspend-dns-record | 82 + bin/v-unsuspend-domain | 92 + bin/v-unsuspend-firewall-rule | 55 + bin/v-unsuspend-mail-account | 77 + bin/v-unsuspend-mail-accounts | 59 + bin/v-unsuspend-mail-domain | 79 + bin/v-unsuspend-mail-domains | 54 + bin/v-unsuspend-remote-dns-host | 51 + bin/v-unsuspend-user | 104 + bin/v-unsuspend-web-domain | 110 + bin/v-unsuspend-web-domains | 62 + bin/v-update-database-disk | 61 + bin/v-update-databases-disk | 49 + bin/v-update-dns-templates | 39 + bin/v-update-firewall | 215 + bin/v-update-firewall-ipset | 69 + bin/v-update-host-certificate | 95 + bin/v-update-letsencrypt-ssl | 175 + bin/v-update-mail-domain-disk | 71 + bin/v-update-mail-domain-ssl | 103 + bin/v-update-mail-domains-disk | 65 + bin/v-update-mail-templates | 53 + bin/v-update-sys-defaults | 44 + bin/v-update-sys-hestia | 63 + bin/v-update-sys-hestia-all | 37 + bin/v-update-sys-hestia-git | 385 + bin/v-update-sys-ip | 182 + bin/v-update-sys-ip-counters | 70 + bin/v-update-sys-queue | 62 + bin/v-update-sys-rrd | 134 + bin/v-update-sys-rrd-apache2 | 122 + bin/v-update-sys-rrd-ftp | 117 + bin/v-update-sys-rrd-httpd | 122 + bin/v-update-sys-rrd-la | 123 + bin/v-update-sys-rrd-mail | 116 + bin/v-update-sys-rrd-mem | 140 + bin/v-update-sys-rrd-mysql | 147 + bin/v-update-sys-rrd-net | 140 + bin/v-update-sys-rrd-nginx | 115 + bin/v-update-sys-rrd-pgsql | 164 + bin/v-update-sys-rrd-ssh | 116 + bin/v-update-user-backup-exclusions | 83 + bin/v-update-user-counters | 232 + bin/v-update-user-disk | 60 + bin/v-update-user-package | 50 + bin/v-update-user-quota | 59 + bin/v-update-user-stats | 172 + bin/v-update-web-domain-disk | 66 + bin/v-update-web-domain-ssl | 97 + bin/v-update-web-domain-stat | 147 + bin/v-update-web-domain-traff | 92 + bin/v-update-web-domains-disk | 56 + bin/v-update-web-domains-stat | 55 + bin/v-update-web-domains-traff | 79 + bin/v-update-web-templates | 84 + bin/v-update-white-label-logo | 64 + build.js | 150 + crowdin.yml | 5 + docs/.vitepress/config.js | 163 + .../theme/components/FeatureList.vue | 46 + .../theme/components/FeaturePage.vue | 29 + .../theme/components/FeaturePageSection.vue | 121 + .../theme/components/FeaturePageTitle.vue | 42 + .../theme/components/InstallOptions.vue | 337 + .../components/InstallOptionsSection.vue | 29 + .../theme/components/InstallPage.vue | 28 + .../theme/components/InstallPageTitle.vue | 42 + docs/.vitepress/theme/index.js | 16 + docs/.vitepress/theme/styles/base.css | 27 + docs/.vitepress/theme/styles/vars.css | 18 + docs/_data/features.js | 79 + docs/_data/languages.js | 43 + docs/_data/options.js | 178 + docs/_data/team.js | 74 + docs/docs/community/hestia-nginx-cache.md | 10 + .../community/install-script-generator.md | 6 + .../community/ioncube-hestia-installer.md | 12 + docs/docs/contributing/building.md | 93 + docs/docs/contributing/development.md | 173 + docs/docs/contributing/documentation.md | 15 + docs/docs/contributing/quick-install-app.md | 76 + docs/docs/contributing/testing.md | 54 + docs/docs/contributing/translations.md | 3 + docs/docs/index.md | 57 + docs/docs/introduction/best-practices.md | 15 + docs/docs/introduction/getting-started.md | 142 + docs/docs/reference/api.md | 36 + docs/docs/reference/cli.md | 6219 +++++++++++++++ .../server-administration/backup-restore.md | 214 + .../server-administration/configuration.md | 137 + .../server-administration/customisation.md | 64 + docs/docs/server-administration/databases.md | 120 + docs/docs/server-administration/dns.md | 166 + docs/docs/server-administration/email.md | 110 + .../server-administration/file-manager.md | 53 + docs/docs/server-administration/firewall.md | 103 + .../docs/server-administration/os-upgrades.md | 73 + docs/docs/server-administration/rest-api.md | 76 + .../server-administration/ssl-certificates.md | 98 + .../server-administration/troubleshooting.md | 124 + .../server-administration/web-templates.md | 161 + docs/docs/user-guide/account.md | 100 + docs/docs/user-guide/backups.md | 81 + docs/docs/user-guide/cron-jobs.md | 30 + docs/docs/user-guide/databases.md | 34 + docs/docs/user-guide/dns.md | 125 + docs/docs/user-guide/file-manager.md | 5 + docs/docs/user-guide/mail-domains.md | 156 + docs/docs/user-guide/notifications.md | 5 + docs/docs/user-guide/packages.md | 124 + docs/docs/user-guide/statistics.md | 16 + docs/docs/user-guide/users.md | 72 + docs/docs/user-guide/web-domains.md | 129 + docs/donate.md | 17 + docs/features.md | 59 + docs/index.md | 46 + docs/install.md | 23 + docs/public/_headers | 3 + docs/public/apple-touch-icon.png | Bin 0 -> 2727 bytes docs/public/favicon.ico | Bin 0 -> 4286 bytes docs/public/icon-192.png | Bin 0 -> 3912 bytes docs/public/icon-512.png | Bin 0 -> 15578 bytes .../images/undraw_domain_names_re_0uun.svg | 1 + .../images/undraw_maintenance_re_59vn.svg | 1 + .../images/undraw_personal_email_re_4lx7.svg | 1 + .../images/undraw_server_status_re_n8ln.svg | 1 + .../undraw_two_factor_authentication_namy.svg | 1 + .../images/undraw_web_developer_re_h7ie.svg | 1 + docs/public/logo.svg | 1 + docs/public/site.webmanifest | 11 + docs/public/webfonts/fa-brands-400.ttf | Bin 0 -> 187208 bytes docs/public/webfonts/fa-brands-400.woff2 | Bin 0 -> 108020 bytes docs/public/webfonts/fa-solid-900.ttf | Bin 0 -> 394628 bytes docs/public/webfonts/fa-solid-900.woff2 | Bin 0 -> 150124 bytes docs/team.md | 37 + func/backup.sh | 579 ++ func/db.sh | 653 ++ func/domain.sh | 1071 +++ func/firewall.sh | 25 + func/ip.sh | 280 + func/main.sh | 1714 +++++ func/rebuild.sh | 918 +++ func/remote.sh | 196 + func/syshealth.sh | 568 ++ func/upgrade.sh | 871 +++ install/common/api/billing | 2 + install/common/api/mail-accounts | 2 + install/common/api/phpmyadmin-sso | 2 + install/common/api/purge-nginx-cache | 2 + install/common/api/sync-dns-cluster | 2 + install/common/api/update-dns-records | 2 + install/common/dovecot/conf.d/10-auth.conf | 5 + install/common/dovecot/conf.d/10-logging.conf | 1 + install/common/dovecot/conf.d/10-mail.conf | 8 + install/common/dovecot/conf.d/10-master.conf | 31 + install/common/dovecot/conf.d/10-ssl.conf | 13 + install/common/dovecot/conf.d/20-imap.conf | 59 + install/common/dovecot/conf.d/20-pop3.conf | 92 + install/common/dovecot/conf.d/90-quota.conf | 84 + .../dovecot/conf.d/auth-passwdfile.conf.ext | 9 + install/common/dovecot/dovecot.conf | 66 + .../common/dovecot/sieve/20-managesieve.conf | 88 + .../dovecot/sieve/90-sieve-extprograms.conf | 44 + install/common/dovecot/sieve/90-sieve.conf | 211 + .../Archiver/Adapters/HestiaZipArchiver.php | 48 + .../Services/Auth/Adapters/HestiaAuth.php | 122 + .../Session/Adapters/SessionStorage.php | 64 + install/common/filegator/composer.json | 47 + install/common/filegator/composer.lock | 4771 ++++++++++++ install/common/filegator/configuration.php | 177 + install/common/firewall/ipset/blacklist.sh | 35 + install/common/firewall/rules.conf | 10 + install/common/packages/default.pkg | 20 + install/common/packages/system.pkg | 20 + install/common/phpmyadmin/config.inc.php | 36 + install/common/phpmyadmin/create_tables.sql | 389 + install/common/phpmyadmin/hestia-sso.php | 213 + install/common/phpmyadmin/pma.sh | 103 + install/common/roundcube/apache.conf | 40 + install/common/roundcube/config.inc.php | 32 + install/common/roundcube/hestia.php | 57 + install/common/roundcube/main.inc.php | 104 + install/common/roundcube/mimetypes.php | 56 + .../plugins/config_managesieve.inc.php | 126 + .../plugins/config_newmail_notifier.inc.php | 15 + .../plugins/config_zipdownload.inc.php | 21 + install/common/snappymail/install.php | 73 + install/common/templates/dns/child-ns.tpl | 12 + .../common/templates/dns/default-nomail.tpl | 11 + install/common/templates/dns/default.tpl | 16 + install/common/templates/dns/gmail.tpl | 17 + install/common/templates/dns/office365.tpl | 22 + install/common/templates/dns/zoho.tpl | 15 + .../email/examples/account_ready.html | 12 + .../email/examples/database_credentials.html | 11 + .../email/examples/email_credentials.html | 30 + .../email/examples/ftp_credentials.html | 10 + .../email/examples/reset_password.html | 15 + .../web/skel/document_errors/403.html | 119 + .../web/skel/document_errors/404.html | 119 + .../web/skel/document_errors/410.html | 119 + .../web/skel/document_errors/50x.html | 122 + .../templates/web/skel/public_html/index.html | 119 + .../templates/web/skel/public_html/robots.txt | 3 + .../common/templates/web/suspend/.htaccess | 2 + .../common/templates/web/suspend/index.html | 117 + .../templates/web/unassigned/index.html | 119 + install/deb/apache2/apache2.conf | 96 + install/deb/apache2/hestia-event.conf | 5 + install/deb/apache2/status.conf | 7 + install/deb/apache2/unassigned.conf | 18 + install/deb/bind/named.conf | 12 + install/deb/bind/named.conf.options | 24 + install/deb/clamav/clamd.conf | 88 + install/deb/deb_signing.key | 30 + install/deb/exim/dnsbl.conf | 2 + install/deb/exim/exim4.conf.4.94.template | 476 ++ install/deb/exim/exim4.conf.4.95.template | 512 ++ install/deb/exim/exim4.conf.template | 478 ++ install/deb/exim/limit.conf | 1 + install/deb/exim/spam-blocks.conf | 0 install/deb/exim/srs.conf | 1 + install/deb/exim/system.filter | 16 + install/deb/fail2ban/action.d/hestia.conf | 9 + install/deb/fail2ban/filter.d/hestia.conf | 10 + install/deb/fail2ban/jail.local | 66 + .../Archiver/Adapters/HestiaZipArchiver.php | 48 + .../Services/Auth/Adapters/HestiaAuth.php | 122 + .../Session/Adapters/SessionStorage.php | 64 + .../deb/filemanager/filegator/composer.json | 47 + .../deb/filemanager/filegator/composer.lock | 4771 ++++++++++++ .../filemanager/filegator/configuration.php | 175 + install/deb/filemanager/install-fm.sh | 71 + install/deb/logrotate/apache2 | 19 + install/deb/logrotate/dovecot | 12 + install/deb/logrotate/hestia | 7 + install/deb/logrotate/httpd-prerotate/awstats | 4 + install/deb/logrotate/nginx | 13 + install/deb/logrotate/roundcube | 7 + install/deb/mysql/my-large.cnf | 50 + install/deb/mysql/my-medium.cnf | 49 + install/deb/mysql/my-small.cnf | 49 + install/deb/nginx/0rtt-anti-replay.conf | 39 + install/deb/nginx/agents.conf | 16 + install/deb/nginx/nginx.conf | 130 + install/deb/nginx/phpmyadmin.inc | 26 + install/deb/nginx/phppgadmin.inc | 12 + install/deb/nginx/status.conf | 11 + install/deb/nginx/unassigned.inc | 52 + install/deb/pga/config.inc.php | 166 + install/deb/pga/phppgadmin.conf | 37 + install/deb/php-fpm/dummy.conf | 13 + install/deb/php-fpm/multiphp.tpl | 31 + install/deb/php-fpm/php-fpm.conf | 145 + install/deb/php-fpm/www.conf | 13 + install/deb/phpmyadmin/config.inc.php | 36 + install/deb/phpmyadmin/create_tables.sql | 389 + install/deb/phpmyadmin/hestia-sso.php | 213 + install/deb/phpmyadmin/pma.sh | 103 + install/deb/pma/apache.conf | 40 + install/deb/postgresql/pg_hba.conf | 11 + install/deb/proftpd/proftpd.conf | 33 + install/deb/proftpd/tls.conf | 65 + install/deb/ssl/dhparam.pem | 13 + install/deb/sudo/admin | 10 + .../deb/templates/mail/apache2/default.stpl | 51 + .../deb/templates/mail/apache2/default.tpl | 48 + .../deb/templates/mail/apache2/disabled.stpl | 12 + .../deb/templates/mail/apache2/disabled.tpl | 7 + .../deb/templates/mail/apache2/rainloop.stpl | 31 + .../deb/templates/mail/apache2/rainloop.tpl | 25 + .../templates/mail/apache2/snappymail.stpl | 31 + .../deb/templates/mail/apache2/snappymail.tpl | 25 + install/deb/templates/mail/nginx/default.stpl | 52 + install/deb/templates/mail/nginx/default.tpl | 43 + .../mail/nginx/default_disabled.stpl | 29 + .../templates/mail/nginx/default_disabled.tpl | 20 + .../mail/nginx/default_snappymail.stpl | 52 + .../mail/nginx/default_snappymail.tpl | 48 + .../deb/templates/mail/nginx/disabled.stpl | 34 + install/deb/templates/mail/nginx/disabled.tpl | 25 + .../deb/templates/mail/nginx/snappymail.stpl | 59 + .../deb/templates/mail/nginx/snappymail.tpl | 49 + .../deb/templates/mail/nginx/web_system.stpl | 54 + .../deb/templates/mail/nginx/web_system.tpl | 44 + .../deb/templates/web/apache2/default.stpl | 49 + install/deb/templates/web/apache2/default.tpl | 46 + .../deb/templates/web/apache2/hosting.stpl | 55 + install/deb/templates/web/apache2/hosting.tpl | 52 + .../web/apache2/php-fpm/default.stpl | 41 + .../templates/web/apache2/php-fpm/default.tpl | 38 + install/deb/templates/web/apache2/phpcgi.sh | 16 + install/deb/templates/web/apache2/phpcgi.stpl | 44 + install/deb/templates/web/apache2/phpcgi.tpl | 40 + install/deb/templates/web/apache2/phpfcgid.sh | 22 + .../deb/templates/web/apache2/phpfcgid.stpl | 45 + .../deb/templates/web/apache2/phpfcgid.tpl | 40 + .../deb/templates/web/apache2/www-data.stpl | 41 + .../deb/templates/web/apache2/www-data.tpl | 38 + install/deb/templates/web/awstats/awstats.tpl | 133 + install/deb/templates/web/awstats/index.tpl | 10 + install/deb/templates/web/awstats/nav.tpl | 23 + install/deb/templates/web/nginx/caching.sh | 16 + install/deb/templates/web/nginx/caching.stpl | 76 + install/deb/templates/web/nginx/caching.tpl | 65 + install/deb/templates/web/nginx/default.stpl | 53 + install/deb/templates/web/nginx/default.tpl | 42 + install/deb/templates/web/nginx/hosting.sh | 12 + install/deb/templates/web/nginx/hosting.stpl | 55 + install/deb/templates/web/nginx/hosting.tpl | 44 + .../web/nginx/php-fpm/chevereto.stpl | 99 + .../templates/web/nginx/php-fpm/chevereto.tpl | 87 + .../web/nginx/php-fpm/cms_made_simple.stpl | 69 + .../web/nginx/php-fpm/cms_made_simple.tpl | 57 + .../web/nginx/php-fpm/codeigniter.stpl | 85 + .../web/nginx/php-fpm/codeigniter.tpl | 73 + .../templates/web/nginx/php-fpm/craftcms.stpl | 88 + .../templates/web/nginx/php-fpm/craftcms.tpl | 75 + .../web/nginx/php-fpm/datalife_engine.stpl | 140 + .../web/nginx/php-fpm/datalife_engine.tpl | 128 + .../templates/web/nginx/php-fpm/default.stpl | 67 + .../templates/web/nginx/php-fpm/default.tpl | 55 + .../templates/web/nginx/php-fpm/dokuwiki.stpl | 85 + .../templates/web/nginx/php-fpm/dokuwiki.tpl | 73 + .../web/nginx/php-fpm/drupal-composer.stpl | 119 + .../web/nginx/php-fpm/drupal-composer.tpl | 108 + .../web/nginx/php-fpm/drupal-social.stpl | 119 + .../web/nginx/php-fpm/drupal-social.tpl | 107 + .../templates/web/nginx/php-fpm/drupal.stpl | 129 + .../templates/web/nginx/php-fpm/drupal.tpl | 117 + .../templates/web/nginx/php-fpm/flarum.stpl | 94 + .../templates/web/nginx/php-fpm/flarum.tpl | 82 + .../templates/web/nginx/php-fpm/gitea.stpl | 61 + .../deb/templates/web/nginx/php-fpm/gitea.tpl | 49 + .../deb/templates/web/nginx/php-fpm/grav.stpl | 72 + .../deb/templates/web/nginx/php-fpm/grav.tpl | 60 + .../templates/web/nginx/php-fpm/joomla.stpl | 90 + .../templates/web/nginx/php-fpm/joomla.tpl | 77 + .../templates/web/nginx/php-fpm/laravel.stpl | 80 + .../templates/web/nginx/php-fpm/laravel.tpl | 68 + .../templates/web/nginx/php-fpm/magento.stpl | 208 + .../templates/web/nginx/php-fpm/magento.tpl | 193 + .../templates/web/nginx/php-fpm/mautic.stpl | 100 + .../templates/web/nginx/php-fpm/mautic.tpl | 39 + .../deb/templates/web/nginx/php-fpm/modx.stpl | 97 + .../deb/templates/web/nginx/php-fpm/modx.tpl | 85 + .../templates/web/nginx/php-fpm/moodle.stpl | 98 + .../templates/web/nginx/php-fpm/moodle.tpl | 86 + .../templates/web/nginx/php-fpm/no-php.stpl | 57 + .../templates/web/nginx/php-fpm/no-php.tpl | 46 + .../deb/templates/web/nginx/php-fpm/odoo.stpl | 78 + .../deb/templates/web/nginx/php-fpm/odoo.tpl | 66 + .../templates/web/nginx/php-fpm/opencart.stpl | 78 + .../templates/web/nginx/php-fpm/opencart.tpl | 66 + .../web/nginx/php-fpm/openproject.stpl | 56 + .../web/nginx/php-fpm/openproject.tpl | 42 + .../templates/web/nginx/php-fpm/osticket.stpl | 105 + .../templates/web/nginx/php-fpm/osticket.tpl | 93 + .../templates/web/nginx/php-fpm/owncloud.stpl | 103 + .../templates/web/nginx/php-fpm/owncloud.tpl | 91 + .../templates/web/nginx/php-fpm/phpbb.stpl | 117 + .../deb/templates/web/nginx/php-fpm/phpbb.tpl | 104 + .../templates/web/nginx/php-fpm/piwik.stpl | 88 + .../deb/templates/web/nginx/php-fpm/piwik.tpl | 76 + .../web/nginx/php-fpm/prestashop.stpl | 154 + .../web/nginx/php-fpm/prestashop.tpl | 142 + .../web/nginx/php-fpm/projectsend.stpl | 103 + .../web/nginx/php-fpm/projectsend.tpl | 89 + .../templates/web/nginx/php-fpm/pyrocms.stpl | 78 + .../templates/web/nginx/php-fpm/pyrocms.tpl | 66 + .../templates/web/nginx/php-fpm/sendy.stpl | 104 + .../deb/templates/web/nginx/php-fpm/sendy.tpl | 92 + .../web/nginx/php-fpm/suspended.stpl | 46 + .../templates/web/nginx/php-fpm/suspended.tpl | 37 + .../web/nginx/php-fpm/symfony2-3.stpl | 111 + .../web/nginx/php-fpm/symfony2-3.tpl | 98 + .../web/nginx/php-fpm/symfony4-5.stpl | 80 + .../web/nginx/php-fpm/symfony4-5.tpl | 68 + .../templates/web/nginx/php-fpm/thunder.stpl | 102 + .../templates/web/nginx/php-fpm/thunder.tpl | 90 + .../web/nginx/php-fpm/wordpress.stpl | 93 + .../templates/web/nginx/php-fpm/wordpress.tpl | 81 + .../nginx/php-fpm/wordpress_mu_subdir.stpl | 100 + .../web/nginx/php-fpm/wordpress_mu_subdir.tpl | 88 + .../templates/web/nginx/php-fpm/yourls.stpl | 43 + .../templates/web/nginx/php-fpm/yourls.tpl | 34 + install/deb/templates/web/nginx/proxy_ip.tpl | 30 + .../deb/templates/web/nginx/suspended.stpl | 45 + install/deb/templates/web/nginx/suspended.tpl | 36 + install/deb/templates/web/php-fpm/default.tpl | 34 + install/deb/templates/web/php-fpm/no-php.tpl | 32 + install/deb/templates/web/php-fpm/socket.tpl | 32 + install/deb/vsftpd/vsftpd.conf | 41 + install/hst-install-debian.sh | 2295 ++++++ install/hst-install-rhel.sh | 2080 +++++ install/hst-install-ubuntu.sh | 2269 ++++++ install/hst-install.sh | 147 + install/rpm/bind/named.conf | 3 + install/rpm/bind/named.conf.options | 24 + install/rpm/clamav/clamd.conf | 60 + install/rpm/clamav/clamd.tmpfiles | 1 + install/rpm/clamav/freshclam.conf | 210 + install/rpm/dovecot/conf.d/10-auth.conf | 5 + install/rpm/dovecot/conf.d/10-logging.conf | 1 + install/rpm/dovecot/conf.d/10-mail.conf | 8 + install/rpm/dovecot/conf.d/10-master.conf | 31 + install/rpm/dovecot/conf.d/10-ssl.conf | 9 + install/rpm/dovecot/conf.d/20-imap.conf | 59 + install/rpm/dovecot/conf.d/20-pop3.conf | 92 + install/rpm/dovecot/conf.d/90-quota.conf | 84 + .../dovecot/conf.d/auth-passwdfile.conf.ext | 9 + install/rpm/dovecot/dovecot.conf | 66 + install/rpm/dovecot/sieve/20-managesieve.conf | 88 + .../dovecot/sieve/90-sieve-extprograms.conf | 44 + install/rpm/dovecot/sieve/90-sieve.conf | 211 + install/rpm/exim/dnsbl.conf | 2 + install/rpm/exim/exim.conf | 429 ++ install/rpm/exim/exim.conf.template | 480 ++ install/rpm/exim/limit.conf | 1 + install/rpm/exim/spam-blocks.conf | 0 install/rpm/exim/system.filter | 16 + install/rpm/fail2ban/action.d/hestia.conf | 9 + install/rpm/fail2ban/filter.d/hestia.conf | 10 + install/rpm/fail2ban/jail.local | 66 + install/rpm/hestia/hestia.repo | 7 + install/rpm/httpd/hestia-event.conf | 5 + install/rpm/httpd/hestia.conf | 58 + install/rpm/httpd/httpd.conf | 80 + install/rpm/httpd/status.conf | 6 + install/rpm/httpd/unassigned.conf | 18 + install/rpm/logrotate/dovecot | 12 + install/rpm/logrotate/hestia | 7 + install/rpm/logrotate/httpd | 15 + install/rpm/logrotate/httpd-prerotate/awstats | 4 + install/rpm/logrotate/nginx | 13 + install/rpm/logrotate/roundcube | 7 + install/rpm/mysql/mariadb-aarch64.repo | 6 + install/rpm/mysql/mariadb-x86_64.repo | 6 + install/rpm/mysql/my-large.cnf | 42 + install/rpm/mysql/my-medium.cnf | 41 + install/rpm/mysql/my-small.cnf | 41 + install/rpm/mysql/mysql.repo | 7 + install/rpm/nginx/0rtt-anti-replay.conf | 39 + install/rpm/nginx/agents.conf | 16 + install/rpm/nginx/nginx.conf | 130 + install/rpm/nginx/nginx.repo | 6 + install/rpm/nginx/phpmyadmin.inc | 26 + install/rpm/nginx/phppgadmin.inc | 12 + install/rpm/nginx/status.conf | 11 + install/rpm/nginx/unassigned.inc | 52 + install/rpm/pga/config.inc.php | 166 + install/rpm/pga/phppgadmin.conf | 31 + install/rpm/php-fpm/dummy.conf | 13 + install/rpm/php-fpm/multiphp.tpl | 26 + install/rpm/php-fpm/www.conf | 13 + install/rpm/phpmyadmin/create_tables.sql | 389 + install/rpm/phpmyadmin/pma.sh | 146 + install/rpm/pma/apache.conf | 54 + install/rpm/pma/config.inc.php | 145 + install/rpm/postgresql/pg_hba.conf | 11 + install/rpm/proftpd/proftpd.conf | 36 + install/rpm/proftpd/tls.conf | 65 + install/rpm/ssl/dhparam.pem | 13 + install/rpm/sudo/admin | 10 + .../rpm/templates/mail/apache2/default.stpl | 51 + .../rpm/templates/mail/apache2/default.tpl | 48 + .../rpm/templates/mail/apache2/disabled.stpl | 12 + .../rpm/templates/mail/apache2/disabled.tpl | 7 + .../rpm/templates/mail/apache2/rainloop.stpl | 31 + .../rpm/templates/mail/apache2/rainloop.tpl | 25 + .../templates/mail/apache2/snappymail.stpl | 31 + .../rpm/templates/mail/apache2/snappymail.tpl | 25 + install/rpm/templates/mail/nginx/default.stpl | 52 + install/rpm/templates/mail/nginx/default.tpl | 43 + .../mail/nginx/default_disabled.stpl | 29 + .../templates/mail/nginx/default_disabled.tpl | 20 + .../mail/nginx/default_snappymail.stpl | 52 + .../mail/nginx/default_snappymail.tpl | 48 + .../rpm/templates/mail/nginx/disabled.stpl | 34 + install/rpm/templates/mail/nginx/disabled.tpl | 25 + .../rpm/templates/mail/nginx/snappymail.stpl | 59 + .../rpm/templates/mail/nginx/snappymail.tpl | 49 + .../rpm/templates/mail/nginx/web_system.stpl | 53 + .../rpm/templates/mail/nginx/web_system.tpl | 44 + .../rpm/templates/web/apache2/default.stpl | 49 + install/rpm/templates/web/apache2/default.tpl | 46 + .../rpm/templates/web/apache2/hosting.stpl | 55 + install/rpm/templates/web/apache2/hosting.tpl | 52 + .../web/apache2/php-fpm/default.stpl | 41 + .../templates/web/apache2/php-fpm/default.tpl | 38 + install/rpm/templates/web/apache2/phpcgi.sh | 16 + install/rpm/templates/web/apache2/phpcgi.stpl | 44 + install/rpm/templates/web/apache2/phpcgi.tpl | 40 + install/rpm/templates/web/apache2/phpfcgid.sh | 22 + .../rpm/templates/web/apache2/phpfcgid.stpl | 45 + .../rpm/templates/web/apache2/phpfcgid.tpl | 40 + .../rpm/templates/web/apache2/www-data.stpl | 41 + .../rpm/templates/web/apache2/www-data.tpl | 38 + install/rpm/templates/web/awstats/awstats.tpl | 133 + install/rpm/templates/web/awstats/index.tpl | 10 + install/rpm/templates/web/awstats/nav.tpl | 23 + install/rpm/templates/web/nginx/caching.sh | 16 + install/rpm/templates/web/nginx/caching.stpl | 77 + install/rpm/templates/web/nginx/caching.tpl | 65 + install/rpm/templates/web/nginx/default.stpl | 53 + install/rpm/templates/web/nginx/default.tpl | 42 + install/rpm/templates/web/nginx/hosting.sh | 12 + install/rpm/templates/web/nginx/hosting.stpl | 55 + install/rpm/templates/web/nginx/hosting.tpl | 44 + .../web/nginx/php-fpm/chevereto.stpl | 99 + .../templates/web/nginx/php-fpm/chevereto.tpl | 87 + .../web/nginx/php-fpm/cms_made_simple.stpl | 69 + .../web/nginx/php-fpm/cms_made_simple.tpl | 57 + .../web/nginx/php-fpm/codeigniter.stpl | 85 + .../web/nginx/php-fpm/codeigniter.tpl | 73 + .../templates/web/nginx/php-fpm/craftcms.stpl | 88 + .../templates/web/nginx/php-fpm/craftcms.tpl | 75 + .../web/nginx/php-fpm/datalife_engine.stpl | 140 + .../web/nginx/php-fpm/datalife_engine.tpl | 128 + .../templates/web/nginx/php-fpm/default.stpl | 67 + .../templates/web/nginx/php-fpm/default.tpl | 55 + .../templates/web/nginx/php-fpm/dokuwiki.stpl | 85 + .../templates/web/nginx/php-fpm/dokuwiki.tpl | 73 + .../web/nginx/php-fpm/drupal-composer.stpl | 119 + .../web/nginx/php-fpm/drupal-composer.tpl | 108 + .../web/nginx/php-fpm/drupal-social.stpl | 119 + .../web/nginx/php-fpm/drupal-social.tpl | 107 + .../templates/web/nginx/php-fpm/drupal.stpl | 129 + .../templates/web/nginx/php-fpm/drupal.tpl | 117 + .../templates/web/nginx/php-fpm/flarum.stpl | 94 + .../templates/web/nginx/php-fpm/flarum.tpl | 82 + .../templates/web/nginx/php-fpm/gitea.stpl | 61 + .../rpm/templates/web/nginx/php-fpm/gitea.tpl | 49 + .../rpm/templates/web/nginx/php-fpm/grav.stpl | 72 + .../rpm/templates/web/nginx/php-fpm/grav.tpl | 60 + .../templates/web/nginx/php-fpm/joomla.stpl | 90 + .../templates/web/nginx/php-fpm/joomla.tpl | 77 + .../templates/web/nginx/php-fpm/laravel.stpl | 80 + .../templates/web/nginx/php-fpm/laravel.tpl | 68 + .../templates/web/nginx/php-fpm/magento.stpl | 208 + .../templates/web/nginx/php-fpm/magento.tpl | 193 + .../templates/web/nginx/php-fpm/mautic.stpl | 100 + .../templates/web/nginx/php-fpm/mautic.tpl | 39 + .../rpm/templates/web/nginx/php-fpm/modx.stpl | 97 + .../rpm/templates/web/nginx/php-fpm/modx.tpl | 85 + .../templates/web/nginx/php-fpm/moodle.stpl | 98 + .../templates/web/nginx/php-fpm/moodle.tpl | 86 + .../templates/web/nginx/php-fpm/no-php.stpl | 57 + .../templates/web/nginx/php-fpm/no-php.tpl | 46 + .../rpm/templates/web/nginx/php-fpm/odoo.stpl | 78 + .../rpm/templates/web/nginx/php-fpm/odoo.tpl | 66 + .../templates/web/nginx/php-fpm/opencart.stpl | 78 + .../templates/web/nginx/php-fpm/opencart.tpl | 66 + .../web/nginx/php-fpm/openproject.stpl | 56 + .../web/nginx/php-fpm/openproject.tpl | 42 + .../templates/web/nginx/php-fpm/osticket.stpl | 105 + .../templates/web/nginx/php-fpm/osticket.tpl | 93 + .../templates/web/nginx/php-fpm/owncloud.stpl | 103 + .../templates/web/nginx/php-fpm/owncloud.tpl | 91 + .../templates/web/nginx/php-fpm/phpbb.stpl | 117 + .../rpm/templates/web/nginx/php-fpm/phpbb.tpl | 104 + .../templates/web/nginx/php-fpm/piwik.stpl | 88 + .../rpm/templates/web/nginx/php-fpm/piwik.tpl | 76 + .../web/nginx/php-fpm/prestashop.stpl | 154 + .../web/nginx/php-fpm/prestashop.tpl | 142 + .../web/nginx/php-fpm/projectsend.stpl | 103 + .../web/nginx/php-fpm/projectsend.tpl | 89 + .../templates/web/nginx/php-fpm/pyrocms.stpl | 78 + .../templates/web/nginx/php-fpm/pyrocms.tpl | 66 + .../templates/web/nginx/php-fpm/sendy.stpl | 104 + .../rpm/templates/web/nginx/php-fpm/sendy.tpl | 92 + .../web/nginx/php-fpm/suspended.stpl | 46 + .../templates/web/nginx/php-fpm/suspended.tpl | 37 + .../web/nginx/php-fpm/symfony2-3.stpl | 111 + .../web/nginx/php-fpm/symfony2-3.tpl | 98 + .../web/nginx/php-fpm/symfony4-5.stpl | 80 + .../web/nginx/php-fpm/symfony4-5.tpl | 68 + .../templates/web/nginx/php-fpm/thunder.stpl | 102 + .../templates/web/nginx/php-fpm/thunder.tpl | 90 + .../web/nginx/php-fpm/wordpress.stpl | 93 + .../templates/web/nginx/php-fpm/wordpress.tpl | 81 + .../nginx/php-fpm/wordpress_mu_subdir.stpl | 100 + .../web/nginx/php-fpm/wordpress_mu_subdir.tpl | 88 + .../templates/web/nginx/php-fpm/yourls.stpl | 43 + .../templates/web/nginx/php-fpm/yourls.tpl | 34 + install/rpm/templates/web/nginx/proxy_ip.tpl | 36 + .../rpm/templates/web/nginx/suspended.stpl | 45 + install/rpm/templates/web/nginx/suspended.tpl | 36 + install/rpm/templates/web/php-fpm/default.tpl | 34 + install/rpm/templates/web/php-fpm/no-php.tpl | 32 + install/rpm/templates/web/php-fpm/socket.tpl | 32 + install/rpm/vsftpd/vsftpd.conf | 41 + .../upgrade/manual/configure-server-smtp.sh | 82 + .../upgrade/manual/install_awstats_geoip.sh | 50 + .../upgrade/manual/install_awstats_geoip2.sh | 50 + install/upgrade/manual/install_sieve.sh | 127 + install/upgrade/manual/migrate_apache.sh | 99 + install/upgrade/manual/migrate_mpm_event.sh | 83 + install/upgrade/manual/migrate_multiphp.sh | 162 + .../migrate_ngnix_apache_nginx-php-fpm.sh | 67 + install/upgrade/manual/migrate_phpmyadmin.sh | 198 + install/upgrade/manual/migrate_roundcube.sh | 55 + install/upgrade/manual/remove-mail-stack.sh | 53 + install/upgrade/manual/upgrade_mariadb.sh | 69 + install/upgrade/manual/upgrade_multi_php.sh | 26 + install/upgrade/manual/upgrade_php.sh | 66 + .../3462-exim-helo-autenticted-users.patch | 18 + .../upgrade/patch/3661-exim-srs-support.patch | 38 + install/upgrade/upgrade.conf | 66 + install/upgrade/versions/0.9.8-29.sh | 30 + install/upgrade/versions/1.0.1.sh | 16 + install/upgrade/versions/1.0.2.sh | 70 + install/upgrade/versions/1.0.3.sh | 7 + install/upgrade/versions/1.0.4.sh | 7 + install/upgrade/versions/1.0.5.sh | 7 + install/upgrade/versions/1.0.6.sh | 7 + install/upgrade/versions/1.00.0-190618.sh | 267 + install/upgrade/versions/1.1.0.sh | 224 + install/upgrade/versions/1.1.1.sh | 20 + install/upgrade/versions/1.2.0.sh | 219 + install/upgrade/versions/1.2.1.sh | 7 + install/upgrade/versions/1.2.2.sh | 48 + install/upgrade/versions/1.2.3.sh | 7 + install/upgrade/versions/1.3.0.sh | 76 + install/upgrade/versions/1.3.1.sh | 21 + install/upgrade/versions/1.3.2.sh | 7 + install/upgrade/versions/1.3.3.sh | 21 + install/upgrade/versions/1.3.4.sh | 17 + install/upgrade/versions/1.4.0.sh | 198 + install/upgrade/versions/1.4.1.sh | 7 + install/upgrade/versions/1.4.10.sh | 7 + install/upgrade/versions/1.4.11.sh | 27 + install/upgrade/versions/1.4.12.sh | 16 + install/upgrade/versions/1.4.13.sh | 51 + install/upgrade/versions/1.4.14.sh | 21 + install/upgrade/versions/1.4.15.sh | 29 + install/upgrade/versions/1.4.16.sh | 20 + install/upgrade/versions/1.4.17.sh | 20 + install/upgrade/versions/1.4.2.sh | 29 + install/upgrade/versions/1.4.3.sh | 20 + install/upgrade/versions/1.4.4.sh | 37 + install/upgrade/versions/1.4.5.sh | 7 + install/upgrade/versions/1.4.6.sh | 12 + install/upgrade/versions/1.4.7.sh | 11 + install/upgrade/versions/1.4.8.sh | 28 + install/upgrade/versions/1.4.9.sh | 7 + install/upgrade/versions/1.5.0.sh | 81 + install/upgrade/versions/1.5.1.sh | 56 + install/upgrade/versions/1.5.10.sh | 40 + install/upgrade/versions/1.5.11.sh | 50 + install/upgrade/versions/1.5.2.sh | 22 + install/upgrade/versions/1.5.3.sh | 22 + install/upgrade/versions/1.5.4.sh | 22 + install/upgrade/versions/1.5.5.sh | 103 + install/upgrade/versions/1.5.6.sh | 27 + install/upgrade/versions/1.5.7.sh | 22 + install/upgrade/versions/1.5.8.sh | 33 + install/upgrade/versions/1.5.9.sh | 22 + install/upgrade/versions/1.6.0.sh | 133 + install/upgrade/versions/1.6.1.sh | 51 + install/upgrade/versions/1.6.10.sh | 25 + install/upgrade/versions/1.6.12.sh | 33 + install/upgrade/versions/1.6.13.sh | 22 + install/upgrade/versions/1.6.14.sh | 29 + install/upgrade/versions/1.6.2.sh | 38 + install/upgrade/versions/1.6.3.sh | 30 + install/upgrade/versions/1.6.4.sh | 22 + install/upgrade/versions/1.6.5.sh | 22 + install/upgrade/versions/1.6.6.sh | 30 + install/upgrade/versions/1.6.7.sh | 30 + install/upgrade/versions/1.6.8.sh | 46 + install/upgrade/versions/1.6.9.sh | 28 + install/upgrade/versions/1.7.0.sh | 121 + install/upgrade/versions/1.7.1.sh | 46 + install/upgrade/versions/1.7.2.sh | 24 + install/upgrade/versions/1.7.3.sh | 29 + install/upgrade/versions/1.7.4.sh | 24 + install/upgrade/versions/1.7.5.sh | 24 + install/upgrade/versions/1.7.6.sh | 24 + install/upgrade/versions/1.7.7.sh | 24 + install/upgrade/versions/1.8.0.sh | 298 + install/upgrade/versions/1.8.1.sh | 34 + install/upgrade/versions/1.8.2.sh | 37 + install/upgrade/versions/1.8.3.sh | 30 + package-lock.json | 6698 +++++++++++++++++ package.json | 52 + renovate.json | 28 + src/deb/hestia/control | 14 + src/deb/hestia/copyright | 30 + src/deb/hestia/postinst | 126 + src/deb/hestia/preinst | 19 + src/deb/nginx/control | 14 + src/deb/nginx/copyright | 30 + src/deb/nginx/hestia | 143 + src/deb/nginx/nginx.conf | 178 + src/deb/nginx/postinst | 51 + src/deb/nginx/postrm | 5 + src/deb/php/control | 15 + src/deb/php/copyright | 30 + src/deb/php/php-fpm.conf | 44 + src/deb/php/php.ini | 1977 +++++ src/deb/php/postinst | 43 + src/hst_autocompile.sh | 750 ++ src/hst_bootstrap_install.sh | 29 + src/hst_generate_clidocs.sh | 8 + src/lxd_build_all.sh | 96 + src/lxd_compile.sh | 41 + src/rpm/hestia/hestia.service | 15 + src/rpm/hestia/hestia.spec | 177 + src/rpm/hestia/hestia.tmpfiles | 1 + src/rpm/nginx/hestia-nginx.service | 19 + src/rpm/nginx/hestia-nginx.spec | 136 + src/rpm/nginx/nginx.conf | 180 + src/rpm/php/hestia-php.service | 16 + src/rpm/php/hestia-php.spec | 117 + src/rpm/php/php-fpm.conf | 43 + src/rpm/php/php.ini | 1977 +++++ src/script_template.sh | 38 + test/api.bats | 151 + test/check_php.sh | 40 + test/checks.bats | 388 + test/config-tests.bats | 90 + test/letsencrypt.bats | 137 + test/lint_script.sh | 66 + test/make-test-containers.php | 460 ++ test/restore.bats | 591 ++ test/shellcheck.sh | 43 + test/test.bats | 2239 ++++++ test/wildcard.bats | 52 + web/add/access-key/index.php | 101 + web/add/cron/autoupdate/index.php | 17 + web/add/cron/index.php | 114 + web/add/cron/reports/index.php | 12 + web/add/db/index.php | 248 + web/add/dns/index.php | 406 + web/add/firewall/banlist/index.php | 69 + web/add/firewall/index.php | 125 + web/add/firewall/ipset/index.php | 90 + web/add/ip/index.php | 142 + web/add/key/index.php | 83 + web/add/mail/index.php | 593 ++ web/add/package/index.php | 326 + web/add/user/index.php | 285 + web/add/web/index.php | 190 + web/add/webapp/index.php | 146 + web/api/index.php | 383 + web/bulk/access-key/index.php | 61 + web/bulk/backup/index.php | 36 + web/bulk/cron/index.php | 90 + web/bulk/db/index.php | 63 + web/bulk/dns/index.php | 121 + web/bulk/firewall/banlist/index.php | 46 + web/bulk/firewall/index.php | 51 + web/bulk/firewall/ipset/index.php | 43 + web/bulk/ip/index.php | 47 + web/bulk/mail/index.php | 125 + web/bulk/package/index.php | 43 + web/bulk/restore/index.php | 88 + web/bulk/service/index.php | 53 + web/bulk/user/index.php | 85 + web/bulk/web/index.php | 71 + web/copy/package/index.php | 42 + web/css/src/base.css | 127 + web/css/src/dependencies/animate.css | 76 + web/css/src/fonts.css | 126 + web/css/src/media_queries.css | 6 + web/css/src/themes/dark.css | 810 ++ web/css/src/themes/default.css | 2530 +++++++ web/css/src/themes/flat.css | 186 + web/css/src/themes/vestia.css | 459 ++ web/css/src/utilities.css | 192 + web/delete/access-key/index.php | 50 + web/delete/backup/exclusion/index.php | 32 + web/delete/backup/index.php | 28 + web/delete/cron/autoupdate/index.php | 18 + web/delete/cron/index.php | 29 + web/delete/cron/reports/index.php | 13 + web/delete/db/index.php | 28 + web/delete/dns/index.php | 63 + web/delete/firewall/banlist/index.php | 32 + web/delete/firewall/index.php | 31 + web/delete/firewall/ipset/index.php | 35 + web/delete/ip/index.php | 26 + web/delete/key/index.php | 29 + web/delete/log/auth/index.php | 60 + web/delete/log/index.php | 39 + web/delete/mail/index.php | 65 + web/delete/notification/index.php | 41 + web/delete/package/index.php | 32 + web/delete/user/index.php | 27 + web/delete/web/cache/index.php | 22 + web/delete/web/index.php | 33 + web/download/backup/index.php | 44 + web/download/database/index.php | 18 + web/download/site/index.php | 18 + web/download/web-log/index.php | 42 + web/edit/backup/exclusions/index.php | 133 + web/edit/cron/index.php | 98 + web/edit/db/index.php | 114 + web/edit/dns/index.php | 355 + web/edit/firewall/index.php | 153 + web/edit/ip/index.php | 106 + web/edit/mail/index.php | 1181 +++ web/edit/package/index.php | 336 + web/edit/server/apache2/index.php | 59 + web/edit/server/bind9/index.php | 78 + web/edit/server/clamav-daemon/index.php | 59 + web/edit/server/cron/index.php | 31 + web/edit/server/crond/index.php | 31 + web/edit/server/dovecot/index.php | 232 + web/edit/server/exim/index.php | 59 + web/edit/server/exim4/index.php | 59 + web/edit/server/fail2ban/index.php | 59 + web/edit/server/httpd/index.php | 59 + web/edit/server/index.php | 1748 +++++ web/edit/server/iptables/index.php | 9 + web/edit/server/mariadb/index.php | 68 + web/edit/server/mysql/index.php | 68 + web/edit/server/mysqld/index.php | 68 + web/edit/server/named/index.php | 59 + web/edit/server/nginx/index.php | 73 + web/edit/server/php-fpm/index.php | 69 + web/edit/server/php/index.php | 69 + web/edit/server/php5-fpm/index.php | 69 + web/edit/server/postgresql/index.php | 87 + web/edit/server/proftpd/index.php | 59 + web/edit/server/spamassassin/index.php | 59 + web/edit/server/spamd/index.php | 59 + web/edit/server/ssh/index.php | 59 + web/edit/server/vsftpd/index.php | 59 + web/edit/server/whitelabel/index.php | 104 + web/edit/user/index.php | 567 ++ web/edit/web/index.php | 1666 ++++ web/error/403.html | 119 + web/error/404.html | 119 + web/error/410.html | 119 + web/error/50x.html | 122 + web/favicon.ico | Bin 0 -> 1150 bytes web/generate/ssl/index.php | 147 + web/images/arrow.svg | 1 + web/images/favicon.png | Bin 0 -> 1336 bytes web/images/logo-header.svg | 18 + web/images/logo.png | Bin 0 -> 9087 bytes web/images/logo.svg | 117 + web/inc/2fa/check.php | 23 + web/inc/2fa/secret.php | 10 + web/inc/composer.json | 7 + web/inc/composer.lock | 218 + web/inc/helpers.php | 178 + web/inc/i18n.php | 85 + web/inc/mail-wrapper.php | 43 + web/inc/main.php | 578 ++ web/inc/policies.php | 20 + web/inc/prevent_csrf.php | 151 + web/inc/secure_login.php | 31 + web/index.php | 3 + web/js/custom_scripts/README.txt | 9 + web/js/src/addIpLists.js | 25 + web/js/src/alpineInit.js | 75 + web/js/src/confirmAction.js | 16 + web/js/src/copyCreds.js | 27 + web/js/src/cronGenerator.js | 25 + web/js/src/databaseHints.js | 44 + web/js/src/discardAllMail.js | 30 + web/js/src/dnsRecordHint.js | 49 + web/js/src/docRootHint.js | 29 + web/js/src/editWebListeners.js | 66 + web/js/src/errorHandler.js | 10 + web/js/src/focusFirstInput.js | 13 + web/js/src/formSubmit.js | 37 + web/js/src/ftpAccountHints.js | 54 + web/js/src/ftpAccounts.js | 156 + web/js/src/helpers.js | 138 + web/js/src/index.js | 62 + web/js/src/ipListDataSource.js | 38 + web/js/src/listSorting.js | 75 + web/js/src/listUnitSelect.js | 45 + web/js/src/nameServerInput.js | 38 + web/js/src/navigation.js | 119 + web/js/src/passwordInput.js | 38 + web/js/src/rrdCharts.js | 108 + web/js/src/shortcuts.js | 462 ++ web/js/src/stickyToolbar.js | 22 + web/js/src/syncEmailValues.js | 23 + web/js/src/tabPanels.js | 31 + web/js/src/toggleAdvanced.js | 36 + web/js/src/unlimitedInput.js | 60 + web/list/access-key/index.php | 61 + web/list/backup/exclusions/index.php | 16 + web/list/backup/index.php | 34 + web/list/cron/index.php | 21 + web/list/db/index.php | 21 + web/list/dns/index.php | 108 + web/list/firewall/banlist/index.php | 23 + web/list/firewall/index.php | 27 + web/list/firewall/ipset/index.php | 22 + web/list/index.php | 8 + web/list/ip/index.php | 28 + web/list/key/index.php | 23 + web/list/log/auth/index.php | 29 + web/list/log/index.php | 50 + web/list/mail/index.php | 71 + web/list/notifications/index.php | 29 + web/list/package/index.php | 28 + web/list/rrd/ajax.php | 63 + web/list/rrd/image.php | 18 + web/list/rrd/index.php | 49 + web/list/server/index.php | 140 + web/list/server/preview/index.php | 11 + web/list/stats/index.php | 37 + web/list/updates/index.php | 25 + web/list/user/index.php | 36 + web/list/web-log/index.php | 26 + web/list/web/index.php | 21 + web/locale/ar/LC_MESSAGES/hestiacp.mo | Bin 0 -> 63221 bytes web/locale/az/LC_MESSAGES/hestiacp.mo | Bin 0 -> 9741 bytes web/locale/bg/LC_MESSAGES/hestiacp.mo | Bin 0 -> 23663 bytes web/locale/bn/LC_MESSAGES/hestiacp.mo | Bin 0 -> 31844 bytes web/locale/bs/LC_MESSAGES/hestiacp.mo | Bin 0 -> 7415 bytes web/locale/ca/LC_MESSAGES/hestiacp.mo | Bin 0 -> 12812 bytes web/locale/cs/LC_MESSAGES/hestiacp.mo | Bin 0 -> 15864 bytes web/locale/da/LC_MESSAGES/hestiacp.mo | Bin 0 -> 5364 bytes web/locale/de/LC_MESSAGES/hestiacp.mo | Bin 0 -> 50990 bytes web/locale/el/LC_MESSAGES/hestiacp.mo | Bin 0 -> 16882 bytes web/locale/es/LC_MESSAGES/hestiacp.mo | Bin 0 -> 50180 bytes web/locale/fa/LC_MESSAGES/hestiacp.mo | Bin 0 -> 10472 bytes web/locale/fi/LC_MESSAGES/hestiacp.mo | Bin 0 -> 7248 bytes web/locale/fr/LC_MESSAGES/hestiacp.mo | Bin 0 -> 21333 bytes web/locale/hestiacp.pot | 4787 ++++++++++++ web/locale/hr/LC_MESSAGES/hestiacp.mo | Bin 0 -> 17745 bytes web/locale/hst_convert_po2mo.sh | 20 + web/locale/hst_scan_i18n.sh | 36 + web/locale/hu/LC_MESSAGES/hestiacp.mo | Bin 0 -> 51165 bytes web/locale/id/LC_MESSAGES/hestiacp.mo | Bin 0 -> 9496 bytes web/locale/it/LC_MESSAGES/hestiacp.mo | Bin 0 -> 21944 bytes web/locale/ja/LC_MESSAGES/hestiacp.mo | Bin 0 -> 10946 bytes web/locale/ka/LC_MESSAGES/hestiacp.mo | Bin 0 -> 34144 bytes web/locale/ko/LC_MESSAGES/hestiacp.mo | Bin 0 -> 9272 bytes web/locale/ku/LC_MESSAGES/hestiacp.mo | Bin 0 -> 25374 bytes web/locale/languages.json | 84 + web/locale/nl/LC_MESSAGES/hestiacp.mo | Bin 0 -> 48459 bytes web/locale/no/LC_MESSAGES/hestiacp.mo | Bin 0 -> 5738 bytes web/locale/pl/LC_MESSAGES/hestiacp.mo | Bin 0 -> 21227 bytes web/locale/pt-br/LC_MESSAGES/hestiacp.mo | Bin 0 -> 49812 bytes web/locale/pt/LC_MESSAGES/hestiacp.mo | Bin 0 -> 49494 bytes web/locale/ro/LC_MESSAGES/hestiacp.mo | Bin 0 -> 8976 bytes web/locale/ru/LC_MESSAGES/hestiacp.mo | Bin 0 -> 64940 bytes web/locale/sk/LC_MESSAGES/hestiacp.mo | Bin 0 -> 21178 bytes web/locale/sr/LC_MESSAGES/hestiacp.mo | Bin 0 -> 17408 bytes web/locale/sv/LC_MESSAGES/hestiacp.mo | Bin 0 -> 6133 bytes web/locale/th/LC_MESSAGES/hestiacp.mo | Bin 0 -> 11604 bytes web/locale/tr/LC_MESSAGES/hestiacp.mo | Bin 0 -> 38168 bytes web/locale/uk/LC_MESSAGES/hestiacp.mo | Bin 0 -> 60372 bytes web/locale/ur/LC_MESSAGES/hestiacp.mo | Bin 0 -> 10111 bytes web/locale/vi/LC_MESSAGES/hestiacp.mo | Bin 0 -> 8754 bytes web/locale/zh-cn/LC_MESSAGES/hestiacp.mo | Bin 0 -> 40169 bytes web/locale/zh-tw/LC_MESSAGES/hestiacp.mo | Bin 0 -> 24040 bytes web/login/index.php | 462 ++ web/logout/index.php | 39 + web/reset/index.php | 249 + web/reset/mail/index.php | 117 + web/reset2fa/index.php | 66 + web/restart/service/index.php | 31 + web/restart/system/index.php | 34 + web/robots.txt | 2 + web/schedule/backup/index.php | 28 + web/schedule/restore/index.php | 79 + web/search/index.php | 42 + web/src/app/Models/DnsDomain.php | 8 + web/src/app/Models/MailDomain.php | 8 + web/src/app/Models/Model.php | 30 + web/src/app/Models/User.php | 8 + web/src/app/Models/WebDomain.php | 8 + web/src/app/System/HestiaApp.php | 353 + web/src/app/System/HestiaCli.php | 8 + web/src/app/System/Util.php | 33 + web/src/app/WebApp/AppWizard.php | 133 + web/src/app/WebApp/InstallerInterface.php | 10 + web/src/app/WebApp/Installers/BaseSetup.php | 201 + .../Installers/DokuWiki/DokuWikiSetup.php | 140 + .../Installers/DokuWiki/dokuwiki-logo.svg | 586 ++ .../WebApp/Installers/Drupal/DrupalSetup.php | 89 + .../WebApp/Installers/Drupal/drupal-thumb.png | Bin 0 -> 15523 bytes .../WebApp/Installers/Flarum/FlarumSetup.php | 214 + .../app/WebApp/Installers/Flarum/fl-thumb.png | Bin 0 -> 10081 bytes .../app/WebApp/Installers/Grav/GravSetup.php | 76 + .../WebApp/Installers/Grav/grav-symbol.svg | 14 + .../Installers/Laravel/LaravelSetup.php | 55 + .../Installers/Laravel/laravel-thumb.png | Bin 0 -> 15869 bytes .../MediaWiki/MediaWiki-2020-logo.svg | 53 + .../Installers/MediaWiki/MediaWikiSetup.php | 92 + .../Installers/Nextcloud/NextcloudSetup.php | 85 + .../Installers/Nextcloud/nextcloud-thumb.png | Bin 0 -> 15683 bytes .../Installers/Opencart/OpencartSetup.php | 134 + .../Installers/Opencart/opencart-thumb.png | Bin 0 -> 27842 bytes .../Installers/Prestashop/PrestashopSetup.php | 93 + .../Prestashop/prestashop-thumb.png | Bin 0 -> 14644 bytes .../Installers/Resources/ComposerResource.php | 37 + .../Installers/Resources/WpResource.php | 28 + .../Installers/Symfony/SymfonySetup.php | 62 + .../Installers/Symfony/symfony-thumb.png | Bin 0 -> 5670 bytes .../Installers/WordPress/WordPressSetup.php | 272 + .../WebApp/Installers/WordPress/wp-thumb.png | Bin 0 -> 32348 bytes web/src/composer.json | 10 + web/src/composer.lock | 140 + web/src/init.php | 19 + web/start/service/index.php | 31 + web/stop/service/index.php | 33 + web/suspend/cron/index.php | 23 + web/suspend/db/index.php | 24 + web/suspend/dns/index.php | 52 + web/suspend/firewall/index.php | 32 + web/suspend/mail/index.php | 53 + web/suspend/user/index.php | 31 + web/suspend/web/index.php | 25 + web/templates/footer.php | 79 + web/templates/header.php | 12 + web/templates/includes/css.php | 25 + web/templates/includes/js.php | 30 + web/templates/includes/panel.php | 394 + web/templates/includes/title.php | 3 + web/templates/pages/add_access_key.php | 45 + web/templates/pages/add_cron.php | 377 + web/templates/pages/add_db.php | 169 + web/templates/pages/add_dns.php | 165 + web/templates/pages/add_dns_rec.php | 88 + web/templates/pages/add_firewall.php | 74 + web/templates/pages/add_firewall_banlist.php | 49 + web/templates/pages/add_firewall_ipset.php | 109 + web/templates/pages/add_ip.php | 90 + web/templates/pages/add_key.php | 41 + web/templates/pages/add_mail.php | 126 + web/templates/pages/add_mail_acc.php | 205 + web/templates/pages/add_package.php | 334 + web/templates/pages/add_user.php | 135 + web/templates/pages/add_web.php | 83 + web/templates/pages/debug_panel.php | 63 + .../pages/edit_backup_exclusions.php | 47 + web/templates/pages/edit_cron.php | 377 + web/templates/pages/edit_db.php | 76 + web/templates/pages/edit_dns.php | 93 + web/templates/pages/edit_dns_rec.php | 89 + web/templates/pages/edit_firewall.php | 74 + web/templates/pages/edit_ip.php | 83 + web/templates/pages/edit_mail.php | 200 + web/templates/pages/edit_mail_acc.php | 210 + web/templates/pages/edit_package.php | 338 + web/templates/pages/edit_server.php | 1425 ++++ web/templates/pages/edit_server_bind9.php | 45 + web/templates/pages/edit_server_dovecot.php | 75 + web/templates/pages/edit_server_httpd.php | 44 + web/templates/pages/edit_server_mysql.php | 75 + web/templates/pages/edit_server_nginx.php | 98 + web/templates/pages/edit_server_pgsql.php | 45 + web/templates/pages/edit_server_php.php | 83 + web/templates/pages/edit_server_service.php | 41 + web/templates/pages/edit_user.php | 304 + web/templates/pages/edit_web.php | 489 ++ web/templates/pages/edit_whitelabel.php | 148 + web/templates/pages/generate_ssl.php | 66 + web/templates/pages/list_access_key.php | 60 + web/templates/pages/list_access_keys.php | 135 + web/templates/pages/list_backup.php | 164 + web/templates/pages/list_backup_detail.php | 284 + .../pages/list_backup_exclusions.php | 62 + web/templates/pages/list_cron.php | 199 + web/templates/pages/list_db.php | 270 + web/templates/pages/list_dns.php | 259 + web/templates/pages/list_dns_public.php | 60 + web/templates/pages/list_dns_rec.php | 184 + web/templates/pages/list_firewall.php | 188 + web/templates/pages/list_firewall_banlist.php | 107 + web/templates/pages/list_firewall_ipset.php | 116 + web/templates/pages/list_ip.php | 157 + web/templates/pages/list_key.php | 91 + web/templates/pages/list_log.php | 137 + web/templates/pages/list_log_auth.php | 109 + web/templates/pages/list_mail.php | 343 + web/templates/pages/list_mail_acc.php | 291 + web/templates/pages/list_mail_dns.php | 168 + web/templates/pages/list_packages.php | 316 + web/templates/pages/list_rrd.php | 41 + web/templates/pages/list_search.php | 188 + web/templates/pages/list_server_info.php | 125 + web/templates/pages/list_server_preview.php | 47 + web/templates/pages/list_services.php | 214 + web/templates/pages/list_ssl.php | 102 + web/templates/pages/list_stats.php | 238 + web/templates/pages/list_updates.php | 77 + web/templates/pages/list_user.php | 315 + web/templates/pages/list_web.php | 352 + web/templates/pages/list_webapps.php | 37 + web/templates/pages/list_weblog.php | 101 + web/templates/pages/login/login.php | 25 + web/templates/pages/login/login_1.php | 34 + web/templates/pages/login/login_2.php | 35 + web/templates/pages/login/login_a.php | 36 + web/templates/pages/login/reset2fa.php | 48 + web/templates/pages/login/reset_1.php | 34 + web/templates/pages/login/reset_2.php | 35 + web/templates/pages/login/reset_3.php | 37 + web/templates/pages/setup_webapp.php | 125 + web/unsuspend/cron/index.php | 26 + web/unsuspend/db/index.php | 25 + web/unsuspend/dns/index.php | 65 + web/unsuspend/firewall/index.php | 31 + web/unsuspend/mail/index.php | 66 + web/unsuspend/user/index.php | 32 + web/unsuspend/web/index.php | 25 + web/update/hestia/index.php | 28 + web/webfonts/exo-v20-latin-300.woff | Bin 0 -> 13936 bytes web/webfonts/exo-v20-latin-300.woff2 | Bin 0 -> 11120 bytes web/webfonts/exo-v20-latin-300italic.woff | Bin 0 -> 15184 bytes web/webfonts/exo-v20-latin-300italic.woff2 | Bin 0 -> 11940 bytes web/webfonts/exo-v20-latin-500.woff | Bin 0 -> 13880 bytes web/webfonts/exo-v20-latin-500.woff2 | Bin 0 -> 10996 bytes web/webfonts/exo-v20-latin-500italic.woff | Bin 0 -> 15204 bytes web/webfonts/exo-v20-latin-500italic.woff2 | Bin 0 -> 12052 bytes web/webfonts/exo-v20-latin-600.woff | Bin 0 -> 13972 bytes web/webfonts/exo-v20-latin-600.woff2 | Bin 0 -> 11096 bytes web/webfonts/exo-v20-latin-600italic.woff | Bin 0 -> 15144 bytes web/webfonts/exo-v20-latin-600italic.woff2 | Bin 0 -> 12008 bytes web/webfonts/exo-v20-latin-700.woff | Bin 0 -> 13964 bytes web/webfonts/exo-v20-latin-700.woff2 | Bin 0 -> 11052 bytes web/webfonts/exo-v20-latin-700italic.woff | Bin 0 -> 15160 bytes web/webfonts/exo-v20-latin-700italic.woff2 | Bin 0 -> 11944 bytes web/webfonts/exo-v20-latin-italic.woff | Bin 0 -> 15204 bytes web/webfonts/exo-v20-latin-italic.woff2 | Bin 0 -> 11984 bytes web/webfonts/exo-v20-latin-regular.woff | Bin 0 -> 13972 bytes web/webfonts/exo-v20-latin-regular.woff2 | Bin 0 -> 11100 bytes web/webfonts/fa-brands-400.ttf | Bin 0 -> 187208 bytes web/webfonts/fa-brands-400.woff2 | Bin 0 -> 108020 bytes web/webfonts/fa-solid-900.ttf | Bin 0 -> 394628 bytes web/webfonts/fa-solid-900.woff2 | Bin 0 -> 150124 bytes web/webfonts/inconsolata-regular.woff | Bin 0 -> 19708 bytes web/webfonts/inconsolata-regular.woff2 | Bin 0 -> 16244 bytes 1572 files changed, 182163 insertions(+) create mode 100644 CHANGELOG.md create mode 100644 CONTRIBUTING.md create mode 100644 LICENSE create mode 100644 README.md create mode 100644 SECURITY.md create mode 100755 bin/v-acknowledge-user-notification create mode 100755 bin/v-add-access-key create mode 100755 bin/v-add-backup-host create mode 100755 bin/v-add-cron-hestia-autoupdate create mode 100755 bin/v-add-cron-job create mode 100755 bin/v-add-cron-letsencrypt-job create mode 100755 bin/v-add-cron-reports create mode 100755 bin/v-add-cron-restart-job create mode 100755 bin/v-add-database create mode 100755 bin/v-add-database-host create mode 100755 bin/v-add-database-temp-user create mode 100755 bin/v-add-dns-domain create mode 100755 bin/v-add-dns-on-web-alias create mode 100755 bin/v-add-dns-record create mode 100755 bin/v-add-domain create mode 100755 bin/v-add-fastcgi-cache create mode 100755 bin/v-add-firewall-ban create mode 100755 bin/v-add-firewall-chain create mode 100755 bin/v-add-firewall-ipset create mode 100755 bin/v-add-firewall-rule create mode 100755 bin/v-add-fs-archive create mode 100755 bin/v-add-fs-directory create mode 100755 bin/v-add-fs-file create mode 100755 bin/v-add-letsencrypt-domain create mode 100755 bin/v-add-letsencrypt-host create mode 100755 bin/v-add-letsencrypt-user create mode 100755 bin/v-add-mail-account create mode 100755 bin/v-add-mail-account-alias create mode 100755 bin/v-add-mail-account-autoreply create mode 100755 bin/v-add-mail-account-forward create mode 100755 bin/v-add-mail-account-fwd-only create mode 100755 bin/v-add-mail-domain create mode 100755 bin/v-add-mail-domain-antispam create mode 100755 bin/v-add-mail-domain-antivirus create mode 100755 bin/v-add-mail-domain-catchall create mode 100755 bin/v-add-mail-domain-dkim create mode 100755 bin/v-add-mail-domain-reject create mode 100755 bin/v-add-mail-domain-smtp-relay create mode 100755 bin/v-add-mail-domain-ssl create mode 100755 bin/v-add-mail-domain-webmail create mode 100755 bin/v-add-remote-dns-domain create mode 100755 bin/v-add-remote-dns-host create mode 100755 bin/v-add-remote-dns-record create mode 100755 bin/v-add-sys-api-ip create mode 100755 bin/v-add-sys-dependencies create mode 100755 bin/v-add-sys-filemanager create mode 100755 bin/v-add-sys-firewall create mode 100755 bin/v-add-sys-ip create mode 100755 bin/v-add-sys-pma-sso create mode 100755 bin/v-add-sys-quota create mode 100755 bin/v-add-sys-roundcube create mode 100755 bin/v-add-sys-sftp-jail create mode 100755 bin/v-add-sys-smtp create mode 100755 bin/v-add-sys-smtp-relay create mode 100755 bin/v-add-sys-snappymail create mode 100755 bin/v-add-user create mode 100755 bin/v-add-user-2fa create mode 100755 bin/v-add-user-composer create mode 100755 bin/v-add-user-notification create mode 100755 bin/v-add-user-package create mode 100755 bin/v-add-user-sftp-jail create mode 100755 bin/v-add-user-sftp-key create mode 100755 bin/v-add-user-ssh-key create mode 100755 bin/v-add-user-wp-cli create mode 100755 bin/v-add-web-domain create mode 100755 bin/v-add-web-domain-alias create mode 100755 bin/v-add-web-domain-allow-users create mode 100755 bin/v-add-web-domain-backend create mode 100755 bin/v-add-web-domain-ftp create mode 100755 bin/v-add-web-domain-httpauth create mode 100755 bin/v-add-web-domain-proxy create mode 100755 bin/v-add-web-domain-redirect create mode 100755 bin/v-add-web-domain-ssl create mode 100755 bin/v-add-web-domain-ssl-force create mode 100755 bin/v-add-web-domain-ssl-hsts create mode 100755 bin/v-add-web-domain-ssl-preset create mode 100755 bin/v-add-web-domain-stats create mode 100755 bin/v-add-web-domain-stats-user create mode 100755 bin/v-add-web-php create mode 100755 bin/v-backup-user create mode 100755 bin/v-backup-users create mode 100755 bin/v-change-cron-job create mode 100755 bin/v-change-database-host-password create mode 100755 bin/v-change-database-owner create mode 100755 bin/v-change-database-password create mode 100755 bin/v-change-database-user create mode 100755 bin/v-change-dns-domain-dnssec create mode 100755 bin/v-change-dns-domain-exp create mode 100755 bin/v-change-dns-domain-ip create mode 100755 bin/v-change-dns-domain-soa create mode 100755 bin/v-change-dns-domain-tpl create mode 100755 bin/v-change-dns-domain-ttl create mode 100755 bin/v-change-dns-record create mode 100755 bin/v-change-dns-record-id create mode 100755 bin/v-change-domain-owner create mode 100755 bin/v-change-firewall-rule create mode 100755 bin/v-change-fs-file-permission create mode 100755 bin/v-change-mail-account-password create mode 100755 bin/v-change-mail-account-quota create mode 100755 bin/v-change-mail-account-rate-limit create mode 100755 bin/v-change-mail-domain-catchall create mode 100755 bin/v-change-mail-domain-rate-limit create mode 100755 bin/v-change-mail-domain-sslcert create mode 100755 bin/v-change-remote-dns-domain-exp create mode 100755 bin/v-change-remote-dns-domain-soa create mode 100755 bin/v-change-remote-dns-domain-ttl create mode 100755 bin/v-change-sys-api create mode 100755 bin/v-change-sys-config-value create mode 100755 bin/v-change-sys-db-alias create mode 100755 bin/v-change-sys-demo-mode create mode 100755 bin/v-change-sys-hestia-ssl create mode 100755 bin/v-change-sys-hostname create mode 100755 bin/v-change-sys-ip-name create mode 100755 bin/v-change-sys-ip-nat create mode 100755 bin/v-change-sys-ip-owner create mode 100755 bin/v-change-sys-ip-status create mode 100755 bin/v-change-sys-language create mode 100755 bin/v-change-sys-php create mode 100755 bin/v-change-sys-port create mode 100755 bin/v-change-sys-release create mode 100755 bin/v-change-sys-service-config create mode 100755 bin/v-change-sys-timezone create mode 100755 bin/v-change-sys-webmail create mode 100755 bin/v-change-user-config-value create mode 100755 bin/v-change-user-contact create mode 100755 bin/v-change-user-language create mode 100755 bin/v-change-user-name create mode 100755 bin/v-change-user-ns create mode 100755 bin/v-change-user-package create mode 100755 bin/v-change-user-password create mode 100755 bin/v-change-user-php-cli create mode 100755 bin/v-change-user-rkey create mode 100755 bin/v-change-user-role create mode 100755 bin/v-change-user-shell create mode 100755 bin/v-change-user-sort-order create mode 100755 bin/v-change-user-template create mode 100755 bin/v-change-user-theme create mode 100755 bin/v-change-web-domain-backend-tpl create mode 100755 bin/v-change-web-domain-dirlist create mode 100755 bin/v-change-web-domain-docroot create mode 100755 bin/v-change-web-domain-ftp-password create mode 100755 bin/v-change-web-domain-ftp-path create mode 100755 bin/v-change-web-domain-httpauth create mode 100755 bin/v-change-web-domain-ip create mode 100755 bin/v-change-web-domain-name create mode 100755 bin/v-change-web-domain-proxy-tpl create mode 100755 bin/v-change-web-domain-sslcert create mode 100755 bin/v-change-web-domain-sslhome create mode 100755 bin/v-change-web-domain-stats create mode 100755 bin/v-change-web-domain-tpl create mode 100755 bin/v-check-access-key create mode 100755 bin/v-check-api-key create mode 100755 bin/v-check-fs-permission create mode 100755 bin/v-check-mail-account-hash create mode 100755 bin/v-check-user-2fa create mode 100755 bin/v-check-user-hash create mode 100755 bin/v-check-user-password create mode 100755 bin/v-copy-fs-directory create mode 100755 bin/v-copy-fs-file create mode 100755 bin/v-copy-user-package create mode 100755 bin/v-delete-access-key create mode 100755 bin/v-delete-backup-host create mode 100755 bin/v-delete-cron-hestia-autoupdate create mode 100755 bin/v-delete-cron-job create mode 100755 bin/v-delete-cron-reports create mode 100755 bin/v-delete-cron-restart-job create mode 100755 bin/v-delete-database create mode 100755 bin/v-delete-database-host create mode 100755 bin/v-delete-database-temp-user create mode 100755 bin/v-delete-databases create mode 100755 bin/v-delete-dns-domain create mode 100755 bin/v-delete-dns-domains create mode 100755 bin/v-delete-dns-domains-src create mode 100755 bin/v-delete-dns-on-web-alias create mode 100755 bin/v-delete-dns-record create mode 100755 bin/v-delete-domain create mode 100755 bin/v-delete-fastcgi-cache create mode 100755 bin/v-delete-firewall-ban create mode 100755 bin/v-delete-firewall-chain create mode 100755 bin/v-delete-firewall-ipset create mode 100755 bin/v-delete-firewall-rule create mode 100755 bin/v-delete-fs-directory create mode 100755 bin/v-delete-fs-file create mode 100755 bin/v-delete-letsencrypt-domain create mode 100755 bin/v-delete-mail-account create mode 100755 bin/v-delete-mail-account-alias create mode 100755 bin/v-delete-mail-account-autoreply create mode 100755 bin/v-delete-mail-account-forward create mode 100755 bin/v-delete-mail-account-fwd-only create mode 100755 bin/v-delete-mail-domain create mode 100755 bin/v-delete-mail-domain-antispam create mode 100755 bin/v-delete-mail-domain-antivirus create mode 100755 bin/v-delete-mail-domain-catchall create mode 100755 bin/v-delete-mail-domain-dkim create mode 100755 bin/v-delete-mail-domain-reject create mode 100755 bin/v-delete-mail-domain-smtp-relay create mode 100755 bin/v-delete-mail-domain-ssl create mode 100755 bin/v-delete-mail-domain-webmail create mode 100755 bin/v-delete-mail-domains create mode 100755 bin/v-delete-remote-dns-domain create mode 100755 bin/v-delete-remote-dns-domains create mode 100755 bin/v-delete-remote-dns-host create mode 100755 bin/v-delete-remote-dns-record create mode 100755 bin/v-delete-sys-api-ip create mode 100755 bin/v-delete-sys-filemanager create mode 100755 bin/v-delete-sys-firewall create mode 100755 bin/v-delete-sys-ip create mode 100755 bin/v-delete-sys-mail-queue create mode 100755 bin/v-delete-sys-pma-sso create mode 100755 bin/v-delete-sys-quota create mode 100755 bin/v-delete-sys-sftp-jail create mode 100755 bin/v-delete-sys-smtp create mode 100755 bin/v-delete-sys-smtp-relay create mode 100755 bin/v-delete-user create mode 100755 bin/v-delete-user-2fa create mode 100755 bin/v-delete-user-auth-log create mode 100755 bin/v-delete-user-backup create mode 100755 bin/v-delete-user-backup-exclusions create mode 100755 bin/v-delete-user-ips create mode 100755 bin/v-delete-user-log create mode 100755 bin/v-delete-user-notification create mode 100755 bin/v-delete-user-package create mode 100755 bin/v-delete-user-sftp-jail create mode 100755 bin/v-delete-user-ssh-key create mode 100755 bin/v-delete-user-stats create mode 100755 bin/v-delete-web-domain create mode 100755 bin/v-delete-web-domain-alias create mode 100755 bin/v-delete-web-domain-allow-users create mode 100755 bin/v-delete-web-domain-backend create mode 100755 bin/v-delete-web-domain-ftp create mode 100755 bin/v-delete-web-domain-httpauth create mode 100755 bin/v-delete-web-domain-proxy create mode 100755 bin/v-delete-web-domain-redirect create mode 100755 bin/v-delete-web-domain-ssl create mode 100755 bin/v-delete-web-domain-ssl-force create mode 100755 bin/v-delete-web-domain-ssl-hsts create mode 100755 bin/v-delete-web-domain-stats create mode 100755 bin/v-delete-web-domain-stats-user create mode 100755 bin/v-delete-web-domains create mode 100755 bin/v-delete-web-php create mode 100755 bin/v-download-backup create mode 100755 bin/v-dump-database create mode 100755 bin/v-dump-site create mode 100755 bin/v-export-rrd create mode 100755 bin/v-extract-fs-archive create mode 100755 bin/v-generate-api-key create mode 100755 bin/v-generate-debug-report create mode 100755 bin/v-generate-password-hash create mode 100755 bin/v-generate-ssl-cert create mode 100755 bin/v-get-dns-domain-value create mode 100755 bin/v-get-fs-file-type create mode 100755 bin/v-get-mail-account-value create mode 100755 bin/v-get-mail-domain-value create mode 100755 bin/v-get-sys-timezone create mode 100755 bin/v-get-sys-timezones create mode 100755 bin/v-get-user-salt create mode 100755 bin/v-get-user-value create mode 100755 bin/v-import-cpanel create mode 100755 bin/v-insert-dns-domain create mode 100755 bin/v-insert-dns-record create mode 100755 bin/v-insert-dns-records create mode 100755 bin/v-list-access-key create mode 100755 bin/v-list-access-keys create mode 100755 bin/v-list-api create mode 100755 bin/v-list-apis create mode 100755 bin/v-list-backup-host create mode 100755 bin/v-list-cron-job create mode 100755 bin/v-list-cron-jobs create mode 100755 bin/v-list-database create mode 100755 bin/v-list-database-host create mode 100755 bin/v-list-database-hosts create mode 100755 bin/v-list-database-types create mode 100755 bin/v-list-databases create mode 100755 bin/v-list-default-php create mode 100755 bin/v-list-dns-domain create mode 100755 bin/v-list-dns-domains create mode 100755 bin/v-list-dns-records create mode 100755 bin/v-list-dns-template create mode 100755 bin/v-list-dns-templates create mode 100755 bin/v-list-dnssec-public-key create mode 100755 bin/v-list-firewall create mode 100755 bin/v-list-firewall-ban create mode 100755 bin/v-list-firewall-ipset create mode 100755 bin/v-list-firewall-rule create mode 100755 bin/v-list-fs-directory create mode 100755 bin/v-list-letsencrypt-user create mode 100755 bin/v-list-mail-account create mode 100755 bin/v-list-mail-account-autoreply create mode 100755 bin/v-list-mail-accounts create mode 100755 bin/v-list-mail-domain create mode 100755 bin/v-list-mail-domain-dkim create mode 100755 bin/v-list-mail-domain-dkim-dns create mode 100755 bin/v-list-mail-domain-ssl create mode 100755 bin/v-list-mail-domains create mode 100755 bin/v-list-remote-dns-hosts create mode 100755 bin/v-list-sys-clamd-config create mode 100755 bin/v-list-sys-config create mode 100755 bin/v-list-sys-cpu-status create mode 100755 bin/v-list-sys-db-status create mode 100755 bin/v-list-sys-disk-status create mode 100755 bin/v-list-sys-dns-status create mode 100755 bin/v-list-sys-dovecot-config create mode 100755 bin/v-list-sys-hestia-autoupdate create mode 100755 bin/v-list-sys-hestia-ssl create mode 100755 bin/v-list-sys-hestia-updates create mode 100755 bin/v-list-sys-info create mode 100755 bin/v-list-sys-interfaces create mode 100755 bin/v-list-sys-ip create mode 100755 bin/v-list-sys-ips create mode 100755 bin/v-list-sys-languages create mode 100755 bin/v-list-sys-mail-status create mode 100755 bin/v-list-sys-memory-status create mode 100755 bin/v-list-sys-mysql-config create mode 100755 bin/v-list-sys-network-status create mode 100755 bin/v-list-sys-nginx-config create mode 100755 bin/v-list-sys-pgsql-config create mode 100755 bin/v-list-sys-php create mode 100755 bin/v-list-sys-php-config create mode 100755 bin/v-list-sys-proftpd-config create mode 100755 bin/v-list-sys-rrd create mode 100755 bin/v-list-sys-services create mode 100755 bin/v-list-sys-shells create mode 100755 bin/v-list-sys-spamd-config create mode 100755 bin/v-list-sys-sshd-port create mode 100755 bin/v-list-sys-themes create mode 100755 bin/v-list-sys-users create mode 100755 bin/v-list-sys-vsftpd-config create mode 100755 bin/v-list-sys-web-status create mode 100755 bin/v-list-sys-webmail create mode 100755 bin/v-list-user create mode 100755 bin/v-list-user-auth-log create mode 100755 bin/v-list-user-backup create mode 100755 bin/v-list-user-backup-exclusions create mode 100755 bin/v-list-user-backups create mode 100755 bin/v-list-user-ips create mode 100755 bin/v-list-user-log create mode 100755 bin/v-list-user-notifications create mode 100755 bin/v-list-user-ns create mode 100755 bin/v-list-user-package create mode 100755 bin/v-list-user-packages create mode 100755 bin/v-list-user-ssh-key create mode 100755 bin/v-list-user-stats create mode 100755 bin/v-list-users create mode 100755 bin/v-list-users-stats create mode 100755 bin/v-list-web-domain create mode 100755 bin/v-list-web-domain-accesslog create mode 100755 bin/v-list-web-domain-errorlog create mode 100755 bin/v-list-web-domain-ssl create mode 100755 bin/v-list-web-domains create mode 100755 bin/v-list-web-stats create mode 100755 bin/v-list-web-templates create mode 100755 bin/v-list-web-templates-backend create mode 100755 bin/v-list-web-templates-proxy create mode 100755 bin/v-log-action create mode 100755 bin/v-log-user-login create mode 100755 bin/v-log-user-logout create mode 100755 bin/v-move-fs-directory create mode 100755 bin/v-move-fs-file create mode 100755 bin/v-open-fs-config create mode 100755 bin/v-open-fs-file create mode 100755 bin/v-purge-nginx-cache create mode 100755 bin/v-rebuild-all create mode 100755 bin/v-rebuild-cron-jobs create mode 100755 bin/v-rebuild-database create mode 100755 bin/v-rebuild-databases create mode 100755 bin/v-rebuild-dns-domain create mode 100755 bin/v-rebuild-dns-domains create mode 100755 bin/v-rebuild-mail-domain create mode 100755 bin/v-rebuild-mail-domains create mode 100755 bin/v-rebuild-user create mode 100755 bin/v-rebuild-users create mode 100755 bin/v-rebuild-web-domain create mode 100755 bin/v-rebuild-web-domains create mode 100755 bin/v-refresh-sys-theme create mode 100755 bin/v-rename-user-package create mode 100755 bin/v-repair-sys-config create mode 100755 bin/v-restart-cron create mode 100755 bin/v-restart-dns create mode 100755 bin/v-restart-ftp create mode 100755 bin/v-restart-mail create mode 100755 bin/v-restart-proxy create mode 100755 bin/v-restart-service create mode 100755 bin/v-restart-system create mode 100755 bin/v-restart-web create mode 100755 bin/v-restart-web-backend create mode 100755 bin/v-restore-cron-job create mode 100755 bin/v-restore-database create mode 100755 bin/v-restore-dns-domain create mode 100755 bin/v-restore-mail-domain create mode 100755 bin/v-restore-user create mode 100755 bin/v-restore-web-domain create mode 100755 bin/v-revoke-api-key create mode 100755 bin/v-run-cli-cmd create mode 100755 bin/v-schedule-letsencrypt-domain create mode 100755 bin/v-schedule-user-backup create mode 100755 bin/v-schedule-user-backup-download create mode 100755 bin/v-schedule-user-restore create mode 100755 bin/v-search-command create mode 100755 bin/v-search-domain-owner create mode 100755 bin/v-search-fs-object create mode 100755 bin/v-search-object create mode 100755 bin/v-search-user-object create mode 100755 bin/v-start-service create mode 100755 bin/v-stop-firewall create mode 100755 bin/v-stop-service create mode 100755 bin/v-suspend-cron-job create mode 100755 bin/v-suspend-cron-jobs create mode 100755 bin/v-suspend-database create mode 100755 bin/v-suspend-database-host create mode 100755 bin/v-suspend-databases create mode 100755 bin/v-suspend-dns-domain create mode 100755 bin/v-suspend-dns-domains create mode 100755 bin/v-suspend-dns-record create mode 100755 bin/v-suspend-domain create mode 100755 bin/v-suspend-firewall-rule create mode 100755 bin/v-suspend-mail-account create mode 100755 bin/v-suspend-mail-accounts create mode 100755 bin/v-suspend-mail-domain create mode 100755 bin/v-suspend-mail-domains create mode 100755 bin/v-suspend-remote-dns-host create mode 100755 bin/v-suspend-user create mode 100755 bin/v-suspend-web-domain create mode 100755 bin/v-suspend-web-domains create mode 100755 bin/v-sync-dns-cluster create mode 100755 bin/v-unsuspend-cron-job create mode 100755 bin/v-unsuspend-cron-jobs create mode 100755 bin/v-unsuspend-database create mode 100755 bin/v-unsuspend-database-host create mode 100755 bin/v-unsuspend-databases create mode 100755 bin/v-unsuspend-dns-domain create mode 100755 bin/v-unsuspend-dns-domains create mode 100755 bin/v-unsuspend-dns-record create mode 100755 bin/v-unsuspend-domain create mode 100755 bin/v-unsuspend-firewall-rule create mode 100755 bin/v-unsuspend-mail-account create mode 100755 bin/v-unsuspend-mail-accounts create mode 100755 bin/v-unsuspend-mail-domain create mode 100755 bin/v-unsuspend-mail-domains create mode 100755 bin/v-unsuspend-remote-dns-host create mode 100755 bin/v-unsuspend-user create mode 100755 bin/v-unsuspend-web-domain create mode 100755 bin/v-unsuspend-web-domains create mode 100755 bin/v-update-database-disk create mode 100755 bin/v-update-databases-disk create mode 100755 bin/v-update-dns-templates create mode 100755 bin/v-update-firewall create mode 100755 bin/v-update-firewall-ipset create mode 100755 bin/v-update-host-certificate create mode 100755 bin/v-update-letsencrypt-ssl create mode 100755 bin/v-update-mail-domain-disk create mode 100755 bin/v-update-mail-domain-ssl create mode 100755 bin/v-update-mail-domains-disk create mode 100755 bin/v-update-mail-templates create mode 100755 bin/v-update-sys-defaults create mode 100755 bin/v-update-sys-hestia create mode 100755 bin/v-update-sys-hestia-all create mode 100755 bin/v-update-sys-hestia-git create mode 100755 bin/v-update-sys-ip create mode 100755 bin/v-update-sys-ip-counters create mode 100755 bin/v-update-sys-queue create mode 100755 bin/v-update-sys-rrd create mode 100755 bin/v-update-sys-rrd-apache2 create mode 100755 bin/v-update-sys-rrd-ftp create mode 100755 bin/v-update-sys-rrd-httpd create mode 100755 bin/v-update-sys-rrd-la create mode 100755 bin/v-update-sys-rrd-mail create mode 100755 bin/v-update-sys-rrd-mem create mode 100755 bin/v-update-sys-rrd-mysql create mode 100755 bin/v-update-sys-rrd-net create mode 100755 bin/v-update-sys-rrd-nginx create mode 100755 bin/v-update-sys-rrd-pgsql create mode 100755 bin/v-update-sys-rrd-ssh create mode 100755 bin/v-update-user-backup-exclusions create mode 100755 bin/v-update-user-counters create mode 100755 bin/v-update-user-disk create mode 100755 bin/v-update-user-package create mode 100755 bin/v-update-user-quota create mode 100755 bin/v-update-user-stats create mode 100755 bin/v-update-web-domain-disk create mode 100755 bin/v-update-web-domain-ssl create mode 100755 bin/v-update-web-domain-stat create mode 100755 bin/v-update-web-domain-traff create mode 100755 bin/v-update-web-domains-disk create mode 100755 bin/v-update-web-domains-stat create mode 100755 bin/v-update-web-domains-traff create mode 100755 bin/v-update-web-templates create mode 100755 bin/v-update-white-label-logo create mode 100644 build.js create mode 100644 crowdin.yml create mode 100644 docs/.vitepress/config.js create mode 100644 docs/.vitepress/theme/components/FeatureList.vue create mode 100644 docs/.vitepress/theme/components/FeaturePage.vue create mode 100644 docs/.vitepress/theme/components/FeaturePageSection.vue create mode 100644 docs/.vitepress/theme/components/FeaturePageTitle.vue create mode 100644 docs/.vitepress/theme/components/InstallOptions.vue create mode 100644 docs/.vitepress/theme/components/InstallOptionsSection.vue create mode 100644 docs/.vitepress/theme/components/InstallPage.vue create mode 100644 docs/.vitepress/theme/components/InstallPageTitle.vue create mode 100644 docs/.vitepress/theme/index.js create mode 100644 docs/.vitepress/theme/styles/base.css create mode 100644 docs/.vitepress/theme/styles/vars.css create mode 100644 docs/_data/features.js create mode 100644 docs/_data/languages.js create mode 100644 docs/_data/options.js create mode 100644 docs/_data/team.js create mode 100644 docs/docs/community/hestia-nginx-cache.md create mode 100644 docs/docs/community/install-script-generator.md create mode 100644 docs/docs/community/ioncube-hestia-installer.md create mode 100644 docs/docs/contributing/building.md create mode 100644 docs/docs/contributing/development.md create mode 100644 docs/docs/contributing/documentation.md create mode 100644 docs/docs/contributing/quick-install-app.md create mode 100644 docs/docs/contributing/testing.md create mode 100644 docs/docs/contributing/translations.md create mode 100644 docs/docs/index.md create mode 100644 docs/docs/introduction/best-practices.md create mode 100644 docs/docs/introduction/getting-started.md create mode 100644 docs/docs/reference/api.md create mode 100644 docs/docs/reference/cli.md create mode 100644 docs/docs/server-administration/backup-restore.md create mode 100644 docs/docs/server-administration/configuration.md create mode 100644 docs/docs/server-administration/customisation.md create mode 100644 docs/docs/server-administration/databases.md create mode 100644 docs/docs/server-administration/dns.md create mode 100644 docs/docs/server-administration/email.md create mode 100644 docs/docs/server-administration/file-manager.md create mode 100644 docs/docs/server-administration/firewall.md create mode 100644 docs/docs/server-administration/os-upgrades.md create mode 100644 docs/docs/server-administration/rest-api.md create mode 100644 docs/docs/server-administration/ssl-certificates.md create mode 100644 docs/docs/server-administration/troubleshooting.md create mode 100644 docs/docs/server-administration/web-templates.md create mode 100644 docs/docs/user-guide/account.md create mode 100644 docs/docs/user-guide/backups.md create mode 100644 docs/docs/user-guide/cron-jobs.md create mode 100644 docs/docs/user-guide/databases.md create mode 100644 docs/docs/user-guide/dns.md create mode 100644 docs/docs/user-guide/file-manager.md create mode 100644 docs/docs/user-guide/mail-domains.md create mode 100644 docs/docs/user-guide/notifications.md create mode 100644 docs/docs/user-guide/packages.md create mode 100644 docs/docs/user-guide/statistics.md create mode 100644 docs/docs/user-guide/users.md create mode 100644 docs/docs/user-guide/web-domains.md create mode 100644 docs/donate.md create mode 100644 docs/features.md create mode 100644 docs/index.md create mode 100644 docs/install.md create mode 100644 docs/public/_headers create mode 100644 docs/public/apple-touch-icon.png create mode 100644 docs/public/favicon.ico create mode 100644 docs/public/icon-192.png create mode 100644 docs/public/icon-512.png create mode 100644 docs/public/images/undraw_domain_names_re_0uun.svg create mode 100644 docs/public/images/undraw_maintenance_re_59vn.svg create mode 100644 docs/public/images/undraw_personal_email_re_4lx7.svg create mode 100644 docs/public/images/undraw_server_status_re_n8ln.svg create mode 100644 docs/public/images/undraw_two_factor_authentication_namy.svg create mode 100644 docs/public/images/undraw_web_developer_re_h7ie.svg create mode 100644 docs/public/logo.svg create mode 100644 docs/public/site.webmanifest create mode 100644 docs/public/webfonts/fa-brands-400.ttf create mode 100644 docs/public/webfonts/fa-brands-400.woff2 create mode 100644 docs/public/webfonts/fa-solid-900.ttf create mode 100644 docs/public/webfonts/fa-solid-900.woff2 create mode 100644 docs/team.md create mode 100644 func/backup.sh create mode 100644 func/db.sh create mode 100644 func/domain.sh create mode 100644 func/firewall.sh create mode 100644 func/ip.sh create mode 100644 func/main.sh create mode 100644 func/rebuild.sh create mode 100644 func/remote.sh create mode 100644 func/syshealth.sh create mode 100644 func/upgrade.sh create mode 100644 install/common/api/billing create mode 100644 install/common/api/mail-accounts create mode 100644 install/common/api/phpmyadmin-sso create mode 100644 install/common/api/purge-nginx-cache create mode 100644 install/common/api/sync-dns-cluster create mode 100644 install/common/api/update-dns-records create mode 100644 install/common/dovecot/conf.d/10-auth.conf create mode 100644 install/common/dovecot/conf.d/10-logging.conf create mode 100644 install/common/dovecot/conf.d/10-mail.conf create mode 100644 install/common/dovecot/conf.d/10-master.conf create mode 100644 install/common/dovecot/conf.d/10-ssl.conf create mode 100644 install/common/dovecot/conf.d/20-imap.conf create mode 100644 install/common/dovecot/conf.d/20-pop3.conf create mode 100644 install/common/dovecot/conf.d/90-quota.conf create mode 100644 install/common/dovecot/conf.d/auth-passwdfile.conf.ext create mode 100644 install/common/dovecot/dovecot.conf create mode 100644 install/common/dovecot/sieve/20-managesieve.conf create mode 100644 install/common/dovecot/sieve/90-sieve-extprograms.conf create mode 100644 install/common/dovecot/sieve/90-sieve.conf create mode 100644 install/common/filegator/backend/Services/Archiver/Adapters/HestiaZipArchiver.php create mode 100644 install/common/filegator/backend/Services/Auth/Adapters/HestiaAuth.php create mode 100644 install/common/filegator/backend/Services/Session/Adapters/SessionStorage.php create mode 100644 install/common/filegator/composer.json create mode 100644 install/common/filegator/composer.lock create mode 100644 install/common/filegator/configuration.php create mode 100755 install/common/firewall/ipset/blacklist.sh create mode 100644 install/common/firewall/rules.conf create mode 100644 install/common/packages/default.pkg create mode 100644 install/common/packages/system.pkg create mode 100644 install/common/phpmyadmin/config.inc.php create mode 100644 install/common/phpmyadmin/create_tables.sql create mode 100644 install/common/phpmyadmin/hestia-sso.php create mode 100644 install/common/phpmyadmin/pma.sh create mode 100644 install/common/roundcube/apache.conf create mode 100644 install/common/roundcube/config.inc.php create mode 100644 install/common/roundcube/hestia.php create mode 100644 install/common/roundcube/main.inc.php create mode 100644 install/common/roundcube/mimetypes.php create mode 100644 install/common/roundcube/plugins/config_managesieve.inc.php create mode 100644 install/common/roundcube/plugins/config_newmail_notifier.inc.php create mode 100644 install/common/roundcube/plugins/config_zipdownload.inc.php create mode 100644 install/common/snappymail/install.php create mode 100755 install/common/templates/dns/child-ns.tpl create mode 100644 install/common/templates/dns/default-nomail.tpl create mode 100755 install/common/templates/dns/default.tpl create mode 100755 install/common/templates/dns/gmail.tpl create mode 100644 install/common/templates/dns/office365.tpl create mode 100644 install/common/templates/dns/zoho.tpl create mode 100644 install/common/templates/email/examples/account_ready.html create mode 100644 install/common/templates/email/examples/database_credentials.html create mode 100644 install/common/templates/email/examples/email_credentials.html create mode 100644 install/common/templates/email/examples/ftp_credentials.html create mode 100644 install/common/templates/email/examples/reset_password.html create mode 100644 install/common/templates/web/skel/document_errors/403.html create mode 100644 install/common/templates/web/skel/document_errors/404.html create mode 100644 install/common/templates/web/skel/document_errors/410.html create mode 100644 install/common/templates/web/skel/document_errors/50x.html create mode 100644 install/common/templates/web/skel/public_html/index.html create mode 100755 install/common/templates/web/skel/public_html/robots.txt create mode 100755 install/common/templates/web/suspend/.htaccess create mode 100644 install/common/templates/web/suspend/index.html create mode 100644 install/common/templates/web/unassigned/index.html create mode 100644 install/deb/apache2/apache2.conf create mode 100644 install/deb/apache2/hestia-event.conf create mode 100644 install/deb/apache2/status.conf create mode 100644 install/deb/apache2/unassigned.conf create mode 100644 install/deb/bind/named.conf create mode 100644 install/deb/bind/named.conf.options create mode 100644 install/deb/clamav/clamd.conf create mode 100644 install/deb/deb_signing.key create mode 100644 install/deb/exim/dnsbl.conf create mode 100644 install/deb/exim/exim4.conf.4.94.template create mode 100644 install/deb/exim/exim4.conf.4.95.template create mode 100644 install/deb/exim/exim4.conf.template create mode 100644 install/deb/exim/limit.conf create mode 100644 install/deb/exim/spam-blocks.conf create mode 100644 install/deb/exim/srs.conf create mode 100644 install/deb/exim/system.filter create mode 100644 install/deb/fail2ban/action.d/hestia.conf create mode 100644 install/deb/fail2ban/filter.d/hestia.conf create mode 100644 install/deb/fail2ban/jail.local create mode 100644 install/deb/filemanager/filegator/backend/Services/Archiver/Adapters/HestiaZipArchiver.php create mode 100644 install/deb/filemanager/filegator/backend/Services/Auth/Adapters/HestiaAuth.php create mode 100644 install/deb/filemanager/filegator/backend/Services/Session/Adapters/SessionStorage.php create mode 100644 install/deb/filemanager/filegator/composer.json create mode 100644 install/deb/filemanager/filegator/composer.lock create mode 100644 install/deb/filemanager/filegator/configuration.php create mode 100755 install/deb/filemanager/install-fm.sh create mode 100644 install/deb/logrotate/apache2 create mode 100644 install/deb/logrotate/dovecot create mode 100644 install/deb/logrotate/hestia create mode 100755 install/deb/logrotate/httpd-prerotate/awstats create mode 100644 install/deb/logrotate/nginx create mode 100644 install/deb/logrotate/roundcube create mode 100644 install/deb/mysql/my-large.cnf create mode 100644 install/deb/mysql/my-medium.cnf create mode 100644 install/deb/mysql/my-small.cnf create mode 100644 install/deb/nginx/0rtt-anti-replay.conf create mode 100644 install/deb/nginx/agents.conf create mode 100644 install/deb/nginx/nginx.conf create mode 100644 install/deb/nginx/phpmyadmin.inc create mode 100644 install/deb/nginx/phppgadmin.inc create mode 100644 install/deb/nginx/status.conf create mode 100644 install/deb/nginx/unassigned.inc create mode 100644 install/deb/pga/config.inc.php create mode 100644 install/deb/pga/phppgadmin.conf create mode 100644 install/deb/php-fpm/dummy.conf create mode 100644 install/deb/php-fpm/multiphp.tpl create mode 100644 install/deb/php-fpm/php-fpm.conf create mode 100644 install/deb/php-fpm/www.conf create mode 100644 install/deb/phpmyadmin/config.inc.php create mode 100644 install/deb/phpmyadmin/create_tables.sql create mode 100644 install/deb/phpmyadmin/hestia-sso.php create mode 100644 install/deb/phpmyadmin/pma.sh create mode 100644 install/deb/pma/apache.conf create mode 100644 install/deb/postgresql/pg_hba.conf create mode 100644 install/deb/proftpd/proftpd.conf create mode 100644 install/deb/proftpd/tls.conf create mode 100644 install/deb/ssl/dhparam.pem create mode 100644 install/deb/sudo/admin create mode 100644 install/deb/templates/mail/apache2/default.stpl create mode 100644 install/deb/templates/mail/apache2/default.tpl create mode 100644 install/deb/templates/mail/apache2/disabled.stpl create mode 100644 install/deb/templates/mail/apache2/disabled.tpl create mode 100644 install/deb/templates/mail/apache2/rainloop.stpl create mode 100644 install/deb/templates/mail/apache2/rainloop.tpl create mode 100644 install/deb/templates/mail/apache2/snappymail.stpl create mode 100644 install/deb/templates/mail/apache2/snappymail.tpl create mode 100644 install/deb/templates/mail/nginx/default.stpl create mode 100644 install/deb/templates/mail/nginx/default.tpl create mode 100644 install/deb/templates/mail/nginx/default_disabled.stpl create mode 100644 install/deb/templates/mail/nginx/default_disabled.tpl create mode 100644 install/deb/templates/mail/nginx/default_snappymail.stpl create mode 100644 install/deb/templates/mail/nginx/default_snappymail.tpl create mode 100644 install/deb/templates/mail/nginx/disabled.stpl create mode 100644 install/deb/templates/mail/nginx/disabled.tpl create mode 100644 install/deb/templates/mail/nginx/snappymail.stpl create mode 100644 install/deb/templates/mail/nginx/snappymail.tpl create mode 100644 install/deb/templates/mail/nginx/web_system.stpl create mode 100644 install/deb/templates/mail/nginx/web_system.tpl create mode 100644 install/deb/templates/web/apache2/default.stpl create mode 100644 install/deb/templates/web/apache2/default.tpl create mode 100644 install/deb/templates/web/apache2/hosting.stpl create mode 100644 install/deb/templates/web/apache2/hosting.tpl create mode 100644 install/deb/templates/web/apache2/php-fpm/default.stpl create mode 100644 install/deb/templates/web/apache2/php-fpm/default.tpl create mode 100755 install/deb/templates/web/apache2/phpcgi.sh create mode 100644 install/deb/templates/web/apache2/phpcgi.stpl create mode 100644 install/deb/templates/web/apache2/phpcgi.tpl create mode 100755 install/deb/templates/web/apache2/phpfcgid.sh create mode 100644 install/deb/templates/web/apache2/phpfcgid.stpl create mode 100644 install/deb/templates/web/apache2/phpfcgid.tpl create mode 100644 install/deb/templates/web/apache2/www-data.stpl create mode 100644 install/deb/templates/web/apache2/www-data.tpl create mode 100755 install/deb/templates/web/awstats/awstats.tpl create mode 100755 install/deb/templates/web/awstats/index.tpl create mode 100755 install/deb/templates/web/awstats/nav.tpl create mode 100755 install/deb/templates/web/nginx/caching.sh create mode 100755 install/deb/templates/web/nginx/caching.stpl create mode 100755 install/deb/templates/web/nginx/caching.tpl create mode 100755 install/deb/templates/web/nginx/default.stpl create mode 100755 install/deb/templates/web/nginx/default.tpl create mode 100755 install/deb/templates/web/nginx/hosting.sh create mode 100755 install/deb/templates/web/nginx/hosting.stpl create mode 100755 install/deb/templates/web/nginx/hosting.tpl create mode 100644 install/deb/templates/web/nginx/php-fpm/chevereto.stpl create mode 100644 install/deb/templates/web/nginx/php-fpm/chevereto.tpl create mode 100644 install/deb/templates/web/nginx/php-fpm/cms_made_simple.stpl create mode 100644 install/deb/templates/web/nginx/php-fpm/cms_made_simple.tpl create mode 100644 install/deb/templates/web/nginx/php-fpm/codeigniter.stpl create mode 100644 install/deb/templates/web/nginx/php-fpm/codeigniter.tpl create mode 100644 install/deb/templates/web/nginx/php-fpm/craftcms.stpl create mode 100644 install/deb/templates/web/nginx/php-fpm/craftcms.tpl create mode 100644 install/deb/templates/web/nginx/php-fpm/datalife_engine.stpl create mode 100644 install/deb/templates/web/nginx/php-fpm/datalife_engine.tpl create mode 100644 install/deb/templates/web/nginx/php-fpm/default.stpl create mode 100644 install/deb/templates/web/nginx/php-fpm/default.tpl create mode 100644 install/deb/templates/web/nginx/php-fpm/dokuwiki.stpl create mode 100644 install/deb/templates/web/nginx/php-fpm/dokuwiki.tpl create mode 100644 install/deb/templates/web/nginx/php-fpm/drupal-composer.stpl create mode 100644 install/deb/templates/web/nginx/php-fpm/drupal-composer.tpl create mode 100644 install/deb/templates/web/nginx/php-fpm/drupal-social.stpl create mode 100644 install/deb/templates/web/nginx/php-fpm/drupal-social.tpl create mode 100644 install/deb/templates/web/nginx/php-fpm/drupal.stpl create mode 100644 install/deb/templates/web/nginx/php-fpm/drupal.tpl create mode 100644 install/deb/templates/web/nginx/php-fpm/flarum.stpl create mode 100644 install/deb/templates/web/nginx/php-fpm/flarum.tpl create mode 100644 install/deb/templates/web/nginx/php-fpm/gitea.stpl create mode 100644 install/deb/templates/web/nginx/php-fpm/gitea.tpl create mode 100644 install/deb/templates/web/nginx/php-fpm/grav.stpl create mode 100644 install/deb/templates/web/nginx/php-fpm/grav.tpl create mode 100644 install/deb/templates/web/nginx/php-fpm/joomla.stpl create mode 100644 install/deb/templates/web/nginx/php-fpm/joomla.tpl create mode 100644 install/deb/templates/web/nginx/php-fpm/laravel.stpl create mode 100644 install/deb/templates/web/nginx/php-fpm/laravel.tpl create mode 100644 install/deb/templates/web/nginx/php-fpm/magento.stpl create mode 100644 install/deb/templates/web/nginx/php-fpm/magento.tpl create mode 100644 install/deb/templates/web/nginx/php-fpm/mautic.stpl create mode 100644 install/deb/templates/web/nginx/php-fpm/mautic.tpl create mode 100644 install/deb/templates/web/nginx/php-fpm/modx.stpl create mode 100644 install/deb/templates/web/nginx/php-fpm/modx.tpl create mode 100644 install/deb/templates/web/nginx/php-fpm/moodle.stpl create mode 100644 install/deb/templates/web/nginx/php-fpm/moodle.tpl create mode 100644 install/deb/templates/web/nginx/php-fpm/no-php.stpl create mode 100644 install/deb/templates/web/nginx/php-fpm/no-php.tpl create mode 100644 install/deb/templates/web/nginx/php-fpm/odoo.stpl create mode 100644 install/deb/templates/web/nginx/php-fpm/odoo.tpl create mode 100644 install/deb/templates/web/nginx/php-fpm/opencart.stpl create mode 100644 install/deb/templates/web/nginx/php-fpm/opencart.tpl create mode 100644 install/deb/templates/web/nginx/php-fpm/openproject.stpl create mode 100644 install/deb/templates/web/nginx/php-fpm/openproject.tpl create mode 100644 install/deb/templates/web/nginx/php-fpm/osticket.stpl create mode 100644 install/deb/templates/web/nginx/php-fpm/osticket.tpl create mode 100644 install/deb/templates/web/nginx/php-fpm/owncloud.stpl create mode 100644 install/deb/templates/web/nginx/php-fpm/owncloud.tpl create mode 100644 install/deb/templates/web/nginx/php-fpm/phpbb.stpl create mode 100644 install/deb/templates/web/nginx/php-fpm/phpbb.tpl create mode 100644 install/deb/templates/web/nginx/php-fpm/piwik.stpl create mode 100644 install/deb/templates/web/nginx/php-fpm/piwik.tpl create mode 100644 install/deb/templates/web/nginx/php-fpm/prestashop.stpl create mode 100644 install/deb/templates/web/nginx/php-fpm/prestashop.tpl create mode 100644 install/deb/templates/web/nginx/php-fpm/projectsend.stpl create mode 100644 install/deb/templates/web/nginx/php-fpm/projectsend.tpl create mode 100644 install/deb/templates/web/nginx/php-fpm/pyrocms.stpl create mode 100644 install/deb/templates/web/nginx/php-fpm/pyrocms.tpl create mode 100644 install/deb/templates/web/nginx/php-fpm/sendy.stpl create mode 100644 install/deb/templates/web/nginx/php-fpm/sendy.tpl create mode 100644 install/deb/templates/web/nginx/php-fpm/suspended.stpl create mode 100644 install/deb/templates/web/nginx/php-fpm/suspended.tpl create mode 100644 install/deb/templates/web/nginx/php-fpm/symfony2-3.stpl create mode 100644 install/deb/templates/web/nginx/php-fpm/symfony2-3.tpl create mode 100644 install/deb/templates/web/nginx/php-fpm/symfony4-5.stpl create mode 100644 install/deb/templates/web/nginx/php-fpm/symfony4-5.tpl create mode 100644 install/deb/templates/web/nginx/php-fpm/thunder.stpl create mode 100644 install/deb/templates/web/nginx/php-fpm/thunder.tpl create mode 100644 install/deb/templates/web/nginx/php-fpm/wordpress.stpl create mode 100644 install/deb/templates/web/nginx/php-fpm/wordpress.tpl create mode 100644 install/deb/templates/web/nginx/php-fpm/wordpress_mu_subdir.stpl create mode 100644 install/deb/templates/web/nginx/php-fpm/wordpress_mu_subdir.tpl create mode 100644 install/deb/templates/web/nginx/php-fpm/yourls.stpl create mode 100644 install/deb/templates/web/nginx/php-fpm/yourls.tpl create mode 100755 install/deb/templates/web/nginx/proxy_ip.tpl create mode 100644 install/deb/templates/web/nginx/suspended.stpl create mode 100644 install/deb/templates/web/nginx/suspended.tpl create mode 100644 install/deb/templates/web/php-fpm/default.tpl create mode 100644 install/deb/templates/web/php-fpm/no-php.tpl create mode 100644 install/deb/templates/web/php-fpm/socket.tpl create mode 100644 install/deb/vsftpd/vsftpd.conf create mode 100755 install/hst-install-debian.sh create mode 100755 install/hst-install-rhel.sh create mode 100755 install/hst-install-ubuntu.sh create mode 100755 install/hst-install.sh create mode 100644 install/rpm/bind/named.conf create mode 100644 install/rpm/bind/named.conf.options create mode 100644 install/rpm/clamav/clamd.conf create mode 100644 install/rpm/clamav/clamd.tmpfiles create mode 100644 install/rpm/clamav/freshclam.conf create mode 100644 install/rpm/dovecot/conf.d/10-auth.conf create mode 100644 install/rpm/dovecot/conf.d/10-logging.conf create mode 100644 install/rpm/dovecot/conf.d/10-mail.conf create mode 100644 install/rpm/dovecot/conf.d/10-master.conf create mode 100644 install/rpm/dovecot/conf.d/10-ssl.conf create mode 100644 install/rpm/dovecot/conf.d/20-imap.conf create mode 100644 install/rpm/dovecot/conf.d/20-pop3.conf create mode 100644 install/rpm/dovecot/conf.d/90-quota.conf create mode 100644 install/rpm/dovecot/conf.d/auth-passwdfile.conf.ext create mode 100644 install/rpm/dovecot/dovecot.conf create mode 100644 install/rpm/dovecot/sieve/20-managesieve.conf create mode 100644 install/rpm/dovecot/sieve/90-sieve-extprograms.conf create mode 100644 install/rpm/dovecot/sieve/90-sieve.conf create mode 100644 install/rpm/exim/dnsbl.conf create mode 100644 install/rpm/exim/exim.conf create mode 100644 install/rpm/exim/exim.conf.template create mode 100644 install/rpm/exim/limit.conf create mode 100644 install/rpm/exim/spam-blocks.conf create mode 100644 install/rpm/exim/system.filter create mode 100644 install/rpm/fail2ban/action.d/hestia.conf create mode 100644 install/rpm/fail2ban/filter.d/hestia.conf create mode 100644 install/rpm/fail2ban/jail.local create mode 100644 install/rpm/hestia/hestia.repo create mode 100644 install/rpm/httpd/hestia-event.conf create mode 100644 install/rpm/httpd/hestia.conf create mode 100644 install/rpm/httpd/httpd.conf create mode 100644 install/rpm/httpd/status.conf create mode 100644 install/rpm/httpd/unassigned.conf create mode 100644 install/rpm/logrotate/dovecot create mode 100644 install/rpm/logrotate/hestia create mode 100644 install/rpm/logrotate/httpd create mode 100755 install/rpm/logrotate/httpd-prerotate/awstats create mode 100644 install/rpm/logrotate/nginx create mode 100644 install/rpm/logrotate/roundcube create mode 100644 install/rpm/mysql/mariadb-aarch64.repo create mode 100644 install/rpm/mysql/mariadb-x86_64.repo create mode 100644 install/rpm/mysql/my-large.cnf create mode 100644 install/rpm/mysql/my-medium.cnf create mode 100644 install/rpm/mysql/my-small.cnf create mode 100644 install/rpm/mysql/mysql.repo create mode 100644 install/rpm/nginx/0rtt-anti-replay.conf create mode 100644 install/rpm/nginx/agents.conf create mode 100644 install/rpm/nginx/nginx.conf create mode 100644 install/rpm/nginx/nginx.repo create mode 100644 install/rpm/nginx/phpmyadmin.inc create mode 100644 install/rpm/nginx/phppgadmin.inc create mode 100644 install/rpm/nginx/status.conf create mode 100644 install/rpm/nginx/unassigned.inc create mode 100644 install/rpm/pga/config.inc.php create mode 100644 install/rpm/pga/phppgadmin.conf create mode 100644 install/rpm/php-fpm/dummy.conf create mode 100644 install/rpm/php-fpm/multiphp.tpl create mode 100644 install/rpm/php-fpm/www.conf create mode 100644 install/rpm/phpmyadmin/create_tables.sql create mode 100644 install/rpm/phpmyadmin/pma.sh create mode 100644 install/rpm/pma/apache.conf create mode 100644 install/rpm/pma/config.inc.php create mode 100644 install/rpm/postgresql/pg_hba.conf create mode 100644 install/rpm/proftpd/proftpd.conf create mode 100644 install/rpm/proftpd/tls.conf create mode 100644 install/rpm/ssl/dhparam.pem create mode 100644 install/rpm/sudo/admin create mode 100644 install/rpm/templates/mail/apache2/default.stpl create mode 100644 install/rpm/templates/mail/apache2/default.tpl create mode 100644 install/rpm/templates/mail/apache2/disabled.stpl create mode 100644 install/rpm/templates/mail/apache2/disabled.tpl create mode 100644 install/rpm/templates/mail/apache2/rainloop.stpl create mode 100644 install/rpm/templates/mail/apache2/rainloop.tpl create mode 100644 install/rpm/templates/mail/apache2/snappymail.stpl create mode 100644 install/rpm/templates/mail/apache2/snappymail.tpl create mode 100644 install/rpm/templates/mail/nginx/default.stpl create mode 100644 install/rpm/templates/mail/nginx/default.tpl create mode 100644 install/rpm/templates/mail/nginx/default_disabled.stpl create mode 100644 install/rpm/templates/mail/nginx/default_disabled.tpl create mode 100644 install/rpm/templates/mail/nginx/default_snappymail.stpl create mode 100644 install/rpm/templates/mail/nginx/default_snappymail.tpl create mode 100644 install/rpm/templates/mail/nginx/disabled.stpl create mode 100644 install/rpm/templates/mail/nginx/disabled.tpl create mode 100644 install/rpm/templates/mail/nginx/snappymail.stpl create mode 100644 install/rpm/templates/mail/nginx/snappymail.tpl create mode 100644 install/rpm/templates/mail/nginx/web_system.stpl create mode 100644 install/rpm/templates/mail/nginx/web_system.tpl create mode 100644 install/rpm/templates/web/apache2/default.stpl create mode 100644 install/rpm/templates/web/apache2/default.tpl create mode 100644 install/rpm/templates/web/apache2/hosting.stpl create mode 100644 install/rpm/templates/web/apache2/hosting.tpl create mode 100644 install/rpm/templates/web/apache2/php-fpm/default.stpl create mode 100644 install/rpm/templates/web/apache2/php-fpm/default.tpl create mode 100755 install/rpm/templates/web/apache2/phpcgi.sh create mode 100644 install/rpm/templates/web/apache2/phpcgi.stpl create mode 100644 install/rpm/templates/web/apache2/phpcgi.tpl create mode 100755 install/rpm/templates/web/apache2/phpfcgid.sh create mode 100644 install/rpm/templates/web/apache2/phpfcgid.stpl create mode 100644 install/rpm/templates/web/apache2/phpfcgid.tpl create mode 100644 install/rpm/templates/web/apache2/www-data.stpl create mode 100644 install/rpm/templates/web/apache2/www-data.tpl create mode 100755 install/rpm/templates/web/awstats/awstats.tpl create mode 100755 install/rpm/templates/web/awstats/index.tpl create mode 100755 install/rpm/templates/web/awstats/nav.tpl create mode 100755 install/rpm/templates/web/nginx/caching.sh create mode 100755 install/rpm/templates/web/nginx/caching.stpl create mode 100755 install/rpm/templates/web/nginx/caching.tpl create mode 100755 install/rpm/templates/web/nginx/default.stpl create mode 100755 install/rpm/templates/web/nginx/default.tpl create mode 100755 install/rpm/templates/web/nginx/hosting.sh create mode 100755 install/rpm/templates/web/nginx/hosting.stpl create mode 100755 install/rpm/templates/web/nginx/hosting.tpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/chevereto.stpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/chevereto.tpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/cms_made_simple.stpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/cms_made_simple.tpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/codeigniter.stpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/codeigniter.tpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/craftcms.stpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/craftcms.tpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/datalife_engine.stpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/datalife_engine.tpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/default.stpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/default.tpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/dokuwiki.stpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/dokuwiki.tpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/drupal-composer.stpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/drupal-composer.tpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/drupal-social.stpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/drupal-social.tpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/drupal.stpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/drupal.tpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/flarum.stpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/flarum.tpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/gitea.stpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/gitea.tpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/grav.stpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/grav.tpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/joomla.stpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/joomla.tpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/laravel.stpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/laravel.tpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/magento.stpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/magento.tpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/mautic.stpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/mautic.tpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/modx.stpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/modx.tpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/moodle.stpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/moodle.tpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/no-php.stpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/no-php.tpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/odoo.stpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/odoo.tpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/opencart.stpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/opencart.tpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/openproject.stpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/openproject.tpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/osticket.stpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/osticket.tpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/owncloud.stpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/owncloud.tpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/phpbb.stpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/phpbb.tpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/piwik.stpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/piwik.tpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/prestashop.stpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/prestashop.tpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/projectsend.stpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/projectsend.tpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/pyrocms.stpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/pyrocms.tpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/sendy.stpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/sendy.tpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/suspended.stpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/suspended.tpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/symfony2-3.stpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/symfony2-3.tpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/symfony4-5.stpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/symfony4-5.tpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/thunder.stpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/thunder.tpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/wordpress.stpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/wordpress.tpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/wordpress_mu_subdir.stpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/wordpress_mu_subdir.tpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/yourls.stpl create mode 100644 install/rpm/templates/web/nginx/php-fpm/yourls.tpl create mode 100755 install/rpm/templates/web/nginx/proxy_ip.tpl create mode 100644 install/rpm/templates/web/nginx/suspended.stpl create mode 100644 install/rpm/templates/web/nginx/suspended.tpl create mode 100644 install/rpm/templates/web/php-fpm/default.tpl create mode 100644 install/rpm/templates/web/php-fpm/no-php.tpl create mode 100644 install/rpm/templates/web/php-fpm/socket.tpl create mode 100644 install/rpm/vsftpd/vsftpd.conf create mode 100755 install/upgrade/manual/configure-server-smtp.sh create mode 100755 install/upgrade/manual/install_awstats_geoip.sh create mode 100755 install/upgrade/manual/install_awstats_geoip2.sh create mode 100755 install/upgrade/manual/install_sieve.sh create mode 100755 install/upgrade/manual/migrate_apache.sh create mode 100755 install/upgrade/manual/migrate_mpm_event.sh create mode 100755 install/upgrade/manual/migrate_multiphp.sh create mode 100755 install/upgrade/manual/migrate_ngnix_apache_nginx-php-fpm.sh create mode 100755 install/upgrade/manual/migrate_phpmyadmin.sh create mode 100755 install/upgrade/manual/migrate_roundcube.sh create mode 100644 install/upgrade/manual/remove-mail-stack.sh create mode 100755 install/upgrade/manual/upgrade_mariadb.sh create mode 100755 install/upgrade/manual/upgrade_multi_php.sh create mode 100755 install/upgrade/manual/upgrade_php.sh create mode 100644 install/upgrade/patch/3462-exim-helo-autenticted-users.patch create mode 100644 install/upgrade/patch/3661-exim-srs-support.patch create mode 100644 install/upgrade/upgrade.conf create mode 100644 install/upgrade/versions/0.9.8-29.sh create mode 100644 install/upgrade/versions/1.0.1.sh create mode 100644 install/upgrade/versions/1.0.2.sh create mode 100644 install/upgrade/versions/1.0.3.sh create mode 100644 install/upgrade/versions/1.0.4.sh create mode 100644 install/upgrade/versions/1.0.5.sh create mode 100644 install/upgrade/versions/1.0.6.sh create mode 100644 install/upgrade/versions/1.00.0-190618.sh create mode 100644 install/upgrade/versions/1.1.0.sh create mode 100644 install/upgrade/versions/1.1.1.sh create mode 100644 install/upgrade/versions/1.2.0.sh create mode 100644 install/upgrade/versions/1.2.1.sh create mode 100644 install/upgrade/versions/1.2.2.sh create mode 100644 install/upgrade/versions/1.2.3.sh create mode 100644 install/upgrade/versions/1.3.0.sh create mode 100644 install/upgrade/versions/1.3.1.sh create mode 100644 install/upgrade/versions/1.3.2.sh create mode 100644 install/upgrade/versions/1.3.3.sh create mode 100644 install/upgrade/versions/1.3.4.sh create mode 100644 install/upgrade/versions/1.4.0.sh create mode 100644 install/upgrade/versions/1.4.1.sh create mode 100644 install/upgrade/versions/1.4.10.sh create mode 100644 install/upgrade/versions/1.4.11.sh create mode 100644 install/upgrade/versions/1.4.12.sh create mode 100644 install/upgrade/versions/1.4.13.sh create mode 100644 install/upgrade/versions/1.4.14.sh create mode 100644 install/upgrade/versions/1.4.15.sh create mode 100644 install/upgrade/versions/1.4.16.sh create mode 100644 install/upgrade/versions/1.4.17.sh create mode 100644 install/upgrade/versions/1.4.2.sh create mode 100644 install/upgrade/versions/1.4.3.sh create mode 100644 install/upgrade/versions/1.4.4.sh create mode 100644 install/upgrade/versions/1.4.5.sh create mode 100644 install/upgrade/versions/1.4.6.sh create mode 100644 install/upgrade/versions/1.4.7.sh create mode 100644 install/upgrade/versions/1.4.8.sh create mode 100644 install/upgrade/versions/1.4.9.sh create mode 100644 install/upgrade/versions/1.5.0.sh create mode 100644 install/upgrade/versions/1.5.1.sh create mode 100644 install/upgrade/versions/1.5.10.sh create mode 100644 install/upgrade/versions/1.5.11.sh create mode 100644 install/upgrade/versions/1.5.2.sh create mode 100644 install/upgrade/versions/1.5.3.sh create mode 100644 install/upgrade/versions/1.5.4.sh create mode 100644 install/upgrade/versions/1.5.5.sh create mode 100644 install/upgrade/versions/1.5.6.sh create mode 100644 install/upgrade/versions/1.5.7.sh create mode 100644 install/upgrade/versions/1.5.8.sh create mode 100644 install/upgrade/versions/1.5.9.sh create mode 100644 install/upgrade/versions/1.6.0.sh create mode 100644 install/upgrade/versions/1.6.1.sh create mode 100644 install/upgrade/versions/1.6.10.sh create mode 100644 install/upgrade/versions/1.6.12.sh create mode 100644 install/upgrade/versions/1.6.13.sh create mode 100644 install/upgrade/versions/1.6.14.sh create mode 100644 install/upgrade/versions/1.6.2.sh create mode 100644 install/upgrade/versions/1.6.3.sh create mode 100644 install/upgrade/versions/1.6.4.sh create mode 100644 install/upgrade/versions/1.6.5.sh create mode 100644 install/upgrade/versions/1.6.6.sh create mode 100644 install/upgrade/versions/1.6.7.sh create mode 100644 install/upgrade/versions/1.6.8.sh create mode 100644 install/upgrade/versions/1.6.9.sh create mode 100644 install/upgrade/versions/1.7.0.sh create mode 100644 install/upgrade/versions/1.7.1.sh create mode 100644 install/upgrade/versions/1.7.2.sh create mode 100644 install/upgrade/versions/1.7.3.sh create mode 100644 install/upgrade/versions/1.7.4.sh create mode 100644 install/upgrade/versions/1.7.5.sh create mode 100644 install/upgrade/versions/1.7.6.sh create mode 100644 install/upgrade/versions/1.7.7.sh create mode 100644 install/upgrade/versions/1.8.0.sh create mode 100644 install/upgrade/versions/1.8.1.sh create mode 100644 install/upgrade/versions/1.8.2.sh create mode 100644 install/upgrade/versions/1.8.3.sh create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 renovate.json create mode 100644 src/deb/hestia/control create mode 100644 src/deb/hestia/copyright create mode 100644 src/deb/hestia/postinst create mode 100644 src/deb/hestia/preinst create mode 100644 src/deb/nginx/control create mode 100644 src/deb/nginx/copyright create mode 100644 src/deb/nginx/hestia create mode 100644 src/deb/nginx/nginx.conf create mode 100755 src/deb/nginx/postinst create mode 100755 src/deb/nginx/postrm create mode 100644 src/deb/php/control create mode 100644 src/deb/php/copyright create mode 100644 src/deb/php/php-fpm.conf create mode 100644 src/deb/php/php.ini create mode 100644 src/deb/php/postinst create mode 100755 src/hst_autocompile.sh create mode 100755 src/hst_bootstrap_install.sh create mode 100755 src/hst_generate_clidocs.sh create mode 100755 src/lxd_build_all.sh create mode 100644 src/lxd_compile.sh create mode 100644 src/rpm/hestia/hestia.service create mode 100644 src/rpm/hestia/hestia.spec create mode 100644 src/rpm/hestia/hestia.tmpfiles create mode 100644 src/rpm/nginx/hestia-nginx.service create mode 100644 src/rpm/nginx/hestia-nginx.spec create mode 100644 src/rpm/nginx/nginx.conf create mode 100644 src/rpm/php/hestia-php.service create mode 100644 src/rpm/php/hestia-php.spec create mode 100644 src/rpm/php/php-fpm.conf create mode 100644 src/rpm/php/php.ini create mode 100755 src/script_template.sh create mode 100644 test/api.bats create mode 100755 test/check_php.sh create mode 100644 test/checks.bats create mode 100644 test/config-tests.bats create mode 100644 test/letsencrypt.bats create mode 100644 test/lint_script.sh create mode 100644 test/make-test-containers.php create mode 100644 test/restore.bats create mode 100755 test/shellcheck.sh create mode 100755 test/test.bats create mode 100644 test/wildcard.bats create mode 100644 web/add/access-key/index.php create mode 100644 web/add/cron/autoupdate/index.php create mode 100644 web/add/cron/index.php create mode 100644 web/add/cron/reports/index.php create mode 100644 web/add/db/index.php create mode 100644 web/add/dns/index.php create mode 100644 web/add/firewall/banlist/index.php create mode 100644 web/add/firewall/index.php create mode 100644 web/add/firewall/ipset/index.php create mode 100644 web/add/ip/index.php create mode 100644 web/add/key/index.php create mode 100644 web/add/mail/index.php create mode 100644 web/add/package/index.php create mode 100644 web/add/user/index.php create mode 100644 web/add/web/index.php create mode 100644 web/add/webapp/index.php create mode 100644 web/api/index.php create mode 100644 web/bulk/access-key/index.php create mode 100644 web/bulk/backup/index.php create mode 100644 web/bulk/cron/index.php create mode 100644 web/bulk/db/index.php create mode 100644 web/bulk/dns/index.php create mode 100644 web/bulk/firewall/banlist/index.php create mode 100644 web/bulk/firewall/index.php create mode 100644 web/bulk/firewall/ipset/index.php create mode 100644 web/bulk/ip/index.php create mode 100644 web/bulk/mail/index.php create mode 100644 web/bulk/package/index.php create mode 100644 web/bulk/restore/index.php create mode 100644 web/bulk/service/index.php create mode 100644 web/bulk/user/index.php create mode 100644 web/bulk/web/index.php create mode 100644 web/copy/package/index.php create mode 100644 web/css/src/base.css create mode 100644 web/css/src/dependencies/animate.css create mode 100644 web/css/src/fonts.css create mode 100644 web/css/src/media_queries.css create mode 100644 web/css/src/themes/dark.css create mode 100644 web/css/src/themes/default.css create mode 100644 web/css/src/themes/flat.css create mode 100644 web/css/src/themes/vestia.css create mode 100644 web/css/src/utilities.css create mode 100644 web/delete/access-key/index.php create mode 100644 web/delete/backup/exclusion/index.php create mode 100644 web/delete/backup/index.php create mode 100644 web/delete/cron/autoupdate/index.php create mode 100644 web/delete/cron/index.php create mode 100644 web/delete/cron/reports/index.php create mode 100644 web/delete/db/index.php create mode 100644 web/delete/dns/index.php create mode 100644 web/delete/firewall/banlist/index.php create mode 100644 web/delete/firewall/index.php create mode 100644 web/delete/firewall/ipset/index.php create mode 100644 web/delete/ip/index.php create mode 100644 web/delete/key/index.php create mode 100644 web/delete/log/auth/index.php create mode 100644 web/delete/log/index.php create mode 100644 web/delete/mail/index.php create mode 100644 web/delete/notification/index.php create mode 100644 web/delete/package/index.php create mode 100644 web/delete/user/index.php create mode 100644 web/delete/web/cache/index.php create mode 100644 web/delete/web/index.php create mode 100644 web/download/backup/index.php create mode 100644 web/download/database/index.php create mode 100644 web/download/site/index.php create mode 100644 web/download/web-log/index.php create mode 100644 web/edit/backup/exclusions/index.php create mode 100644 web/edit/cron/index.php create mode 100644 web/edit/db/index.php create mode 100644 web/edit/dns/index.php create mode 100644 web/edit/firewall/index.php create mode 100644 web/edit/ip/index.php create mode 100644 web/edit/mail/index.php create mode 100644 web/edit/package/index.php create mode 100644 web/edit/server/apache2/index.php create mode 100644 web/edit/server/bind9/index.php create mode 100644 web/edit/server/clamav-daemon/index.php create mode 100644 web/edit/server/cron/index.php create mode 100644 web/edit/server/crond/index.php create mode 100644 web/edit/server/dovecot/index.php create mode 100644 web/edit/server/exim/index.php create mode 100644 web/edit/server/exim4/index.php create mode 100644 web/edit/server/fail2ban/index.php create mode 100644 web/edit/server/httpd/index.php create mode 100644 web/edit/server/index.php create mode 100644 web/edit/server/iptables/index.php create mode 100644 web/edit/server/mariadb/index.php create mode 100644 web/edit/server/mysql/index.php create mode 100644 web/edit/server/mysqld/index.php create mode 100644 web/edit/server/named/index.php create mode 100644 web/edit/server/nginx/index.php create mode 100644 web/edit/server/php-fpm/index.php create mode 100644 web/edit/server/php/index.php create mode 100644 web/edit/server/php5-fpm/index.php create mode 100644 web/edit/server/postgresql/index.php create mode 100644 web/edit/server/proftpd/index.php create mode 100644 web/edit/server/spamassassin/index.php create mode 100644 web/edit/server/spamd/index.php create mode 100644 web/edit/server/ssh/index.php create mode 100644 web/edit/server/vsftpd/index.php create mode 100644 web/edit/server/whitelabel/index.php create mode 100644 web/edit/user/index.php create mode 100644 web/edit/web/index.php create mode 100644 web/error/403.html create mode 100644 web/error/404.html create mode 100644 web/error/410.html create mode 100644 web/error/50x.html create mode 100644 web/favicon.ico create mode 100644 web/generate/ssl/index.php create mode 100644 web/images/arrow.svg create mode 100644 web/images/favicon.png create mode 100644 web/images/logo-header.svg create mode 100644 web/images/logo.png create mode 100644 web/images/logo.svg create mode 100644 web/inc/2fa/check.php create mode 100644 web/inc/2fa/secret.php create mode 100644 web/inc/composer.json create mode 100644 web/inc/composer.lock create mode 100644 web/inc/helpers.php create mode 100644 web/inc/i18n.php create mode 100755 web/inc/mail-wrapper.php create mode 100644 web/inc/main.php create mode 100644 web/inc/policies.php create mode 100644 web/inc/prevent_csrf.php create mode 100644 web/inc/secure_login.php create mode 100644 web/index.php create mode 100644 web/js/custom_scripts/README.txt create mode 100644 web/js/src/addIpLists.js create mode 100644 web/js/src/alpineInit.js create mode 100644 web/js/src/confirmAction.js create mode 100644 web/js/src/copyCreds.js create mode 100644 web/js/src/cronGenerator.js create mode 100644 web/js/src/databaseHints.js create mode 100644 web/js/src/discardAllMail.js create mode 100644 web/js/src/dnsRecordHint.js create mode 100644 web/js/src/docRootHint.js create mode 100644 web/js/src/editWebListeners.js create mode 100644 web/js/src/errorHandler.js create mode 100644 web/js/src/focusFirstInput.js create mode 100644 web/js/src/formSubmit.js create mode 100644 web/js/src/ftpAccountHints.js create mode 100644 web/js/src/ftpAccounts.js create mode 100644 web/js/src/helpers.js create mode 100644 web/js/src/index.js create mode 100644 web/js/src/ipListDataSource.js create mode 100644 web/js/src/listSorting.js create mode 100644 web/js/src/listUnitSelect.js create mode 100644 web/js/src/nameServerInput.js create mode 100644 web/js/src/navigation.js create mode 100644 web/js/src/passwordInput.js create mode 100644 web/js/src/rrdCharts.js create mode 100644 web/js/src/shortcuts.js create mode 100644 web/js/src/stickyToolbar.js create mode 100644 web/js/src/syncEmailValues.js create mode 100644 web/js/src/tabPanels.js create mode 100644 web/js/src/toggleAdvanced.js create mode 100644 web/js/src/unlimitedInput.js create mode 100644 web/list/access-key/index.php create mode 100644 web/list/backup/exclusions/index.php create mode 100644 web/list/backup/index.php create mode 100644 web/list/cron/index.php create mode 100644 web/list/db/index.php create mode 100644 web/list/dns/index.php create mode 100644 web/list/firewall/banlist/index.php create mode 100644 web/list/firewall/index.php create mode 100644 web/list/firewall/ipset/index.php create mode 100644 web/list/index.php create mode 100644 web/list/ip/index.php create mode 100644 web/list/key/index.php create mode 100644 web/list/log/auth/index.php create mode 100644 web/list/log/index.php create mode 100644 web/list/mail/index.php create mode 100644 web/list/notifications/index.php create mode 100644 web/list/package/index.php create mode 100644 web/list/rrd/ajax.php create mode 100644 web/list/rrd/image.php create mode 100644 web/list/rrd/index.php create mode 100644 web/list/server/index.php create mode 100644 web/list/server/preview/index.php create mode 100644 web/list/stats/index.php create mode 100644 web/list/updates/index.php create mode 100644 web/list/user/index.php create mode 100644 web/list/web-log/index.php create mode 100644 web/list/web/index.php create mode 100644 web/locale/ar/LC_MESSAGES/hestiacp.mo create mode 100644 web/locale/az/LC_MESSAGES/hestiacp.mo create mode 100644 web/locale/bg/LC_MESSAGES/hestiacp.mo create mode 100644 web/locale/bn/LC_MESSAGES/hestiacp.mo create mode 100644 web/locale/bs/LC_MESSAGES/hestiacp.mo create mode 100644 web/locale/ca/LC_MESSAGES/hestiacp.mo create mode 100644 web/locale/cs/LC_MESSAGES/hestiacp.mo create mode 100644 web/locale/da/LC_MESSAGES/hestiacp.mo create mode 100644 web/locale/de/LC_MESSAGES/hestiacp.mo create mode 100644 web/locale/el/LC_MESSAGES/hestiacp.mo create mode 100644 web/locale/es/LC_MESSAGES/hestiacp.mo create mode 100644 web/locale/fa/LC_MESSAGES/hestiacp.mo create mode 100644 web/locale/fi/LC_MESSAGES/hestiacp.mo create mode 100644 web/locale/fr/LC_MESSAGES/hestiacp.mo create mode 100644 web/locale/hestiacp.pot create mode 100644 web/locale/hr/LC_MESSAGES/hestiacp.mo create mode 100755 web/locale/hst_convert_po2mo.sh create mode 100755 web/locale/hst_scan_i18n.sh create mode 100644 web/locale/hu/LC_MESSAGES/hestiacp.mo create mode 100644 web/locale/id/LC_MESSAGES/hestiacp.mo create mode 100644 web/locale/it/LC_MESSAGES/hestiacp.mo create mode 100644 web/locale/ja/LC_MESSAGES/hestiacp.mo create mode 100644 web/locale/ka/LC_MESSAGES/hestiacp.mo create mode 100644 web/locale/ko/LC_MESSAGES/hestiacp.mo create mode 100644 web/locale/ku/LC_MESSAGES/hestiacp.mo create mode 100644 web/locale/languages.json create mode 100644 web/locale/nl/LC_MESSAGES/hestiacp.mo create mode 100644 web/locale/no/LC_MESSAGES/hestiacp.mo create mode 100644 web/locale/pl/LC_MESSAGES/hestiacp.mo create mode 100644 web/locale/pt-br/LC_MESSAGES/hestiacp.mo create mode 100644 web/locale/pt/LC_MESSAGES/hestiacp.mo create mode 100644 web/locale/ro/LC_MESSAGES/hestiacp.mo create mode 100644 web/locale/ru/LC_MESSAGES/hestiacp.mo create mode 100644 web/locale/sk/LC_MESSAGES/hestiacp.mo create mode 100644 web/locale/sr/LC_MESSAGES/hestiacp.mo create mode 100644 web/locale/sv/LC_MESSAGES/hestiacp.mo create mode 100644 web/locale/th/LC_MESSAGES/hestiacp.mo create mode 100644 web/locale/tr/LC_MESSAGES/hestiacp.mo create mode 100644 web/locale/uk/LC_MESSAGES/hestiacp.mo create mode 100644 web/locale/ur/LC_MESSAGES/hestiacp.mo create mode 100644 web/locale/vi/LC_MESSAGES/hestiacp.mo create mode 100644 web/locale/zh-cn/LC_MESSAGES/hestiacp.mo create mode 100644 web/locale/zh-tw/LC_MESSAGES/hestiacp.mo create mode 100644 web/login/index.php create mode 100644 web/logout/index.php create mode 100644 web/reset/index.php create mode 100644 web/reset/mail/index.php create mode 100644 web/reset2fa/index.php create mode 100644 web/restart/service/index.php create mode 100644 web/restart/system/index.php create mode 100644 web/robots.txt create mode 100644 web/schedule/backup/index.php create mode 100644 web/schedule/restore/index.php create mode 100644 web/search/index.php create mode 100644 web/src/app/Models/DnsDomain.php create mode 100644 web/src/app/Models/MailDomain.php create mode 100644 web/src/app/Models/Model.php create mode 100644 web/src/app/Models/User.php create mode 100644 web/src/app/Models/WebDomain.php create mode 100644 web/src/app/System/HestiaApp.php create mode 100644 web/src/app/System/HestiaCli.php create mode 100644 web/src/app/System/Util.php create mode 100644 web/src/app/WebApp/AppWizard.php create mode 100644 web/src/app/WebApp/InstallerInterface.php create mode 100644 web/src/app/WebApp/Installers/BaseSetup.php create mode 100644 web/src/app/WebApp/Installers/DokuWiki/DokuWikiSetup.php create mode 100644 web/src/app/WebApp/Installers/DokuWiki/dokuwiki-logo.svg create mode 100644 web/src/app/WebApp/Installers/Drupal/DrupalSetup.php create mode 100644 web/src/app/WebApp/Installers/Drupal/drupal-thumb.png create mode 100644 web/src/app/WebApp/Installers/Flarum/FlarumSetup.php create mode 100755 web/src/app/WebApp/Installers/Flarum/fl-thumb.png create mode 100644 web/src/app/WebApp/Installers/Grav/GravSetup.php create mode 100644 web/src/app/WebApp/Installers/Grav/grav-symbol.svg create mode 100644 web/src/app/WebApp/Installers/Laravel/LaravelSetup.php create mode 100644 web/src/app/WebApp/Installers/Laravel/laravel-thumb.png create mode 100644 web/src/app/WebApp/Installers/MediaWiki/MediaWiki-2020-logo.svg create mode 100644 web/src/app/WebApp/Installers/MediaWiki/MediaWikiSetup.php create mode 100644 web/src/app/WebApp/Installers/Nextcloud/NextcloudSetup.php create mode 100644 web/src/app/WebApp/Installers/Nextcloud/nextcloud-thumb.png create mode 100644 web/src/app/WebApp/Installers/Opencart/OpencartSetup.php create mode 100644 web/src/app/WebApp/Installers/Opencart/opencart-thumb.png create mode 100644 web/src/app/WebApp/Installers/Prestashop/PrestashopSetup.php create mode 100644 web/src/app/WebApp/Installers/Prestashop/prestashop-thumb.png create mode 100644 web/src/app/WebApp/Installers/Resources/ComposerResource.php create mode 100644 web/src/app/WebApp/Installers/Resources/WpResource.php create mode 100644 web/src/app/WebApp/Installers/Symfony/SymfonySetup.php create mode 100644 web/src/app/WebApp/Installers/Symfony/symfony-thumb.png create mode 100644 web/src/app/WebApp/Installers/WordPress/WordPressSetup.php create mode 100644 web/src/app/WebApp/Installers/WordPress/wp-thumb.png create mode 100644 web/src/composer.json create mode 100644 web/src/composer.lock create mode 100644 web/src/init.php create mode 100644 web/start/service/index.php create mode 100644 web/stop/service/index.php create mode 100644 web/suspend/cron/index.php create mode 100644 web/suspend/db/index.php create mode 100644 web/suspend/dns/index.php create mode 100644 web/suspend/firewall/index.php create mode 100644 web/suspend/mail/index.php create mode 100644 web/suspend/user/index.php create mode 100644 web/suspend/web/index.php create mode 100644 web/templates/footer.php create mode 100644 web/templates/header.php create mode 100644 web/templates/includes/css.php create mode 100644 web/templates/includes/js.php create mode 100644 web/templates/includes/panel.php create mode 100644 web/templates/includes/title.php create mode 100644 web/templates/pages/add_access_key.php create mode 100644 web/templates/pages/add_cron.php create mode 100644 web/templates/pages/add_db.php create mode 100644 web/templates/pages/add_dns.php create mode 100644 web/templates/pages/add_dns_rec.php create mode 100644 web/templates/pages/add_firewall.php create mode 100644 web/templates/pages/add_firewall_banlist.php create mode 100644 web/templates/pages/add_firewall_ipset.php create mode 100644 web/templates/pages/add_ip.php create mode 100644 web/templates/pages/add_key.php create mode 100644 web/templates/pages/add_mail.php create mode 100644 web/templates/pages/add_mail_acc.php create mode 100644 web/templates/pages/add_package.php create mode 100644 web/templates/pages/add_user.php create mode 100644 web/templates/pages/add_web.php create mode 100644 web/templates/pages/debug_panel.php create mode 100644 web/templates/pages/edit_backup_exclusions.php create mode 100644 web/templates/pages/edit_cron.php create mode 100644 web/templates/pages/edit_db.php create mode 100644 web/templates/pages/edit_dns.php create mode 100644 web/templates/pages/edit_dns_rec.php create mode 100644 web/templates/pages/edit_firewall.php create mode 100644 web/templates/pages/edit_ip.php create mode 100644 web/templates/pages/edit_mail.php create mode 100644 web/templates/pages/edit_mail_acc.php create mode 100644 web/templates/pages/edit_package.php create mode 100644 web/templates/pages/edit_server.php create mode 100644 web/templates/pages/edit_server_bind9.php create mode 100644 web/templates/pages/edit_server_dovecot.php create mode 100644 web/templates/pages/edit_server_httpd.php create mode 100644 web/templates/pages/edit_server_mysql.php create mode 100644 web/templates/pages/edit_server_nginx.php create mode 100644 web/templates/pages/edit_server_pgsql.php create mode 100644 web/templates/pages/edit_server_php.php create mode 100644 web/templates/pages/edit_server_service.php create mode 100644 web/templates/pages/edit_user.php create mode 100644 web/templates/pages/edit_web.php create mode 100644 web/templates/pages/edit_whitelabel.php create mode 100644 web/templates/pages/generate_ssl.php create mode 100644 web/templates/pages/list_access_key.php create mode 100644 web/templates/pages/list_access_keys.php create mode 100644 web/templates/pages/list_backup.php create mode 100644 web/templates/pages/list_backup_detail.php create mode 100644 web/templates/pages/list_backup_exclusions.php create mode 100644 web/templates/pages/list_cron.php create mode 100644 web/templates/pages/list_db.php create mode 100644 web/templates/pages/list_dns.php create mode 100644 web/templates/pages/list_dns_public.php create mode 100644 web/templates/pages/list_dns_rec.php create mode 100644 web/templates/pages/list_firewall.php create mode 100644 web/templates/pages/list_firewall_banlist.php create mode 100644 web/templates/pages/list_firewall_ipset.php create mode 100644 web/templates/pages/list_ip.php create mode 100644 web/templates/pages/list_key.php create mode 100644 web/templates/pages/list_log.php create mode 100644 web/templates/pages/list_log_auth.php create mode 100644 web/templates/pages/list_mail.php create mode 100644 web/templates/pages/list_mail_acc.php create mode 100644 web/templates/pages/list_mail_dns.php create mode 100644 web/templates/pages/list_packages.php create mode 100644 web/templates/pages/list_rrd.php create mode 100644 web/templates/pages/list_search.php create mode 100644 web/templates/pages/list_server_info.php create mode 100644 web/templates/pages/list_server_preview.php create mode 100644 web/templates/pages/list_services.php create mode 100644 web/templates/pages/list_ssl.php create mode 100644 web/templates/pages/list_stats.php create mode 100644 web/templates/pages/list_updates.php create mode 100644 web/templates/pages/list_user.php create mode 100644 web/templates/pages/list_web.php create mode 100644 web/templates/pages/list_webapps.php create mode 100644 web/templates/pages/list_weblog.php create mode 100644 web/templates/pages/login/login.php create mode 100644 web/templates/pages/login/login_1.php create mode 100644 web/templates/pages/login/login_2.php create mode 100644 web/templates/pages/login/login_a.php create mode 100644 web/templates/pages/login/reset2fa.php create mode 100644 web/templates/pages/login/reset_1.php create mode 100644 web/templates/pages/login/reset_2.php create mode 100644 web/templates/pages/login/reset_3.php create mode 100644 web/templates/pages/setup_webapp.php create mode 100644 web/unsuspend/cron/index.php create mode 100644 web/unsuspend/db/index.php create mode 100644 web/unsuspend/dns/index.php create mode 100644 web/unsuspend/firewall/index.php create mode 100644 web/unsuspend/mail/index.php create mode 100644 web/unsuspend/user/index.php create mode 100644 web/unsuspend/web/index.php create mode 100644 web/update/hestia/index.php create mode 100644 web/webfonts/exo-v20-latin-300.woff create mode 100644 web/webfonts/exo-v20-latin-300.woff2 create mode 100644 web/webfonts/exo-v20-latin-300italic.woff create mode 100644 web/webfonts/exo-v20-latin-300italic.woff2 create mode 100644 web/webfonts/exo-v20-latin-500.woff create mode 100644 web/webfonts/exo-v20-latin-500.woff2 create mode 100644 web/webfonts/exo-v20-latin-500italic.woff create mode 100644 web/webfonts/exo-v20-latin-500italic.woff2 create mode 100644 web/webfonts/exo-v20-latin-600.woff create mode 100644 web/webfonts/exo-v20-latin-600.woff2 create mode 100644 web/webfonts/exo-v20-latin-600italic.woff create mode 100644 web/webfonts/exo-v20-latin-600italic.woff2 create mode 100644 web/webfonts/exo-v20-latin-700.woff create mode 100644 web/webfonts/exo-v20-latin-700.woff2 create mode 100644 web/webfonts/exo-v20-latin-700italic.woff create mode 100644 web/webfonts/exo-v20-latin-700italic.woff2 create mode 100644 web/webfonts/exo-v20-latin-italic.woff create mode 100644 web/webfonts/exo-v20-latin-italic.woff2 create mode 100644 web/webfonts/exo-v20-latin-regular.woff create mode 100644 web/webfonts/exo-v20-latin-regular.woff2 create mode 100644 web/webfonts/fa-brands-400.ttf create mode 100644 web/webfonts/fa-brands-400.woff2 create mode 100644 web/webfonts/fa-solid-900.ttf create mode 100644 web/webfonts/fa-solid-900.woff2 create mode 100644 web/webfonts/inconsolata-regular.woff create mode 100644 web/webfonts/inconsolata-regular.woff2 diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..15f004d --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,1794 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +## [1.8.2] - Service release + +- Added more files to default proxy extensions (#3768) +- Increased width of menu bar dropdowns on mobile (#3765) +- Increased HSTS max-age to 31536000 (#3762) +- Add prompt to `v-update-sys-hestia-git` to install NodeJS if not present (#3779) +- Fixed an issue where `v-update-sys-ip` was not run on boot on Debian systems +- Fixed an issue where the system hostname would lose its FQDN format on reboot when using Proxmox VE containers +- Fixed an issue ith `v-generate-ssl-cert` (#3783) +- Fixed an issue where the port was missing in welcome email (#3784) +- Fixed an issue with the `is_mail_new` function (#3785) +- Fixed an issue where the "Save" button would appear before warning was dismissed when attempting to add a domain or database as admin (#3786) +- Fixed an issue where MySQL 8 could not be installed on Ubuntu (#3788) +- Fixed an issue with TLS connections when using ProFTPD (#3790) +- Fixed an issue where vlan or virtual NIC connections would fail the adapter validity check when adding an IP address (#3797) +- Fixed several PHP 500 errors and warnings in the Control Panel backend (#3789) +- Fixed an issue with v-change-dns-domain-ip and DNS cluster (#3803) +- Update Multiple Quick install apps (#3800 and #3801) +- Updated language translations + +## [1.8.1] - Service release + +- Fixed Debian 10 not working with IP addresses check +- Fixed Exim4 update config via patch was unreliable added few safety checks and add notice if failed. +- Fixed hestia-nginx not loading with custom port + +## [1.8.0] - Feature / Major release + +### Notes + +- Dropped support for Ubuntu 18.04 Bionic due to EOL Please upgrade to 20.04 or 22.04. +- Custom nginx templates require some changes due to deprecated http2 parameter for the listen directive by Nginx 1.25.1 (#3684, #3704) and 0-RRT Protection introduced in (#3692) +- Dropped support for Rainloop and replaced by Snappymail (#3590) + +### Features + +- Added support for Debian 12 (#3661) + +- Enhanced and Optimized TLS (#3555 @myrevery) +- TLS 1.3 0-RTT with replay protection (#3692 @myrevery) +- Add support for SRS in Exim >= 4.9.5 (#3197 @henri-hulski) +- White label support and refactor translations (#3441 #3572) +- Improve user notifications UI (#3709) +- Continue work on UI improvements (#3700, #3693, #3691, #3685, #3682, #3680, #3672, #3668, #3662, #3659, #3651, #3634, #3629, #3628, #3619, #3615, #3608, #3606, #3602, #3600, #3598) +- Allow option to enable/disable backup suspended users (#3696 ) +- Feature: v-dump-database (#3644) +- Allow users to create own document error / skeleton and do not overwrite them with updating (#3622) +- Consistent overlay styles (#3617) +- Integrate SnappyMail (#3590) +- Allow sorting on package name (#3726) +- Add templates for yourls (#3755 @ediazmurillo) + +### Bugfixes + +- Fix: DNS cluster expected return code instead of string (#3706) +- Resolve #3684 Process "http2" directive for NGINX (#3704 @myrevery) +- Upload hestiacp.pot file directly to Crowdin (#3702) +- Refactor add ns buttons (#3701) +- Remove \r chars from VestaCP cron.conf (#3708 @maunklana) +- Unable to edit password domain smtp relay (#3690) +- Fix: #3687 Improve check if alias already exists (#3689) +- Fixed bug in v-update-sys-ip when multiple interfaces / ip addresses are available (#3688) +- Prevent empty ns1 / ns2 to be used (#3683) +- Reload web server up on deleting web domain. #3705 +- Fix sed for installing sieve (#3679) +- Tidy development docs (#3677) +- Fix typo in v-delete-sys-filemanager (#3678) +- Improve DNS SEC Public key information display (#3676) +- Switch from Yarn v3 to npm (#3675) +- Fix #3643: SOA updating on rebuild command from main server (#3660) +- Fix: Import CPanel when account email is non existing (#3670 #3667) +- Fix: Import CPanel when mail domain and or web domain already exists (#3670 #3667) +- Normalize v-add-user-package input (#3671 #3669) +- smtputf8_advertise_hosts is not supported by deb10 (#3652) +- fix Gitea template (#3650 @asessa) +- Fix issue with redirect to subfolder (#3623) +- Replace current nginx template with suspended template (#3641) +- Fix issue with duplicated phpmyadmin-auth blocks in jail.local (#3642) +- Fix error in rebuild script (#3639) +- Fix bug in syshealth script +- Refactor and fixes for handling system IP/Interfaces (#3605 @myrevery) +- Fix #3496 Fix issue with Sieve and SMTP relay (#3581 @s4069b) +- Add jail rule for incorrect for phpmyadmin (#3596) +- Fix #3599 Disable SMTPUTF8 (#3603) +- Fix content shift on stats row hover (#3614) +- Fix issue with checkbox is not selected port return "no" (#3616) +- Encode passwords in emails send (#3566) +- Add support for PHPmyAdmin SSO support for Mysql 8 (#3539) +- add alias to wp-cli to the user's .bashrc and fix error handling. (#3569 @aosmichenko) +- Simplify suspend/unsuspend dialog translations (#3565) +- Tidy notifications copy (#3561) +- Predefined Ipset lists not loading #3552 (#3557) +- Minor UI fixes to server console output (#3556 @myrevery) +- Fix #3745 Translations not loading (#3746) +- Make IPset visible when F2B is not installed (#3750) +- Fix: #3729 Missing robots.txt get redirected to WP (#3739) / Add WordPress Multisite subdir support (#3741 @hudokkow ) +- Fix issue with Global SMTP settings not updating (#3730) +- Add phpbb Nginx template (#3732 #3731 @xchwarze) +- Update Nextcloud template (#3725 @Steveorevo) +- Fix php error when DNS disabled when updating user (#3726) +- Fix: #3712 Unable to restore domain with custom doc root (#3726) +- Add BIENNIALLY & TRIENNIALLY stats on TaskMonitor (#3721 @caos30) + +### Dependencies + +- Update hestia-php to 8.2.7 +- Update hestia-nginx to 1.25.1 +- Update Quick install apps versions + +## [1.7.8] - Service releae + +### Bugfixes + +- Fix reflected XXS in debug panel when debug mode was enabled or the user accessed directly the debug panel template. [CVE-2023-3479](https://nvd.nist.gov/vuln/detail/CVE-2023-3479) + +## [1.7.7] - Service release + +### Bugfixes + +- Fix #3588: Delete issue DNS record (#3589) +- Tidy notifications copy (#3561) +- Predefined ipset lists not loading #3552 (#3557) + +## [1.7.6] - Service release + +### Bugfixes + +- Fixed Error message "deleted" before shown due to register_shutdown_function (#3548 #3547) +- Fixed an in issue in humanize_usage_size with number format (#3546 #3547) +- Fixed rounding issue with humanize_usage_measure (#3540 #3541) + +## [1.7.5] - Service release + +### Bugfixes + +- Fix issue with install MariaDB (#3543) +- Add a check to prevent ARM64 installs with Mysql8 on Debian (#3543) + +## [1.7.4] - Service release + +### Features + +- Build JS/CSS Theme on release (#3525) +- Refactor away jQuery + +### Bugfixes + +- Remove Font Awesome "brands" usage (#3535) +- Make uft8mb4 default charset for databases (#3534) +- Remove extra slash in SSO url (#3533) +- Improve Quick Install App password input (#3530) +- Kill OpenSSL server if its already running before validating SSL certificate (#3505) +- Improve redirect behaviour (#3503) +- Fix: PMA SSO for cp panel template (#3493) +- Fix: Bug in sftp backup (#3489) +- Improve Quick Install App password input (#3530) +- Refactor away on click usage on login pages (#3526) +- Refactor Add/Edit Firewall Rule JS (#3522) +- Build Alpine.js bundle (#3521) +- Improve charts JS (#3519) +- Show spinner when confirming dialog action (#3517) +- Refactor Edit Web JS/remove jQuery (#3513) +- Refactor Add/Edit Database JS (#3511) +- UI updates (#3510) +- Refactor JS (#3508) +- Fix #3318 Remove: decrepitation warning MariaDB (#3465) +- Fix: 3514 Fix UI not matching true value (#3515) +- Refactor form submit JS (#3502) +- Refactor JS (#3500) +- Refactor unlimited input JS (#3495) +- Tidy JS (#3492) +- IPV6 compatible prevent CSRF (#3491) +- Rewrite statistics UI mobile-first (#3490) +- Refactor JS (#3488) +- Add Quota info to the user list (#3487) +- Minor UI updates (#3485) +- Dynamically load Chart.js bundle (#3480) +- Refactor JS to use ES modules (#3476) + +## [1.7.3] - Service release + +### Features + +- Re-implement RRD charts in Chart.js (#3452) +- Add JS/CSS build script (#3471) + +### Dependencies + +- Update hestia-php to 8.2.5 +- Update hestia-nginx to 1.23.4 + +### Bugfixes + +- Fix: named command warning (#3447 @neto737) +- Fix: Include Cloudflare IPS during install (#3449 #3448) +- Fix: Bug in upgrade_phppgadmin preventing folder from being created when not exists (#3450) +- Add warnings to php-fpm templates (#3450) +- Exim: Never show HELO for authenticated users (#3462 @myvesta) +- Misleading title "Error" on popup notification when creating manual backup (#3460 #3461) +- Fix: Do not add a trailing . on DNSKEY #3458 +- Fix toolbar spacing on mobile in some scenarios e.g. Backups page (#3460) +- Fix: Users can not create a new DNS domain (#3451) +- Fix: Error message containing html are encode twice (#3473) +- Fix button width regression (#3474) +- Remove opacity from modal background (#3460) +- Refactor add/remove name server javascript (#3468) +- Refactor "Unlimited" inputs (#3464) +- Refactor password strength JS (#3459) + +## [1.7.2] - Service release + +### Note + +- HestiaCP 1.7.2 fixes an issue with downloading certificates from Let's Encrypt due to the implementation of asynchronous requests which will go live on 10th April 2023. Please update your server before this date to ensure compatibility with Let's Encrypt. + +### Bugfixes + +- Fixed an issue php after default php version change (#3145 #3414) +- Fixed importing Add Domains v-import-cpanel (#3242 @adion-gorani) +- Fixed and issue with DNSSSEC check if DNSEC is available (#3430) +- Fixed an issue with v-add-web-domain-redirection (#3438 #3440) +- Remove leading and trailing spaces on a domain (#3439 #3440) +- Fixed an issue with domain.com:/public_html in v-backup-users (#3434) +- Fix and issue with custom webmail clients (#3419 #3420) +- Refine :focus styles (#3432) +- Replace jQuery UI tabs with vanilla JS (#3413) +- Reduce amount of animation styles (#3418) +- Minor UI updates (#3425) +- Fixed an issue with v-suspend-dns-record still loading after being disabled (#3441 @setiseta) +- Replace jQuery UI dialogs with (#3401) +- Fixed an issue SSL not found + php error on login page. (#3404) + +## [1.7.1] - Service release + +### Bugfixes + +- Fixed an issue with wildcard overruling webmail.domain.com config in Apache2 (#3400 #1631) +- Removed delete button edit user page (#3997) +- Fixed an issue with serial not increasing (#3396) +- Fixed an issue with new hestia-zone sync and servers behind NAT or with multiple IPs (#3388 #3396) +- Remove option to enable DNSSEC when DNSSEC is not supported (#3372 #3396) +- Fix toolbar items on locales with long words (#3380 #3395) +- Only count \*.tar files in rotate routine (#3393 #3385) +- Fixed broken upgrade_mariadb.sh (#3391 @myrevery) +- Improve add_firewall_ipset.php (#3390 @myrevery) +- Update Path change of IPset blacklist.sh (#3389 @myrevery) +- Improve upgrade script Cloudflare ips (#3388 @myrevery) +- Update supported message hst-install.sh (#3377 @shizualand) +- Fixed an issue with adding own ssl certificated to website config (#3374 #3371) +- Fixed javascript logic edit mail domains (#3373) +- Add required attribute to login forms (#3376) + +## [1.7.0] - Feature / Major release + +### Note + +- Debian 9 (Stretch) is no longer supported as it has reached end-of-life status. +- Basic mobile support has been added in this release. This is early stages and we'd very much appreciate your feedback and any reporting of bugs, to further improve the mobile experience + +### Features + +- Added basic support for mobile devices (#3166, #3141, #3142, #3157, #3155, #3120, and many more) +- Added DNSSEC support for DNS domains (#2938) +- Added support for MySQL 8 (for new installations) (#xxxx @xxxxx) +- Added support for exim rate limiting in package definitions (#2920) +- Added support for ssh keys for SFTP backups (#2906) +- Added Rclone support for backups to AWS, Cloudfare and [+40 other storage systems](https://rclone.org/overview/) (#2928) +- Added support for importing Cpanel backups (#3238, #3232 @skamasle) +- Added support for folder wildcards in backup exclusions (#2338 @youradds) +- Added Nginx template for Mautic (#3192 3188 @youradds) +- Added alias for composer (#3070) +- Updated PhpPgAdmin and with support for PostgreSQL 15 () +- Upgrade MariaDB to 10.11 (#3305) +- Add Quick installer for Flarum (#3342 and #3298 @Steveorevo) +- Enable UTF8MB4 on default for Mysql (#3337 #1882) +- Update Cloudflare ip adresses on each update (#3338 #2575) + +### Bugfixes + +- Make .yaml files editable in the file manager (#3200 @BelleNottelling) +- Fixed an issue with search not supporting user impersonation. (#3208 #3199) +- Prevent users from renaming directories in /home/user/web/ (#3211) +- Allow special characters for user account "Name" field (#3210) +- Prevent usernames from containing special characters (#3220 #3213) +- Increase DKIM length (#3218) +- Improve password meter CSS (#3221) +- Improve restart behaviour v-update-letsencrypt-ssl (#3231) +- Fix order of applied patches on upgrade (#3239) +- Improve upgrade behaviour for Roundcube and Filegator (#3237 #3236) +- Allow for login via Dovecot/Email (#3024) +- Return a proper error code when unable to connect via API (#3235 #3169) +- Synchronise $BIN and $HESTIA/BIN (#2185 @Steveorevo) +- Block usage of unlimited backups (#3181) +- Update paths /var/run/ to /run (#3159) +- Update PHP versions on various Quick Install apps (#3167 #3149 @dadangnh) +- Update Media Wiki version to 1.39.1 (#3168 @kizule) +- Replace custom HTTPS socket code with libcurl (#3160) +- Add config to avoid restarting daemons on error (#3183 @joeakun) +- Fixed an issue with default template and Quick App installer #3133 +- Generalise password reset instructions. #3112 +- Allow .tpl files to be editable in File Manager (#3148 @neto737) +- Fixed an issue where domain alias was not being created for domains with two-tier TLD's (such as .co.uk) (#3030) +- Fix/sync issues with existing domains (#3028) +- Fixed an issue Unable to create tmp directory (#3019) +- Fixed an issue with mysqld-iptables in Fail2Ban (#3025) +- Fixed an issue with Logrotate and Awstats (#3297) +- Added Google Public DNS as a secondary resolver to nginx configuration +- Fixed an issue with Proftpd and passive mode external IP (#3266) +- Improve IPv6 handling in v-change-sys-port (#3276 @asmcc) +- Set the correct conflicts for hestia-php on Ubuntu 22.04 +- Fixed an issue with erroneous deleting $domain.\* instead of $domain.pem (#3221) +- Fixed an issue with domain redirect and idn2 domains (#3323 #3325) +- Fixed an issue in Dokuwiki due to changing repository owner (#3327) +- Fixed an issue with B2 and changing access keys +- Fixed an issue with Drupal install via Quick installer (#3353 #3352) +- Fixed issues with default state jQuery UI modals (#3344) +- Fixed an issue with login with passwords that contains a - or -- on the first character (#3365 #3354) +- Add option to disable ip check (#3365) +- Replace sdocroot with docroot in default.tpl for Apache2 / PHP-FPM setups (#3360) + +### Dependencies + +- Updated hestia-nginx to 1.23.3 +- Updated hestia-php to 8.2.4 +- Update OpenSSL to 3.1.0 +- Updated Roundcube to 1.6.1 +- Updated Filegator to 7.9.2 +- Updated phpMyAdmin to 5.2.21 +- Updated phpPgAdmin to 7.3.14-hestiacp +- Update MediaWiki to 1.39.2 +- Update Prestashop to 8.0.1 +- Update TwoFactorAuth to 2.0.0 + +## [1.6.14] - Service release + +## Bugfixes + +- Improve firewall rules cleanup #3135 @myrevery +- Reverted changes to v-add-web-php as php8.2-imagick is now available +- Fixed an issue with editing timezone in when editing a server (#3127) +- Fixed an issue with hostname during install +- Fixed an issue with WordPress installer not working properly (#3129) + +### Dependencies + +- Update MediaWiki to 1.39.0 + +## [1.6.13] - Service release + +### Bugfixes + +- Fix issue with php8.2-imagick not available +- Fixed an issue with Letsnecrypt and no mail features enabled (#2930 #2931) + +## [1.6.12] - Service release + +### Features + +- Add support for PHP 8.2 + +### Bugfixes + +- Fixed an issue with Europe/Kyiv not existing in Debian / Ubuntu causing issues with saving (#3031 #2971) +- Fixed an issue with v-backup-user loop when the user is unable to create a temp folder or not enough space (#2923 #3019) +- Fixed an issue with restarting with via api (#1236 #30230) +- Fixed an issue with \*.co.uk and similar domains that does not create a www alias (#1750 and #3030) +- Fixed an issue with enabling mysqld-iptables (#3035 @Krzysiek86 @neto737) +- Add an alias for composer in bash_aliases (#3070 @madito) +- Fix issues with multiple ips and hostname in installers (#3068) +- Fixed an issue with Nginx + Apache2 settup and clearing proxy cache (#3060) +- Update WordPress to avoid caching of WordPress Rest API (#3069 @niktest) +- Fixed an issue with firewall and IPset tables shorter then 10 records (#3110 @myrevery) +- Delete rrd database on deleting database host +- Fixed an issue where a user was unable to change database user #3051 +- Fixed an issue with unsuspend database user permissions (remote) #3011 #3046 +- Fixed an issue with v-add-domain and package doesn't allow mail / web or DNS domains + +### Dependencies + +- Update PHPmailer to 6.7.1 + +## [1.6.11] - Service release + +### Important + +A bug in v-update-sys-hestia caused auto update to be not working. Please run: `apt update && apt upgrade` + +### Security + +- Fix issues with session timeout and filemnanger (#3004) + +### Bugfixes + +- Fixed an issue in auto update script for HestiaCP (#2967) +- Fixed an issue in download ssl certificate in Firefox (#2979) +- Resolve issue with idn domains and redirect (#2988) +- Update Ipverse url for United Kingdom (#2962) +- Fixed an issue with icons disapearing when viewing system logs +- Fixd issue with unlimeted quota button on edit mail account + +### Dependencies + +- Update Rainloop to 1.17.0 (#2957) +- Update Zlib to 1.2.13 +- Update hestia-nginx to 1.23.2 +- Update hestia-php to 8.1.12 +- Update OpenSSL to 3.0.7 +- Update Filegator to 7.8.7 + +## [1.6.10] - Service release + +### Security + +- Delete temp files after password has been verified (#2958) + +### Dependencies + +- Update Filegator to 7.8.3 +- Update PHPmailer to 6.6.5 + +## [1.6.9] - Service release + +- Fixed an issue when Installing Wordpress in a non english locale (#2788 #2818) +- Reload Nginx on purging fast cgi cache (#2925) +- Update max number of chars allowed for name (#2924) +- Fixed few small issues with Lets Encypt for hostname (#2922) +- Fixed few issues with Quick installers (#2921) +- Fixed an issue with v-change-web-domain-name +- Update sync-dns-cluster role to run v-delete-dns-domain (#2943) +- Fixed issue with connection with sftp server running FreeBSD (#2950 @gdarko) +- Add support for Kurdish Sorani (#2945 @qezwan) +- Small improvements in syntax for v-add-remote-dns-host (#2951) +- Check if email is valid for PHPMailer (#2944) + +### Dependencies + +- Update Dokuwiki to stable_2022-07-31a +- Update Opencart to 4.0.1.11 +- Update Prestashop to 1.7.8.7 +- Update Jquery on login pages to 3.6.1 (#2932 @4183r) +- Update hestia-php to 8.1.11 + +## [1.6.8] - Service release + +### Features + +- Update default php settings (#2849 #2635) + +### Security + +- Fix issue in is_hestia_package (#2889) + +### Bugfixes + +- Force update composer to v2 instead of v1 when no version is provided (#2839 #2777) +- Fixed an issue with v-change-web-domain-owner and mail only domains (#2840, #2841) +- Grey out phpmyadmin buttons + add link to docs.hestiacp.com for support (#2843) +- Block the use of CNAME records on @ or root records DNS domain (#2838, #2842) +- Code clean up and remove unused tests and templates (#2829 and #2831) +- Fixed an issue where no password was send when a user create a new mail account (#2819 #2815) +- Fixed an issue with Proxmox LXC and hostnames (#2819 #2048) +- Improve new email account email send to the user (#2819 #1417) +- Improve buffers nginx.conf (#2796) +- Improve Letsencrypt error message (#1804 #2854) +- Fixed an issue with error logs failed login attempts (#2853) +- Fixed and issue with saving UTC time zone in Edit server (#2851 #2853) +- Fixed an issue with sshd not running but still showing up in rare cases (#2850 @manuelserol) +- Improve error message "Domain already exists" when the "main" domain belonged to an other user (#2848 #2771) +- Fixed an issue with v-delete-letsencrypt not working when deleting a mail domains SSL (#2878) +- Fixed an issue with storing B2 Secret key in b2.conf (#2843) +- Update jail.local with example to add ignore ip (#2856) +- Add use_temp_path to no to slightly speedup caching (#2855) +- Fix small php errors (#2863 #2857 @YacineSahli) +- Fixed an issue API and DNS cluster over multiple servers where username/password and hash where mixed (#2888) +- Add option to use custom javascript code (#2747) +- Add "v-rebuild-dns-domains" to sync-dns-cluster options +- Fixed an issue with Yescript and api (#2899) +- Add logrotate config for Roundcube (#2868 #2904) +- Fixed an issue with session files in /tmp/ folder caused by /web/inc/mail-wrapper.php (#2904) +- Fixed an issue with v-restore-user does not delete old database before restoring causing new tables to remain exists (#2911 #2909) +- Fixed an issue with deleting mail account does not remove ratelimit for that email account (#2905 #2903) + +### Enhancements + +- Clean up / decrease size of images, favicons, javascript, css and html (#2879, #2871, #2872, #2873, #2884, #2883, #2879 @AlecRust) + +### Dependencies + +- Update hestia-nginx to 1.23.1 +- Update hestia-php to 8.1.9 +- Update animate.js to 3.0.2 (#2879) +- Update normalize.css to 3.0.3 (#2875) +- Update jQuery to 3.6.1 (#2885) +- Update MediaWiki to 1.38.2 +- Update PHPmailer to 6.6.4 +- Update Blackblaze CLI to 3.5.0 + +## [1.6.7] - Service release + +### Bugfixes + +- Fixed an issue with upgrade script Roundcube that caused issues with upgrade of new installs +- Fixed an bug with DNS templates #2827 +- Update v-update-sys-hestia-git + +## [1.6.6] - Service release + +### Bugfixes + +- Update DNS templates with CNAME for ftp, www and webmail (#2808) +- Fix name server A record validation error (#2807) +- Fixed issue with renaming domains and config files not properly removed (#2803) +- Add loading indicator after clicking save button (#2740) +- Improve hostname detection in mail-wrapper (#2805 @clarkchentw) + +### Security + +- Fixed an vulnerability in v-add-web-domain-redirect (CVE-2022-2636) +- Fixed an vulnerability in Ubuntu that can lead in privilege escalation for admin to root user (CVE-2022-2626) + +### Dependencies + +- Update Roundcube to 1.6.0 +- Update Dokuwiki to "2022-07-31" Igor (#2811) + +## [1.6.5] - Service release + +### Bugfixes + +- Add missing translation strings (#2778 @myrevery) +- Add check if folder exists in v-change-web-domain-docroot (#2778) + +### Security + +- Improve random bytes generator (#2774) +- Don't allow /inc/2fa/secret.php called from the web browser directly (#2784 @mayappear) +- Improve CSRF Origin Check Bypass (#2785 @mayappear) +- Fix vulnerability in Dokuwiki Quick Install App @redstarp2 (CVE-2022-2550) +- Fixed an issue where custom ports where not saved on restart fail2ban service making Hestia login screen vulnerable for brute force + +### Dependencies + +- Update Filegator to 7.8.2 + +## [1.6.4] - Service release + +### Bugfixes + +- Fixed an issue with downloading log files () +- Fixed an issue with installing Quick Installers (#2762, #2760, @divinity76) +- Fixed an issue with Apache Access / Awstats logs IP after using v-update-sys-ip (#2759 @adion-gorani) + +## [1.6.3] - Service release + +### Features + +- Add additional support for bcrypt for mail passwords (#2752 @divinity76) + +### Enhancements + +- Simplify md5crypt on reset form email (#2751 @divinity76) +- Use secure RNG to generate passwords (#2726) +- Add twig support filemanger (#2714, @anvme) + +### Bugfixes + +- Fixed an issue with restart Apache2 and Nginx after v-update-letsencrypt (#2748, #2563, #2744, #2677) +- Prevent transversing path in Quick installer apps (#2742) +- Avoid out of memory serving large logfiles (#2741, #2736, @divinity76 +- Improve passwords loading in password_valid (#2739) +- Use secure RNG to generate passwords (#2726) +- Utilise entire alphabet for random string (#2735 @Shadowfied) +- Don't use hosts_try_fastopen in Exim for Gmail / Google hostnames +- Add check if Sieve is already installed (#2719 #manuelserol) +- Allow PHP templates to be selected in Quick installer apps (#2713, #2711, #2690) +- Small changes to translation strings (#2700 @V4M0N0S) +- Rate limit in email address blank in UI (saved correct in limits) (#2710, #2707) +- Fixed a bug in Settings sites where always websites got rebuild on save (#2705, #2710) +- Fixed a bug in Weblog where the session got incorrectly reset as admin user (#2710) +- Prevent v-add-web-php to be used for non fpm installs (#2753) +- Update translations (#2750) +- Chmod o+x .ssh folder when creating file manager ssh key (#2755) + +### Dependencies + +- Update hestia-php to 8.1.8 + - Update disable_functions list php.ini for hestia-php (#2746, #2741) + +## [1.6.2] - Service release + +- Fixed an issue with rate limits in Exim4 and make it more bullet proof (#2703) +- Fixed an issue with system-filter not properly loaded in Exim4 for Exim 4.94 and Ugrades from 1.5.x + +## [1.6.1] - Service release + +### Bugfixes + +- Fixed an issue with rate limit and alias domains (#2676, #2666) +- Fixed an issue with reject spam option (#2687, #2864) +- Fixed an issue in the installer when sieve is enabled (#2675, #2668) +- Fixed an issue with File manager in development mode (#2682 #2644) +- Fixed multiple small in templates (#2659 @ledoktre, #2680, #2671, #2679, #2670, #2681, #2699) +- Fixed add second check if DNS resolving fails (#2678) +- Fixed an issue where v-change-sys-hostname does not update host file (#2688 #2683) +- Fixed an issue with IDN conversions not working on new server installs (#2692 @wojsmol) + +### Enhancements + +- Improve restart behaviour php-fpm +- Improve updating process to make it faster. +- Removed outdated / never used test scripts (#2685) + +### Dependencies + +- Update hestia-nginx to 1.23.0 +- Update PHPmailer to 6.6.3 +- Update Roundcube to 1.5.3 + +## [1.6.0] - Major Release (Feature / Quality Update) + +### Important Notes + +- Added support for Ubuntu 22.04 Jammy. If you planning to upgrade your server from Ubuntu 20.04 or 18.04 to Ubuntu 22.04 read the instruction carefully! +- Issues with Ubuntu and Netplan and additional ip addresses has been discovered if this is the case for your setup please check if Netplan configuration is correct. +- Due to know security issues with Rainloop [CVE-2022-29360](https://blog.sonarsource.com/rainloop-emails-at-risk-due-to-code-flaw/) and the lack of updates from there side we are planning to update / replace Rainloop with [Snappymail](https://github.com/the-djmaze/snappymail). How ever minor changes are needed to the release of Snappymail. The required changes have been made however we are waiting for for the final release of 2.16.4 +- Added support for Yescrypt and ARGON2ID for storing passwords of the users / email accounts password. If you encounter any issues (after importing a backup) with logging change the user / email account password and it will solve any issues. + +### Deprecated + +- Dropped support for Debian 9 for new installs (#2537) +- Dropped support for RSSH on Ubuntu 18.04 on install (#2537) +- Dropped support for TLS1.1 and older for Dovecot (#2012 and #2538) + +### Features + +- Added support for Ubuntu 22.04 Jammy (#2537 #2489) +- Added support Exim rate limits for email accounts via UI (#2225 and #2523 @madito) +- Added support to delete spam when reaching certain threshold (#2206 and #2200 @madito) +- Added support to send mail to an unauthenticated SMTP relay (#2441 @clarkchentw) +- Replace default MD5 encoding with ARGON2ID for Debian 10 and Ubuntu 20.04 and higher (#2421 @stsimb) +- Added support for Yescrypt (#2235 / #2499) +- Upgrade backend to PHP8.1 due to compatibility issues Jammy (#2515) +- Introduce new api allowing users to use certain commands over API (#2535 and #1333) +- Allow "Purge" cache button visible on templates with the name cacheing-your-template-name (#2526 #2530) +- Add hooks to hestia-nginx and hestia-php (#2440) +- Update DNS cluster to support new API system (#2587) + +### Bugfixes + +- Fixed an issue where --hostname and --email did not validated when using --interactive no (#2532 #2531) +- Fixed an issue with the detection if MariaDB 10.7 was running (#2536 @gOOvER) +- Fixed an issue with downloading a backup as a standard user (#2524 #2525) +- Remove duplicated package installer (#2520 @rfzh1996) +- Fixed an issue with "Do not allow user to login" checkbox sync up with real settings (#2507 #2513) +- Fixed an issue where deleting a suspended users did not decrease the suspended user counter (#2504 #2531) +- Fixed an issue where domain with redirect enabled was not able to "request" Lets encrypt ssl (#2514 #2176) +- Add an notice when using Blackblaze on a ARM64 based server (#2394 @zedpr0) +- Add rsyslog as a dependency (#2505) +- Fixed an issue when a user import a backup a let's encrypt cronjob was not created on default. (#2498 @NickCoolii) +- Add missing translation conversions in backup list (#2501) +- Update example in v-add-web-domain-backend (#2500 gingerbeardman) +- Update example in v-add-letsencrypt-domain (#2442) +- Fixed an issue in configure-server-smtp.sh by loading /etc/hestiacp/hestia.conf (#2488) +- Update Cloudflare ips in nginx.conf (#2542 @clarkchentw) +- Remove duplicate code in Ubuntu installer (#2542 @clarkchentw) +- Fixed an issue in Nginx + Apache2 mail "disabled" template. Causing users unable to request an valid ssl certificate (#2550 #2549) +- Fixed an issue with "Reject spam" option not working (#2551 #2545) +- Fixed an issue with Editing / Adding DNS records (#2546, #2547, #2548 @DunoCZ) +- Fixed an issue with TXT records longer then 255 characters (#2559) +- Fixed an issue with wp-cli permission denied and allow wp-cli to be run in v-run-cmd command (#2562 and #2565) +- Fixed an issue with apt-get install output not written to install log (#2585) +- Fixed multiple issues with improved Quick installer app for Wordpress (#2583) +- Changes in upstream package caused phpMyAdmin Single Sign on feature to break (#2591) +- Fixed issues with DNS cluster and the new API (#2587) +- Fixed an issue where PHPpgAdmin config files was not renamed to .inc for Apache2 setups (#2592) +- Startup Fail2ban on boot for Ubuntu 22.04 (#2596 #2594) +- Fixed issue with duplicate config value (#2640 @Kujoe and #2605 #2610 ) +- Fixed an issue with change password function for webmail clients +- Fixed multiple issues with Quick install apps in general (#2444, #1092, #2638) +- Fixed an issue with memory usage graph and non english locale (#2643 #2540) +- Fixed an issue with incorrect download path ftp backup (#2636 @cloudyhostcom) +- Add php8.1 in v-run-cli-cmd (#2630 @gOOvER) +- Fixed multiple issues with wildcard and Letsencrypt (#2627, #2626, #2624, #2623) +- Fixed multiple issues in v-change-domain-owner (#2618, #2617, #1864) +- Fixed an issue with MariadDB 10.8 detection (#2616) +- Fixed an issue with netplan and additional ip addresses (#2612) +- Removed MariaDB repo form Ubuntu 22.04 install +- Don not install Roundcube dependencies if Roundcube is missing while installing sieve. +- Remove duplicated code in v-add-web-domain-ssl + +### Dependencies + +- Update hestia-nginx to 1.22.0 + - Update OpenSSL to 3.0.3 + - Update zlib to 1.2.12 + - Update PCRE to 10.40 +- Update hestia-php to 8.1.7 +- Updated phpMyAdmin to 5.2.0 () +- Update Filegator to 7.8.1 +- Update PHPmailer to 6.6.2 +- Update composer dependencies + +## [1.5.15] - Service release + +### Bugfixes + +- Fixed an issue with wildcard DNS records + +### Dependencies + +- Update phpMyAdmin to 5.1.4 () (#2529) + +## [1.5.14] - Service release + +### Bugfixes + +- Fixed an issue with login with ipv6 (#2564) +- Fixed an issue with dns records containing an . (#2559) + +## [1.5.13] - Service release + +### Bugfixes + +- Fixed an issue in add / change dns record via GUI. (#2557) + +## [1.5.12] - Service release + +### Bugfixes + +- Fixed vulnerability with Sed [CVE-2022-1509](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-1509) +- Remove localhost exception for invalidating sessions [SSD disclosure](https://ssd-disclosure.com/ssd-advisory-vestacp-multiple-vulnerabilities/) + +## [1.5.11] - Service release + +### Bugfixes + +- Fixed an issue where Hestia port change did not update chain for fail2ban (#2465) +- Fixed permission issues with /var/log/roundcube (#2466) +- Fixed multiple issues in UI (#2464) +- Allow v-change-user-template update backend templates (#2475) +- Update composer dependencies (#2458 #2459) +- Fixed an XSS vulnerability in "Edit" server page. (#2471) [CVE-2022-0986](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-0986) +- Fixed an issue with caching templates and internal redirects (#2482) + +## [1.5.10] - Service release + +### Bugfixes + +- Fixed an issue where webmail client options were not displayed in the Web UI (#2445) +- Fixed an issue where users where not able to create an backup. (#2448 / #2449) +- Fixed an issue where saving server settings could fail due to an incorrect PHP version check on mod-php servers (#2451) +- Fixed an issue where MariaDB installations were broken when performing a clean install of HestiaCP v1.5.9 (#2452 | 2446) +- Fixed recently discovered XSS vulnerabilities (#2453) [CVE-2022-0838](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-0838) + +## [1.5.9] - Service release + +### Bugfixes + +- Fixed multiple XSS vulnerabilities in the web user interface. [CVE-2022-0752](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-0752) / [CVE-2022-0753](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-0753) +- Fixed an issues with mariadb.sys user didn't work properly on MariaDB 10.6.x installs #2427 +- Change ipverse.net urls to new format hosted on Github #2429 and forum +- Allow PTR to be used on domain.com + +### Dependencies + +- Update PHPMailer to 6.6.0 () +- Update Filegator to 7.7.2 () + +## [1.5.8] - Service release + +### Features + +- No new features has been introduced + +### Bugfixes + +- Fixed an issue where SFTP jail was not enabled correctly for additional FTP accounts #2403 +- Fixed an issue in the installer where the "Press any key to continue" prompt only responded to the Enter key #2398 +- Fixed an issue where list sort order preference variable wasn't saved properly #2391 +- Fixed an issue with inconsistent behaviour in mail account settings information dialog #2392 +- Fixed an issue where .gnupg folder in /root/ had the wrong permissions set. +- Fixed an issue where users were being redirected to login page when visiting /reset/ endpoint #2401 +- Fixed an issue where deleting sftp jail did not revert back permissions of said user. #2143 +- Fixed an issue where "REDIRECT" variable wasn't cleared correctly causing other sites to redirect to the domain after v-update-letsencrypt-ssl +- Changed repository url MariaDB for new installs to + +### Dependencies + +- Update phpMyAdmin to 5.1.3 () + +## [1.5.7] - Service release + +### Bugfixes + +- Fixed an issue with apt update and public key missing + +If you have to following error + +```bash +The following signatures couldn't be verified because the public key is not available: NO_PUBKEY A189E93654F0B0E5 +``` + +Follow the following instructions + +```bash +rm /usr/share/keyrings/hestia-keyring.gpg +mkdir /root/.gnupg/ +gpg --no-default-keyring --keyring /usr/share/keyrings/hestia-keyring.gpg --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys A189E93654F0B0E5 +``` + +After that run apt update && apt upgrade + +## [1.5.6] - Service release + +### Bugfixes + +- Fixed an issue with the installer. system.pkg didn't allow for a Web alias #2381 +- Fixed an issue with upgrade script causing command to to be executed () + +## [1.5.5] - Service release + +### Features + +- Improve default php-fpm.conf files. (#2318, #2343) +- Notify user when a suspended user tries to login (#2310, #2345) +- Allow setting default web install templates for Quick install (#2344) () +- Improve security how apt keys are downloaded #2299 () +- Allow users to set system php version in Web GUI (#2357) +- Added a link to the firewall in list services (#2371) @fra81 + +### Changes + +- Modify template warning #2346 +- Removed 127.0.0.1 from the default accepted ip list api. (#2325) +- Update translations + +### Bugfixes + +- Update CSS to prevent wrapping in email info box (#2353) @chriscapisce +- Remove unwanted debug information regarding PhpMyAdmin SSO causing emails to be send to administrator +- Allow the use of 8 name servers for DNS templates (Gmail, Zoho and Office 365) (#2369, #2370) +- Fixed an issue where databases where not able to backup if it required custom settings +- Allow users to edit default.pkg again. On new installs the default admin user will get assigned a new system.pkg (#2365) +- Disable enabling PMA SSO when Api was disabled + Added link to FAQ for frequently asked questions. (#2365) +- Remove error_reporting(null) and allow all errors to be logged in /var/log/hestia/nginx-error.log (#2365) +- Fixed an issue where value "Allow suspended wasn't saved" (#2356, #2355) +- Fixed and issue where AUTH_USER and AUTH_HASH was not present and there for during rebuild caused issues with Nginx (#2350, #2355) + +### Dependencies + +- Update PHPmyadmin to 5.1.2 () +- Update Filegator to 7.7.1 () +- Update B2CLI to 3.2.0 () (#2349) @ptrinh + +## [1.5.4] - Service release + +### Features + +### Bugfixes + +- Fixed an issue with v-add-sys-phpmailer not updating properly (#2336) +- Fixed an issue where users where not able to download backups via UI (#2335) +- Fixed an issue where php8.0 got "rounded" to php8 causing default.tpl falling back to 8.1 (#2340) +- Fixed an issue with recalculating disk usage (#2341) +- Fixed an issue where php files where still executable in upload folder Wordpress +- Fixed an bug where version numbers includeing revisions (-x) where unable to build properly + +## [1.5.3] - Service release + +### Features + +### Bugfixes + +- Fixed an issue where suspended objects where excluded in disk size calculation (#2312 #2313) +- Fixed an issue when a users was unable edit them self when 2FA was enabled (#2314 #2316) +- Fixed an issue in v-add-user-sftp as ftp users where not recognised as valid sftp jail set ups (#2308 #2319) +- Fixed an issue when "Preview" features got disabled it kept the preview features enabled (#2322 #2323) +- Limit access openbase dir hestia-php +- Fixed an issue where an email was send after install nginx command not found (#2328) + +### Dependencies + +- Update PCRE 8.84 to PCRE2 10.39 for hestia-nginx package +- Update Roundcube to 1.5.2 ([Release notes](https://github.com/roundcube/roundcubemail/releases/tag/1.5.2)) +- Update PHPMailer to 6.5.3 ([Release message](https://github.com/PHPMailer/PHPMailer/releases/tag/v6.5.3)) + +## [1.5.2] - Service release + +### Features + +- Release notes are now available from the notification panel (#2276) +- Web domain aliases are now displayed in the domain list (#2278 / #2289) +- DNS, Mail, and Database sections will now be hidden in /edit/server if not installed (#2300) +- Turkey has been added as an option for ipset (#2294) + +### Bugfixes + +- Improvements have been made to overall code quality (#2293, #2298, #2307) +- Added improvements to the automated testing suite (bats) (#2280) +- Clarified text that is shown during upgrade process (#2270) +- Updated web domain templates to allow the use of .user.ini (#2267 / #2269) +- Fixed an issue with the curl symlink on Debian during build process (#2275) +- Fixed an issue where CAA records were deleted when turning off SSL for webmail (#2279) +- Fixed an issue where email validation would fail when using IDN domains (#2273) +- Changed behavior to prevent php-fpm restarts when modphp is installed (#2270) +- Fixed an issue where passwords may not be correctly set on Debian 11 (#2270) +- Fixed an issue with command path v-change-firewall-rule (#2249) +- Fixed an issue in `v-backup-user` where you may encounter an error "invalid parameters for check_result" (#2284) +- Fixed an issue which impacted the performance of Nextcloud/Owncloud ([forum post](https://forum.hestiacp.com/t/tip-create-a-nginx-template-for-nextcloud-to-let-synchronize-files-bigger-than-10mb/5123)) +- Fixed an issue where the access port for HestiaCP was not properly set on install (#2288 / #2291) +- Fixed an issue where admins could not log in as a suspended user in the panel (#2286 / #2289) +- Fixed an issue where the "Delete" button in the Edit User interface did not work as expected (#2282 / #2289) +- Fixed an issue where editing an existing firewall rule with ipset would fail (#2292) +- Fixed an error that may occur in /edit/server when no extra php versions were installed (#2289) +- Fixed an issue where accessing the panel via Safari would result in error NSPOSIXErrorDomain:100 (#2274) +- Corrected command syntax in v-delete-dns-records (#2295) +- Fixed an issue where API allowed IP list values would be lost when saving changes (#2296 / #2300) +- Fixed an issue where the debug mode option was not displayed on release builds and would be reset when saving server settings (#2300) +- Fixed an issue where grep would throw an error when adding ipset rules for the first time (#2307) +- Fixed incorrect variable spelling ($v_interace > $v_interface) (#2307) +- Updated mail domain templates +- Updated command line examples for docs.hestiacp.com +- Fixed an issue where Lets encrypt was not able to obtain an valid ssl certificate when force ssl and / or redirect was enabled (#2176 / #2304 / #2304) +- Fixed a issue in v-list-sys-dns-status + +### Dependencies + +## [1.5.1] - Service release + +### Bugfixes + +- Add B2 delete file support to BlackBlaze +- Open phpmyadmin in new tab or window #2250 @manuelserol +- Fix issue with ipset not working properly [Forum](https://forum.hestiacp.com/t/error-ipset-object-not-found/5015) +- Improve port detection on multiple servers for SSH #2242 and #2255 +- Fixed an issue with # in config files +- Fixed multiple bugs in installer +- Set correct permission /install/deb/ folder +- Adjust /etc/apt/sources.list.d/hestia.list to include architecture to resolve issue with I386 missing in apt.hestiacp.com +- Fallback to hostname without retrying ptr lookup in exim (#2259) +- Enable quota with in dovecot when sieve is enabled @madito +- Unable to edit php8.1 service #2261 + +### Dependencies + +- Update Roundcube to 1.5.1 [Release Notice](https://roundcube.net/news/2021/11/28/update-1.5.1-released) + +## [1.5.0] - Major Release (Feature / Quality Update) + +### Breaking changes + +- **NOTE:** Changes have been made on how phpmyadmin/phppgadmin config are included in apache2 config. To restore to the old behaviour add `IncludeOptional conf.d/*.inc` below `IncludeOptional conf.d/*.conf` in /etc/apache2/apache2.conf and restart your server. +- **NOTE:** Hestia packages for arm64 has been added to atp.hestiacp.com please use the normal install instructions instead! For current ARM installs to enable auto update remove the `#` in /etc/apt/sources.list.d/hestia.list `# deb https://apt.hestiacp.com/ focal main` becomes `deb https://apt.hestiacp.com/ focal main` and then run `apt update && apt upgrade -y` +- **NOTE:** Make sure your server / VPS has a valid PTR record or otherwise you will not be able to send any mail! + +### Features + +- Add support for Dovecote Sieve #2163 (@gejobj) => [How to enable Managesieve](https://hestiacp.com/docs/server-administration/email.html#how-can-i-enable-managesieve) +- Improve HELO based system and use RDNS lookup instead our old system +- Add support for PHP 8.1 #2233 +- Set default php version for new installs to PHP 8.0 +- Add support for ARM64 Processors +- Disable access phpmyadmin/phppgadmin over ip address in Apache2 #2072 + +### Bugfixes + +- Disable /reset/ endpoint when POLICY_SYSTEM_PASSWORD_RESET = no #2167 +- Add rate limit forgot password #2199 +- Prevent SOA count up after v-change-dns-records with no changes are made +- Fix #1296 Log rotate does not rotate logs any more on Ubuntu 20.04 and Debian 11 +- Run shellcheck to improve code quality +- Improve ssh port detection for filemanager. Allowing users to create /etc/ssh/sshd.conf.d/custom.conf with custom port +- Fix an bug in v-add-letsencrypt-host due to changes of Lets Encrypt causing issues with rate limiting +- Improve Update process Hestia and allow versions to decide a a rebuild is required +- Add Download SSL certificate function for self generated ssl certificates #2181 +- Block access to .user.ini for Nginx + Apache2 #2179 +- Add support for download B2 backup to local server to allow for restore #2199 +- Update permissions /var/log/roundcube on older installations #2173 +- Update translations +- Fix Roundcube permissions +- Add .webp to list of media formats that can be cached by the browser +- Disable /list/log/auth when in Demo mode +- Fix #1139 By force rebuilding webmail config files +- Fix a bug in rebuild mysql database @depca +- Fix #1239 Bug in basic auth not working properly +- Add validation for email address before install server for admin account +- Fix bug in v-change-domain-owner #2210 +- Improve input validation Add / Edit User package and improve reading config files to prevent security issues. + +### Dependencies + +- Update Roundcube to 1.5.0 +- Update jQuery UI to the last version [CVE-2021-41182](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-41182) + +## [1.4.17] - Service release + +### Bugfixes + +- Fix bug with nginx and phmyadmin not loading +- Fix #2166 Search function broken +- Update Quick installers to the last version + +## [1.4.16] - Service release + +### Bugfixes + +- Fix bug with .json not loading on Apache2 due to rule in /etc/apache2/conf.d/phpmyadmin.conf + +## [1.4.15] - Service release + +## Features + +- Add templates Chevereto #2153 @ManualRechkle + +### Bugfixes + +- Fix bug in v-add-sys-ip with netplan active +- Limit access to files/folders that are not required on default /phpmyadmin (\*.json, templates, locale, vendor) #2143 +- Update translations +- Fix issue with Exim 4.94 and Autoreply #2151 +- Fix multiple UI bugs #2415 +- Fix link broken link to Documentation #2142 +- Improve detection for MariaDB #2141 thanks @gejobj + +## [1.4.14] - Service release + +### Bugfixes + +- Fixed an issue with edit package +- Fixed an issue with v-update-letsencrypt and v-restart-service +- Fixed an issue with v-add-sys-ip and Ubuntu with no netplan enabled +- Fixed broken UPGRADE_MESSAGE variable not showing up in email +- Include / expand the config backup system during update + +## [1.4.13] - Service release + +### Features + +- Introduce UPGRADE_MESSAGE variable to support custom messages in e-mail upgrade notification. + +### Bugfixes + +- Improve the hostname check to prevent invalid hostnames or the use of an ip address (RFC1178). +- Prevent CSRF from other domains / websites +- Fix #2096 Hostname SSL got overwritten by mail.hostname.com certificate +- Add small wait for /usr/bin/iptables-restore [Forum](https://forum.hestiacp.com/t/clean-install-arm64-does-not-start-after-reboot-v-start-service-iptables/4395/7) + Fixed v-add-firewall / v-delete-firewall function (#2112) @myrevery +- Fix bug in v-change-sys-api. When using v-change-sys-api remove and then v-change-sys-api enable + custom release branch the resetting of api failed + no "error" output was producted +- Improve error reporting PMA Single sign on function function +- Fixed an issue in v-change-web-domain-name where webserserver where not able to start because old config files where not properly deleted #2104 +- Fixed potential XSS vulnerability in /list/keys/ @wtwwer [Disclosure](https://huntr.dev/bounties/0fefa2f6-7024-44c8-87c7-4d01fb93403e/) +- Removed /edit/file as it has been replaced by Filegator and part of the old Vesta Filemanager +- Fixed potential External control / path vulnerability in /add/package @wtwwer [Disclosure](https://huntr.dev/bounties/e0a2c6ff-b4fe-45a2-9d79-1f4dc1b381ab/) +- Add extra checks to prevent type juggling @vikychoi [Disclosure](https://huntr.dev/bounties/c24fb15c-3c84-45c8-af04-a660f8da388f/) +- Improved and updated some missing translation strings @myrevery +- Sync translations with Github + +## [1.4.12] - Service release + +### Bugfixes + +- Allow custom mail domains with own certificates #2061 @myrevery +- Fixed Replace tabulation with \u0009 in v-list-dns-records #2089 @codibit +- Fix #2087 Exim 4.94 Did not send any email to remote servers. +- Fixed #2082 v-delete-web-php creates always new config file +- Add /home/user/.composer in open_basedir #2088 @anvme + +## [1.4.11] - Service release + +### Features + +- Added support for Debian 11 (Bullseye) #1661 +- Added support for openssl in hestia-php +- Use hestia-php for installing dependencies to solve issue user configurations (hestia-php 7.4.22 required) +- Replace old firewall system with systemd service / startup script #2064 @myrevery +- Add Quick installers for GravCMS, Docuwiki and Mediawiki (#2002) @PsychotherapistSam + +### Bugfixes + +- Improve handling upgrade of Roundcube #1917 +- Fix an issue with sorting the update scripts when version goes higher then 1.x.10 +- Allow the use of multiple CAA records for domain. #2073 +- Add missing group (www-data) to migrate_phpmyadmin script #2077 @bet0x +- Fix an issue where get forwarded to /var/spool/news +- Synced up translations with HestiaCP (IT, PL, RU, SK and ZN-CN updated) + +## [1.4.10] - Service release + +### Features + +- Added v-delete-firewall-ban ip all #2031 +- Include config tests for nginx/apache2 templates + +### Bugfixes + +- Fixed UI issues after upgrade jQuery + jQuery UI to last version (#2021 and #2032) + [forum](https://forum.hestiacp.com/t/confusion-about-send-welcome-email-checkbox/4259/11) +- Fixed security issues in caching templates of Nginx when used as Reverse Proxy +- Fixed an issue with deleting multiple mail accounts (#2047) +- Fixed an issue with phpmailer + non latin characters (#2050) thanks @Faymir +- Remove caching template for CraftCMS (#2039) @anvme +- Fixed an issue with phpmailer + non latin characters (#2050) thanks @Faymir +- Fix Unable to load dynamic library 'pdo_mysql.so' after php reinstalling (#2069) + +## [1.4.9] - Service release + +### Bugfixes + +- Updated jQuery and jQuery UI to the latest version due to a vulnerability in jQuery. @dependabot +- Fixed bug in /etc/dovecot/conf.d/10-ssl.conf for new installs +- Fixed bug with notifications +- Fixed translation string @myrevery + +## [1.4.8] - Service release + +### Features + +- Add support for automated testing for HestiaCP code with @drone +- Add support for SMTP server for internal email #1988 @Myself5 / #1165 + +### Bugfixes + +- Updated jQuery and jQuery UI to the latest version due to a vulnerability in jQuery. @dependabot +- Resolve issue with double ENFORCE_SUBDOMAIN_OWNERSHIP keys in hestia.conf +- Resolve issue with create new user during install in some cases #2000 +- Fixed an issue with Quick Install apps named Test123 (@PsychotherapistSam) +- Fix an issue with dovecot 2.3 ssl config (#1432) +- Load $HESTIA path during upgrade script (#1698) +- Remove TLS 1.1 from Proftpd config (#950) +- Don't remove postfix when Exim is not installed (#1995) +- Fix a bug in no-php Nginx FPM template (##2007) +- Update German translations +- Fixed a few minor error in Mail DMS records (#2005) + +## [1.4.7] - Service release + +### Bugfixes + +- Fixed #1984 phppgadmin not working on apache2 systems +- Fixed #1985 Restart service not working + +## [1.4.6] - Service release + +### Features + +- Add support for custom install hooks #1757 +- Add template for CraftCMS #1973 @anvme +- Upgrade Filegator to 7.6.0 + +### Bugfixes + +- Fixed #1961 Renewal Apache2 only SSL certificate fails +- Fixed #1956 to prevent reset of defined webmail client. +- Explicitly disable cron reports #1978 +- Fixed an issue where in rare cases certificate failed to install @dpeca and @myvesta +- Fixed an issue where composer failed to install when .composer folder is missing +- Fixed #1980 Lets Encrypt Auto Renewal Reverts Webmail Client back to Roundcube + +## [1.4.5] - Service release + +### Bugfixes + +- Revert #1943 and rework it to fix possible errors occurring on v-rebuild-cron-jobs. +- Fixed #1956 to prevent reset of defined webmail client. +- Explicitly disable cron reports #1978 + +## [1.4.4] - Service release + +### Features + +- Add nginx user_agent separation to desktop/mobile (e.g. for fastcgi cache) +- Run phpmyadmin folder under www-data user instead of "user" improving security. (@bet0x) +- Added new template for mod php users to access phpmyadmin + +### Bugfixes + +- Add template for when webmail is disabled allowing to generate SSL. +- Fixed PHP bug in /list/log/ +- Fixed issue with time in /list/services as it was showing as 50 minute1 instead of minutes +- Add missing back buttons + fix behaviour of back buttons on login page. +- Set "default" when WEB_TEMPLATE and PROXY_TEMPLATE is missing in user.conf +- Add BACKEND_TEMPLATE to default package +- Fixed possible error occur for v-rebuild-cron-jobs #1943 (thanks @clarkchentw) +- Restrict access file manager when SSH is enabled for the user (@bet0x) +- Check for DNS domains when running v-change-sys-ip-nat (@clarkchentw) +- Fixed logical error in installer (@clarkchentw) + +## [1.4.3] - Service release + +### Features + +- Include DMARC record in DNS record list #1836 +- Enabled phpMyAdmin Single Sign On support #1460 +- Add command to add / delete from API_ALLOWED_IP list (#1904) + +### Bugfixes + +- Improve the calculated disk size of a new backup estimated by excluding the exclude folders, mail accounts and database in backups (#1616) @Myself5 +- Improve v-update-firewall / v-stop-firewall to make it self healing (#1892) @myrevery +- Update phpMyAdmin version to 1.5.1 (See ) +- Fixed a bug after rebuilding mail with Exim4 and suspended domains (#1886) +- Fixed "Allowed IP addresses for API" field with strange behaviour #1866 +- Fixed an issue where the "Saved confirmation" was not set due to a redirect #1879 +- Increased minimal memory requirements for ClamD / ClamAV. #1840 +- Restore of backup did not rebuild the "Forced SSL" and "HSTS" config on new account #1862 +- Keep changes made by /install/upgrade/manual/install_awstats_geopip.sh on update HestiaCP (via Discord) +- Refactor/improve PHP and HTML code @s0t (#1860) +- Fixed XSS vulnerability in login page and a few other locations @briansemrau / @numanturle +- Delete old session after session_regenerate_id() @briansemrau +- Improve error message when domain all ready exists on different account. +- Fixed an issue where phpmyadmin did not update when Postgresql was available. +- Webmail clients set to rainloop where not able to create a SSL certificate via LE #1913 +- Fixed an issue where plugin-hestia-change-pasword did not change the port on v-change-sys-port (Rainloop) #1895 +- Fixed an issue where HELO message was not set / error was created on NAT IP + +## [1.4.2] - Service release + +- **NOTE:** During the 1.4.1 / 1.4.0 release we have introduced a bug for Ubuntu 20.04 and 18.04 users with multiple network ports on the server. This release will solve the problems caused by this bug! If you are unable to download the Hestia packages via apt. Run the following command via CLI or SSH as root + +```bash +iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT +``` + +Then run the update via + +```bash +apt update && apt upgrade +``` + +### Bugfixes + +- Fixed issue wit startup script for iptables / network (#1849) (@myrevery) +- Fixed problem with accidentally replacing nginx.conf during upgrade nginx (#1878 / @myrevery) +- Fixed issue with installing Ubuntu 18.04 +- Fixed issue with login into file manger as admin user +- Added proxy_extentions back to support older custom templates +- Added the possibility to skip the forced reboot when interactive is set to no +- Fixed an issue with modx template +- Updated translations (Croatian, Czech and Italian) +- Fixed an issue where users where not able to save / update web domains when POLICY_USER_EDIT_WEB_TEMPLATES is enabled (#1872) +- Fixed an issue where admin users where not able to add new ssh key for users (#1870) +- Fixed an issue where domain.com was not affected as a valid domain (#1874) +- Fixed an issue where "development" icon was not removed on update to release (#1835) + +## [1.4.1] - Bug fix + +- Fixed bug with 2FA enabled logins + +## [1.4.0] - Major Release (Feature / Quality Update) + +- **NOTE:** Ubuntu 16.04 (Xenial) is no longer supported as it has reached EOL (end-of-life) status. +- **NOTE:** Apache in "standalone" mode is no longer actively supported and has been removed from installer options. Nginx (Proxy) + Apache2 will remain supported. +- **NOTE:** Custom "quick installer apps" will not work anymore due to changes in how we handle quick installer apps. Minimal changes to the Quick installer apps are required! Please check for how to migrate! +- **NOTE:** Manual upgrade scripts are available to update Roundcube, Rainloop and PHPmyadmin to the last version they can be found in /usr/local/hestia/install/upgrade/manual/ + +### Features + +- Introduced support for NGINX FastCGI cache. +- Introduced support for SMTP Relay / smarthosts (server-wide or per-domain). +- Introduced the ability to choose which webmail client to use per-domain (Roundcube or Rainloop). +- Added support for Rainloop (Run v-add-sys-rainloop to install it) +- Added B2 Backup Support for Remote Backup Location - thanks **@rez0n**! +- Added template support for osTicket - thanks **@madito**! +- Packages for phpMyAdmin, Roundcube, and Rainloop will be pulled directly from their upstream source instead of APT for new installations. +- Added DNS records view to mail domains which provides DKIM, SPF, and other entries to use with an external provider. +- Added an upgrade script to provide in-place upgrades to php7.4 (or any other version). +- Added Drupal and Nextcloud quick installer support (Removed placeholder Joomla) +- Added a new optional theme "Vestia" +- Added a switch to disable the API and also limit the api by default to 127.0.0.1 only. For current installs added the option "allow-all" on default +- After first reboot of Hestia will try do 1 attempt to request / generate a valid Lets encrypt certificate +- Introduced multiple new security policies via WebUI. + - Allow users to edit Web / Proxy / DNS / Backend templates + - Allow users to edit account details + - Allow suspended users to login with "read-only" access + - Allow users view / delete user history + - Enforce sub domain ownership + - Limit access to admin account when other users have the role "Administrator" assigned to them. +- Disable user to login via WebUI / Limit access to WebUI to certain IP address per user. +- Discourage websites to be created under "admin" account and redirect users to create new users. +- Added support for redirecting to www / non www domains (or custom) #427 / #1638. +- Allow users to see failed login attempts on there account. +- Introduced support for ARM based systems. Currently the packages are not available via ATP! +- Force reboot of system after install + +### Bugfixes + +- Fixed an issue where user name was duplicated when editing FTP users. (#1411) +- Fixed an issue where the iptables service would appear to be in a stopped state when fail2ban is stopped. (#1374) +- Fixed an issue where the default language value was incorrectly set under Server Settings > Configure. +- Fixed an issue with the dark theme where available updates were incorrectly displayed. +- Fixed an issue where local and FTP backup files were not deleted when running `v-delete-user-backup`. (#1421) +- Fixed an issue where IP addresses could not be deleted. (#1423) +- Fixed an issue where `v-rebuild-user` would incorrectly rebuild domain items in addition to user account configuration. +- Fixed an issue which caused a web domain's custom document root value to be lost when restoring from backup. +- Fixed an issue which caused a `NSPOSIXErrorDomain:100` error when using Safari/iOS (thanks **@stsimb**). +- Fixed an issue where exim ignored the configured mail quota limit. +- Fixed an issue where invalid character validation was performed when editing mail auto replies. +- Fixed an issue which caused Let's Encrypt to fail when using the Moodle template (thanks **@ArturoBlanco**). +- Fixed an issue where the MySQL `wait_timeout` value was not saved due to wrong regexp attribute (thanks **@guicapanema**). +- Fixed an issue where nginx web statistics authorization file was placed in the wrong directory. +- Fixed several small issues that were reported when using PostgreSQL. +- Improved reliability of mail domains and webmail clients. +- Improved reliability of service restarts during upgrades. +- Improved compatibility with Blesta / WHMCS plugins. +- Improved API error handling routines - thanks **@danielalexis**! +- Improved backup performance through the use of multi-threading when creating archives using the `zstd` compression type. +- Improved error handling when creating firewall rules. +- Improved handling of suspended users and domains to allow deletion without unsuspension. +- Improved dependencies over package control to install `lsb-release` and `zstd`. +- Improved SFTP connection handling to be case insensitive (thanks **@lazzurs**). +- Improved domain validation to prevent creating subdomains when the top-level domain belongs to another account (thanks **@KuJoe** and **@sickcodes**). +- Improved IDN domain handling to resolve issues with Let's Encrypt SSL and mail domain services. +- Added private folder to openbasedir permissions for all main templates. +- Disabled changing backup folder via Web UI because it used symbolic link instead of mount causing issues with restore mail / user files. +- Fixed XSS vulnerability in `v-add-sys-ip` and user history log (thanks **@numanturle**). +- Fixed remote code execution vulnerability which could occur when deleting SSH keys (thanks **@numanturle**). +- Fixed vulnerability in v-update-sys-hestia (thanks **@numanturle**) +- Disabled the Update via WebUI due to timeout issues. Please update via `apt update && apt upgrade` in command line instead. +- Improve how Quick install of web apps are handled and allow users added apps to be maintained in list view. +- Fixed an issue where the api was enabled after an update of HestiaCP +- Fixed an issue when the default php version got deleted webmail didn't work any more. #1477 +- Limit access when "demo" mode is enabled. +- Fixed an issue where limitations on aliases didn't work properly +- Fixed an issue where "Exit to control pannel" link got changed to "Logout" #1669 +- Allow packages to be deleted when in use. Current users are changed to "Default" package. +- Fixed multiple bugs with in v-restore-users +- Redesign statics page +- Allow self signed certificates to be created with aliases. +- Fixed issue where mail accounts where sorting incorrectly by size #1687 +- Improve results v-search-command #1703 +- Merge Codeiginiter / Drupal templates. +- Prepare template for FastCGI support an improve security by allowing only .well-known for Let's encrypt requests +- Update Cloudflare Ips in nginx.conf +- Fixed an issue where emails where send to nobody when connection failed to database #1765 +- Fixed an issue where no notifications where send on failure and save local backup if remote backup failed. +- Fixed an issue where domains containing 2 dots in the top level domain could accidentally got removed #1763 +- Fixed an issue where www could be created and after delete webmail doesn't work anymore #1746 +- Standardize headers for upgrade scripts +- Improved how we handle custom themes +- Refactored HMTL / PHP code WebUI +- Updated ClamAV configuration +- Fixed issue where file manger key got the wrong permissions +- Update version Laveral @mariojgt + +## [1.3.5] - Service Release + +### Features + +- No new features have been introduced in this release. + +### Bugfixes + +- Updated APT repository key for PHP from packages.sury.org () +- Updated phpMyAdmin to v5.1.0. + +## [1.3.4] - Service Release + +### Features + +- No new features have been introduced in this release. + +### Bugfixes + +- Fixed xss vulnerability in v-add-sys-ip and user history log (thanks **@numanturle**) +- Fixed remote execution possibility when deleting ssh key (thanks **@numanturle**) + +## [1.3.3] - Service Release + +### Bugfixes + +- Improved if web folder already exists and do not follow symlink on chmod (thanks @0xGsch and @kikoas1995). +- Improved api key authentification to prevent brute force attacks. +- Improved ssh keys folder permission to prevent unauthorized access. + +## [1.3.2] - Service Release + +### Features + +- Added PHP v8.0 support for multiphp environment. + +### Bugfixes + +- Improved session token handling in login as function, thanks to Vulnerability Laboratory - [Evolution Security GmbH]™. +- Fixed an where fpm pool config was not deleted when changing backend template. +- Improved bats testing with multiphp (5.6-8.0) tests. +- Fixed an issue where full webmail path was loaded as default value. + +## [1.3.1] - Service Release + +### Features + +- No new features have been introduced in this release. + +### Bugfixes + +- Fixed an issue where updates for `hestia-php` were incorrectly being marked as out-of-date in the UI due to a change in our servicing and package versioning scheme. +- Fixed an issue that occurred on the Updates page where the table row color of available updates would be difficult to read. +- Fixed an issue where an administrator would get stuck in a loop trying to navigate back after adding a SSH key. +- Fixed an issue where long table entries which exceeded the table length would overlap other UI elements. +- Fixed an issue where the total amount of items on a page would fail to display correctly. +- Improved the accuracy and reliability of tooltips throughout the the Control Panel UI: + - Removed unnecessary tooltips from buttons and other elements. + - Fixed incorrect tags which prevented tooltips from being displayed. + - Introduced tooltips to counter items on the Users, Packages, and Statistics pages to help better distinguish statistics. +- Improved the display of items, quotas, and suspended items in the Control Panel navigation header - thanks **@cmstew**! +- Fixed an issue which caused higher than normal CPU usage during an upgrade due to a duplicate condition in the rebuild process. +- Fixed minor spelling inconsistencies in command line script comments and output text. +- Fixed an issue where old configuration files were not cleaned up when moving domains with `v-change-domain-owner`. +- Fixed an issue where a `no backend template doesn't exist` could potentially would appear after upgrade with older templates (#1322). +- Introduced caching templates for nginx + php-fpm configurations - thanks **@cmstew**! +- Fixed an issue where DNS cluster updates could fail due to the format of a DKIM record in an available zone - thanks **@jrohde**! +- Improved the quality of comment formatting in command line scripts - thanks **@bisubus**! +- Fixed an issue where the logo was not displayed in the File Manager - thanks **@robothemes**! +- Fixed an issue in the Control Panel UI which caused databases and additional FTP accounts to be named incorrectly if manually prefaced with the username. +- Fixed an issue where custom document roots were not saved correctly. +- Improved the visibility of service availability in the Control Panel UI. +- Fixed an issue which let you unsuspend a cronjob on active demo mode. +- Updated DE, EN, ES, KO, NL and TR languages, thanks to @Wibol, Blackjack, @emrahkayihan, areo and @hahagu! +- Fixed an issue which let the auto compiler fail with local src builds. +- Added turkish language to system installers, thanks to @emrahkayihan! +- Fixed incorrect error message when using unknown domain with v-delete-domain. + +## [1.3.0] - Major Release (Feature / Quality Update) + +### Features + +- Users can now choose to point a domain to a different document root location (similar to domain parking). +- The software update process will now perform a system health check before proceeding with installation. +- Administrators now have control over software update notifications through the following settings in `$HESTIA/conf/hestia.conf` and through the Control Panel web interface: + - `UPGRADE_SEND_EMAIL` = Sends an email notification to primary admin account's email address + - `UPGRADE_SEND_EMAIL_LOG` = Sends installation log output to the primary admin account's email address +- The upgrade process will now save installation logs to the `/root/hst_backups` directory by default for post-install troubleshooting. + - **Note:** We may adjust this path in the future and will document such changes as they happen. +- We've introduced the ability to assign Administrator rights to other user accounts, enabling them to perform tasks under the Server Settings tab. +- We've introduced a more robust translation system which will allow us to provide higher quality translations in future releases. + - **Note:** Some country codes have been updated, as a result your language setting may default back to English after upgrading. +- For new installations, MariaDB 10.5 is now the default version. + - For existing installations, we've provided a manual post-install upgrade script. Please run `$HESTIA/install/upgrade/manual/upgrade_mariadb.sh` to migrate to MariaDB 10.5). +- The user interface theme has been set to "Dark" by default. This can be changed from **Server Settings > Configure > Basic Options > Appearance**. + - **Note:** The name of the default theme has not been adjusted, and the change to the "dark" theme only applies to new installations at this time. This behavior may be changed in a future release. + +### Bugfixes + +- Fixed a security issue where user password reset keys could potentially be gleaned from system process list - thanks **RACK911 LABS** +- Fixed an issue with passwords containing "`'`" - [Forum](https://forum.hestiacp.com/t/two-factor-authentication-issue-with-standard-user/1652/) +- Fixed an issue with database backups when the port was not specified (#1068) +- Fixed an issue where websites without SSL enabled would display the content of the first valid SSL enabled website (#1103) +- Fixed an issue that would occur when using the `--with-debs` flag with the installer due to an incorrect version check routine (#1110) +- Fixed an issue with incorrect permissions which would occur when restoring email accounts (#1114) +- Fixed an issue where the File Manager would apply the wrong permissions on new directories +- Fixed an issue that prevented successful restoration of SSL-enabled mail domains from a backup archive (#1069) +- Fixed an issue where the phpMyAdmin button would not work in the Control Panel Web UI (#1078) +- Fixed an issue where passwords were generated incorrectly (#1184) +- Fixed an issue in `v-add-sys-ip` to ensure IP configuration is set to the correct port - thanks **@madito** +- Fixed an issue that resulted in an extended loop condition when running `v-rebuild-all` +- Improved support for API key usage with the `v-add-remote-dns-host` command (#1265) +- Improved validation of free disk space when executing backup routine (#1115) +- Improved support for SSH key types other than RSA / DSA +- Improved reliability of backup function when removing remote locations (#1083) +- Improved spam filtering by adding additional known-dangerous file extensions in exim's blacklist (#1138) - thanks **@kpapad904** +- Updated Apache2 configuration to use Include with IncludeOptional (#1072) +- Removed the ability to log in as "root" (whic logged to the admin account, deemed no longer necessary) +- Add ca-certificates, software-properties-common to the dependencies (#1073 + [Forum](https://forum.hestiacp.com/t/hestiscp-fails-on-new-debian-9-vps/1623/8)) - thanks **@daniel-eder** +- Create .npm directory by default when creating new user accounts (#1113) - thanks **@hahagu** +- Improved accuracy of several UI translations (NL, DE, UK, RU, ES, IT, ZH-CN) - thanks **@myrevery** and other contributors for your work! +- Added `$restart` flag to `v-add-web-domain-backend` command (#1094) (#797) - thanks **@bright-soft** +- PostgreSQL: forbid the use of upper case (#1084) causing issues with backup / creating database or user +- Changed WordPress name in Quick Web App installer (#1074) +- Cleaned up entries used in the Google / Gmail DNS template - thanks **@madito** +- Enhanced ProFTPd support for TLS +- Refactored LXD compiler script +- Updated phpMyAdmin to version 5.0.4 + +## [1.2.4] - Service Release + +### Features + +- No new features have been introduced in this release. + +### Bugfixes + +- Fixes an issue on auto renewing let's encrypt certificates. + +## [1.2.3] - Service Release + +### Features + +- No new features have been introduced in this release. + +### Bugfixes + +- Fixes an issue where non-ASCII characters were rejected in the password field. + +## [1.2.2] - Service Release + +### Features + +- No new features have been introduced in this release. + +### Bugfixes + +- Create mailhelo.conf if it doesn't exist to prevent a error message during grep. +- Corrected the display of DNS record types to appear in alphabetical order. +- Fixed an issue where the DNS record type field would reset if an error occurred while adding a new DNS record. (#992) +- Fixed an issue where the DNS domain hint would not appear correctly when editing a DNS record. (#993) +- Fixed an issue where a DNS record would become malformed if changed from A to CNAME. (#988) +- Fixed an issue with the back button on the DNS records page. (#989) +- Fixed an issue where phpMyAdmin/phpPgAdmin would not load correctly due to an incorrect vhost configuration. (#970) +- Fixed an issue where malformed JSON output was returned when custom theme files are present. (#967) +- Fixed an error that would occur when running `v-change-user-php-cli` for the first time if .bash_aliases did not exist. (#960) +- Corrected an issue where tooltips were not displayed when hovering over the top level menu items. +- Improved handling of APT repository keys during installation. +- Reworked the Let's Encrypt renew functionality to skip removed aliases. +- Improved reliability of list handling when using IP lists. +- Enforce minimum password requirements with visual indication of password strength. +- Fixed an issue where user display name value was incorrectly set when changing packages. +- Improved installer version detection. +- Improved detection of MariaDB and MySQL services. + +## [1.2.1] - Service Release + +### Features + +- Consolidated First and Last Name fields to a singular name field to simply input. + - v-change-user-name will now accept both "First Last" (single argument) and First Last (two arguments) for backward compatibility. +- Removed ntpdate from new installations and enable systemd timesync daemon instead (thanks **@braewoods**) + +### Bugfixes + +- Fixed an issue where Composer would fail to install due to missing default directory. +- Corrected an issue where two-factor authentication validation was causing high CPU load during the login process. The login screen has been re-designed as a multi-step process (Username > Password > OTP PIN). +- Corrected an issue where text entry fields on the login screen were not automatically focused by default. +- Fixed an issue where RDNS value was incorrectly set if dig failed to resolve the server name. +- Fixed an issue where icons were pushed down in the header when using Bulgarian as the display language. (#932) +- Fixed an issue where new backups were not created when running v-schedule-user-backup-download. (#918) +- Fixed an issue where default configuration files and templates were not backed up correctly. +- Improved quality of default web domain templates for Drupal. (#916) +- Added missing strings to translation files (translations to follow). +- Corrected an issue where toolbars were out of place on the Mail and Firewall pages when using Bulgarian or Greek languages due to string length. +- Improved Spanish translations (thanks **@Wibol**) +- Improved German translations (thanks **@ronald-at**) +- Improved Russian translations (thanks **@Pleskan**) + +## [1.2.0] - Major Release (Feature / Quality Update) + +### Features + +- **NOTE:** Debian 8 is no longer supported as it has reached EOL (end-of-life) status. +- Added support for Ubuntu Server 20.04 LTS. +- Added File Manager functionality (with File Gator backend) with the ability to add or remove at any time (`v-add-sys-filemanager` and `v-delete-sys-filemanager`) +- Extended built-in firewall to support allowing or blocking traffic using IP lists. +- Improved Apache2 performance by switching to mpm_event instead mod_prefork by default for new installations. +- Added support for configuring individual TTL per DNS record. Thanks to **@jaapmarcus**! +- Updated translations for Polish (thanks to @RejectPL!), Dutch, French, German, and Italian (WIP). +- Added the ability to set the default PHP command line version per-user. +- Added geolocation support to awstats to improve traffic reports. +- Enabled Roundcube plugins newmail_notifier and zipdownload by default. +- Added HELO support for multiple domains and IPs. +- Added the ability to manage SSH keys from CLI and web interface. +- Added a manual migration script for apache2 mpm_event for existing installations/upgrades (`$HESTIA/install/upgrade/manual/migrate_mpm_event.sh`). +- Added BATS system for testing the functionality of Bash scripts (WIP). +- Added **v-change-sys-db-alias** to change phpMyAdmin and phpPgAdmin access points (`v-change-sys-db-alias pma/pga myCustomURL`). + +### Bugfixes + +- Prevent ability to change the password of a non-Hestia user account. Thanks to **Alexandre Zanni**! +- Adjust Let's Encrypt validation check for IDN domains, thanks to **@zanami**! +- Set backup download location on FTP/SFTP restore, thanks to **@Daniyal-Javani**! +- Stop trying to renew Let's Encrypt certificates after multiple consecutive failed attempts. Thanks to **@dpeca**! +- Fixed an issue with auto-logout when used behind Cloudflare proxy and reworked 2FA authentication part. Thanks to **@rmj-s**! +- Fixed an issue where changing an email account password would fail if similar account names were present. +- Fixed an issue where e-mail quota was not preserved when (un)suspending or rebuilding a mail account. +- Fixed an issue where SSH configuration was not saved currently when edited from the Web interface. +- Fixed an issue where DNS IP did not use NAT/Public IP when available after changing web domain IP. +- Fixed an issue that would occur when a user would attempt to recover their account when two-factor authentication is enabled. +- Fixed permission issues that were presented when restoring a user backup. +- Improved page load performance of Control Panel web interface. +- Use Sury.org repository for Apache2 packages. +- Improved compatibility with Roundcube and PHP 7.4. +- Restrict the ability to edit crontab service via Control Panel web interface. +- Check whether Nginx, Apache2 and MariaDB are selected for installation prior to adding third party repositories. +- Restrict public access to Apache2 server-status page. +- Remove duplicated set-cookie line in default fpm config. +- Ignore empty lines when listing firewall rules. +- Improved top-level navigation in the Control Panel web interface (Server tab has been moved next to the Notification icon). +- Corrected various minor user interface and theme issues. +- Cleanup temporary files when uploading custom SSL certificate from Web interface. +- Cleanup temporary files when adding/renewing Let's Encrypt SSL certificate. +- Cleanup temporary files after running v-list-sys-services. +- Removed some legacy code and unused assets. +- Don't calculate /home folder size in v-list-sys-info. +- Adjust v-list-sys-services to honor the changed fail2ban service name. +- Rework busy port validation in v-change-sys-port. +- Implement a validation function to verify the correct version in hestia.conf prior to installation. +- Introduced a delay when an incorrect username, password, or 2FA code has been entered repeatedly. +- Improved "Forgot password" function prevent brute force attacks. +- Fixed an issue where the backup update counter was not updated properly when v-delete-user-backup was executed. +- Fixed an issue with public\_(s)html file ownership. +- Fixed an issue with phpPgAdmin access. +- Fixed an issue where the wrong port was set for on certain configurations. +- Fixed an issue where Composer would fail to install. +- Fixed an issue where the selected theme was not immediately applied. +- Fixed an issue where HTTP-to-HTTPS redirection and HTTP Strict Transport Security (HSTS) events were not shown in the user history log. +- Fixed an issue where the web domain access log page was incorrectly formatted. +- Fixed an issue where awstats would show a HostAliases error if a web domain did not have any aliases. +- Fixed an issue where awstats configuration was not updated if web domain aliases were added or removed. +- Fixed an issue where user interface elements would overlap or display in the wrong place when using non-English locales. +- Fixed an issue where phpMyAdmin and phpPgAdmin were inaccessible from the Web UI if custom URLs had been set. +- Fixed an issue where mail SSL certificates were not restored properly from a backup archive. +- Fixed an issue where mail domain configuration files were not removed when the domain was deleted. +- Improved the functionality of `v-change-domain-owner` to correctly move mail domains and provide status output and logging/notifications. +- Improved the functionality of `v-update-sys-hestia-git` to allow user to specify GitHub repository and whether to build only core package or core and dependencies. +- Corrected the behavior of phpMyAdmin and phpPgAdmin so that alias dialogs accept custom word only and not full URL, aligns with webmail alias behavior. +- Corrected the behavior of the installer so that APT repositories are not added if installation is aborted due to version mismatch. +- Fixed an issue where upgrade procedures were not executed correctly when skipping between versions (e.g. 1.0.6 > 1.2.0). + +### Known issues and notes + +- **NOTE:** Custom phpMyAdmin and phpPgAdmin URL's will be reset once during this upgrade to correct a legacy code issue. +- Let's Encrypt renewal fails when removing alias from web domain (#856) +- Some translation strings need to be updated for accuracy (#746) +- v-restore-user only works with backup archives stored in /backup mount point (#641) + +## [1.1.1] - 2020-03-24 - Hotfix + +### Features + +- No new features introduced with v1.1.1, this is strictly a security/bug fix release. + +### Bugfixes + +- Fixed phpMyAdmin blowfish and tmp directory issues. +- Added additional verification of host domain in password reset. Thanks to @FalzoMAD and @mmetince! +- Fixed issue with rc.local not executing properly. +- Rework of Let's Encrypt routine to use progressive delay between validation retries. +- Fixed syntax issue in v-list-sys-db-status which prevented main functions from loading. +- Removed /home size reporting when running v-list-sys-info due to performance issues. +- Updated installer to use Ubuntu key server for Hestia APT repository. +- Fixed duplicate demo mode check in v-change-user-password. + +## [1.1.0] - 2020-03-11 - Major Release (Feature / Quality Update) + +### Features + +- Added support for custom user interface themes. +- Introduced official Dark and Flat themes. +- Added read-only/demo mode - DEMO_MODE must be set to yes in hestia.conf to enable. +- Added php-imagick module to installer and upgrade scripts. +- Added recidive filter function to fail2ban. +- Improved and refactored Multi-PHP functionality. +- Multi-PHP will be enabled by default on new installations. +- Allow admin user to add/remove PHP versions from Web UI (Server -> Configure -> Web Server). +- Extended v-extract-fs-archive to allow archive testing and extracting only specific paths (for tar) +- Allow renaming of existing packages from console (v-rename-package). +- Added PHP 7.4 to Multi-PHP. +- Addded official support for Debian 10 (Buster). + +### Bugfixes + +- Added a detection of web root for add .well-known ACME challenge. +- Reworked Let's Encrypt ACME staging to use Hestia code standards. +- Fixed issues with incorrect font rendering on Windows and Linux. +- Fixed issues with Let's Encrypt - use Nginx for Let's Encrypt ACME request if present. +- Reworked v-add-sys-ip, removed deprecated CentOS/Red Hat code and reworked conditions. +- Enabled HSTS and force SSL on v-add-letsencrypt-host. +- Removed hardcoded mail in HELO data (cosmetic fix). +- Fixed SFTP server validation check - thanks @dbannik. +- Implemented security warning message when creating web domains with the default admin account. +- Fixed wrong quotes used for default keys folder location in v-generate-api-key backend script. +- Fixed permissions to allow access for FTP users created in web domains under admin account. +- Check if user home directory exists before setting permissions on SFTP fail2ban jail. +- Fixed several reported security issues, thanks to Andrea Cardaci () +- Security fix: Command line arguments arguments were glob expanded when written to log file. +- Ensure that SFTP accounts remain configured in sshd when removing web domains/ +- Improved security by ensuring that file operations in user home folder will be executed as the real user. +- Added a confirmation dialog when deleting user logs. +- Fixed an issue where the SFTP fail2ban jail was not working correctly for user accounts which were restored from backup archives. +- Enhanced input validation in backend command line scripts. +- Improved page load performance by optimizing how the notifications list is loaded (in some cases, improvement measured from 1sec to under 100ms). +- Improved page load performance when loading IP ban rules in the Control Panel. +- Updated panel framework to use jQuery to 3.4.1. +- Fixed an issue with SFTP fail2ban jail due to missing user. +- Fixed an issue where remote backup hostname would reject an IP address without reverse DNS (PTR record). (#569) +- Create default writable folders in user home directory (#580). +- Added gnupg/gnupg2 check to prevent issues with pubkey installation. +- Fixed DNS nameserver validation when adding new packages. +- Implemented additional debug information for Let's Encrypt validation - thanks @shakaran. +- Disabled alerts for successful cronjob backups. +- Fixed an issue with suspending resources when logged in as a normal (non admin) user. +- Fixed an issue with unsuspending a user, PHP-FPM website pool configuration was being deleted. +- Fixed potential upgrade issue when using v-update-sys-hestia-git. +- Fixed corruption of global user stats when rebuilding a mail domain. +- Fixed formatting of backup exclusions textbox. +- Fixed MultiPHP upgrade script to update all web templates. +- Fixed report issue link in installer scripts. +- Fixed database user authentification on backup restore. +- Added robots.txt for Roundcube webmail to prevent search bot crawling. +- Re-Enable force ssl function on let's encrypt certification renew. +- Added official PostgreSQL repository so system stays up-to-date with latest available upstream packages. +- Hardening MySQL configuration, prevent local infile. +- Fixed lograte bug and cleans up the messed up nginx/apache2 log permissions. +- Fixed IfModule mpm_itk.c for apache2 templates. +- Added mpm_itk for Debian 10 (non Multi-PHP installations only.) +- Hardening nginx configuration, dropped support for TLSv1.1. +- Fixed excluding folders named "logs" from restore backup, thanks to @davidgolsen. +- Fixed typo in delete psql database part, thanks to @joshbmarshall. +- Split long txt records to 255 chunks to prevent bind issues, thanks to @setiseta. +- Fixed missing restart routine for vsftp on v-add-letsencrypt-host. +- Show amount of disk space consumed by /home when running v-list-sys-info. +- Remove broken /webmail alias from previous versions. +- Webmail IP address is now inherited from web domain when using multiple IPs. +- Exim now uses the web domain IP if it exists. +- Fixed incorrect MX record for DNS domains using the Office 365 template. + +## [1.0.6] - 2019-09-24 - Hotfix + +### Bugfixes + +- Add support for HTTP/2 Let's Encrypt Server. + +## [1.0.5] - 2019-08-06 - Hotfix + +### Bugfixes + +- Fixed several security issues, thanks to Andrea Cardaci () +- Rework Let's Encrypt ACME staging to use hestia conform standard. +- Fixed if condition, use nginx for Let's Encrypt ACME request if present. + +## [1.0.4] - 2019-07-09 - Hotfix + +### Bugfixes + +- Delayed start of services to prevent restart limit. + +## [1.0.3] - 2019-07-09 - Hotfix + +### Bugfixes + +- Fixed Let's Encrypt Mail SSL permission issue. + +## [1.0.1] - 2019-06-25 + +### Features + +- Improved support for Let's Encrypt certificate generation. +- v-add-letsencrypt-host: Added Let's Encrypt support for Control Panel's own SSL. +- Enabled use of per-domain SSL certificates for inbound and outbound mail services. +- Consolidated template structure, removing over 50% duplicate code. +- Re-organised file system structure for domain configuration files. +- Added the ability to change release branches through the user interface and the command line. +- v-sys-update-hestia-git: Added the ability to update using Git from the command line. +- Implemented support for SFTP chroot jails. +- A newly redesigned user interface which features: + - A softer color palette which better matches the Hestia Control Panel logo colors. + - A consolidated overview of domains and other information. + - Improved navigation paths to make things easier to find. + - Improved compatibility when viewing the Control Panel interface from a mobile device. +- Improved handling of mail domain DNS zone values. +- Enabled OCSP stapling on SSL-enabled web domains. +- v-change-web-domain-hsts: Enabled support for HTTP Strict Transport Security (HSTS) on SSL. +- Improved logging and console output during new installations and upgrades. + +### Bugfixes + +- Fixed issues with HTTP-to-HTTPS redirecton. +- Fixed an issue where another website would load if browsing to a non-SSL enabled domaing using HTTPS. + +## [1.0.0-190618] - 2019-06-25 + +### Features + +- + +### Bugfixes + +- + +## [0.9.8-28] - 2019-05-16 + +### Features + +- Implemented force SSL function for web domains. + +### Bugfixes + +- + +[1.0.4]: https://github.com/hestiacp/hestiacp/releases/tag/1.0.4 +[1.0.3]: https://github.com/hestiacp/hestiacp/releases/tag/1.0.3 +[1.0.1]: https://github.com/hestiacp/hestiacp/releases/tag/1.0.1 +[1.0.0-190618]: https://github.com/hestiacp/hestiacp/releases/tag/1.0.0-190618 +[0.9.8-28]: https://github.com/hestiacp/hestiacp/releases/tag/0.9.8-28 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..7d1c1b2 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,76 @@ +# Hestia Control Panel - Contribution Guidelines + +## Ways to contribute + +- **Beta testing**: + - Download and install builds from the `beta` branch. If you encounter an issue with a beta build, file an issue report on [GitHub](https://www.github.com/hestiacp/hestiacp/issues).
+ `v-update-sys-hestia-git hestiacp beta install` will install the latest beta build from our GitHub repository. +- **Code review and bug fixes**: + - Read over the code and if you notice errors (even spelling mistakes), submit a pull request with your changes. +- **New features**: + - Is there an awesome feature that you'd love to see included? Submit a pull request with your changes, and if approved your PR will be reviewed and merged for inclusion in an upcoming release. While our development team tries to accommodate all reasonable requests please remember that it does take time to develop, implement and test new features and as such we may not be able to fulfill all requests or may have to put a feature on backlog for a later date. +- **Translations**: + - If you are a non-English speaker and would like to improve the quality of the translations used in Hestia Control Panel's web interface, please go to [Hestia Translate](https://translate.hestiacp.com/projects/hestiacp/) to review the translations database. For more information please read [How to contribute with Translations](https://forum.hestiacp.com/t/how-to-contribute-with-translations/1664) on our forum. You can also open an issue report [GitHub](https://www.github.com/hestiacp/hestiacp/issues) highlighting the issue with the current translation so that it can be corrected. +- **Donations**: + - If you're not a developer but you still want to make a contribution to support Hestia Control Panel and our developers, you can make a donation to the Hestia Control Panel project to further its development (or if you'd just like to buy our developers a lunch, we'd appreciate that too). We currently accept donations through [PayPal](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=ST87LQH2CHGLA). + +## Development Guidelines + +Additional information on how to contribute to Hestia Control Panel can be found in the [Development](docs/docs/contributing/development.md) documentation. + +### Code formatting and comments + +We ask that you follow existing naming schemes and coding conventions where possible, and that you add comments in your source code where appropriate to aid other developers in debugging and understanding your code in the future. + +To ensure your changes meet our formatting requirements, please run `npm install` from the root of the repository before committing your changes. This will set up pre-commit hooks for automatic formatting, which will help to get your changes merged as quickly as possible. + +### Workflow and process + +Development for this project takes place in branches to effectively develop, manage, and test new features and code changes. Our tiered approach allows us to closely control the quality of code as it is checked in for inclusion. + +We have three primary or "evergreen" branches, which exist throughout our product's lifetime. Please refer to the following table for a description: + +| Branch | Description | +| --------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------: | +| `main` | Contains a snapshot of the latest development code.
**Not intended for production use and contains code from a merge snapshot.** | +| `beta` | Contains a snapshot of the next version which is currently in testing.
**Not intended for production use, however code from this branch should be stable.** | +| `release` | Contains a snapshot of the latest stable release.
**Intended for production use. This repository contains the same code as our compiled packages.** | + +### Creating a new branch and submitting pull requests + +The first step is to create a fork of the `hestiacp/hestiacp` repository under your GitHub account so that you may submit pull requests and patches. + +Once you've created your fork, clone the repository to your computer and make sure that you've checked out the `main` branch. **Always** create a new topic branch for your work. + +### Branch naming convention + +- **Prefix:** `topic/` (such as **fix**, **feature**, **refactor**, etc.) +- **ID**: `888` (GitHub Issue ID if an issue exists) +- **Title:** `my-awesome-patch` + +Branch name examples: + +- `feature/777-my-awesome-new-feature` or `feature/my-other-new-feature` +- `fix/000-some-bug-fix` or `fix/this-feature-is-broken` +- `refactor/v-change-domain-owner` +- `test/mail-domain-ssl` + +### Squashing commits for smaller changes + +To aid other developers and keep the project's commit history clean, please **squash your commits** when it's appropriate. For example with smaller commits related to the same piece of code, such as commits labelled "Fixed item 1", "Adjusted color of button XYZ", "Adjusted alignment of button XYZ" can be squashed into one commit with the title "Fixed button issues in item". + +### What happens when I submit a pull request? + +- Our internal development team will review your work and validate your request. +- Your changes will be tested to ensure that there are no issues. +- If changes need to be made, you will be notified via GitHub. +- Once approved, your code will be merged for inclusion in an upcoming release of Hestia Control Panel. + +All pull requests must include a brief but descriptive title, and a detailed description of the changes that you've made. **Only include commits that are related to your feature, bug fix, or patch in your pull request!** + +## Thank you + +We appreciate **all** contributions no matter what size; your feedback and input directly shapes the future of Hestia Control Panel and we could not do it without your support. + +Thank you for your time and we look forward to seeing your pull requests,
+The Hestia Control Panel development team diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..94a9ed0 --- /dev/null +++ b/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/README.md b/README.md new file mode 100644 index 0000000..7b4585a --- /dev/null +++ b/README.md @@ -0,0 +1,138 @@ +

Hestia Control Panel

+ +![HestiaCP Web Interface screenshot](https://storage.hestiacp.com/hestiascreen.png) + +

Lightweight and powerful control panel for the modern web

+ +

Latest stable release: Version 1.8.2 | View Changelog

+ +

+ HestiaCP.com | + Documentation | + Forum +

+ + Drone Status + + + Lint Status + +

+ +## **Welcome!** + +Hestia Control Panel is designed to provide administrators an easy to use web and command line interface, enabling them to quickly deploy and manage web domains, mail accounts, DNS zones, and databases from one central dashboard without the hassle of manually deploying and configuring individual components or services. + +## Donate + +[![paypal](https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=ST87LQH2CHGLA)

+Bitcoin : bc1q48jt5wg5jaj8g9zy7c3j03cv57j2m2u5anlutu
+Ethereum : 0xfF3Dd2c889bd0Ff73d8085B84A314FC7c88e5D51
+Binance: bnb1l4ywvw5ejfmsgjdcx8jn5lxj7zsun8ktfu7rh8
+Smart Chain: 0xfF3Dd2c889bd0Ff73d8085B84A314FC7c88e5D51
+ +## Features and Services + +- Apache2 and NGINX with PHP-FPM +- Multiple PHP versions (5.6 - 8.2, 8.0 as default) +- DNS Server (Bind) with clustering capabilities +- POP/IMAP/SMTP mail services with Anti-Virus, Anti-Spam, and Webmail (ClamAV, SpamAssassin, Sieve, Roundcube) +- MariaDB/MySQL and/or PostgreSQL databases +- Let's Encrypt SSL support with wildcard certificates +- Firewall with brute-force attack detection and IP lists (iptables, fail2ban, and ipset). + +## Supported platforms and operating systems + +- **Debian:** 12, 11, or 10 +- **Ubuntu:** 22.04 LTS, 20.04 LTS + +**NOTES:** + +- Hestia Control Panel does not support 32 bit operating systems! +- Hestia Control Panel in combination with OpenVZ 7 or lower might have issues with DNS and/or firewall. If you use a Virtual Private Server we strongly advice you to use something based on KVM or LXC! + +## Installing Hestia Control Panel + +- **NOTE:** You must install Hestia Control Panel on top of a fresh operating system installation to ensure proper functionality. + +While we have taken every effort to make the installation process and the control panel interface as friendly as possible (even for new users), it is assumed that you will have some prior knowledge and understanding in the basics how to set up a Linux server before continuing. + +### Step 1: Log in + +To start the installation, you will need to be logged in as **root** or a user with super-user privileges. You can perform the installation either directly from the command line console or remotely via SSH: + +```bash +ssh root@your.server +``` + +### Step 2: Download + +Download the installation script for the latest release: + +```bash +wget https://raw.githubusercontent.com/hestiacp/hestiacp/release/install/hst-install.sh +``` + +If the download fails due to an SSL validation error, please be sure you've installed the ca-certificate package on your system - you can do this with the following command: + +```bash +apt-get update && apt-get install ca-certificates +``` + +### Step 3: Run + +To begin the installation process, simply run the script and follow the on-screen prompts: + +```bash +bash hst-install.sh +``` + +You will receive a welcome email at the address specified during installation (if applicable) and on-screen instructions after the installation is completed to log in and access your server. + +### Custom installation + +You may specify a number of various flags during installation to only install the features in which you need. To view a list of available options, run: + +```bash +bash hst-install.sh -h +``` + +Alternatively, You can use which allows you to easily generate the installation command via GUI. + +## How to upgrade an existing installation + +Automatic Updates are enabled by default on new installations of Hestia Control Panel and can be managed from **Server Settings > Updates**. To manually check for and install available updates, use the apt package manager: + +```bash +apt-get update +apt-get upgrade +``` + +## Issues & Support Requests + +- If you encounter a general problem while using Hestia Control Panel and need help, please [visit our forum](https://forum.hestiacp.com/) to search for potential solutions or post a new thread where community members can assist. +- Bugs and other reproducible issues should be filed via GitHub by [creating a new issue report](https://github.com/hestiacp/hestiacp/issues) so that our developers can investigate further. Please note that requests for support will be redirected to our forum. + +**IMPORTANT: We _cannot_ provide support for requests that do not describe the troubleshooting steps that have already been performed, or for third-party applications not related to Hestia Control Panel (such as WordPress). Please make sure that you include as much information as possible in your forum posts or issue reports!** + +## Contributions + +If you would like to contribute to the project, please [read our Contribution Guidelines](https://github.com/hestiacp/hestiacp/blob/release/CONTRIBUTING.md) for a brief overview of our development process and standards. + +## Copyright + +"Hestia Control Panel", "HestiaCP", and the Hestia logo are original copyright of hestiacp.com and the following restrictions apply: + +**You are allowed to:** + +- use the names "Hestia Control Panel", "HestiaCP", or the Hestia logo in any context directly related to the application or the project. This includes the application itself, local communities and news or blog posts. + +**You are not allowed to:** + +- sell or redistribute the application under the name "Hestia Control Panel", "HestiaCP", or similar derivatives, including the use of the Hestia logo in any brand or marketing materials related to revenue generating activities, +- use the names "Hestia Control Panel", "HestiaCP", or the Hestia logo in any context that is not related to the project, +- alter the name "Hestia Control Panel", "HestiaCP", or the Hestia logo in any way. + +## License + +Hestia Control Panel is licensed under [GPL v3](https://github.com/hestiacp/hestiacp/blob/release/LICENSE) license, and is based on the [VestaCP](https://vestacp.com/) project.
diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..a605973 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,51 @@ +# Hestia CP Security policy + +Welcome and thanks for taking interest in Hestia CP! + +We are mostly interested in reports by actual Hestia CP users but all high quality contributions are welcome. + +If you believe that you have have discovered a vulnerability in Hestia Control Panel, +please let our development team know by submitting a report [Huntr.dev](https://huntr.dev/bounties/disclose/?target=https://github.com/hestiacp/hestiacp) Bounties and CVEs are automatically managed and allocated via the platform. + +If you are unable to use [Huntr.dev](https://huntr.dev/bounties/disclose/?target=https://github.com/hestiacp/hestiacp) please send an email to + +We ask you to include a detailed description of the vulnerability, a list of services involved (e.g. exim, dovecot) and the versions which you've tested, full steps to reproduce the vulnerability, and include your findings and expected results. + +Please do not open any public issue on Github or any other social media before the report has been published and a fix has been released. + +With that, good luck hacking us ;) + +## Supported versions + +| Version | Supported | +| ------- | ------------------ | +| Latest | :white_check_mark: | + +## Qualifying Vulnerabilities + +### Vulnerabilities we really care about + +- Remote command execution +- Code/SQL Injection +- Authentication bypass +- Privilege Escalation +- Cross-site scripting (XSS) +- Performing limited admin actions without authorization +- CSRF + +### Vulnerabilities we accept + +- Open redirects +- Password brute-forcing that circumvents rate limiting + +## Non-Qualifying Vulnerabilities + +- Theoretical attacks without proof of exploitability +- Attacks that are the result of a third party library should be reported to the library maintainers +- Social engineering +- Reflected file download +- Physical attacks +- Weak SSL/TLS/SSH algorithms or protocols +- Attacks involving physical access to a user’s device, or involving a device or network that’s already seriously compromised (eg man-in-the-middle). +- The user attacks themselves +- anything in `/test/` folder diff --git a/bin/v-acknowledge-user-notification b/bin/v-acknowledge-user-notification new file mode 100755 index 0000000..c63cd89 --- /dev/null +++ b/bin/v-acknowledge-user-notification @@ -0,0 +1,81 @@ +#!/bin/bash +# info: update user notification +# options: USER NOTIFICATION +# +# example: v-acknowledge-user-notification +# +# This function updates user notification. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +id=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER NOTIFICATION' +if [ "$id" = "all" ]; then + is_format_valid 'user' +else + is_format_valid 'user' 'id' +fi +is_object_valid 'user' 'USER' "$user" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Updating notification +if [ "$id" = 'all' ]; then + for id in $(v-list-user-notifications admin plain | cut -f1); do + update_object_value 'notifications' 'NID' "$id" '$ACK' 'yes' 2> /dev/null + done +else + update_object_value 'notifications' 'NID' "$id" '$ACK' 'yes' 2> /dev/null + + # Checking last notification + if [ -e "$USER_DATA/notifications.conf" ]; then + if [ -z "$(grep NID= $USER_DATA/notifications.conf)" ]; then + notice='no' + fi + if [ -z "$(grep "ACK='no'" $USER_DATA/notifications.conf)" ]; then + notice='no' + fi + else + notice='no' + fi +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Updating notification counter +if [ "$notice" = 'no' ]; then + if [ -z "$(grep NOTIFICATIONS $USER_DATA/user.conf)" ]; then + sed -i "s/^TIME/NOTIFICATIONS='no'\nTIME/g" $USER_DATA/user.conf + else + update_user_value "$user" '$NOTIFICATIONS' "no" + fi +fi + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-add-access-key b/bin/v-add-access-key new file mode 100755 index 0000000..0e624a2 --- /dev/null +++ b/bin/v-add-access-key @@ -0,0 +1,106 @@ +#!/bin/bash +# info: generate access key +# options: USER [PERMISSIONS] [COMMENT] [FORMAT] +# +# example: v-add-access-key admin v-purge-nginx-cache,v-list-mail-accounts comment json +# +# The "PERMISSIONS" argument is optional for the admin user only. +# This function creates a key file in $HESTIA/data/access-keys/ + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +permissions=$2 +comment=$3 +format=${4-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +keygen() { + local LENGTH=${1:-20} + local USE_SPECIAL_CHARACTERS="${2:-no}" + + local MATRIX='0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz' + if [[ "$USE_SPECIAL_CHARACTERS" == "yes" ]]; then + MATRIX+='_-=' + fi + + local PASS N + while [ ${N:=1} -le $LENGTH ]; do + PASS="$PASS${MATRIX:$(($RANDOM % ${#MATRIX})):1}" + let N+=1 + done + + echo "$PASS" +} + +access_key_id="$(keygen)" +secret_access_key="$(keygen 40 yes)" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +# Remove whitespace and bin path from permissions +permissions="$(cleanup_key_permissions "$permissions")" + +time_n_date=$(date +'%T %F') +time=$(echo "$time_n_date" | cut -f 1 -d \ ) +date=$(echo "$time_n_date" | cut -f 2 -d \ ) + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'USER [PERMISSIONS] [COMMENT] [FORMAT]' +is_format_valid 'user' 'comment' 'format' +is_object_valid 'user' 'USER' "$user" +is_key_permissions_format_valid "$permissions" "$user" + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +if [ ! -d "$HESTIA/data/access-keys/" ]; then + mkdir -p $HESTIA/data/access-keys/ + chown root:root $HESTIA/data/access-keys/ + chmod 750 $HESTIA/data/access-keys/ +fi + +if [[ -e "$HESTIA/data/access-keys/${access_key_id}" ]]; then + while [[ -e "$HESTIA/data/access-keys/${access_key_id}" ]]; do + access_key_id=$(keygen) + done +fi + +echo "SECRET_ACCESS_KEY='$secret_access_key'" > "$HESTIA/data/access-keys/${access_key_id}" +echo "USER='$user'" >> "$HESTIA/data/access-keys/${access_key_id}" +echo "PERMISSIONS='$permissions'" >> "$HESTIA/data/access-keys/${access_key_id}" +echo "COMMENT='$comment'" >> "$HESTIA/data/access-keys/${access_key_id}" +echo "TIME='$time'" >> "$HESTIA/data/access-keys/${access_key_id}" +echo "DATE='$date'" >> "$HESTIA/data/access-keys/${access_key_id}" +# TODO Index reserved for future implementation +echo "EXPIRES_IN=''" >> "$HESTIA/data/access-keys/${access_key_id}" +echo "IP=''" >> "$HESTIA/data/access-keys/${access_key_id}" + +chmod 640 "$HESTIA/data/access-keys/${access_key_id}" + +$BIN/v-list-access-key "$access_key_id" "$format" + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +log_history "Access key $access_key_id generated" "Warning" "$user" "API" +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-add-backup-host b/bin/v-add-backup-host new file mode 100755 index 0000000..f5781a9 --- /dev/null +++ b/bin/v-add-backup-host @@ -0,0 +1,344 @@ +#!/bin/bash +# info: add backup host +# options: TYPE HOST USERNAME PASSWORD [PATH] [PORT] +# +# example: v-add-backup-host sftp backup.acme.com admin p4$$w@Rd +# v-add-backup-host b2 bucketName keyID applicationKey +# +# Add a new remote backup location. Currently SFTP, FTP and Backblaze are supported + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +type=$1 +host=$2 +user=$3 +raw_password=$4 +HIDE=4 +password=$(perl -e 'print quotemeta shift(@ARGV)' "${raw_password}") +path=${5-/backup} +port=$6 + +# CPU Architecture +arch=$(arch) + +# Includes +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" +# Fetch current verison B2 CLI tool +source_conf "$HESTIA/install/upgrade/upgrade.conf" + +# Paths +b2cli="/usr/local/bin/b2" +b2lnk="https://github.com/Backblaze/B2_Command_Line_Tool/releases/download/v$b2_v/b2-linux" + +# Defining ftp command function +ftpc() { + ftp -p -n $host $port << EOF + quote USER $user + quote PASS $password + binary + $1 + $2 + $3 + quit +EOF +} + +# Defining sftp command function +sftpc() { + if [ "$privatekey" != "yes" ]; then + expect -f "-" "$@" << EOF + set count 0 + spawn /usr/bin/sftp -o StrictHostKeyChecking=no -o Port=$port $user@$host + expect { + -nocase "password:" { + send "$password\r" + exp_continue + } + + -re "Password for (.*)@(.*)" { + send "$password\r" + exp_continue + } + + -re "Couldn't|(.*)disconnect|(.*)stalled|(.*)not found" { + set count \$argc + set output "Disconnected." + set rc $E_FTP + exp_continue + } + + -re ".*denied.*(publickey|password)." { + set output "Permission denied, wrong publickey or password." + set rc $E_CONNECT + } + + "sftp>" { + if {\$count < \$argc} { + set arg [lindex \$argv \$count] + send "\$arg\r" + incr count + } else { + send "exit\r" + set output "Disconnected." + if {[info exists rc] != 1} { + set rc $OK + } + } + exp_continue + } + + timeout { + set output "Connection timeout." + set rc $E_CONNECT + } + } + + if {[info exists output] == 1} { + puts "\$output" + } + + exit \$rc +EOF + else + expect -f "-" "$@" << EOF + set count 0 + spawn /usr/bin/sftp -o StrictHostKeyChecking=no -o Port=$port -i $raw_password $user@$host + expect { + + -re "Couldn't|(.*)disconnect|(.*)stalled|(.*)not found" { + set count \$argc + set output "Disconnected." + set rc $E_FTP + exp_continue + } + + -re ".*denied.*(publickey|password)." { + set output "Permission denied, wrong publickey or password." + set rc $E_CONNECT + } + + "sftp>" { + if {\$count < \$argc} { + set arg [lindex \$argv \$count] + send "\$arg\r" + incr count + } else { + send "exit\r" + set output "Disconnected." + if {[info exists rc] != 1} { + set rc $OK + } + } + exp_continue + } + + timeout { + set output "Connection timeout." + set rc $E_CONNECT + } + } + + if {[info exists output] == 1} { + puts "\$output" + } + + exit \$rc +EOF + fi +} + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +if [ "$type" != 'local' ]; then + check_args '2' "$#" "TYPE HOST USERNAME PASSWORD [PATH] [PORT]" + is_format_valid 'host' 'path' 'port' + is_type_valid 'sftp,ftp,b2,rclone' "$type" + is_username_format_valid "$user" "username" + privatekey="no" + if [ -f "$raw_password" ]; then + if [[ $(cat "$raw_password" | grep "OPENSSH PRIVATE") ]]; then + privatekey="yes" + password="$raw_password" + else + is_password_valid + fi + else + is_password_valid + fi + format_no_quotes "$password" "password" + + if [ "$type" = 'sftp' ]; then + which expect > /dev/null 2>&1 + check_result $? "expect command not found" "$E_NOTEXIST" + fi + if [ "$type" != 'b2' ] && [ "$type" != 'rclone' ]; then + if ! (is_ip_format_valid "$host" > /dev/null); then + host "$host" > /dev/null 2>&1 + check_result $? "host connection failed" "$E_CONNECT" + fi + fi +fi + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Checking network connection +if [ "$type" = 'ftp' ]; then + if [ -z $port ]; then + port=21 + fi + fconn=$(ftpc 2>&1) + ferror=$(echo $fconn \ + | grep -i -e failed -e error -e "can't" -e "not conn" -e "incorrect") + if [ -n "$ferror" ]; then + echo "Error: can't login to ftp $user@$host" + log_event "$E_CONNECT" "$ARGUMENTS" + exit "$E_CONNECT" + fi + + # Checking write permissions + if [ -z $path ]; then + ftmpdir="vst.bK76A9SUkt" + else + ftpc "mkdir $path" > /dev/null 2>&1 + ftmpdir="$path/vst.bK76A9SUkt" + fi + ftp_result=$(ftpc "mkdir $ftmpdir" "rm $ftmpdir" | grep -v Trying) + if [ -n "$ftp_result" ]; then + echo "$ftp_result" + rm -rf $tmpdir + echo "Error: can't create $ftmpdir folder on the ftp" + log_event "$E_FTP" "$ARGUMENTS" + exit "$E_FTP" + fi +fi + +if [ "$type" = 'sftp' ]; then + if [ -z $port ]; then + port=22 + fi + if [ -z $path ]; then + sftmpdir="vst.bK76A9SUkt" + sftpc "mkdir $sftmpdir" "rmdir $sftmpdir" > /dev/null 2>&1 + else + if sftpc "mkdir $path" > /dev/null 2>&1; then + sftmpdir="$path/vst.bK76A9SUkt" + sftpc "mkdir $sftmpdir" "rmdir $sftmpdir" > /dev/null 2>&1 + else + sftmpdir="$path/vst.bK76A9SUkt" + sftpc "mkdir $sftmpdir" "rmdir $sftmpdir" > /dev/null 2>&1 + fi + fi + rc=$? + if [[ "$rc" != 0 ]]; then + case $rc in + $E_CONNECT) echo "Error: can't login to sftp $user@$host" ;; + $E_FTP) echo "Error: can't create temp folder on the sftp host" ;; + esac + log_event "$rc" "$ARGUMENTS" + exit "$rc" + fi +fi + +if [ "$type" = 'b2' ]; then + # Download b2 binary + if [ ! -f "$b2cli" ]; then + if [ "$arch" = 'aarch64' ] || [ "$arch" = 'arm64' ]; then + echo "Error: B2 binary for arm64 must be downloaded manually." + exit 3 + else + wget -O $b2cli $b2lnk > /dev/null 2>&1 + chmod +x $b2cli > /dev/null 2>&1 + fi + if [ ! -f "$b2cli" ]; then + echo "Error: Binary download failed, b2 doesn't work as expected." + exit 3 + fi + fi + + # Validate b2 binary + b2version="$(b2 version)" + if [[ ! "$b2version" =~ "b2 command line tool" ]]; then + echo "Error: Binary download failed, b2 doesn't work as expected." + exit 3 + fi + + b2 clear-account > /dev/null 2>&1 + b2 authorize-account "$user" "$raw_password" > /dev/null 2>&1 + b2 ls --long "$host" "$user" > /dev/null 2>&1 + + if [ $? -ne 0 ]; then + check_result "$E_CONNECT" "b2 failed to verify connection" + fi +fi + +if [ "$type" = 'rclone' ]; then + curl -s https://rclone.org/install.sh | bash /dev/null > /dev/null 2>&1 + # Verify account exists + if [ ! -z "$(cat /root/.config/rclone/rclone.conf | grep "\[$host\]")" ]; then + echo "test" > /tmp/hestia-backup.txt + # Try to upload a single file + if [ -z "$path" ]; then + rclone copy /tmp/hestia-backup.txt $host:/hestia-backup.txt + rclone delete $host:/hestia-backup.txt + else + rclone copy /tmp/hestia-backup.txt $host:$path/hestia-backup.txt + rclone delete $host:$path/hestia-backup.txt + fi + else + check_result "$E_CONNECT" "Rclone config does not exist" + fi +fi + +# Adding backup host +if [ $type == 'ftp' ] || [ $type = 'sftp' ]; then + new_timestamp + str="HOST='$host'\nUSERNAME='$user'\nPASSWORD='$password'\nPRIVATEKEY='$privatekey'" + str="$str\nBPATH='$path'\nPORT='$port'\nTIME='$time'\nDATE='$date'" + echo -e "$str" > $HESTIA/conf/$type.backup.conf + chmod 660 $HESTIA/conf/$type.backup.conf +elif [ $type == 'b2' ]; then + new_timestamp + str="BUCKET='$host'\nB2_KEYID='$user'\nB2_KEY='$raw_password'" + str="$str\nTIME='$time'\nDATE='$date'" + echo -e "$str" > $HESTIA/conf/$type.backup.conf + chmod 660 $HESTIA/conf/$type.backup.conf +elif [ $type == "rclone" ]; then + new_timestamp + str="HOST='$host'\nBPATH='$path'" + str="$str\nTIME='$time'\nDATE='$date'" + echo -e "$str" > $HESTIA/conf/$type.backup.conf +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Update hestia.conf +if [ -z "$(grep BACKUP_SYSTEM $HESTIA/conf/hestia.conf)" ]; then + echo "BACKUP_SYSTEM='$type'" >> $HESTIA/conf/hestia.conf +else + bckp=$(echo "$BACKUP_SYSTEM,$type" \ + | sed "s/,/\n/g" \ + | sort -r -u \ + | sed "/^$/d" \ + | sed ':a;N;$!ba;s/\n/,/g') + sed -i "s/BACKUP_SYSTEM=.*/BACKUP_SYSTEM='$bckp'/g" $HESTIA/conf/hestia.conf +fi + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-add-cron-hestia-autoupdate b/bin/v-add-cron-hestia-autoupdate new file mode 100755 index 0000000..f02ff48 --- /dev/null +++ b/bin/v-add-cron-hestia-autoupdate @@ -0,0 +1,99 @@ +#!/bin/bash +# info: add cron job for hestia automatic updates +# options: MODE +# +# This function adds a cronjob for hestia automatic updates +# that can be downloaded from apt or git. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=admin +mode=$1 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +is_system_enabled "$CRON_SYSTEM" 'CRON_SYSTEM' +is_package_full 'CRON_JOBS' +get_next_cronjob +check_cron_apt=$(grep 'v-update-sys-hestia-all' $USER_DATA/cron.conf) +check_cron_git=$(grep 'v-update-sys-hestia-git' $USER_DATA/cron.conf) +if [ -n "$check_cron_apt" ] || [ -n "$check_cron_git" ]; then + exit +fi + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Generating timestamp +time_n_date=$(date +'%T %F') +time=$(echo "$time_n_date" | cut -f 1 -d \ ) +date=$(echo "$time_n_date" | cut -f 2 -d \ ) + +# Define time somewhere at night +if [ -z "$mode" ] || [ "$mode" = "apt" ]; then + min=$(generate_password '012345' '2') + hour=$(generate_password '1234567' '1') + day='*' + month='*' + wday='*' + command="sudo $BIN/v-update-sys-hestia-all" +fi + +if [ "$mode" = "git" ]; then + min='0' + hour='0' + day='*' + month='*' + wday='*' + command="sudo $BIN/v-update-sys-hestia-git" +fi + +# Concatenating cron string +str="JOB='$job' MIN='$min' HOUR='$hour' DAY='$day' MONTH='$month' WDAY='$wday'" +str="$str CMD='$command' SUSPENDED='no' TIME='$time' DATE='$date'" + +# Adding to crontab +echo "$str" >> $HESTIA/data/users/$user/cron.conf + +# Changing permissions +chmod 660 $HESTIA/data/users/$user/cron.conf + +# Sort jobs by id number +sort_cron_jobs + +# Sync cronjobs with system cron +sync_cron_jobs + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Increasing cron value +increase_user_value "$user" '$U_CRON_JOBS' + +# Restarting cron +$BIN/v-restart-cron +check_result $? "Cron restart failed" > /dev/null + +# Logging +$BIN/v-log-action "system" "Info" "Updates" "Automatic updates enabled." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-add-cron-job b/bin/v-add-cron-job new file mode 100755 index 0000000..53469c6 --- /dev/null +++ b/bin/v-add-cron-job @@ -0,0 +1,93 @@ +#!/bin/bash +# info: add cron job +# options: USER MIN HOUR DAY MONTH WDAY COMMAND [JOB] [RESTART] +# +# example: v-add-cron-job admin * * * * * sudo /usr/local/hestia/bin/v-backup-users +# +# This function adds a job to cron daemon. When executing commands, any output +# is mailed to user's email if parameter REPORTS is set to 'yes'. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +min=$2 +hour=$3 +day=$4 +month=$5 +wday=$6 +command=$(echo $7 | sed "s/'/%quote%/g") +job=$8 +restart=$9 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +HIDE=7 + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '7' "$#" 'USER MIN HOUR DAY MONTH WDAY COMMAND [JOB] [RESTART]' +is_format_valid 'user' 'min' 'hour' 'day' 'month' 'wday' 'command' +is_system_enabled "$CRON_SYSTEM" 'CRON_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_package_full 'CRON_JOBS' +get_next_cronjob +is_format_valid 'job' +is_format_valid 'restart' +is_object_new 'cron' 'JOB' "$job" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Generating timestamp +time_n_date=$(date +'%T %F') +time=$(echo "$time_n_date" | cut -f 1 -d \ ) +date=$(echo "$time_n_date" | cut -f 2 -d \ ) + +# Concatenating cron string +str="JOB='$job' MIN='$min' HOUR='$hour' DAY='$day' MONTH='$month' WDAY='$wday'" +str="$str CMD='$command' SUSPENDED='no' TIME='$time' DATE='$date'" + +# Adding to crontab +echo "$str" >> $HESTIA/data/users/$user/cron.conf + +# Changing permissions +chmod 660 $HESTIA/data/users/$user/cron.conf + +# Sort jobs by id number +sort_cron_jobs + +# Sync cronjobs with system crond +sync_cron_jobs + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Increasing cron value +increase_user_value $user '$U_CRON_JOBS' + +# Restarting cron +$BIN/v-restart-cron "$restart" +check_result $? "Cron restart failed" > /dev/null + +# Logging +$BIN/v-log-action "$user" "Info" "Cron Jobs" "Cron job added (ID: $job, Command: $command)" +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-add-cron-letsencrypt-job b/bin/v-add-cron-letsencrypt-job new file mode 100755 index 0000000..a3dafb1 --- /dev/null +++ b/bin/v-add-cron-letsencrypt-job @@ -0,0 +1,46 @@ +#!/bin/bash +# info: add cron job for Let's Encrypt certificates +# options: NONE +# +# This function adds a new cron job for Let's Encrypt. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +is_system_enabled "$CRON_SYSTEM" 'CRON_SYSTEM' + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Add cron job +cmd="sudo $BIN/v-update-sys-queue letsencrypt" +check_cron=$(grep "$cmd" $HESTIA/data/users/admin/cron.conf 2> /dev/null) +if [ -z "$check_cron" ] && [ -n "$CRON_SYSTEM" ]; then + $BIN/v-add-cron-job admin '*/5' '*' '*' '*' '*' "$cmd" +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-add-cron-reports b/bin/v-add-cron-reports new file mode 100755 index 0000000..4010568 --- /dev/null +++ b/bin/v-add-cron-reports @@ -0,0 +1,60 @@ +#!/bin/bash +# info: add cron reports +# options: USER +# +# example: v-add-cron-reports admin +# +# This function for enabling reports on cron tasks and administrative +# notifications. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'USER' +is_format_valid 'user' +is_system_enabled "$CRON_SYSTEM" 'CRON_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Changing user report value +update_user_value "$user" '$CRON_REPORTS' 'yes' + +# Sync system cron with user +sync_cron_jobs + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Restart cron +$BIN/v-restart-cron +check_result $? "Cron restart failed" > /dev/null + +# Logging +$BIN/v-log-action "$user" "Info" "Cron Jobs" "Cron job notifications and reporting enabled." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-add-cron-restart-job b/bin/v-add-cron-restart-job new file mode 100755 index 0000000..ae6a306 --- /dev/null +++ b/bin/v-add-cron-restart-job @@ -0,0 +1,46 @@ +#!/bin/bash +# info: add cron reports +# options: NONE +# +# This function for enabling restart cron tasks + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +is_system_enabled "$CRON_SYSTEM" 'CRON_SYSTEM' + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Add cron job +cmd="sudo $BIN/v-update-sys-queue restart" +check_cron=$(grep "$cmd" $HESTIA/data/users/admin/cron.conf 2> /dev/null) +if [ -z "$check_cron" ] && [ -n "$CRON_SYSTEM" ]; then + $BIN/v-add-cron-job admin '*' '*' '*' '*' '*' "$cmd" +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-add-database b/bin/v-add-database new file mode 100755 index 0000000..691b164 --- /dev/null +++ b/bin/v-add-database @@ -0,0 +1,113 @@ +#!/bin/bash +# info: add database +# options: USER DATABASE DBUSER DBPASS [TYPE] [HOST] [CHARSET] +# +# example: v-add-database admin wordpress_db matt qwerty123 +# +# This function creates the database concatenating username and user_db. +# Supported types of databases you can get using v-list-sys-config script. +# If the host isn't stated and there are few hosts configured on the server, +# then the host will be defined by one of three algorithms. "First" will choose +# the first host in the list. "Random" will chose the host by a chance. +# "Weight" will distribute new database through hosts evenly. Algorithm and +# types of supported databases is designated in the main configuration file. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +database="$user"_"$2" +dbuser="$user"_"$3" +password=$4 +HIDE=4 +type=${5-mysql} +host=$6 +charset=${7-UTF8MB4} +charset=$(echo "$charset" | tr '[:lower:]' '[:upper:]') + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/db.sh +source $HESTIA/func/db.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +if [ "$type" = "pgsql" ]; then + database=$(echo "$user"_"$2" | tr '[:upper:]' '[:lower:]') + dbuser=$(echo "$user"_"$3" | tr '[:upper:]' '[:lower:]') +fi + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '4' "$#" 'USER DATABASE DBUSER DBPASS [TYPE] [HOST] [CHARSET]' +is_format_valid 'user' 'database' 'dbuser' 'charset' +is_system_enabled "$DB_SYSTEM" 'DB_SYSTEM' +is_type_valid "$DB_SYSTEM" "$type" +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_new 'db' 'DB' "$database" +is_object_new 'db' 'DBUSER' "$dbuser" +get_next_dbhost +is_object_valid "../../../conf/$type" 'HOST' "$host" +is_object_unsuspended "../../../conf/$type" 'DBHOST' "$host" +#is_charset_valid +is_package_full 'DATABASES' +is_password_valid + +if [ "$type" = "pgsql" ]; then + exclude="-" + if [[ "$dbuser" =~ $exclude ]]; then + check_result "$E_INVALID" "invalid database user format" + fi + if [[ "$database" =~ $exclude ]]; then + check_result "$E_INVALID" "invalid database format" + fi +fi + +dbpass="$password" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Switching on db type +case $type in + mysql) add_mysql_database ;; + pgsql) add_pgsql_database ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Generating timestamp +time_n_date=$(date +'%T %F') +time=$(echo "$time_n_date" | cut -f 1 -d \ ) +date=$(echo "$time_n_date" | cut -f 2 -d \ ) + +# Adding db to db conf +str="DB='$database' DBUSER='$dbuser' MD5='$md5' HOST='$host' TYPE='$type'" +str="$str CHARSET='$charset' U_DISK='0' SUSPENDED='no' TIME='$time'" +str="$str DATE='$date'" +echo "$str" >> $USER_DATA/db.conf +chmod 660 $USER_DATA/db.conf + +# Increasing counters +increase_dbhost_values +increase_user_value "$user" '$U_DATABASES' + +# Logging +$BIN/v-log-action "$user" "Info" "Databases" "Added new database $database ($type)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-add-database-host b/bin/v-add-database-host new file mode 100755 index 0000000..6f07f3c --- /dev/null +++ b/bin/v-add-database-host @@ -0,0 +1,169 @@ +#!/bin/bash +# info: add new database server +# options: TYPE HOST DBUSER DBPASS [MAX_DB] [CHARSETS] [TEMPLATE] [PORT] +# +# example: v-add-database-host mysql localhost alice p@$$wOrd +# +# This function add new database server to the server pool. It supports local +# and remote database servers, which is useful for clusters. By adding a host +# you can set limit for number of databases on a host. Template parameter is +# used only for PostgreSQL and has an default value "template1". You can read +# more about templates in official PostgreSQL documentation. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +type=$1 +host=$2 +dbuser=$3 +password=$4 +HIDE=4 +max_db=${5-500} +charsets=${6} +template=${7} +port=${8} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/db.sh +source $HESTIA/func/db.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +is_mysql_host_alive() { + mycnf=$(mktemp) + echo "[client]" > $mycnf + echo "host='$host'" >> $mycnf + echo "user='$dbuser'" >> $mycnf + echo "password='$password'" >> $mycnf + echo "port='$port'" >> $mycnf + + chmod 600 $mycnf + mysql_out=$(mktemp) + if [ -f '/usr/bin/mariadb' ]; then + mariadb --defaults-file=$mycnf -e 'SELECT VERSION()' > $mysql_out 2>&1 + else + mysql --defaults-file=$mycnf -e 'SELECT VERSION()' > $mysql_out 2>&1 + fi + if [ "$?" -ne '0' ]; then + echo "Error: MySQL connection to $host failed" + rm $mycnf + log_event "$E_CONNECT" "$ARGUMENTS" + exit "$E_CONNECT" + fi + + if [ -f '/usr/bin/mariadb' ]; then + grants=$(mariadb --defaults-file=$mycnf -e 'SHOW GRANTS FOR CURRENT_USER();') + else + grants=$(mysql --defaults-file=$mycnf -e 'SHOW GRANTS FOR CURRENT_USER();') + fi + + if [ "$?" -ne '0' ]; then + echo "Error: MySQL connection to $host failed" + rm $mycnf + log_event "$E_CONNECT" "$ARGUMENTS" + exit "$E_CONNECT" + fi + + # Check allow to grant user + check_grants=$(echo $grants | grep "WITH GRANT OPTION") + if [ -z "$check_grants" ]; then + echo "Error: MySQL connection to $host failed. Unable to grant other users" + rm $mycnf + log_event "$E_CONNECT" "$ARGUMENTS" + exit "$E_CONNECT" + fi + rm $mycnf +} + +is_pgsql_host_alive() { + export PGPASSWORD="$dbpass" + psql -h $host -U $dbuser -p $port -c "SELECT VERSION()" > /dev/null 2>&1 + if [ "$?" -ne '0' ]; then + echo "Error: PostgreSQL connection to $host failed" + log_event "$E_CONNECT" "$ARGUMENTS" + exit "$E_CONNECT" + fi +} + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +args_usage='TYPE HOST DBUSER DBPASS [MAX_DB] [CHARSETS] [TPL] [PORT]' +check_args '4' "$#" "$args_usage" + +if [ -z $charsets ]; then charsets="UTF8,LATIN1,WIN1250,WIN1251,WIN1252,WIN1256,WIN1258,KOI8"; fi +if [ -z $template ]; then template="template1"; fi + +database_set_default_ports + +is_format_valid 'host' 'dbuser' 'max_db' 'charsets' 'template' 'port' +is_system_enabled "$DB_SYSTEM" 'DB_SYSTEM' +is_type_valid "$DB_SYSTEM" "$type" +is_dbhost_new +is_password_valid +dbpass="$password" + +case $type in + mysql) is_mysql_host_alive ;; + pgsql) is_pgsql_host_alive ;; +esac + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Generating timestamp +time_n_date=$(date +'%T %F') +time=$(echo "$time_n_date" | cut -f 1 -d \ ) +date=$(echo "$time_n_date" | cut -f 2 -d \ ) + +# Concatenating db host string +case $type in + mysql) + str="HOST='$host' USER='$dbuser' PASSWORD='$dbpass'" + str="$str CHARSETS='$charsets' MAX_DB='$max_db' U_SYS_USERS=''" + str="$str U_DB_BASES='0' SUSPENDED='no' TIME='$time' DATE='$date' PORT='$port'" + ;; + pgsql) + str="HOST='$host' USER='$dbuser' PASSWORD='$dbpass'" + str="$str CHARSETS='$charsets' TPL='$template' MAX_DB='$max_db'" + str="$str U_SYS_USERS='' U_DB_BASES='0' SUSPENDED='no'" + str="$str TIME='$time' DATE='$date' PORT='$port'" + ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Adding host to conf +echo "$str" >> $HESTIA/conf/$type.conf +chmod 660 $HESTIA/conf/$type.conf + +# Updating hestia.conf +if [ -z "$(grep DB_SYSTEM $HESTIA/conf/hestia.conf)" ]; then + echo "DB_SYSTEM='$type'" >> $HESTIA/conf/hestia.conf +else + db=$(echo "$DB_SYSTEM,$type" \ + | sed "s/,/\n/g" \ + | sort -r -u \ + | sed "/^$/d" \ + | sed ':a;N;$!ba;s/\n/,/g') + sed -i "s/DB_SYSTEM=.*/DB_SYSTEM='$db'/g" $HESTIA/conf/hestia.conf +fi + +# Logging +$BIN/v-log-action "system" "Info" "Database" "Added external $type database server ($host) to the system." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-add-database-temp-user b/bin/v-add-database-temp-user new file mode 100755 index 0000000..95628c2 --- /dev/null +++ b/bin/v-add-database-temp-user @@ -0,0 +1,87 @@ +#!/bin/bash +# info: add temp database user +# options: USER DATABASE [TYPE] [HOST] [TTL] +# +# example: v-add-database-temp-user wordress wordpress_db mysql +# +# This function creates an temporary database user mysql_sso_db_XXXXXXXX and a random password +# The user has an limited validity and only granted access to the specific database +# Returns json to be read SSO Script + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +database="$2" +type=${3-mysql} +host=$4 +ttl=$5 + +if [ "$ttl" == '' ]; then + ttl=60 +fi + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/db.sh +source $HESTIA/func/db.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DATABASE [TYPE] [HOST] [TTL]' +is_format_valid 'user' 'database' 'ttl' +is_type_valid "$DB_SYSTEM" "$type" +is_system_enabled "$DB_SYSTEM" 'DB_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'db' 'DB' "$database" +is_object_unsuspended 'db' 'DB' "$database" +get_next_dbhost + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Get database values +get_database_values + +#generate password and unique user +dbpass=$(generate_password) +dbuser="hestia_sso_$(generate_password)" + +add_mysql_database_temp_user +if [ $? -ne 0 ]; then + echo "Error: Unable to create temp user" + exit 2 +fi + +if [[ "$ttl" -gt 0 ]]; then + echo "$BIN/v-delete-database-temp-user $user $database $dbuser mysql $host" | at "now +${ttl} minute" > /dev/null 2>&1 +fi +echo '{ + "login": { + "user": "'$dbuser'", + "password": "'$dbpass'" + } +}' + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +$BIN/v-log-action "$user" "Info" "Databases" "Granted user $dbuser access to database $database." +log_event "$OK" "$ARGUMENTS" +exit diff --git a/bin/v-add-dns-domain b/bin/v-add-dns-domain new file mode 100755 index 0000000..8dec557 --- /dev/null +++ b/bin/v-add-dns-domain @@ -0,0 +1,222 @@ +#!/bin/bash +# info: add dns domain +# options: USER DOMAIN IP [NS1] [NS2] [NS3] [NS4] [NS5] [NS6] [NS7] [NS8] [RESTART] +# +# example: v-add-dns-domain admin example.com ns1.example.com ns2.example.com '' '' '' '' '' '' yes +# +# This function adds DNS zone with records defined in the template. If the exp +# argument isn't stated, the expiration date value will be set to next year. +# The soa argument is responsible for the relevant record. By default the first +# user's NS server is used. TTL is set as common for the zone and for all of +# its records with a default value of 14400 seconds. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +ip=$3 +ns1=$4 +ns2=$5 +ns3=$6 +ns4=$7 +ns5=$8 +ns6=$9 +ns7=${10} +ns8=${11} +restart=${12} +dnssec=${13} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# shellcheck source=/usr/local/hestia/func/rebuild.sh +source $HESTIA/func/rebuild.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn +domain_utf=$(idn2 --quiet -d "$domain_idn") + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '3' "$#" 'USER DOMAIN IP [NS1] [NS2] [NS3] [..] [NS8] [RESTART]' +is_format_valid 'user' 'domain' 'ip' +is_system_enabled "$DNS_SYSTEM" 'DNS_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" + +if [ "$($BIN/v-list-dns-domain $user $domain_utf plain | cut -f 1) " != "$domain" ]; then + is_domain_new 'dns' "$domain_utf" +fi +if [ "$($BIN/v-list-dns-domain $user $domain_idn plain | cut -f 1) " != "$domain" ]; then + is_domain_new 'dns' "$domain_idn" +else + is_domain_new 'dns' "$domain" +fi +if [ -z "$(is_ip_format_valid $domain)" ]; then + echo "Error: Invalid domain format. IP address detected as input." + exit 1 +fi + +if [ -n "$restart" ]; then + is_format_valid 'restart' +fi + +if [ -n "$dnssec" ]; then + is_boolean_format_valid "$dnssec" 'dnssec' +fi + +is_package_full 'DNS_DOMAINS' +template=$(get_user_value '$DNS_TEMPLATE') +is_dns_template_valid "$template" + +is_base_domain_owner "$domain" + +if [ -n "$ns1" ]; then + ns1=$(echo $4 | sed -e 's/\.*$//g' -e 's/^\.*//g') + is_format_valid 'ns1' +fi +if [ -n "$ns2" ]; then + ns2=$(echo $5 | sed -e 's/\.*$//g' -e 's/^\.*//g') + is_format_valid 'ns2' +fi +if [ -n "$ns3" ]; then + ns3=$(echo $6 | sed -e 's/\.*$//g' -e 's/^\.*//g') + is_format_valid 'ns3' +fi +if [ -n "$ns4" ]; then + ns4=$(echo $7 | sed -e 's/\.*$//g' -e 's/^\.*//g') + is_format_valid 'ns4' +fi +if [ -n "$ns5" ]; then + ns5=$(echo $8 | sed -e 's/\.*$//g' -e 's/^\.*//g') + is_format_valid 'ns5' +fi +if [ -n "$ns6" ]; then + ns6=$(echo $9 | sed -e 's/\.*$//g' -e 's/^\.*//g') + is_format_valid 'ns6' +fi +if [ -n "$ns7" ]; then + ns7=$(echo ${10} | sed -e 's/\.*$//g' -e 's/^\.*//g') + is_format_valid 'ns7' +fi +if [ -n "$ns8" ]; then + ns8=$(echo ${11} | sed -e 's/\.*$//g' -e 's/^\.*//g') + is_format_valid 'ns8' +fi + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Defining NS variables +if [ -z $ns2 ]; then + i=1 + ns=$(get_user_value '$NS') + for nameserver in ${ns//,/ }; do + eval ns$i=$nameserver + ((++i)) + done +fi +soa="$ns1" +exp=$(date +%F -d "+ 1 year") +serial=$(date +'%Y%m%d01') +ttl=14400 + +# Reading template +template_data=$(cat "$DNSTPL/$template.tpl") + +# Deleting unused nameservers +if [ -z "$ns3" ]; then + template_data=$(echo "$template_data" | grep -v %ns3%) +fi +if [ -z "$ns4" ]; then + template_data=$(echo "$template_data" | grep -v %ns4%) +fi +if [ -z "$ns5" ]; then + template_data=$(echo "$template_data" | grep -v %ns5%) +fi +if [ -z "$ns6" ]; then + template_data=$(echo "$template_data" | grep -v %ns6%) +fi +if [ -z "$ns7" ]; then + template_data=$(echo "$template_data" | grep -v %ns7%) +fi +if [ -z "$ns8" ]; then + template_data=$(echo "$template_data" | grep -v %ns8%) +fi +if [ -z "$dnssec" ]; then + dnssec="no" +fi + +# Generating timestamp +time_n_date=$(date +'%T %F') +time=$(echo "$time_n_date" | cut -f 1 -d \ ) +date=$(echo "$time_n_date" | cut -f 2 -d \ ) + +# Adding dns zone to the user config +echo "$template_data" \ + | sed -e "s/%ip%/$ip/g" \ + -e "s/%domain_idn%/$domain_idn/g" \ + -e "s/%domain%/$domain/g" \ + -e "s/%ns1%/$ns1/g" \ + -e "s/%ns2%/$ns2/g" \ + -e "s/%ns3%/$ns3/g" \ + -e "s/%ns4%/$ns4/g" \ + -e "s/%ns5%/$ns5/g" \ + -e "s/%ns6%/$ns6/g" \ + -e "s/%ns7%/$ns7/g" \ + -e "s/%ns8%/$ns8/g" \ + -e "s/%time%/$time/g" \ + -e "s/%date%/$date/g" > $USER_DATA/dns/$domain.conf + +chmod 660 $USER_DATA/dns/$domain.conf +records="$(wc -l $USER_DATA/dns/$domain.conf | cut -f 1 -d ' ')" + +# Adding dns.conf record +dns_rec="DOMAIN='$domain' IP='$ip' TPL='$template' TTL='$ttl' EXP='$exp'" +dns_rec="$dns_rec SOA='$soa' SERIAL='$serial' SRC='' RECORDS='$records'" +dns_rec="$dns_rec DNSSEC='$dnssec' KEY='' SLAVE='no' MASTER='' SUSPENDED='no' TIME='$time' DATE='$date'" + +echo "$dns_rec" >> $USER_DATA/dns.conf +chmod 660 $USER_DATA/dns.conf + +rebuild_dns_domain_conf + +# Updating dns-cluster queue +if [ "$DNS_CLUSTER" = "yes" ]; then + cmd="$BIN/v-add-remote-dns-domain $user $domain yes" + echo "$cmd" >> $HESTIA/data/queue/dns-cluster.pipe +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Increasing domain value +increase_user_value "$user" '$U_DNS_DOMAINS' +increase_user_value "$user" '$U_DNS_RECORDS' "$records" + +# Restart named +$BIN/v-restart-dns $restart +check_result $? "DNS restart failed" + +# Logging +$BIN/v-log-action "$user" "Info" "DNS" "Added new DNS domain (Name: $domain)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-add-dns-on-web-alias b/bin/v-add-dns-on-web-alias new file mode 100755 index 0000000..c4ee4a0 --- /dev/null +++ b/bin/v-add-dns-on-web-alias @@ -0,0 +1,91 @@ +#!/bin/bash +# info: add dns domain or dns record after web domain alias +# options: USER ALIAS IP [RESTART] +# +# example: v-add-dns-on-web-alias admin www.example.com 8.8.8.8 +# +# This function adds dns domain or dns record based on web domain alias. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +alias=$2 +ip=$3 +restart=$4 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '3' "$#" 'USER ALIAS IP [RESTART]' +is_format_valid 'user' 'alias' 'ip' 'restart' +is_system_enabled "$DNS_SYSTEM" 'DNS_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +if [ -e "$USER_DATA/dns/$alias.conf" ]; then + exit +fi + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Logging +log_event "$OK" "$ARGUMENTS" + +# Define additional vars +sub_domain=$(echo "$alias" | awk -F '.' '{print $1}') +top_domain=$(echo "$alias" | sed -e "s/^$sub_domain.//") +domain_lvl=$(echo "$alias" | grep -o "\." | wc -l) + +# Adding second level domain +if [ "$domain_lvl" -eq 1 ] || [ "${#top_domain}" -le '6' ]; then + $BIN/v-add-dns-domain \ + "$user" "$alias" "$ip" '' '' '' '' '' '' '' '' "$restart" >> /dev/null + exit +fi + +# Adding top-level domain and then its sub +$BIN/v-add-dns-domain "$user" "$top_domain" "$ip" '' '' '' '' '' '' '' '' "$restart" >> /dev/null + +# Checking top-level domain +if [ ! -e "$USER_DATA/dns/$top_domain.conf" ]; then + exit +fi + +# Checking subdomain record +if [ "$sub_domain" == '*' ]; then + check_record=$(grep -w "RECORD='\*'" $USER_DATA/dns/$top_domain.conf) +else + check_record=$(grep -w "RECORD='$sub_domain'" $USER_DATA/dns/$top_domain.conf) +fi + +# Adding subdomain record +if [ -z "$check_record" ]; then + $BIN/v-add-dns-record \ + "$user" "$top_domain" "$sub_domain" A "$ip" '' '' "$restart" >> /dev/null +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# No logging + +exit diff --git a/bin/v-add-dns-record b/bin/v-add-dns-record new file mode 100755 index 0000000..2a5b0ea --- /dev/null +++ b/bin/v-add-dns-record @@ -0,0 +1,172 @@ +#!/bin/bash +# info: add dns record +# options: USER DOMAIN RECORD TYPE VALUE [PRIORITY] [ID] [RESTART] [TTL] +# +# example: v-add-dns-record admin acme.com www A 162.227.73.112 +# +# This function is used to add a new DNS record. Complex records of TXT, MX and +# SRV types can be used by a filling in the 'value' argument. This function also +# gets an ID parameter for definition of certain record identifiers or for the +# regulation of records. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 +record=$(idn2 --quiet -d "$3") +record=$(echo "$record" | tr '[:upper:]' '[:lower:]') +rtype=$(echo "$4" | tr '[:lower:]' '[:upper:]') +dvalue=$5 +priority=$6 +id=$7 +restart=$8 +ttl=$9 +quiet=${10} + +if [ -z "$priority" ]; then + priority=10 +fi + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# shellcheck source=/usr/local/hestia/func/rebuild.sh +source $HESTIA/func/rebuild.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Null priority for none MX/SRV records +if [ "$rtype" != 'MX' ] && [ "$rtype" != 'SRV' ]; then + priority='' +fi + +# Add trailing dot at the end of NS/CNAME/MX/PTR/SRV record +if [[ $rtype =~ ^NS|CNAME|MX|PTR|SRV ]]; then + trailing_dot=$(echo $dvalue | grep "\.$") + if [ -z "$trailing_dot" ]; then + dvalue="$dvalue." + fi +fi + +if [[ $rtype =~ ^NS|CNAME|MX|PTR|SRV ]]; then + dvalue=$(idn2 --quiet "$dvalue") + record=$(idn2 --quiet "$record") +fi + +# Cleanup quotes on dvalue +# - [CAA] records will be left unchanged +# - [SRV] will be stripped of double quotes even when containing spaces +# - [DNSKEY] will be stripped of double quotes even when containing spaces +# - Rest of record types will be striped of quotes and the final string +# will be enclosed in double quotes if containing spaces or semicolons + +if [ "$rtype" != "CAA" ]; then + dvalue=${dvalue//\"/} + # Add support for DS key + if [ "$rtype" != "DNSKEY" ] && [ "$rtype" != "DS" ]; then + if [ "$rtype" != 'SRV' ] && [[ "$dvalue" =~ [\;[:space:]] ]]; then + dvalue='"'"$dvalue"'"' + fi + fi +fi + +if [ "$record" = "@" ] && [ "$rtype" = "CNAME" ]; then + check_result $E_INVALID "CNAME on root is not allowed" +fi + +# Additional argument formatting +format_domain +format_domain_idn +# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ? + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '5' "$#" 'USER DOMAIN RECORD TYPE VALUE [PRIORITY] [ID] [RESTART] [TTL]' +is_format_valid 'user' 'domain' 'record' 'rtype' 'dvalue' +is_system_enabled "$DNS_SYSTEM" 'DNS_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'dns' 'DOMAIN' "$domain" +is_object_unsuspended 'dns' 'DOMAIN' "$domain" +is_package_full 'DNS_RECORDS' +get_next_dnsrecord +is_format_valid 'id' +is_object_new "dns/$domain" 'ID' "$id" +is_dns_fqnd "$rtype" "$dvalue" +is_dns_nameserver_valid "$domain" "$rtype" "$dvalue" +is_format_valid 'ttl' +if [ -n "$restart" ]; then + is_format_valid 'restart' +fi + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Generating timestamp +time_n_date=$(date +'%T %F') +time=$(echo "$time_n_date" | cut -f 1 -d \ ) +date=$(echo "$time_n_date" | cut -f 2 -d \ ) + +# Adding record +zone="$USER_DATA/dns/$domain.conf" +dns_rec="ID='$id' RECORD='$record' TYPE='$rtype' PRIORITY='$priority'" +dns_rec="$dns_rec VALUE='$dvalue' SUSPENDED='no' TIME='$time' DATE='$date'" +[ -n "$ttl" ] && dns_rec="$dns_rec TTL='$ttl'" +echo "$dns_rec" >> $zone +chmod 660 $zone + +# Sorting records +sort_dns_records + +# Update serial +update_domain_serial +# Updating zone +if [[ "$DNS_SYSTEM" =~ named|bind ]]; then + # Do full rebuild due DNS SEC + rebuild_dns_domain_conf +fi + +# Updating dns-cluster queue +if [ "$DNS_CLUSTER" = "yes" ]; then + # Check for first sync + dlock=$(grep "domain $user $domain" $HESTIA/data/queue/dns-cluster.pipe) + if [ -z "$dlock" ]; then + cmd="$BIN/v-add-remote-dns-record $user $domain $id" + echo "$cmd" >> $HESTIA/data/queue/dns-cluster.pipe + fi +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Update counters +records="$(wc -l $USER_DATA/dns/$domain.conf | cut -f1 -d ' ')" +update_object_value 'dns' 'DOMAIN' "$domain" '$RECORDS' "$records" +increase_user_value "$user" '$U_DNS_RECORDS' + +# Restart named +$BIN/v-restart-dns "$restart" +check_result $? "$E_RESTART" 'dns failed to restart' + +# Logging +if [ "$quiet" != "yes" ]; then + $BIN/v-log-action "$user" "Info" "DNS" "Added DNS record (Type: $rtype, Value: $record, Domain: $domain)." +fi +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-add-domain b/bin/v-add-domain new file mode 100755 index 0000000..be69cbe --- /dev/null +++ b/bin/v-add-domain @@ -0,0 +1,100 @@ +#!/bin/bash +# info: add web/dns/mail domain +# options: USER DOMAIN [IP] [RESTART] +# +# example: v-add-domain admin example.com +# +# This function adds web/dns/mail domain to a server. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +ip=$3 +restart=$4 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/ip.sh +source $HESTIA/func/ip.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# +check_args '2' "$#" 'USER DOMAIN [IP] [RESTART]' +is_format_valid 'user' 'domain' 'restart' +if [ -n "$ip" ]; then + is_format_valid 'ip' +fi +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Get ip if it wasn't defined +if [ -z "$ip" ]; then + get_user_ip + if [ -z "$ip" ]; then + check_result "$E_NOTEXIST" "no available IP address" + fi +fi + +# Working on web domain +if [ -n "$WEB_SYSTEM" ]; then + check1=$(is_package_full 'WEB_DOMAINS') + if [ $? -eq 0 ]; then + $BIN/v-add-web-domain "$user" "$domain" "$ip" 'no' + check_result $? "can't add web domain" + fi +fi + +# Working on DNS domain +if [ -n "$DNS_SYSTEM" ]; then + check2=$(is_package_full 'DNS_DOMAINS') + if [ $? -eq 0 ]; then + $BIN/v-add-dns-domain "$user" "$domain" "$ip" "" "" "" "" "" "" "" "" "no" + check_result $? "can't add dns domain" + fi +fi + +# Working on mail domain +if [ -n "$MAIL_SYSTEM" ]; then + check3=$(is_package_full 'MAIL_DOMAINS') + if [ $? -eq 0 ]; then + $BIN/v-add-mail-domain $user $domain 'no' + check_result $? "can't add mail domain" + fi +fi + +if [[ "$check1" != '' && "$check2" != '' && "$check3" != '' ]]; then + check_result 8 "Package limit reached" +fi + +# Restarting services +$BIN/v-restart-web "$restart" +check_result $? "can't restart web" > /dev/null + +$BIN/v-restart-proxy "$restart" +check_result $? "can't restart proxy" > /dev/null + +$BIN/v-restart-dns "$restart" +check_result $? "can't restart dns" > /dev/null + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-add-fastcgi-cache b/bin/v-add-fastcgi-cache new file mode 100755 index 0000000..59cc60c --- /dev/null +++ b/bin/v-add-fastcgi-cache @@ -0,0 +1,118 @@ +#!/bin/bash +# info: Enable FastCGI cache for nginx +# options: USER DOMAIN [DURATION] [RESTART] +# +# example: v-add-fastcgi-cache user domain.tld 30m +# +# This function enables FastCGI cache for nginx +# Acceptable values for duration is time in seconds (10s) minutes (10m) or days (10d) +# Add "yes" as last parameter to restart nginx + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +duration=${3-2m} +restart=${4-no} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DOMAIN [DURATION] [RESTART]' +is_format_valid 'user' 'domain' 'restart' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'web' 'DOMAIN' "$domain" +is_object_unsuspended 'web' 'DOMAIN' "$domain" + +if ! [[ "$duration" =~ ^[0-9].*[s|m|d]$ ]]; then + echo "Invalid duration" + exit 2 +fi + +if [[ "$duration" =~ ^[0].*[s|m|d]$ ]]; then + echo "Invalid duration" + exit 2 +fi + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Load domain data +parse_object_kv_list $(grep "DOMAIN='$domain'" $USER_DATA/web.conf) + +# Check that nginx is not in proxy mode +if [ "$WEB_SYSTEM" != 'nginx' ]; then + echo "Error: nginx is in proxy mode" + exit "$E_NOTEXIST" +fi + +fastcgi="$HOMEDIR/$user/conf/web/$domain/$WEB_SYSTEM.fastcgi_cache.conf" +no_cache='$no_cache' + +cat << EOF > $fastcgi + fastcgi_cache $domain; + fastcgi_cache_valid 200 $duration; + fastcgi_cache_valid 301 302 10m; + fastcgi_cache_valid 404 10m; + fastcgi_cache_bypass $no_cache; + fastcgi_no_cache $no_cache; + set $no_cache 0; +EOF + +chown root:$user $fastcgi +chmod 640 $fastcgi + +str="fastcgi_cache_path /var/cache/nginx/micro/$domain levels=1:2" +str="$str keys_zone=$domain:10m max_size=512m inactive=30m use_temp_path=off;" +conf='/etc/nginx/conf.d/fastcgi_cache_pool.conf' +if [ -f "$conf" ]; then + if [ -z "$(grep "=${domain}:" $conf)" ]; then + echo "$str" >> $conf + fi +else + echo "$str" >> $conf +fi + +mkdir -p /var/cache/nginx/micro/$domain + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +if [ -z "$FASTCGI_CACHE" ]; then + add_object_key "web" 'DOMAIN' "$domain" 'FASTCGI_CACHE' 'ALIAS' +fi +if [ -z "$FASTCGI_DURATION" ]; then + add_object_key "web" 'DOMAIN' "$domain" 'FASTCGI_DURATION' 'ALIAS' +fi + +# Set FastCGI cache flag to enabled +update_object_value 'web' 'DOMAIN' "$domain" '$FASTCGI_CACHE' 'yes' +update_object_value 'web' 'DOMAIN' "$domain" '$FASTCGI_DURATION' "$duration" + +# Restart web server +$BIN/v-restart-web "$restart" +check_result $? "Web server restart failed" > /dev/null + +# Logging +$BIN/v-log-action "$user" "Info" "Web" "FastCGI cache enabled (Domain: $domain)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-add-firewall-ban b/bin/v-add-firewall-ban new file mode 100755 index 0000000..014335b --- /dev/null +++ b/bin/v-add-firewall-ban @@ -0,0 +1,91 @@ +#!/bin/bash +# info: add firewall blocking rule +# options: IP CHAIN +# +# example: v-add-firewall-ban 37.120.129.20 MAIL +# +# This function adds new blocking rule to system firewall + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +ip=$1 +chain=$(echo $2 | tr '[:lower:]' '[:upper:]') + +# Defining absolute path for iptables and modprobe +iptables="/sbin/iptables" + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/firewall.sh +source $HESTIA/func/firewall.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'IP CHAIN' +is_format_valid 'ip' 'chain' +is_system_enabled "$FIREWALL_SYSTEM" 'FIREWALL_SYSTEM' + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Self heal iptables links +heal_iptables_links + +# Checking server ip +if [ -e "$HESTIA/data/ips/$ip" ] || [ "$ip" = '127.0.0.1' ]; then + exit +fi + +# Checking ip exclusions +excludes="$HESTIA/data/firewall/excludes.conf" +check_excludes=$(grep "^$ip$" $excludes 2> /dev/null) +if [ -n "$check_excludes" ]; then + exit +fi + +# Checking ip in banlist +conf="$HESTIA/data/firewall/banlist.conf" +check_ip=$(grep "IP='$ip' CHAIN='$chain'" $conf 2> /dev/null) +if [ -n "$check_ip" ]; then + exit +fi + +# Adding chain +$BIN/v-add-firewall-chain $chain + +# Generating timestamp +time_n_date=$(date +'%T %F') +time=$(echo "$time_n_date" | cut -f 1 -d \ ) +date=$(echo "$time_n_date" | cut -f 2 -d \ ) + +# Adding ip to banlist +echo "IP='$ip' CHAIN='$chain' TIME='$time' DATE='$date'" >> $conf +$iptables -I fail2ban-$chain 1 -s $ip \ + -j REJECT --reject-with icmp-port-unreachable 2> /dev/null + +# Changing permissions +chmod 660 $conf + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +$BIN/v-log-action "system" "Warning" "Firewall" "Banned IP address $ip." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-add-firewall-chain b/bin/v-add-firewall-chain new file mode 100755 index 0000000..273f814 --- /dev/null +++ b/bin/v-add-firewall-chain @@ -0,0 +1,130 @@ +#!/bin/bash +# info: add firewall chain +# options: CHAIN [PORT] [PROTOCOL] [PROTOCOL] +# +# example: v-add-firewall-chain CRM 5678 TCP +# +# This function adds new rule to system firewall + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +chain=$(echo $1 | tr '[:lower:]' '[:upper:]') +port=$2 +port_ext=$2 +protocol=${4-TCP} +protocol=$(echo $protocol | tr '[:lower:]' '[:upper:]') + +# Defining absolute path to iptables +iptables="/sbin/iptables" + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/firewall.sh +source $HESTIA/func/firewall.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Get hestia port by reading nginx.conf +hestiaport=$(grep -m 1 'listen' $HESTIA/nginx/conf/nginx.conf | awk '{print $2}' | sed "s|;||") +if [ -z "$hestiaport" ]; then + hestiaport=8083 +fi + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'CHAIN [PORT] [PROTOCOL]' +is_format_valid 'chain' 'port_ext' 'protocol' +is_system_enabled "$FIREWALL_SYSTEM" 'FIREWALL_SYSTEM' + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Self heal iptables links +heal_iptables_links + +# Checking known chains +case $chain in + SSH) # Get ssh port by reading ssh config file. + sshport=$(grep '^Port ' /etc/ssh/sshd_config | head -1 | cut -d ' ' -f 2) + if [ -z "$sshport" ]; then + sshport=22 + fi + port=$sshport + protocol=TCP + ;; + FTP) + port=21 + protocol=TCP + ;; + MAIL) + port='25,465,587,110,995,143,993' + protocol=TCP + ;; + DNS) + port=53 + protocol=UDP + ;; + WEB) + port='80,443' + protocol=TCP + ;; + DB) + port='3306,5432' + protocol=TCP + ;; + HESTIA) + port=$hestiaport + protocol=TCP + ;; + RECIDIVE) + port='1:65535' + protocol=TCP + ;; + *) check_args '2' "$#" 'CHAIN PORT' ;; +esac + +# Adding chain +$iptables -N fail2ban-$chain 2> /dev/null +if [ $? -eq 0 ]; then + $iptables -A fail2ban-$chain -j RETURN + + # Adding multiport module + if [[ "$port" =~ ,|-|: ]]; then + port_str="-m multiport --dports $port" + else + port_str="--dport $port" + fi + $iptables -I INPUT -p $protocol $port_str -j fail2ban-$chain +fi + +# Preserving chain +chains=$HESTIA/data/firewall/chains.conf +check_chain=$(grep "CHAIN='$chain'" $chains 2> /dev/null) +if [ -z "$check_chain" ]; then + echo "CHAIN='$chain' PORT='$port' PROTOCOL='$protocol'" >> $chains +fi + +# Changing permissions +chmod 660 $chains + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +$BIN/v-log-action "system" "Info" "Firewall" "Added service to firewall (Service: $chain, Port: $port, Protocol: $protocol)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-add-firewall-ipset b/bin/v-add-firewall-ipset new file mode 100755 index 0000000..4a90cdd --- /dev/null +++ b/bin/v-add-firewall-ipset @@ -0,0 +1,205 @@ +#!/bin/bash +# info: add firewall ipset +# options: NAME [SOURCE] [IPVERSION] [AUTOUPDATE] [REFRESH] +# +# example: v-add-firewall-ipset country-nl "https://raw.githubusercontent.com/ipverse/rir-ip/master/country/nl/ipv4-aggregated.txt" +# +# This function adds new ipset to system firewall + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +ip_name=${1} +data_source=${2} +ip_version=${3:-v4} +autoupdate=${4:-yes} +refresh=${5:-no} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'NAME [SOURCE] [IPVERSION] [AUTOUPDATE] [FORCE]' +is_format_valid 'ip_name' +is_boolean_format_valid "$autoupdate" 'Automatically update IP list (yes/no)' +is_boolean_format_valid "$refresh" 'Refresh IP list (yes/no)' +is_system_enabled "$FIREWALL_SYSTEM" 'FIREWALL_SYSTEM' + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +# Define variables for ipset configuration +ipset_hstobject='../../data/firewall/ipset' +IPSET_BIN="$(command -v ipset)" +IPSET_PATH="$HESTIA/data/firewall/ipset" + +# Ensure ipset is installed +if [ -z "$IPSET_BIN" ]; then + if [ -f '/etc/redhat-release' ]; then + dnf install -q -y ipset > /dev/null + else + apt-get --quiet --yes install ipset > /dev/null + fi + check_result $? "Installing IPset package" + + IPSET_BIN="$(which ipset)" + check_result $? "IPset binary not found" +fi + +# Ensure ipset configuration path and master file exist before attempting to parse +mkdir -p "$IPSET_PATH" +if [ ! -f "$HESTIA/data/firewall/ipset.conf" ]; then + touch $HESTIA/data/firewall/ipset.conf +fi + +if [ -z "$data_source" ]; then + if [ ! -f "${IPSET_PATH}.conf" ] || [[ ! $(grep "LISTNAME='$ip_name'" "${IPSET_PATH}.conf") ]]; then + check_args '2' "$#" 'NAME SOURCE [IPVERSION] [AUTOUPDATE] [FORCE]' + fi + + data_source="$(get_object_value "$ipset_hstobject" 'LISTNAME' "$ip_name" '$SOURCE')" + ip_version="$(get_object_value "$ipset_hstobject" 'LISTNAME' "$ip_name" '$IP_VERSION')" +else + is_object_new "$ipset_hstobject" 'LISTNAME' "$ip_name" +fi + +if [ "$ip_version" != "v4" ] && [ "$ip_version" != "v6" ]; then + check_result "$E_INVALID" "invalid ip version, valid: (v4|v6)" +fi + +if ! echo "$data_source" | egrep -q '^(https?|script|file):'; then + check_result "$E_INVALID" "invalid ipset source, valid: (http[s]://|script:|file:)" +fi + +IPSET_FILE="${ip_name}.${ip_version}" +IPSET_MIN_SIZE=10 + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Generate ip lists file if missing or required refresh +if [ ! -f "${IPSET_PATH}/${IPSET_FILE}.iplist" ] || [ "$refresh" = "yes" ]; then + + iplist_tempfile=$(mktemp) + + if [[ "$data_source" =~ ^https?:// ]]; then + + wget --tries=3 --timeout=15 --read-timeout=15 --waitretry=3 --no-dns-cache --quiet "$data_source" -O "$iplist_tempfile" + check_result $? "Downloading ip list" + + # Advanced: execute script with the same basename for aditional pre-processing + # ex: + if [ -x "${IPSET_PATH}/${IPSET_FILE}.sh" ]; then + if [ -e '/etc/redhat-release' ]; then + preprocess_output="$(cat "$iplist_tempfile" | setpriv --clear-groups --reuid nobody --regid nobody -- ${IPSET_PATH}/${IPSET_FILE}.sh "$ip_name" "$iplist_tempfile")" + else + preprocess_output="$(cat "$iplist_tempfile" | setpriv --clear-groups --reuid nobody --regid nogroup -- ${IPSET_PATH}/${IPSET_FILE}.sh "$ip_name" "$iplist_tempfile")" + fi + check_result $? "Preprocessing script failed (${IPSET_FILE}.sh)" + [[ "$preprocess_output" ]] && echo "$preprocess_output" > "$iplist_tempfile" + fi + + elif [[ "$data_source" =~ ^script:/ ]]; then + + # Generate the ip list file trough a external script + # ex: compiling a ip list from multiple sources on demand + if [ -x "${data_source#script:}" ]; then + if [ -e '/etc/redhat-release' ]; then + setpriv --clear-groups --reuid nobody --regid nobody -- ${data_source#script:} "$ip_name" > "$iplist_tempfile" + else + setpriv --clear-groups --reuid nobody --regid nogroup -- ${data_source#script:} "$ip_name" > "$iplist_tempfile" + fi + check_result $? "Running custom ip list update script" + + fi + + elif [[ "$data_source" =~ ^file:/ ]]; then + + # Use a external ip-list file managed by other apps + # ex: Using a ip list that is continuously updated + [ -f "${data_source#file:}" ] && cp -f "${data_source#file:}" "$iplist_tempfile" + + fi + + # Cleanup ip list + sed -r -i -e 's/[;#].*$//' -e 's/[ \t]*$//' -e '/^$/d' "$iplist_tempfile" + if [[ $ip_version == 'v4' ]]; then + sed -i -r -n -e '/^((1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])/p' "$iplist_tempfile" + elif [[ $ip_version == 'v6' ]]; then + sed -i -r -n -e '/^([0-9a-fA-F]{0,4}:){1,7}[0-9a-fA-F]{0,4}/p' "$iplist_tempfile" + fi + + # Validate iplist file size + iplist_size=$(sed -r -e '/^#|^$/d' "$iplist_tempfile" | wc -l) + [[ "$iplist_size" -le "$IPSET_MIN_SIZE" ]] && check_result "$E_INVALID" "IP list file too small (<${IPSET_MIN_SIZE}), ignoring" + mv -f "$iplist_tempfile" "${IPSET_PATH}/${IPSET_FILE}.iplist" + +fi + +# Load ipset in kernel +inet_ver="inet" +[ "$ip_version" == "v6" ] && inet_ver="inet6" + +$IPSET_BIN -quiet create -exist "$ip_name" hash:net family $inet_ver +$IPSET_BIN -quiet destroy "${ip_name}-tmp" +$IPSET_BIN create "${ip_name}-tmp" -exist hash:net family $inet_ver maxelem 1048576 +$IPSET_BIN flush "${ip_name}-tmp" + +sed -rn -e '/^#|^$/d' -e "s/^(.*)/add ${ip_name}-tmp \\1/p" "${IPSET_PATH}/${IPSET_FILE}.iplist" | $IPSET_BIN -quiet restore +check_result $? "Populating ipset table" + +$IPSET_BIN swap "${ip_name}-tmp" "${ip_name}" +$IPSET_BIN -quiet destroy "${ip_name}-tmp" + +# Generating timestamp +time_n_date=$(date +'%T %F') +time=$(echo "$time_n_date" | cut -f 1 -d \ ) +date=$(echo "$time_n_date" | cut -f 2 -d \ ) + +if [ ! -f "${IPSET_PATH}.conf" ] || [ -z "$(get_object_value "$ipset_hstobject" 'LISTNAME' "$ip_name" '$LISTNAME')" ]; then + + # Concatenating rule + str="LISTNAME='$ip_name' IP_VERSION='$ip_version' SOURCE='$data_source'" + str="$str AUTOUPDATE='$autoupdate' SUSPENDED='no'" + str="$str TIME='$time' DATE='$date'" + echo "$str" >> $HESTIA/data/firewall/ipset.conf + log_type="added" + +elif [ "$refresh" = "yes" ]; then + + # Update iplist last regen time + update_object_value "$ipset_hstobject" 'LISTNAME' "$ip_name" '$TIME' "$time" + update_object_value "$ipset_hstobject" 'LISTNAME' "$ip_name" '$DATE' "$date" + log_type="refreshed" + +fi + +# Changing permissions +chmod 660 $HESTIA/data/firewall/ipset.conf +chmod 660 "${IPSET_PATH}/${IPSET_FILE}.iplist" + +# Install ipset daily cron updater +if ! grep --silent --no-messages "v-update-firewall-ipset" $HESTIA/data/queue/daily.pipe; then + cmd="$BIN/v-update-firewall-ipset yes" + echo "$cmd" >> $HESTIA/data/queue/daily.pipe +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +$BIN/v-log-action "system" "Info" "Firewall" "IPset IP list ${log_type:-loaded} (Name: $ip_name, IP version: $ip_version, Autoupdate: $autoupdate)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-add-firewall-rule b/bin/v-add-firewall-rule new file mode 100755 index 0000000..a1131ca --- /dev/null +++ b/bin/v-add-firewall-rule @@ -0,0 +1,109 @@ +#!/bin/bash +# info: add firewall rule +# options: ACTION IP PORT [PROTOCOL] [COMMENT] [RULE] +# +# example: v-add-firewall-rule DROP 185.137.111.77 25 +# +# This function adds new rule to system firewall + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +action=$(echo $1 | tr '[:lower:]' '[:upper:]') +ip=$2 +port_ext=$3 +protocol=${4-TCP} +protocol=$(echo $protocol | tr '[:lower:]' '[:upper:]') +comment=$5 +rule=$6 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Get next firewall rule id +get_next_fw_rule() { + if [ -z "$rule" ]; then + curr_str=$(grep "RULE=" $HESTIA/data/firewall/rules.conf \ + | cut -f 2 -d \' | sort -n | tail -n1) + rule="$((curr_str + 1))" + fi +} + +sort_fw_rules() { + cat $HESTIA/data/firewall/rules.conf \ + | sort -n -k 2 -t \' > $HESTIA/data/firewall/rules.conf.tmp + mv -f $HESTIA/data/firewall/rules.conf.tmp \ + $HESTIA/data/firewall/rules.conf +} + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '3' "$#" 'ACTION IP PORT [PROTOCOL] [COMMENT] [RULE]' +is_format_valid 'action' 'protocol' 'port_ext' +is_system_enabled "$FIREWALL_SYSTEM" 'FIREWALL_SYSTEM' +get_next_fw_rule +is_format_valid 'rule' +is_object_new '../../data/firewall/rules' 'RULE' "$rule" +if [ -n "$comment" ]; then + is_format_valid 'comment' +fi +if [[ "$ip" =~ ^ipset: ]]; then + ipset_name="${ip#ipset:}" + $BIN/v-list-firewall-ipset plain | grep "^$ipset_name\s" > /dev/null + check_result $? 'ipset object not found' "$E_NOTEXIST" +else + is_format_valid 'ip' +fi + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Generating timestamp +time_n_date=$(date +'%T %F') +time=$(echo "$time_n_date" | cut -f 1 -d \ ) +date=$(echo "$time_n_date" | cut -f 2 -d \ ) + +# Concatenating rule +str="RULE='$rule' ACTION='$action' PROTOCOL='$protocol' PORT='$port_ext'" +str="$str IP='$ip' COMMENT='$comment' SUSPENDED='no'" +str="$str TIME='$time' DATE='$date'" + +# Adding to config +echo "$str" >> $HESTIA/data/firewall/rules.conf + +# Changing permissions +chmod 660 $HESTIA/data/firewall/rules.conf + +# Sorting firewall rules by id number +sort_fw_rules + +# Updating system firewall +$BIN/v-update-firewall + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Fix missing port value in log if zero +if [ -z "$port" ]; then + port="0" +fi + +# Logging +$BIN/v-log-action "system" "Info" "Firewall" "Added firewall rule (Action: $action, Port: $port, Protocol: $protocol)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-add-fs-archive b/bin/v-add-fs-archive new file mode 100755 index 0000000..14a5118 --- /dev/null +++ b/bin/v-add-fs-archive @@ -0,0 +1,85 @@ +#!/bin/bash +# info: archive directory +# options: USER ARCHIVE SOURCE [SOURCE...] +# +# example: v-add-fs-archive admin archive.tar readme.txt +# +# This function creates tar archive + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +user=$1 +archive=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '3' "$#" 'USER ARCHIVE FILE [FILE_2] [FILE_3] [FILE ...]' +is_format_valid 'user' +is_object_valid 'user' 'USER' "$user" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +# Checking user homedir +homedir=$(grep "^$user:" /etc/passwd | cut -f 6 -d :) +if [ -z "$homedir" ]; then + echo "Error: user home directory doesn't exist" + exit 12 +fi + +# Checking archive +if [ -e "$archive" ]; then + echo "Error: archive already exist $archive" + exit 1 +fi + +# Checking source path +IFS=$'\n' +i=1 +for src in $*; do + if [ "$i" -gt 2 ]; then + rpath=$(readlink -f "$src") + if [ -z "$(echo $rpath | egrep "^/tmp|^$homedir")" ]; then + echo "Error: invalid source path $src" + exit 1 + fi + fi + ((i++)) +done + +i=1 +for src in $*; do + if [ "$i" -gt 2 ]; then + # Deleting leading home path + src=$(echo "$src" | sed -e "s|/home/$user/||") + + # Creating tar.gz archive + user_exec tar -rf "${archive/.gz/}" -C /home/$user $src > /dev/null 2>&1 + if [ "$?" -ne 0 ]; then + echo "Error: archive $archive was not created" + exit 3 + fi + fi + ((i++)) +done + +# Checking gzip +if [[ "$archive" =~ \.gz$ ]]; then + user_exec gzip "${archive/.gz/}" > /dev/null 2>&1 + if [ "$?" -ne 0 ]; then + echo "Error: archive $archive was not gziped" + exit 3 + fi +fi + +exit diff --git a/bin/v-add-fs-directory b/bin/v-add-fs-directory new file mode 100755 index 0000000..497d675 --- /dev/null +++ b/bin/v-add-fs-directory @@ -0,0 +1,55 @@ +#!/bin/bash +# info: add directory +# options: USER DIRECTORY +# +# example: v-add-fs-directory admin mybar +# +# This function creates new directory on the file system + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +user=$1 +dst_dir=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DIR' +is_format_valid 'user' +is_object_valid 'user' 'USER' "$user" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +# Checking user homedir +homedir=$(grep "^$user:" /etc/passwd | cut -f 6 -d :) +if [ -z "$homedir" ]; then + echo "Error: user home directory doesn't exist" + exit 12 +fi + +# Checking destination path +rpath=$(readlink -f "$dst_dir") +if [ -z "$(echo $rpath | egrep "^/tmp|^$homedir")" ]; then + echo "Error: invalid destination path $dst_dir" + exit 2 +fi + +# Adding directory +user_exec mkdir -p "$dst_dir" > /dev/null 2>&1 +if [ $? -ne 0 ]; then + echo "Error: directory $dst_dir was not created" + exit 3 +fi + +# Exiting +exit diff --git a/bin/v-add-fs-file b/bin/v-add-fs-file new file mode 100755 index 0000000..fc86309 --- /dev/null +++ b/bin/v-add-fs-file @@ -0,0 +1,55 @@ +#!/bin/bash +# info: add file +# options: USER FILE +# +# example: v-add-fs-file admin readme.md +# +# This function creates new files on file system + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +user=$1 +dst_file=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER FILE' +is_format_valid 'user' +is_object_valid 'user' 'USER' "$user" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +# Checking user homedir +homedir=$(grep "^$user:" /etc/passwd | cut -f 6 -d :) +if [ -z $homedir ]; then + echo "Error: user home directory doesn't exist" + exit 12 +fi + +# Checking destination path +rpath=$(readlink -f "$dst_file") +if [ -z "$(echo $rpath | egrep "^/tmp|^$homedir")" ]; then + echo "Error: invalid destination path $dst_file" + exit 2 +fi + +# Creating file +user_exec touch "$dst_file" > /dev/null 2>&1 +if [ $? -ne 0 ]; then + echo "Error: file $dst_file was not created" + exit 3 +fi + +# Exiting +exit diff --git a/bin/v-add-letsencrypt-domain b/bin/v-add-letsencrypt-domain new file mode 100755 index 0000000..7a98ef5 --- /dev/null +++ b/bin/v-add-letsencrypt-domain @@ -0,0 +1,629 @@ +#!/bin/bash +# info: check letsencrypt domain +# options: USER DOMAIN [ALIASES] [MAIL] +# +# example: v-add-letsencrypt-domain admin wonderland.com www.wonderland.com,demo.wonderland.com +# example: v-add-letsencrypt-domain admin wonderland.com '' yes +# +# This function check and validates domain with Let's Encrypt + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +aliases=$3 +mail=${4// /} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# LE API +LE_API='https://acme-v02.api.letsencrypt.org' + +if [[ "$LE_STAGING" = 'yes' ]]; then + LE_API='https://acme-staging-v02.api.letsencrypt.org' +fi + +# encode base64 +encode_base64() { + cat | base64 | tr '+/' '-_' | tr -d '\r\n=' +} + +# Let's Encrypt v2 curl function +query_le_v2() { + protected='{"nonce": "'$3'",' + protected=''$protected' "url": "'$1'",' + protected=''$protected' "alg": "RS256", "kid": "'$KID'"}' + content="Content-Type: application/jose+json" + + payload_=$(echo -n "$2" | encode_base64) + protected_=$(echo -n "$protected" | encode_base64) + signature_=$(printf "%s" "$protected_.$payload_" \ + | openssl dgst -sha256 -binary -sign $USER_DATA/ssl/user.key \ + | encode_base64) + + post_data='{"protected":"'"$protected_"'",' + post_data=$post_data'"payload":"'"$payload_"'",' + post_data=$post_data'"signature":"'"$signature_"'"}' + + # Save http response to file passed as "$4" arg or print to stdout if not provided + # http response headers are always sent to stdout + local save_to_file=${4:-"/dev/stdout"} + curl --location --user-agent "HestiaCP" --insecure --retry 5 --retry-connrefused --silent --dump-header /dev/stdout --data "$post_data" "$1" --header "$content" --output "$save_to_file" + debug_log "API call" "exit status: $?" +} + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DOMAIN [ALIASES] [MAIL]' +is_format_valid 'user' 'domain' 'aliases' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +if [ -n "$mail" ]; then + is_boolean_format_valid "$mail" 'mail' +fi + +# Set DNS CAA record retrieval commands +if [ -n "$DNS_SYSTEM" ]; then + dns_domain=$($BIN/v-list-dns-domains "$user" | grep "$domain" | cut -d' ' -f1) + caa_record=$($BIN/v-list-dns-records "$user" "$domain" | grep -i "CAA" | grep -i "letsencrypt.org" | cut -d' ' -f1) +fi + +if [ -z "$mail" ] || [ "$mail" = 'no' ]; then + mail='' + is_system_enabled "$WEB_SYSTEM" 'WEB_SYSTEM' + is_object_valid 'web' 'DOMAIN' "$domain" + is_object_unsuspended 'web' 'DOMAIN' "$domain" + get_domain_values 'web' + # check if alias is the letsencrypt wildcard domain, if not, make the normal checks + if [[ "$aliases" != "*.$domain" ]]; then + for alias in $(echo "$aliases" | tr ',' '\n' | sort -u); do + check_alias="$(echo $ALIAS | tr ',' '\n' | grep ^$alias$)" + if [ -z "$check_alias" ]; then + check_result "$E_NOTEXIST" "domain alias $alias doesn't exist" + fi + done + fi +else + is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM' + is_object_valid 'mail' 'DOMAIN' "$domain" + is_object_unsuspended 'mail' 'DOMAIN' "$domain" +fi + +# Dump debug info +debug_log() { + echo -e "\n==[${1}]==\n${2}\n" >> "$log_file" +} + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Generate correct variables for mail domain SSL certificates +if [ -n "$mail" ]; then + root_domain=$domain + domain="mail.$root_domain" + webmail=$(get_object_value "mail" "DOMAIN" "$root_domain" '$WEBMAIL') + if [ -n "$webmail" ]; then + aliases="$WEBMAIL_ALIAS.$root_domain" + fi +else + parse_object_kv_list $(grep "DOMAIN='$domain'" $USER_DATA/web.conf) + + domain_redirect="$REDIRECT" + if [[ -n "$domain_redirect" ]]; then + domain_redirect_code="$REDIRECT_CODE" + $BIN/v-delete-web-domain-redirect $user $domain + fi + + domain_forcessl="$SSL_FORCE" + if [[ "$domain_forcessl" == 'yes' ]]; then + $BIN/v-delete-web-domain-ssl-force $user $domain + fi +fi + +log_file="/var/log/hestia/LE-${user}-${domain}.log" +touch "$log_file" +chmod 600 "$log_file" + +echo -e "\n\n============================= +Date Time: $(date +%Y-%m-%d) $(date +%H:%M:%S) +WEB_SYSTEM: ${WEB_SYSTEM} +PROXY_SYSTEM: ${PROXY_SYSTEM} +user: ${user} +domain: ${domain} +" >> "$log_file" + +# Registering LetsEncrypt user account +$BIN/v-add-letsencrypt-user $user +if [ "$?" -ne 0 ]; then + touch $HESTIA/data/queue/letsencrypt.pipe + sed -i "/ $domain /d" $HESTIA/data/queue/letsencrypt.pipe + send_notice "LETSENCRYPT" "Account registration failed ($user)" + check_result "$E_CONNECT" "LE account registration ($user)" > /dev/null +fi + +# Parsing LetsEncrypt account data +source $USER_DATA/ssl/le.conf + +# Checking wildcard alias +if [ "$aliases" = "*.$domain" ]; then + wildcard='yes' + proto="dns-01" + if [ ! -e "$HESTIA/data/users/$user/dns/$domain.conf" ]; then + check_result "$E_NOTEXIST" "DNS domain $domain doesn't exist" + fi +else + proto="http-01" +fi + +echo -e " +- aliases: ${aliases} +- proto: ${proto} +- wildcard: ${wildcard} +" >> "$log_file" + +# Check if dns records exist for requested domain/aliases +if [ "$proto" = "http-01" ]; then + for identifier in $(echo $domain,$aliases | tr ',' '\n' | sort -u); do + if [[ "$identifier" = *[![:ascii:]]* ]]; then + identifier=$(idn2 --quiet $identifier) + fi + if ! nslookup "${identifier}" > /dev/null 2>&1; then + # Attempt against Cloudflare DNS + if ! nslookup "${identifier}" 1.1.1.1 > /dev/null 2>&1; then + check_result "$E_NOTEXIST" "DNS record for $identifier doesn't exist" + fi + fi + done +fi + +# Ensure DNS CAA record exists for Let's Encrypt before requesting certificate +if [ -n "$DNS_SYSTEM" ]; then + # Check for DNS zone + if [ "$dns_domain" = "$domain" ]; then + # Replace DNS domain CAA records with Let's Encrypt values + if [ -z "$caa_record" ]; then + $BIN/v-add-dns-record "$user" "$domain" '@' 'CAA' '0 issue "letsencrypt.org"' + else + $BIN/v-delete-dns-record "$user" "$domain" "$caa_record" + $BIN/v-add-dns-record "$user" "$domain" '@' 'CAA' '0 issue "letsencrypt.org"' + fi + fi +fi + +# Requesting nonce / STEP 1 +answer=$(curl --user-agent "HestiaCP" -s -I "$LE_API/directory") +nonce=$(echo "$answer" | grep -i nonce | cut -f2 -d \ | tr -d '\r\n') +status=$(echo "$answer" | grep HTTP/ | tail -n1 | cut -f 2 -d ' ') + +debug_log "Step 1" "- status: ${status}\n- nonce: ${nonce}\n- answer: ${answer}" + +if [[ "$status" -ne 200 ]]; then + # Delete DNS CAA record + if [ -n "$DNS_SYSTEM" ]; then + if [ "$dns_domain" = "$domain" ]; then + if [ -n "$caa_record" ]; then + $BIN/v-delete-dns-record "$user" "$domain" "$caa_record" + fi + fi + fi + check_result "$E_CONNECT" "Let's Encrypt nonce request status $status ($domain)" +fi + +# Placing new order / STEP 2 +url="$LE_API/acme/new-order" +payload='{"identifiers":[' +for identifier in $(echo $domain,$aliases | tr ',' '\n' | sort -u); do + if [[ "$identifier" = *[![:ascii:]]* ]]; then + identifier=$(idn2 --quiet $identifier) + fi + payload=$payload'{"type":"dns","value":"'$identifier'"},' +done +payload=$(echo "$payload" | sed "s/,$//") +payload=$payload']}' +answer=$(query_le_v2 "$url" "$payload" "$nonce") +nonce=$(echo "$answer" | grep -i nonce | cut -f2 -d \ | tr -d '\r\n') +authz=$(echo "$answer" | grep "acme/authz" | cut -f2 -d '"') +finalize=$(echo "$answer" | grep 'finalize":' | cut -f4 -d '"') +status=$(echo "$answer" | grep HTTP/ | tail -n1 | cut -f2 -d ' ') +order=$(echo -e "$answer" | grep -i location | cut -f2 -d \ | tr -d '\r\n') + +debug_log "Step 2" "- status: ${status}\n- nonce: ${nonce}\n- authz: ${authz}\n- finalize: ${finalize}\n- payload: ${payload}\n- answer: ${answer}\n order: ${order}" + +if [[ "$status" -ne 201 ]]; then + # Delete DNS CAA record + if [ -n "$DNS_SYSTEM" ]; then + if [ "$dns_domain" = "$domain" ]; then + if [ -n "$caa_record" ]; then + $BIN/v-delete-dns-record "$user" "$domain" "$caa_record" + fi + fi + fi + check_result $E_CONNECT "Let's Encrypt new auth status $status ($domain)" +fi + +# Requesting authorization token / STEP 3 +for auth in $authz; do + payload='' + answer=$(query_le_v2 "$auth" "$payload" "$nonce") + url=$(echo "$answer" | grep -A3 $proto | grep -m1 url | cut -f 4 -d \") + token=$(echo "$answer" | grep -A3 $proto | grep token | cut -f 4 -d \") + nonce=$(echo "$answer" | grep -i nonce | cut -f2 -d \ | tr -d '\r\n') + status=$(echo "$answer" | grep HTTP/ | tail -n1 | cut -f 2 -d ' ') + + debug_log "Step 3" "- status: ${status}\n- nonce: ${nonce}\n- url: ${url}\n- token: ${token}\n- answer: ${answer}" + + if [[ "$status" -ne 200 ]]; then + # Delete DNS CAA record + if [ -n "$DNS_SYSTEM" ]; then + dns_domain=$($BIN/v-list-dns-domains "$user" | grep "$domain" | cut -d' ' -f1) + caa_record=$($BIN/v-list-dns-records "$user" "$domain" | grep -i "letsencrypt" | cut -d' ' -f1) + + if [ "$dns_domain" = "$domain" ]; then + if [ -n "$caa_record" ]; then + $BIN/v-delete-dns-record "$user" "$domain" "$caa_record" + fi + fi + fi + check_result "$E_CONNECT" "Let's Encrypt acme/authz bad status $status ($domain)" + fi + + # Accepting challenge / STEP 4 + if [ "$wildcard" = 'yes' ]; then + record=$(printf "%s" "$token.$THUMB" \ + | openssl dgst -sha256 -binary | encode_base64) + old_records=$($BIN/v-list-dns-records "$user" "$domain" plain | grep 'TXT') + old_records=$(echo "$old_records" | grep _acme-challenge | cut -f 1) + for old_record in $old_records; do + $BIN/v-delete-dns-record "$user" "$domain" "$old_record" + done + $BIN/v-add-dns-record "$user" "$domain" "_acme-challenge" "TXT" "$record" + check_result $? "DNS _acme-challenge record wasn't created ($domain)" + else + if [ -z "$mail" ]; then + if [ "$WEB_SYSTEM" = 'nginx' ] || [ "$PROXY_SYSTEM" = 'nginx' ]; then + conf="$HOMEDIR/$user/conf/web/$domain/nginx.conf_letsencrypt" + sconf="$HOMEDIR/$user/conf/web/$domain/nginx.ssl.conf_letsencrypt" + echo 'location ~ "^/\.well-known/acme-challenge/([-_A-Za-z0-9]+)$" {' \ + > $conf + echo ' default_type text/plain;' >> $conf + echo ' return 200 "$1.'$THUMB'";' >> $conf + echo '}' >> $conf + if [ ! -e "$sconf" ]; then + ln -s "$conf" "$sconf" + fi + if [ -n "$PROXY_SYSTEM" ]; then + $BIN/v-restart-proxy + check_result $? "Proxy restart failed" > /dev/null + fi + else + # Get root directory from configuration + domain_config="$HOMEDIR/$user/conf/web/$domain" + if [ -f "$domain_config/apache2.conf" ]; then + well_known="$(cat $domain_config/apache2.conf | egrep \ + '^\s+DocumentRoot' | awk '{split($0, a, " "); \ + print a[2]}')/.well-known" + else + well_known="$(cat $domain_config/nginx.conf | egrep '^\s+root' \ + | awk '{split($0, a, " "); print a[2]}' \ + | sed 's/;$//')/.well-known" + fi + acme_challenge="$well_known/acme-challenge" + mkdir -p $acme_challenge + echo "$token.$THUMB" > $acme_challenge/$token + chown -R $user:$user $well_known + fi + else + if [ "$WEB_SYSTEM" = 'nginx' ] || [ "$PROXY_SYSTEM" = 'nginx' ]; then + conf="$HOMEDIR/$user/conf/mail/$root_domain/nginx.conf_letsencrypt" + sconf="$HOMEDIR/$user/conf/mail/$root_domain/nginx.ssl.conf_letsencrypt" + echo 'location ~ "^/\.well-known/acme-challenge/([-_A-Za-z0-9]+)$" {' \ + > $conf + echo ' default_type text/plain;' >> $conf + echo ' return 200 "$1.'$THUMB'";' >> $conf + echo '}' >> $conf + if [ ! -e "$sconf" ]; then + ln -s "$conf" "$sconf" + fi + if [ -n "$PROXY_SYSTEM" ]; then + $BIN/v-restart-proxy + check_result $? "Proxy restart failed" > /dev/null + fi + else + get_object_value 'mail' 'DOMAIN' "$root_domain" "WEBMAIL" + if [ -n "$WEBMAIL" ]; then + well_known="/var/lib/$WEBMAIL/.well-known" + acme_challenge="$well_known/acme-challenge" + mkdir -p $acme_challenge + echo "$token.$THUMB" > $acme_challenge/$token + chown -R $user:$user $well_known + fi + fi + fi + if [ "$WEB_SYSTEM" = 'nginx' ]; then + $BIN/v-restart-web + check_result $? "Web restart failed" > /dev/null + fi + fi + + if [ "$DNS_CLUSTER" = "yes" ]; then + $BIN/v-update-sys-queue dns-cluster + fi + + # Requesting ACME validation / STEP 5 + validation_check=$(echo "$answer" | grep '"valid"') + if [[ -n "$validation_check" ]]; then + validation='valid' + else + validation='pending' + sleep 5 + fi + + # Doing pol check on status + i=1 + while [ "$validation" = 'pending' ]; do + payload='{}' + answer=$(query_le_v2 "$url" "$payload" "$nonce") + validation=$(echo "$answer" | grep -A1 $proto | tail -n1 | cut -f4 -d \") + nonce=$(echo "$answer" | grep -i nonce | cut -f2 -d \ | tr -d '\r\n') + status=$(echo "$answer" | grep HTTP/ | tail -n1 | cut -f 2 -d ' ') + details=$(echo "$answer" | grep detail | cut -f 1 -d ',' | cut -f 2-4 -d ':' | cut -f 2 -d '"') + + debug_log "Step 5" "- status: ${status}\n- url: ${url}\n- nonce: ${nonce}\n- validation: ${validation}\n- details: ${details}\n- answer: ${answer}" + + if [[ "$status" -ne 200 ]]; then + # Delete DNS CAA record + if [ -n "$DNS_SYSTEM" ]; then + dns_domain=$($BIN/v-list-dns-domains "$user" | grep "$domain" | cut -d' ' -f1) + caa_record=$($BIN/v-list-dns-records "$user" "$domain" | grep -i "letsencrypt" | cut -d' ' -f1) + + if [ "$dns_domain" = "$domain" ]; then + if [ -n "$caa_record" ]; then + $BIN/v-delete-dns-record "$user" "$domain" "$caa_record" + fi + fi + fi + # Download debug info from LE server + result=$(wget -qO- $url) + debug_log "Debug information Step 5" "$result" + details=$(echo $result | jq '.error.detail') + error_code=$(echo $result | jq '.error.status') + + debug_log "Abort Step 5" "=> Wrong status" + check_result "$E_CONNECT" "Let's Encrypt validation status $status ($domain). Details: $error_code:$details" + fi + + i=$((i + 1)) + if [ "$i" -gt 10 ]; then + # Delete DNS CAA record + if [ -n "$DNS_SYSTEM" ]; then + dns_domain=$($BIN/v-list-dns-domains "$user" | grep "$domain" | cut -d' ' -f1) + caa_record=$($BIN/v-list-dns-records "$user" "$domain" | grep -i "letsencrypt" | cut -d' ' -f1) + + if [ "$dns_domain" = "$domain" ]; then + if [ -n "$caa_record" ]; then + $BIN/v-delete-dns-record "$user" "$domain" "$caa_record" + fi + fi + fi + debug_log "Abort Step 5" "=> Too many validation retries" + check_result "$E_CONNECT" "Let's Encrypt domain validation timeout ($domain)" + fi + sleep $((i * 2)) + done + if [ "$validation" = 'invalid' ]; then + # Delete DNS CAA record + if [ -n "$DNS_SYSTEM" ]; then + dns_domain=$($BIN/v-list-dns-domains "$user" | grep "$domain" | cut -d' ' -f1) + caa_record=$($BIN/v-list-dns-records "$user" "$domain" | grep -i "letsencrypt" | cut -d' ' -f1) + + if [ "$dns_domain" = "$domain" ]; then + if [ -n "$caa_record" ]; then + $BIN/v-delete-dns-record "$user" "$domain" "$caa_record" + fi + fi + fi + check_result "$E_CONNECT" "Let's Encrypt domain verification failed ($domain)" + fi +done + +# Generating new ssl certificate +ssl_dir=$($BIN/v-generate-ssl-cert "$domain" "info@$domain" "US" "California" \ + "San Francisco" "Hestia" "IT" "$aliases" | tail -n1 | awk '{print $2}') + +# Sending CSR to finalize order / STEP 6 +csr=$(openssl req -in $ssl_dir/$domain.csr -outform DER | encode_base64) +payload='{"csr":"'$csr'"}' +answer=$(query_le_v2 "$finalize" "$payload" "$nonce") +nonce=$(echo "$answer" | grep -i nonce | cut -f2 -d \ | tr -d '\r\n') +status=$(echo "$answer" | grep HTTP/ | tail -n1 | cut -f 2 -d ' ') +certificate=$(echo "$answer" | grep 'certificate":' | cut -f4 -d '"') + +debug_log "Step 6" "- status: ${status}\n- nonce: ${nonce}\n- payload: ${payload}\n- certificate: ${certificate}\n- answer: ${answer}" + +if [[ "$status" -ne 200 ]]; then + [ -d "$ssl_dir" ] && rm -rf "$ssl_dir" + check_result "$E_CONNECT" "Let's Encrypt finalize bad status $status ($domain)" +fi + +if [ -z "$certificate" ]; then + validation="processing" + i=1 + while [ "$validation" = "processing" ]; do + answer=$(query_le_v2 "$order" "" "$nonce") + i=$((i + 1)) + + nonce=$(echo "$answer" | grep -i nonce | cut -f2 -d \ | tr -d '\r\n') + status=$(echo "$answer" | grep HTTP/ | tail -n1 | cut -f 2 -d ' ') + validation=$(echo "$answer" | grep 'status":' | cut -f4 -d '"') + certificate=$(echo "$answer" | grep 'certificate":' | cut -f4 -d '"') + sleep $((i * 2)) # Sleep for 2s, 4s, 6s, 8s + if [ $i -gt 10 ]; then + check_result "$E_CONNECT" "Certificate processing timeout ($domain)" + fi + debug_log "Step 7" "- status: ${status}\n- nonce: ${nonce}\n- payload: ${payload}\n- certificate: ${certificate}\n- answer: ${answer}" + done +fi + +# Downloading signed certificate / STEP 7 +status=0 +retry=0 + +while [[ $status != 200 && $retry -lt 3 ]]; do + + answer=$(query_le_v2 "$certificate" "" "$nonce" "$ssl_dir/$domain.pem") + status=$(echo "$answer" | grep HTTP/ | tail -n1 | cut -f 2 -d ' ') + + debug_log "Step 8" "- status: ${status}\n- retry: ${retry}\n- answer: ${answer}" + + if [[ $status != 200 ]]; then + retry=$((retry + 1)) + sleep $((retry * 2)) # Sleep for 2s, 4s, 6s, 8s + fi + +done + +# Fallback on depreciated download method for certs (unauthenticated GET) +if [[ $status != 200 ]]; then + answer=$(curl --insecure --user-agent "HestiaCP" --retry 5 --retry-connrefused --silent --dump-header /dev/stdout "$certificate" --output "$ssl_dir/$domain.pem") + status=$(echo "$answer" | grep HTTP/ | tail -n1 | cut -f 2 -d ' ') + + debug_log "Step 8 - Fallback" "- status: ${status}\n- answer: ${answer}" +fi + +debug_log "CERT DIR" "$(ls -las "$ssl_dir/")" +debug_log "CERT PEM" "$(cat "$ssl_dir/$domain.pem")" + +if [[ "$status" -ne 200 ]]; then + [ -d "$ssl_dir" ] && rm -rf "$ssl_dir" + check_result "$E_NOTEXIST" "Let's Encrypt downloading signed cert failed status:$status ($domain)" +fi + +# Splitting up downloaded pem +crt_end=$(grep -n 'END CERTIFICATE' $ssl_dir/$domain.pem | head -n1 | cut -f1 -d:) +head -n $crt_end $ssl_dir/$domain.pem > $ssl_dir/$domain.crt + +pem_lines=$(wc -l $ssl_dir/$domain.pem | cut -f 1 -d ' ') +ca_end=$(grep -n 'BEGIN CERTIFICATE' $ssl_dir/$domain.pem | tail -n1 | cut -f 1 -d :) +ca_end=$((pem_lines - crt_end + 1)) +tail -n $ca_end $ssl_dir/$domain.pem > $ssl_dir/$domain.ca + +debug_log "CERT CRT" "$(cat "$ssl_dir/$domain.crt")" +debug_log "CERT CA-1" "$(cat "$ssl_dir/$domain.ca")" +# Temporary fix for double "END CERTIFICATE" +if [[ $(head -n 1 $ssl_dir/$domain.ca) = "-----END CERTIFICATE-----" ]]; then + sed -i '1,2d' $ssl_dir/$domain.ca +fi +debug_log "CERT CA-2" "$(cat "$ssl_dir/$domain.ca")" + +# Rename certs for mail +if [ -n "$mail" ]; then + mv $ssl_dir/$domain.ca $ssl_dir/$root_domain.ca + mv $ssl_dir/$domain.crt $ssl_dir/$root_domain.crt + mv $ssl_dir/$domain.csr $ssl_dir/$root_domain.csr + mv $ssl_dir/$domain.key $ssl_dir/$root_domain.key + mv $ssl_dir/$domain.pem $ssl_dir/$root_domain.pem +fi + +# Adding SSL +if [ -z "$mail" ]; then + ssl_home="$(get_object_value 'web' 'DOMAIN' "$domain" '$SSL_HOME')" + ssl_enabled="$(get_object_value 'web' 'DOMAIN' "$domain" '$SSL')" + if [ "$ssl_enabled" = "yes" ]; then + $BIN/v-update-web-domain-ssl "$user" "$domain" "$ssl_dir" "updatessl" + else + $BIN/v-add-web-domain-ssl "$user" "$domain" "$ssl_dir" "$ssl_home" "updatessl" + fi +else + # TODO replace with v-update-mail-domain-ssl if ssl is enabled + ssl_enabled="$(get_object_value 'mail' 'DOMAIN' "$root_domain" '$SSL')" + if [ "$ssl_enabled" = "yes" ]; then + $BIN/v-update-mail-domain-ssl "$user" "$root_domain" "$ssl_dir" "updatessl" + else + $BIN/v-add-mail-domain-ssl "$user" "$root_domain" "$ssl_dir" "updatessl" + fi +fi + +if [ "$?" -ne '0' ]; then + [ -d "$ssl_dir" ] && rm -rf "$ssl_dir" + touch $HESTIA/data/queue/letsencrypt.pipe + sed -i "/ $domain /d" $HESTIA/data/queue/letsencrypt.pipe + send_notice 'LETSENCRYPT' "$domain certificate installation failed ($domain)" + check_result $? "SSL install" > /dev/null +fi + +# Adding LE autorenew cronjob +if [ -z "$(grep v-update-lets $HESTIA/data/users/admin/cron.conf)" ]; then + min=$(generate_password '012345' '2') + hour=$(generate_password '1234567' '1') + cmd="sudo $BIN/v-update-letsencrypt-ssl" + $BIN/v-add-cron-job admin "$min" "$hour" '*' '*' '*' "$cmd" > /dev/null +fi + +# Updating letsencrypt key +if [ -z "$mail" ]; then + if [ -z "$LETSENCRYPT" ]; then + add_object_key "web" 'DOMAIN' "$domain" 'LETSENCRYPT' 'FTP_USER' + add_object_key "web" 'DOMAIN' "$domain" 'LETSENCRYPT_FAIL_COUNT' 'LETSENCRYPT' + fi + update_object_value 'web' 'DOMAIN' "$domain" '$LETSENCRYPT' 'yes' + update_object_value 'web' 'DOMAIN' "$domain" '$LETSENCRYPT_FAIL_COUNT' "0" + + if [[ "$domain_forcessl" == 'yes' ]]; then + $BIN/v-add-web-domain-ssl-force $user $domain + fi + if [[ -n "$domain_redirect" ]]; then + $BIN/v-add-web-domain-redirect $user $domain $domain_redirect $domain_redirect_code + fi + +else + if [ -z "$LETSENCRYPT" ]; then + add_object_key "mail" 'DOMAIN' "$root_domain" 'LETSENCRYPT' + add_object_key "mail" 'DOMAIN' "$root_domain" 'LETSENCRYPT_FAIL_COUNT' 'LETSENCRYPT' + fi + update_object_value 'mail' 'DOMAIN' "$root_domain" '$LETSENCRYPT' 'yes' + update_object_value 'mail' 'DOMAIN' "$root_domain" '$LETSENCRYPT_FAIL_COUNT' "0" +fi + +# Remove challenge folder if exist +if [ -n "$well_known" ]; then + rm -fr $well_known +fi + +# Remove temporary SSL folder +[ -d "$ssl_dir" ] && rm -rf "$ssl_dir" + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Deleting task from queue +touch $HESTIA/data/queue/letsencrypt.pipe +sed -i "/ $domain /d" $HESTIA/data/queue/letsencrypt.pipe + +# Notifying user +send_notice 'LETSENCRYPT' "$domain SSL has been installed successfully" + +# Logging +log_event "$OK" "$ARGUMENTS" + +# Cleanup debug since the SSL was issues successfully +rm -f "$log_file" + +exit diff --git a/bin/v-add-letsencrypt-host b/bin/v-add-letsencrypt-host new file mode 100755 index 0000000..9817aef --- /dev/null +++ b/bin/v-add-letsencrypt-host @@ -0,0 +1,98 @@ +#!/bin/bash +# info: add letsencrypt for host and backend +# options: NONE +# +# example: v-add-letsencrypt-host +# +# This function check and validates the backend certificate and generate +# a new let's encrypt certificate. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +# Argument definition +domain=$(hostname -f) +if [ -z $domain ]; then + domain=$HOSTNAME +fi +user="$($BIN/v-search-domain-owner "$domain" web)" +[[ -z "$user" ]] && user="admin" + +USER_DATA=$HESTIA/data/users/$user + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +is_format_valid 'user' 'domain' 'aliases' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_system_enabled "$WEB_SYSTEM" 'WEB_SYSTEM' + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Check if hostname already exists as domain +if [ "$($BIN/v-list-web-domain $user $domain plain | cut -f 1)" != "$domain" ]; then + # Create web domain for hostname + $BIN/v-add-web-domain "$user" "$domain" +fi + +# Validate web domain +is_object_valid 'web' 'DOMAIN' "$domain" +is_object_unsuspended 'web' 'DOMAIN' "$domain" +get_domain_values 'web' + +# Load domain data +parse_object_kv_list $(grep "DOMAIN='$domain'" $USER_DATA/web.conf) + +# Set ssl installation to yes +add_ssl="yes" + +if [ "$SSL" = "yes" ]; then + # Valildate SSL Certificate + if [ -e "$USER_DATA/ssl/$domain.ca" ]; then + if openssl verify -CAfile <(openssl x509 -in $USER_DATA/ssl/$domain.ca) $USER_DATA/ssl/$domain.pem | grep -q "$domain.pem: OK"; then + add_ssl="no" + fi + else + if openssl verify $USER_DATA/ssl/$domain.pem | grep -q "$domain.pem: OK"; then + add_ssl="no" + fi + fi +fi + +# Add let's encrypt ssl if needed +if [ "$add_ssl" = "yes" ]; then + # Add let's encrypt ssl + $BIN/v-add-letsencrypt-domain "$user" "$domain" + check_result $? "Let's Encrypt SSL creation failed" "$E_UPDATE" +fi + +# Add certificate to backend +$BIN/v-update-host-certificate "$user" "$domain" + +# Enable automatic ssl forward and hsts +$BIN/v-add-web-domain-ssl-force "$user" "$domain" > /dev/null 2>&1 +$BIN/v-add-web-domain-ssl-hsts "$user" "$domain" > /dev/null 2>&1 + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-add-letsencrypt-user b/bin/v-add-letsencrypt-user new file mode 100755 index 0000000..ba4b01c --- /dev/null +++ b/bin/v-add-letsencrypt-user @@ -0,0 +1,148 @@ +#!/bin/bash +# info: register letsencrypt user account +# options: USER +# +# example: v-add-letsencrypt-user bob +# +# This function creates and register LetsEncrypt account + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# LE API +LE_API='https://acme-v02.api.letsencrypt.org' + +if [[ "$LE_STAGING" = 'yes' ]]; then + LE_API='https://acme-staging-v02.api.letsencrypt.org' +fi + +# encode base64 +encode_base64() { + cat | base64 | tr '+/' '-_' | tr -d '\r\n=' +} + +# Let's Encrypt v2 curl function +query_le_v2() { + protected='{"nonce": "'$3'",' + protected=''$protected' "url": "'$1'",' + protected=''$protected' "alg": "RS256", "jwk": '$jwk'}' + content="Content-Type: application/jose+json" + + payload_=$(echo -n "$2" | encode_base64) + protected_=$(echo -n "$protected" | encode_base64) + signature_=$(printf "%s" "$protected_.$payload_" \ + | openssl dgst -sha256 -binary -sign $USER_DATA/ssl/user.key \ + | encode_base64) + + post_data='{"protected":"'"$protected_"'",' + post_data=$post_data'"payload":"'"$payload_"'",' + post_data=$post_data'"signature":"'"$signature_"'"}' + + curl --user-agent "HestiaCP" -s -i -d "$post_data" "$1" -H "$content" +} + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'USER' +is_format_valid 'user' +is_object_valid 'user' 'USER' "$user" +if [ -e "$USER_DATA/ssl/le.conf" ]; then + source "$USER_DATA/ssl/le.conf" +fi +if [ -n "$KID" ]; then + exit +fi + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Defining user email +if [[ -z "$EMAIL" ]]; then + EMAIL=$(get_user_value '$CONTACT') +fi + +# Defining user agreement +agreement='' + +# Generating user key +KEY="$USER_DATA/ssl/user.key" +if [ ! -e "$KEY" ]; then + openssl genrsa -out "$KEY" 4096 > /dev/null 2>&1 + chmod 600 $KEY +fi + +# Defining key exponent +if [ -z "$EXPONENT" ]; then + EXPONENT=$(openssl pkey -inform pem -in "$KEY" -noout -text_pub \ + | grep Exponent: | cut -f 2 -d '(' | cut -f 1 -d ')' | sed -e 's/x//' \ + | xxd -r -p | encode_base64) +fi + +# Defining key modulus +if [ -z "$MODULUS" ]; then + MODULUS=$(openssl rsa -in "$KEY" -modulus -noout \ + | sed -e 's/^Modulus=//' | xxd -r -p | encode_base64) +fi + +# Defining JWK +jwk='{"e":"'$EXPONENT'","kty":"RSA","n":"'"$MODULUS"'"}' + +# Defining key thumbnail +if [ -z "$THUMB" ]; then + THUMB="$(echo -n "$jwk" | openssl dgst -sha256 -binary | encode_base64)" +fi + +# Requesting ACME nonce +nonce=$(curl -s -I "$LE_API/directory" | grep -i nonce | cut -f2 -d\ | tr -d '\r\n') + +# Creating ACME account +url="$LE_API/acme/new-acct" +payload='{"termsOfServiceAgreed": true}' +answer=$(query_le_v2 "$url" "$payload" "$nonce") +kid=$(echo "$answer" | grep -i location: | cut -f2 -d ' ' | tr -d '\r') + +# Checking answer status +status=$(echo "$answer" | grep HTTP/ | tail -n1 | cut -f2 -d ' ') +if [[ "${status:0:2}" -ne "20" ]]; then + check_result "$E_CONNECT" "Let's Encrypt acc registration failed $status" +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Adding le.conf +if [ ! -e "$USER_DATA/ssl/le.conf" ]; then + echo "EXPONENT='$EXPONENT'" > $USER_DATA/ssl/le.conf + echo "MODULUS='$MODULUS'" >> $USER_DATA/ssl/le.conf + echo "THUMB='$THUMB'" >> $USER_DATA/ssl/le.conf + echo "EMAIL='$EMAIL'" >> $USER_DATA/ssl/le.conf + echo "KID='$kid'" >> $USER_DATA/ssl/le.conf + chmod 660 $USER_DATA/ssl/le.conf +else + sed -i '/^KID=/d' $USER_DATA/ssl/le.conf + echo "KID='$kid'" >> $USER_DATA/ssl/le.conf +fi + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-add-mail-account b/bin/v-add-mail-account new file mode 100755 index 0000000..2459678 --- /dev/null +++ b/bin/v-add-mail-account @@ -0,0 +1,139 @@ +#!/bin/bash +# info: add mail domain account +# options: USER DOMAIN ACCOUNT PASSWORD [QUOTA] +# +# example: v-add-mail-account user example.com john P4$$vvOrD +# +# This function add new email account. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 +account=$3 +password=$4 +HIDE=4 +quota=${5-unlimited} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# shellcheck source=/usr/local/hestia/func/syshealth.sh +source $HESTIA/func/syshealth.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +if [[ "$account" =~ [[:upper:]] ]]; then + account=$(echo "$account" | tr '[:upper:]' '[:lower:]') +fi + +format_domain +format_domain_idn + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '4' "$#" 'USER DOMAIN ACCOUNT PASSWORD [QUOTA]' +is_format_valid 'user' 'domain' 'account' +if [ "$quota" != 'unlimited' ]; then + is_format_valid 'quota' +fi +is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'mail' 'DOMAIN' "$domain" +is_object_unsuspended 'mail' 'DOMAIN' "$domain" +is_package_full 'MAIL_ACCOUNTS' +is_mail_new "$account" +is_password_valid + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Generating hashed password + +if [ -n "$(doveadm pw -l | grep BLF-CRYPT)" ]; then + set +H # disable ! style history substitution + md5="$(doveadm pw -s BLF-CRYPT -p "$password")" +elif [ -n "$(doveadm pw -l | grep ARGON2ID)" ]; then + # Fall back on Argon2id if bcrypt is not available + set +H # disable ! style history substitution + md5="$(doveadm pw -s ARGON2ID -p "$password")" +else + # Fall back on MD5 if neither bcrypt nor argon2id is available + salt=$(generate_password "$PW_MATRIX" "8") + md5="{MD5}$($BIN/v-generate-password-hash md5 $salt <<< $password)" +fi +# Adding account info into password file +if [[ "$MAIL_SYSTEM" =~ exim ]]; then + if [ "$quota" = 'unlimited' ]; then + quota='0' + fi + str="$account:$md5:$user:mail::$HOMEDIR/$user:${quota}:userdb_quota_rule=*:storage=${quota}M" + echo $str >> $HOMEDIR/$user/conf/mail/$domain/passwd + userstr="$account:$account:$user:mail:$HOMEDIR/$user" + echo $userstr >> $HOMEDIR/$user/conf/mail/$domain/accounts +fi + +# Create mail account folder (mailbox) +mkdir $HOMEDIR/$user/mail/$domain_idn/$account +chown $user:mail $HOMEDIR/$user/mail/$domain_idn/$account +chmod 700 $HOMEDIR/$user/mail/$domain_idn/$account + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Generating timestamp +time_n_date=$(date +'%T %F') +time=$(echo "$time_n_date" | cut -f 1 -d \ ) +date=$(echo "$time_n_date" | cut -f 2 -d \ ) + +if [[ "$quota" -eq '0' ]]; then + quota='unlimited' +fi + +str="ACCOUNT='$account' ALIAS='' AUTOREPLY='no' FWD='' FWD_ONLY=''" +str="$str MD5='$md5' QUOTA='$quota' U_DISK='0' SUSPENDED='no'" +str="$str TIME='$time' DATE='$date'" +echo "$str" >> $USER_DATA/mail/$domain.conf +chmod 660 $USER_DATA/mail/$domain.conf + +syshealth_repair_mail_account_config + +touch $HOMEDIR/$user/conf/mail/$domain/limits + +user_rate_limit=$(get_object_value 'mail' 'DOMAIN' "$domain" '$RATE_LIMIT') +if [ -n "$user_rate_limit" ]; then + sed -i "/^$account@$domain_idn:/ d" $HOMEDIR/$user/conf/mail/$domain/limits + echo "$account@$domain_idn:$user_rate_limit" >> $HOMEDIR/$user/conf/mail/$domain/limits +else + system=$(cat /etc/exim4/limit.conf) + sed -i "/^$account@$domain_idn:/ d" $HOMEDIR/$user/conf/mail/$domain/limits + echo "$account@$domain_idn:$system" >> $HOMEDIR/$user/conf/mail/$domain/limits +fi + +# Increase mail accounts counter +accounts=$(wc -l $USER_DATA/mail/$domain.conf | cut -f 1 -d ' ') +increase_user_value "$user" '$U_MAIL_ACCOUNTS' +update_object_value 'mail' 'DOMAIN' "$domain" '$ACCOUNTS' "$accounts" + +# Logging +$BIN/v-log-action "$user" "Info" "Mail" "Added new mail account ($account@$domain)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-add-mail-account-alias b/bin/v-add-mail-account-alias new file mode 100755 index 0000000..9cad927 --- /dev/null +++ b/bin/v-add-mail-account-alias @@ -0,0 +1,80 @@ +#!/bin/bash +# info: add mail account alias aka nickname +# options: USER DOMAIN ACCOUNT ALIAS +# +# example: v-add-mail-account-alias admin acme.com alice alicia +# +# This function add new email alias. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 +account=$3 +malias=$4 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn +# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ? + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '4' "$#" 'USER DOMAIN ACCOUNT ALIAS' +is_format_valid 'user' 'domain' 'account' 'malias' +is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'mail' 'DOMAIN' "$domain" +is_object_unsuspended 'mail' 'DOMAIN' "$domain" +is_object_valid "mail/$domain" 'ACCOUNT' "$account" +is_object_unsuspended "mail/$domain" 'ACCOUNT' "$account" +is_mail_new "$malias" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Adding exim alias +if [[ "$MAIL_SYSTEM" =~ exim ]]; then + str="$malias@$domain_idn:$account@$domain_idn" + echo "$str" >> $HOMEDIR/$user/conf/mail/$domain/aliases +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Adding hestia alias +aliases=$(get_object_value "mail/$domain" 'ACCOUNT' "$account" '$ALIAS') +if [ -z "$aliases" ]; then + aliases="$malias" +else + aliases="$aliases,$malias" +fi +update_object_value "mail/$domain" 'ACCOUNT' "$account" '$ALIAS' "$aliases" + +# Logging +$BIN/v-log-action "$user" "Info" "Mail" "Added alias $malias to mail account $account@$domain." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-add-mail-account-autoreply b/bin/v-add-mail-account-autoreply new file mode 100755 index 0000000..d961603 --- /dev/null +++ b/bin/v-add-mail-account-autoreply @@ -0,0 +1,85 @@ +#!/bin/bash +# info: add mail account autoreply message +# options: USER DOMAIN ACCOUNT MESSAGE +# +# example: v-add-mail-account-autoreply admin example.com user Hello from e-mail! +# +# This function add new email account. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 +account=$3 +autoreply=$4 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Define mail user +if [ "$MAIL_SYSTEM" = 'exim4' ]; then + MAIL_USER=Debian-exim +else + MAIL_USER=exim +fi + +# Additional argument formatting +format_domain +format_domain_idn +# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ? + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '4' "$#" 'USER DOMAIN ACCOUNT MESSAGE' +is_format_valid 'user' 'domain' 'account' 'autoreply' +is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'mail' 'DOMAIN' "$domain" +is_object_unsuspended 'mail' 'DOMAIN' "$domain" +is_object_valid "mail/$domain" 'ACCOUNT' "$account" +is_object_unsuspended "mail/$domain" 'ACCOUNT' "$account" +# is_object_value_empty "mail/$domain" 'ACCOUNT' "$account" '$AUTOREPLY' + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Adding exim autoreply +if [[ "$MAIL_SYSTEM" =~ exim ]]; then + msg="$HOMEDIR/$user/conf/mail/$domain/autoreply.$account.msg" + echo -e "$autoreply" > $msg + chown $MAIL_USER:mail $msg + chmod 660 $msg +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Adding autoreply message +echo -e "$autoreply" > $USER_DATA/mail/$account@$domain.msg +chmod 660 $USER_DATA/mail/$account@$domain.msg +update_object_value "mail/$domain" 'ACCOUNT' "$account" '$AUTOREPLY' 'yes' + +# Logging +$BIN/v-log-action "$user" "Info" "Mail" "Added auto-reply message for mail account $account@$domain." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-add-mail-account-forward b/bin/v-add-mail-account-forward new file mode 100755 index 0000000..98e3d31 --- /dev/null +++ b/bin/v-add-mail-account-forward @@ -0,0 +1,88 @@ +#!/bin/bash +# info: add mail account forward address +# options: USER DOMAIN ACCOUNT FORWARD +# +# example: v-add-mail-account-forward admin acme.com alice bob +# +# This function add new email account. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 +account=$3 +email_forward=$4 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '4' "$#" 'USER DOMAIN ACCOUNT FORWARD' +is_format_valid 'user' 'domain' 'account' +if [ "$email_forward" != ':blackhole:' ]; then + is_format_valid 'email_forward' +fi +is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'mail' 'DOMAIN' "$domain" +is_object_unsuspended 'mail' 'DOMAIN' "$domain" +is_object_valid "mail/$domain" 'ACCOUNT' "$account" +is_object_unsuspended "mail/$domain" 'ACCOUNT' "$account" +fwd=$(get_object_value "mail/$domain" 'ACCOUNT' "$account" '$FWD') +if [ -n "$(echo $fwd | grep -w "$email_forward")" ]; then + echo "Error: forward $email_forward exists" + log_event "$E_EXISTS" "$ARGUMENTS" + exit $E_EXISTS +fi + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Define fwd string +if [ -z "$fwd" ]; then + fwd="$email_forward" +else + fwd="$fwd,$email_forward" +fi + +# Adding forward to exim +if [[ "$MAIL_SYSTEM" =~ exim ]]; then + sed -i "/^$account@$domain_idn:/ d" $HOMEDIR/$user/conf/mail/$domain/aliases + echo "$account@$domain_idn:$fwd" >> $HOMEDIR/$user/conf/mail/$domain/aliases +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Updating config +update_object_value "mail/$domain" 'ACCOUNT' "$account" '$FWD' "$fwd" + +# Logging +$BIN/v-log-action "$user" "Warning" "Mail" "Mail forwarding on mail account $account@$domain enabled (send to: $email_forward)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-add-mail-account-fwd-only b/bin/v-add-mail-account-fwd-only new file mode 100755 index 0000000..2a88ed3 --- /dev/null +++ b/bin/v-add-mail-account-fwd-only @@ -0,0 +1,86 @@ +#!/bin/bash +# info: add mail account forward-only flag +# options: USER DOMAIN ACCOUNT +# +# example: v-add-mail-account-fwd-only admin example.com user +# +# This function adds fwd-only flag + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 +account=$3 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Define mail user +if [ "$MAIL_SYSTEM" = 'exim4' ]; then + MAIL_USER=Debian-exim +else + MAIL_USER=exim +fi + +# Additional argument formatting +format_domain +format_domain_idn +# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ? + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '3' "$#" 'USER DOMAIN ACCOUNT' +is_format_valid 'user' 'domain' 'account' +is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'mail' 'DOMAIN' "$domain" +is_object_unsuspended 'mail' 'DOMAIN' "$domain" +is_object_valid "mail/$domain" 'ACCOUNT' "$account" +is_object_unsuspended "mail/$domain" 'ACCOUNT' "$account" +fwd=$(get_object_value "mail/$domain" 'ACCOUNT' "$account" '$FWD') +if [ -z "$fwd" ]; then + echo "Error: forward doesn't exist" + log_event "$E_NOTEXIST" "$ARGUMENTS" + exit "$E_NOTEXIST" +fi + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Adding account to fwd_only +if [[ "$MAIL_SYSTEM" =~ exim ]]; then + echo "$account" >> $HOMEDIR/$user/conf/mail/$domain/fwd_only + chown -R $MAIL_USER:mail $HOMEDIR/$user/conf/mail/$domain/fwd_only +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Updating config +add_object_key "mail/$domain" 'ACCOUNT' "$account" 'FWD_ONLY' 'MD5' +update_object_value "mail/$domain" 'ACCOUNT' "$account" '$FWD_ONLY' "yes" + +# Logging +$BIN/v-log-action "$user" "Warning" "Mail" "Forward-only flag enabled on mail account $account@$domain." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-add-mail-domain b/bin/v-add-mail-domain new file mode 100755 index 0000000..c8b1ca4 --- /dev/null +++ b/bin/v-add-mail-domain @@ -0,0 +1,224 @@ +#!/bin/bash +# info: add mail domain +# options: USER DOMAIN [ANTISPAM] [ANTIVIRUS] [DKIM] [DKIM_SIZE] [RESTART] [REJECT_SPAM] +# +# example: v-add-mail-domain admin mydomain.tld +# +# This function adds MAIL domain. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +antispam=${3-yes} +antivirus=${4-yes} +dkim=${5-yes} +dkim_size=${6-1024} +restart="$7" +reject=${8-no} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# shellcheck source=/usr/local/hestia/func/ip.sh +source $HESTIA/func/ip.sh +# shellcheck source=/usr/local/hestia/func/syshealth.sh +source $HESTIA/func/syshealth.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Define mail user +if [ "$MAIL_SYSTEM" = 'exim4' ]; then + MAIL_USER=Debian-exim +else + MAIL_USER=exim +fi + +# Additional argument formatting +format_domain +format_domain_idn +domain_utf=$(idn2 --quiet -d "$domain_idn") + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DOMAIN [ANTISPAM] [ANTIVIRUS] [DKIM] [DKIM_SIZE] [RESTART] [REJECT_SPAM]' +is_format_valid 'user' 'domain' 'antispam' 'antivirus' 'dkim' 'dkim_size' 'restart' 'reject' +is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" + +if [ "$($BIN/v-list-mail-domain $user $domain_utf plain | cut -f 1) " != "$domain" ]; then + is_domain_new 'mail' "$domain_utf" +fi +if [ "$($BIN/v-list-mail-domain $user $domain_idn plain | cut -f 1) " != "$domain" ]; then + is_domain_new 'mail' "$domain_idn" +else + is_domain_new 'mail' "$domain" +fi +if [ -z "$(is_ip_format_valid $domain)" ]; then + echo "Error: Invalid domain format. IP address detected as input." + exit 1 +fi + +is_package_full 'MAIL_DOMAINS' +is_dir_symlink $HOMEDIR/$user/mail + +is_base_domain_owner "$domain" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +source_conf "$USER_DATA/user.conf" +# Inherit web domain local ip address +domain_ip=$(get_object_value 'web' 'DOMAIN' "$domain" '$IP') +if [ ! -z "$domain_ip" ]; then + local_ip=$(get_real_ip "$domain_ip") + is_ip_valid "$local_ip" "$user" +else + get_user_ip +fi + +# Generating timestamp +new_timestamp + +if [ -z "$ANTISPAM_SYSTEM" ]; then + antispam="no" + reject="no" +fi +if [ -z "$ANTIVIRUS_SYSTEM" ]; then + antivirus="no" +fi + +# Adding domain to mail.conf +s="DOMAIN='$domain' ANTIVIRUS='$antivirus' ANTISPAM='$antispam' REJECT='$reject' DKIM='$dkim' WEBMAIL=''" +s="$s SSL='no' LETSENCRYPT='no' CATCHALL='' ACCOUNTS='0' RATE_LIMIT='$RATE_LIMIT' U_DISK='0' SUSPENDED='no' TIME='$time'" +s="$s DATE='$date'" +echo $s >> $USER_DATA/mail.conf +touch $USER_DATA/mail/$domain.conf + +syshealth_repair_mail_config + +# Generating DKIM keys +if [ "$dkim" = 'yes' ]; then + openssl genrsa -out $USER_DATA/mail/$domain.pem $dkim_size &> /dev/null + openssl rsa -pubout -in $USER_DATA/mail/$domain.pem \ + -out $USER_DATA/mail/$domain.pub &> /dev/null +fi + +# Set permissions +chmod 660 $USER_DATA/mail/$domain.* +chmod 660 $USER_DATA/mail.conf + +# Building exim configs +if [[ "$MAIL_SYSTEM" =~ exim ]]; then + mkdir $HOMEDIR/$user/conf/mail/$domain + mkdir $HOMEDIR/$user/mail/$domain_idn + touch $HOMEDIR/$user/conf/mail/$domain/aliases + touch $HOMEDIR/$user/conf/mail/$domain/passwd + touch $HOMEDIR/$user/conf/mail/$domain/fwd_only + touch $HOMEDIR/$user/conf/mail/$domain/accounts + ln -s $HOMEDIR/$user/conf/mail/$domain \ + /etc/$MAIL_SYSTEM/domains/$domain_idn + + # Seeting outgoing ip address + if [ -n "$local_ip" ]; then + echo "$local_ip" > $HOMEDIR/$user/conf/mail/$domain/ip + fi + + if [ -n "$ANTISPAM_SYSTEM" ]; then + # Adding antispam protection + if [ "$antispam" = 'yes' ]; then + touch "$HOMEDIR/$user/conf/mail/$domain/antispam" + fi + if [ "$reject" = 'yes' ]; then + touch "$HOMEDIR/$user/conf/mail/$domain/reject_spam" + fi + fi + + if [ -n "$ANTIVIRUS_SYSTEM" ]; then + # Adding antivirus protection + if [ "$antivirus" = 'yes' ]; then + touch "$HOMEDIR/$user/conf/mail/$domain/antivirus" + fi + fi + + # Adding dkim support + if [ "$dkim" = 'yes' ]; then + cp -f $USER_DATA/mail/$domain.pem \ + $HOMEDIR/$user/conf/mail/$domain/dkim.pem + fi + + # Set permission + chmod 771 $HOMEDIR/$user/conf/mail/$domain + chmod 660 $HOMEDIR/$user/conf/mail/$domain/* + chmod 771 /etc/$MAIL_SYSTEM/domains/$domain_idn + chmod 770 $HOMEDIR/$user/mail/$domain_idn + + # Set ownership + chown -R $MAIL_USER:mail $HOMEDIR/$user/conf/mail/$domain + if [ "$IMAP_SYSTEM" = 'dovecot' ]; then + chown -R dovecot:mail $HOMEDIR/$user/conf/mail/$domain/passwd + fi + chown $MAIL_USER:mail $HOMEDIR/$user/conf/mail/$domain/accounts + chown $user:mail $HOMEDIR/$user/mail/$domain_idn +fi + +# Adding dkim dns records +if [ -n "$DNS_SYSTEM" ] && [ "$dkim" = 'yes' ]; then + check_dns_domain=$(is_object_valid 'dns' 'DOMAIN' "$domain") + if [ "$?" -eq 0 ]; then + p=$(cat $USER_DATA/mail/$domain.pub | grep -v ' KEY---' | tr -d '\n') + record='_domainkey' + policy="\"t=y; o=~;\"" + $BIN/v-add-dns-record "$user" "$domain" "$record" TXT "$policy" '' '' 'no' '' 'yes' + + record='mail._domainkey' + selector="\"v=DKIM1\; k=rsa\; p=$p\"" + $BIN/v-add-dns-record "$user" "$domain" "$record" TXT "$selector" '' '' 'yes' '' 'yes' + fi +fi + +# Add webmail configuration to mail domain +if [ -n "$WEB_SYSTEM" ] || [ -n "$PROXY_SYSTEM" ]; then + if [ -n "$IMAP_SYSTEM" ]; then + $BIN/v-add-mail-domain-webmail "$user" "$domain" '' 'no' + fi +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Increasing domain value +increase_user_value "$user" '$U_MAIL_DOMAINS' + +if [ "$dkim" = 'yes' ]; then + increase_user_value "$user" '$U_MAIL_DKIM' +fi + +# Restarting web server +$BIN/v-restart-web "$restart" +check_result $? "Web restart failed" > /dev/null + +# Restarting proxy server +$BIN/v-restart-proxy "$restart" +check_result $? "Proxy restart failed" > /dev/null + +# Logging +$BIN/v-log-action "$user" "Info" "Mail" "Added new mail domain ($domain)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-add-mail-domain-antispam b/bin/v-add-mail-domain-antispam new file mode 100755 index 0000000..2d1ace4 --- /dev/null +++ b/bin/v-add-mail-domain-antispam @@ -0,0 +1,69 @@ +#!/bin/bash +# info: add mail domain antispam support +# options: USER DOMAIN +# +# example: v-add-mail-domain-antispam admin mydomain.tld +# +# This function enables spamassasin for incoming emails. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn +# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ? + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DOMAIN' +is_format_valid 'user' 'domain' +is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'mail' 'DOMAIN' "$domain" +is_object_unsuspended 'mail' 'DOMAIN' "$domain" +is_object_value_empty 'mail' 'DOMAIN' "$domain" '$ANTISPAM' + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Adding antispam flag +if [[ "$MAIL_SYSTEM" =~ exim ]]; then + touch $HOMEDIR/$user/conf/mail/$domain/antispam +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Adding antispam in config +update_object_value 'mail' 'DOMAIN' "$domain" '$ANTISPAM' 'yes' + +# Logging +$BIN/v-log-action "$user" "Info" "Mail" "Anti-spam protection enabled (Domain: $domain)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-add-mail-domain-antivirus b/bin/v-add-mail-domain-antivirus new file mode 100755 index 0000000..b778a8d --- /dev/null +++ b/bin/v-add-mail-domain-antivirus @@ -0,0 +1,69 @@ +#!/bin/bash +# info: add mail domain antivirus support +# options: USER DOMAIN +# +# example: v-add-mail-domain-antivirus admin mydomain.tld +# +# This function enables clamav scan for incoming emails. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn +# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ? + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DOMAIN' +is_format_valid 'user' 'domain' +is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'mail' 'DOMAIN' "$domain" +is_object_unsuspended 'mail' 'DOMAIN' "$domain" +is_object_value_empty 'mail' 'DOMAIN' "$domain" '$ANTIVIRUS' + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Adding antivirus flag +if [[ "$MAIL_SYSTEM" =~ exim ]]; then + touch $HOMEDIR/$user/conf/mail/$domain/antivirus +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Adding antivirus in config +update_object_value 'mail' 'DOMAIN' "$domain" '$ANTIVIRUS' 'yes' + +# Logging +$BIN/v-log-action "$user" "Info" "Mail" "Anti-virus scanning enabled (Domain: $domain)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-add-mail-domain-catchall b/bin/v-add-mail-domain-catchall new file mode 100755 index 0000000..94fd4b4 --- /dev/null +++ b/bin/v-add-mail-domain-catchall @@ -0,0 +1,70 @@ +#!/bin/bash +# info: add mail domain catchall account +# options: USER DOMAIN EMAIL +# +# example: v-add-mail-domain-catchall admin example.com master@example.com +# +# This function enables catchall account for incoming emails. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 +email="$3" + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '3' "$#" 'USER DOMAIN EMAIL' +is_format_valid 'user' 'domain' 'email' +is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'mail' 'DOMAIN' "$domain" +is_object_unsuspended 'mail' 'DOMAIN' "$domain" +is_object_value_empty 'mail' 'DOMAIN' "$domain" '$CATCHALL' + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Adding catchall alias +if [[ "$MAIL_SYSTEM" =~ exim ]]; then + sed -i "/*@$domain_idn:/d" $HOMEDIR/$user/conf/mail/$domain/aliases + echo "*@$domain_idn:$email" >> $HOMEDIR/$user/conf/mail/$domain/aliases +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Adding antispam in config +update_object_value 'mail' 'DOMAIN' "$domain" '$CATCHALL' "$email" + +# Logging +$BIN/v-log-action "$user" "Warning" "Mail" "Catch-all forwarding enabled (Domain: $domain, Send to: $email)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-add-mail-domain-dkim b/bin/v-add-mail-domain-dkim new file mode 100755 index 0000000..870cb33 --- /dev/null +++ b/bin/v-add-mail-domain-dkim @@ -0,0 +1,98 @@ +#!/bin/bash +# info: add mail domain dkim support +# options: USER DOMAIN [DKIM_SIZE] +# +# example: v-add-mail-domain-dkim admin acme.com +# +# This function adds DKIM signature to outgoing domain emails. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 +dkim_size=${3-2048} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Define mail user +if [ "$MAIL_SYSTEM" = 'exim4' ]; then + MAIL_USER=Debian-exim +else + MAIL_USER=exim +fi + +# Additional argument formatting +format_domain +format_domain_idn +# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ? + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DOMAIN [DKIM_SIZE]' +is_format_valid 'user' 'domain' 'dkim_size' +is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'mail' 'DOMAIN' "$domain" +is_object_unsuspended 'mail' 'DOMAIN' "$domain" +is_object_value_empty 'mail' 'DOMAIN' "$domain" '$DKIM' + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Generating dkim +openssl genrsa -out $USER_DATA/mail/$domain.pem $dkim_size &> /dev/null +openssl rsa -pubout -in $USER_DATA/mail/$domain.pem \ + -out $USER_DATA/mail/$domain.pub &> /dev/null +chmod 660 $USER_DATA/mail/$domain.* + +# Adding dkim keys +if [[ "$MAIL_SYSTEM" =~ exim ]]; then + cp $USER_DATA/mail/$domain.pem $HOMEDIR/$user/conf/mail/$domain/dkim.pem + chown $MAIL_USER:mail $HOMEDIR/$user/conf/mail/$domain/dkim.pem + chmod 660 $HOMEDIR/$user/conf/mail/$domain/dkim.pem +fi + +# Adding dns records +if [ -n "$DNS_SYSTEM" ] && [ -e "$USER_DATA/dns/$domain.conf" ]; then + p=$(cat $USER_DATA/mail/$domain.pub | grep -v ' KEY---' | tr -d '\n') + record="_domainkey" + policy="\"t=y\; o=~\;\"" + $BIN/v-add-dns-record "$user" "$domain" "$record" TXT "$policy" '' '' 'no' '' 'yes' + + record="mail._domainkey" + selector="\"v=DKIM1\; k=rsa\; p=$p\"" + $BIN/v-add-dns-record "$user" "$domain" "$record" TXT "$selector" '' '' 'yes' '' 'yes' +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Adding dkim in config +update_object_value 'mail' 'DOMAIN' "$domain" '$DKIM' 'yes' +increase_user_value "$user" '$U_MAIL_DKIM' + +# Logging +$BIN/v-log-action "$user" "Info" "Mail" "DKIM message signing enabled (Domain: $domain)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-add-mail-domain-reject b/bin/v-add-mail-domain-reject new file mode 100755 index 0000000..ee9ae36 --- /dev/null +++ b/bin/v-add-mail-domain-reject @@ -0,0 +1,71 @@ +#!/bin/bash +# info: add mail domain reject spam support +# options: USER DOMAIN +# labels: mail +# +# example: v-add-mail-domain-reject admin mydomain.tld +# +# The function enables spam rejection for incoming emails. + +#----------------------------------------------------------# +# Variable&Function # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn +# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ? + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DOMAIN' +is_format_valid 'user' 'domain' +is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'mail' 'DOMAIN' "$domain" +is_object_unsuspended 'mail' 'DOMAIN' "$domain" +is_object_value_empty 'mail' 'DOMAIN' "$domain" '$REJECT' + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Adding antivirus flag +if [[ "$MAIL_SYSTEM" =~ exim ]]; then + # Reject spam > 10 when enabled + touch $HOMEDIR/$user/conf/mail/$domain/reject_spam +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Adding antivirus in config +update_object_value 'mail' 'DOMAIN' "$domain" '$REJECT' 'yes' + +# Logging +$BIN/v-log-action "$user" "Info" "Mail" "Anti-virus scanning enabled (Domain: $domain)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-add-mail-domain-smtp-relay b/bin/v-add-mail-domain-smtp-relay new file mode 100755 index 0000000..3745f92 --- /dev/null +++ b/bin/v-add-mail-domain-smtp-relay @@ -0,0 +1,81 @@ +#!/bin/bash +# info: Add mail domain smtp relay support +# options: USER DOMAIN HOST [USERNAME] [PASSWORD] [PORT] +# +# example: v-add-mail-domain-smtp-relay user domain.tld srv.smtprelay.tld uname123 pass12345 +# +# This function adds mail domain smtp relay support. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +host=$3 +username=$4 +password=$5 +port=${6-587} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '3' "$#" 'USER DOMAIN HOST [USERNAME] [PASSWORD] [PORT]' +is_format_valid 'port' 'user' 'domain' 'host' +is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'mail' 'DOMAIN' "$domain" +is_object_unsuspended 'mail' 'DOMAIN' "$domain" +is_password_valid "$password" "Password" +is_username_format_valid "$username" "Username" +format_no_quotes "$password" "Password" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +cat > /etc/exim4/domains/${domain}/smtp_relay.conf << EOL +host:$host +port:$port +user:$username +pass:$password +EOL + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Adding smtp relay values in config +if [ -z "$U_SMTP_RELAY" ]; then + add_object_key 'mail' 'DOMAIN' "$domain" 'U_SMTP_RELAY' 'ACCOUNTS' + add_object_key 'mail' 'DOMAIN' "$domain" 'U_SMTP_RELAY_HOST' 'ACCOUNTS' + add_object_key 'mail' 'DOMAIN' "$domain" 'U_SMTP_RELAY_PORT' 'ACCOUNTS' + add_object_key 'mail' 'DOMAIN' "$domain" 'U_SMTP_RELAY_USERNAME' 'ACCOUNTS' + add_object_key 'mail' 'DOMAIN' "$domain" 'U_SMTP_RELAY_PASSWORD' 'ACCOUNTS' +fi + +update_object_value 'mail' 'DOMAIN' "$domain" '$U_SMTP_RELAY' 'true' +update_object_value 'mail' 'DOMAIN' "$domain" '$U_SMTP_RELAY_HOST' "$host" +update_object_value 'mail' 'DOMAIN' "$domain" '$U_SMTP_RELAY_PORT' "$port" +update_object_value 'mail' 'DOMAIN' "$domain" '$U_SMTP_RELAY_USERNAME' "$username" +update_object_value 'mail' 'DOMAIN' "$domain" '$U_SMTP_RELAY_PASSWORD' "$password" + +# Logging +$BIN/v-log-action "$user" "Info" "Mail" "SMTP Relay enabled (Domain: $domain, Host: $host, Port: $port)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-add-mail-domain-ssl b/bin/v-add-mail-domain-ssl new file mode 100755 index 0000000..218ecd0 --- /dev/null +++ b/bin/v-add-mail-domain-ssl @@ -0,0 +1,144 @@ +#!/bin/bash +# info: add mail SSL for $domain +# options: USER DOMAIN SSL_DIR [RESTART] +# +# This function turns on SSL support for a mail domain. Parameter ssl_dir +# is a path to a directory where 2 or 3 ssl files can be found. Certificate file +# mail.domain.tld.crt and its key mail.domain.tld.key are mandatory. Certificate +# authority mail.domain.tld.ca file is optional. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +ssl_dir=$3 +restart="$4" + +# Additional argument formatting +if [[ "$domain" =~ [[:upper:]] ]]; then + domain=$(echo "$domain" | tr '[:upper:]' '[:lower:]') +fi +if [[ "$domain" =~ ^www\..* ]]; then + domain=$(echo "$domain" | sed -e "s/^www.//") +fi +if [[ "$domain" =~ .*\.$ ]]; then + domain=$(echo "$domain" | sed -e "s/\.$//") +fi + +domain_idn=$(idn2 --quiet "$domain") + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# shellcheck source=/usr/local/hestia/func/ip.sh +source $HESTIA/func/ip.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '3' "$#" 'USER DOMAIN SSL_DIR [RESTART]' +is_format_valid 'user' 'domain' 'ssl_dir' +is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'mail' 'DOMAIN' "$domain" +is_object_unsuspended 'mail' 'DOMAIN' "$domain" +is_object_value_empty 'mail' 'DOMAIN' "$domain" '$SSL' +is_web_domain_cert_valid + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +if [ -n "$restart" ]; then + is_format_valid "$restart" +fi +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Inherit web domain local ip address +domain_ip=$(get_object_value 'web' 'DOMAIN' "$domain" '$IP') +if [ -n "$domain_ip" ]; then + local_ip=$(get_real_ip "$domain_ip") + is_ip_valid "$local_ip" "$user" +else + get_user_ip +fi + +# Call routine to add SSL configuration to mail domain +add_mail_ssl_config + +if [ "$WEBMAIL" == "roundcube" ]; then + WEBMAIL_TEMPLATE="default" + if [ -n "$PROXY_SYSTEM" ]; then + PROXY_TEMPLATE="default" + fi + # Add webmail configuration to mail domain + WEBMAIL_TEMPLATE="default" + if [ "$WEB_SYSTEM" = "nginx" ]; then + WEBMAIL_TEMPLATE="web_system" + fi +elif [ "$WEBMAIL" == "snappymail" ]; then + WEBMAIL_TEMPLATE="snappymail" + if [ -n "$PROXY_SYSTEM" ]; then + PROXY_TEMPLATE="default_snappymail" + fi +elif [ "$WEBMAIL" == "rainloop" ]; then + WEBMAIL_TEMPLATE="rainloop" + if [ -n "$PROXY_SYSTEM" ]; then + PROXY_TEMPLATE="default_rainloop" + fi +else + WEBMAIL_TEMPLATE="disabled" + if [ -n "$PROXY_SYSTEM" ]; then + PROXY_TEMPLATE="default_disabled" + fi +fi + +add_webmail_config "$WEB_SYSTEM" "${WEBMAIL_TEMPLATE}.stpl" + +if [ -n "$PROXY_SYSTEM" ]; then + add_webmail_config "$PROXY_SYSTEM" "${PROXY_TEMPLATE}.stpl" +fi + +# Increase value for domain +increase_user_value "$user" '$U_MAIL_SSL' + +# Set SSL as enabled in configuration +update_object_value 'mail' 'DOMAIN' "$domain" '$SSL' "yes" + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Restarting mail server +$BIN/v-restart-mail "$restart" +check_result $? "Mail restart failed" > /dev/null + +# Restarting web server +$BIN/v-restart-web "$restart" +check_result $? "Web restart failed" > /dev/null + +# Restarting proxy server +$BIN/v-restart-proxy "$restart" +check_result $? "Proxy restart failed" > /dev/null + +# Logging +$BIN/v-log-action "$user" "Info" "Mail" "SSL enabled (Domain: $domain)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-add-mail-domain-webmail b/bin/v-add-mail-domain-webmail new file mode 100755 index 0000000..0cec600 --- /dev/null +++ b/bin/v-add-mail-domain-webmail @@ -0,0 +1,190 @@ +#!/bin/bash +# info: add webmail support for a domain +# options: USER DOMAIN [WEBMAIL] [RESTART] [QUIET] +# +# example: v-add-sys-webmail user domain.com +# example: v-add-sys-webmail user domain.com snappymail +# example: v-add-sys-webmail user domain.com roundcube +# +# This function enables webmail client for a mail domain. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +webmail=$3 +restart="$4" +quiet=$5 + +if [ -z "$restart" ]; then + restart="yes" +fi + +# Additional argument formatting +if [[ "$domain" =~ [[:upper:]] ]]; then + domain=$(echo "$domain" | tr '[:upper:]' '[:lower:]') +fi +if [[ "$domain" =~ ^www\..* ]]; then + domain=$(echo "$domain" | sed -e "s/^www.//") +fi +if [[ "$domain" =~ .*\.$ ]]; then + domain=$(echo "$domain" | sed -e "s/\.$//") +fi + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# shellcheck source=/usr/local/hestia/func/ip.sh +source $HESTIA/func/ip.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +if [ -z "$webmail" ]; then + for client in ${WEBMAIL_SYSTEM//,/ }; do + webmail="$client" + done +fi + +check_args '2' "$#" 'USER DOMAIN [WEBMAIL] [RESTART]' +is_format_valid 'user' 'domain' 'restart' +is_system_enabled "$WEB_SYSTEM" 'WEB_SYSTEM' +is_system_enabled "$IMAP_SYSTEM" 'IMAP_SYSTEM' +is_type_valid "$WEBMAIL_SYSTEM disabled" "$webmail" +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'mail' 'DOMAIN' "$domain" +is_object_unsuspended 'mail' 'DOMAIN' "$domain" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Inherit web domain local ip address +domain_ip=$(get_object_value 'web' 'DOMAIN' "$domain" '$IP') +if [ -n "$domain_ip" ]; then + local_ip=$(get_real_ip "$domain_ip") + is_ip_valid "$local_ip" "$user" + + ip=$local_ip + nat_ip=$(get_ip_value '$NAT') + if [ -n "$nat_ip" ]; then + ip=$nat_ip + fi +else + get_user_ip +fi + +# Verify that webmail alias variable exists and create it if it does not +if [ -z "$WEBMAIL_ALIAS" ]; then + $BIN/v-change-sys-config-value 'WEBMAIL_ALIAS' "webmail" +else + # Ensure DNS record exists if Hestia is hosting DNS zones + if [ -n "$DNS_SYSTEM" ]; then + dns_domain=$($BIN/v-list-dns-domains $user | grep $domain | cut -d' ' -f1) + webmail_record=$($BIN/v-list-dns-records $user $domain | grep -i " $WEBMAIL_ALIAS " | cut -d' ' -f1) + if [ "$dns_domain" = "$domain" ]; then + if [ "$WEBMAIL_ALIAS" != "mail" ]; then + #Prevent mail.domain.com to be cycled + if [ -z "$webmail_record" ]; then + if [ "$quiet" = "yes" ]; then + $BIN/v-add-dns-record "$user" "$domain" "$WEBMAIL_ALIAS" A "$ip" '' '' "$restart" '' 'yes' + else + $BIN/v-add-dns-record "$user" "$domain" "$WEBMAIL_ALIAS" A "$ip" '' '' "$restart" '' 'yes' + fi + else + if [ "$quiet" = "yes" ]; then + $BIN/v-delete-dns-record "$user" "$domain" "$webmail_record" "$restart" 'yes' + $BIN/v-add-dns-record "$user" "$domain" "$WEBMAIL_ALIAS" A "$ip" '' '' "$restart" '' 'yes' + else + $BIN/v-delete-dns-record "$user" "$domain" "$webmail_record" "$restart" 'yes' + $BIN/v-add-dns-record "$user" "$domain" "$WEBMAIL_ALIAS" A "$ip" '' '' "$restart" '' 'yes' + fi + fi + fi + fi + fi + + if [ "$webmail" == "roundcube" ]; then + WEBMAIL_TEMPLATE="default" + if [ -n "$PROXY_SYSTEM" ]; then + PROXY_TEMPLATE="default" + fi + # Add webmail configuration to mail domain + WEBMAIL_TEMPLATE="default" + if [ "$WEB_SYSTEM" = "nginx" ]; then + WEBMAIL_TEMPLATE="web_system" + fi + elif [ -f "$HESTIA/data/templates/mail/$WEB_SYSTEM/$webmail.tpl" ]; then + WEBMAIL_TEMPLATE="$webmail" + if [ -n "$PROXY_SYSTEM" ]; then + PROXY_TEMPLATE="default_$webmail" + fi + else + WEBMAIL_TEMPLATE="disabled" + if [ -n "$PROXY_SYSTEM" ]; then + PROXY_TEMPLATE="default_disabled" + fi + fi + + add_webmail_config "$WEB_SYSTEM" "${WEBMAIL_TEMPLATE}.tpl" + + if [ -n "$PROXY_SYSTEM" ]; then + add_webmail_config "$PROXY_SYSTEM" "${PROXY_TEMPLATE}.tpl" + fi + + # Enable SSL for webmail if available + if [ -f $HOMEDIR/$user/conf/mail/$domain/ssl/$domain.crt ] || [ "$SSL" = 'yes' ]; then + add_webmail_config "$WEB_SYSTEM" "${WEBMAIL_TEMPLATE}.stpl" + + if [ -n "$PROXY_SYSTEM" ]; then + add_webmail_config "$PROXY_SYSTEM" "${PROXY_TEMPLATE}.stpl" + fi + fi +fi + +WEBMAIL=$(get_object_value 'web' 'DOMAIN' "$domain" "$WEBMAIL") +if [ -z "$WEBMAIL" ]; then + add_object_key 'mail' 'DOMAIN' "$domain" 'WEBMAIL' 'SSL' +fi + +# Set SSL as enabled in configuration +update_object_value 'mail' 'DOMAIN' "$domain" '$WEBMAIL' "$webmail" + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +if [ "$restart" = 'yes' ]; then + # Restarting web server + $BIN/v-restart-web "$restart" + check_result $? "Web restart failed" > /dev/null + + $BIN/v-restart-proxy "$restart" + check_result $? "Proxy restart failed" > /dev/null +fi + +# Logging +if [ "$quiet" != 'yes' ]; then + $BIN/v-log-action "$user" "Info" "Mail" "Webmail access enabled (Domain: $domain)." +fi +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-add-remote-dns-domain b/bin/v-add-remote-dns-domain new file mode 100755 index 0000000..5961c1e --- /dev/null +++ b/bin/v-add-remote-dns-domain @@ -0,0 +1,124 @@ +#!/bin/bash +# info: add remote dns domain +# options: USER DOMAIN [FLUSH] +# +# example: v-add-remote-dns-domain admin mydomain.tld yes +# +# This function synchronise dns domain with the remote server. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +flush=$3 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/remote.sh +source $HESTIA/func/remote.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DOMAIN [FLUSH]' +is_format_valid 'user' 'domain' +if [ -n "$flush" ]; then + is_type_valid "records yes no" "$flush" +fi +is_system_enabled "$DNS_CLUSTER" 'DNS_CLUSTER' +is_procces_running +remote_dns_health_check + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Parsing domain record +str=$(grep "DOMAIN='$domain'" $USER_DATA/dns.conf 2> /dev/null) +if [ -z "$str" ]; then + pipe="$HESTIA/data/queue/dns-cluster.pipe" + queue_str=$(grep -n "$SCRIPT $1 $2 " $pipe | cut -f1 -d: | head -n1) + if [ -n "$queue_str" ]; then + sed -i "$queue_str d" $pipe + fi + exit +fi +if [ "$DNS_CLUSTER_SYSTEM" = "hestia-zone" ]; then + str=$(echo "$str" | sed "s/SLAVE='no'/SLAVE='yes'/g") + str=$(echo "$str" | sed "s/SLAVE=''/SLAVE='yes'/g") + ip=$(ip addr | grep 'inet ' | grep global | head -n1 | awk '{print $2}' | cut -f1 -d/) + source_conf $HESTIA/data/ips/$ip + if [ -z $NAT ]; then + str=$(echo "$str" | sed "s/MASTER=''/MASTER='$ip'/g") + else + str=$(echo "$str" | sed "s/MASTER=''/MASTER='$NAT'/g") + fi +fi + +IFS=$'\n' +for cluster in $(grep "SUSPENDED='no'" $HESTIA/conf/dns-cluster.conf); do + # Reset user, password and hash vars + clear_dns_cluster_settings + + # Parsing remote dns host parameters + parse_object_kv_list "$cluster" + + # Parsing domain parameters + parse_object_kv_list "$str" + + if [ "$DNS_CLUSTER_SYSTEM" = "hestia-zone" ]; then + # Syncing domain data + cluster_cmd v-insert-dns-domain $DNS_USER "$str" $HOSTNAME $flush 'no' + check_result $? "$HOST connection failed" "$E_CONNECT" + + cluster_cmd v-rebuild-dns-domain $DNS_USER $domain 'yes' 'no' + check_result $? "$HOST connection failed" "$E_CONNECT" + + else + # Syncing domain data + cluster_cmd v-insert-dns-domain $DNS_USER "$str" $HOSTNAME $flush 'no' + check_result $? "$HOST connection failed" "$E_CONNECT" + + # Syncing domain records + tmp_file="/tmp/vst-sync.$DOMAIN" + cluster_file $USER_DATA/dns/$DOMAIN.conf $tmp_file + check_result $? "$HOST connection failed" "$E_CONNECT" + + # Inserting synced records + cluster_cmd v-insert-dns-records $DNS_USER $DOMAIN $tmp_file 'no' + check_result $? "$HOST connection failed" "$E_CONNECT" + + # Rebuilding dns zone + cluster_cmd v-rebuild-dns-domain $DNS_USER $domain 'yes' 'no' + check_result $? "$HOST connection failed" "$E_CONNECT" + fi +done + +if [ "$DNS_CLUSTER_SYSTEM" = "hestia-zone" ]; then + rndc notify $domain > /dev/null 2>&1 +fi +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Updating pipe +rm -f $tmpfile +pipe="$HESTIA/data/queue/dns-cluster.pipe" +str=$(grep -n "$SCRIPT $1 $2 " $pipe | cut -f1 -d: | head -n1) +if [ -n "$str" ]; then + sed -i "$str d" $pipe +fi + +exit diff --git a/bin/v-add-remote-dns-host b/bin/v-add-remote-dns-host new file mode 100755 index 0000000..bda6e44 --- /dev/null +++ b/bin/v-add-remote-dns-host @@ -0,0 +1,131 @@ +#!/bin/bash +# info: add new remote dns host +# options: HOST PORT USER PASSWORD [TYPE] [DNS_USER] +# +# example: v-add-remote-dns-host slave.your_host.com 8083 admin your_passw0rd +# +# example: v-add-remote-dns-host slave.your_host.com 8083 api_key '' +# +# This function adds remote dns server to the dns cluster. +# As alternative api_key generated on the slave server. +# See v-generate-api-key can be used to connect the remote dns server + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +host=$1 +HOST=$host +port=$2 +PORT=$port +user=$3 +USER=$user +hash=$user +HASH=$user +password=$4 +HIDE=4 +PASSWORD=$password +type=${5} +TYPE="$type" +dns_user=${6-dns-cluster} +DNS_USER=$dns_user + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/remote.sh +source $HESTIA/func/remote.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +if [ -z "$type" ]; then + type='api' + TYPE="$type" +fi + +args_usage='HOST PORT USER [PASSWORD] [TYPE] [DNS_USER]' +check_args '3' "$#" "$args_usage" +is_format_valid 'host' 'port' 'dns_user' +if [ -z "$password" ]; then + is_format_valid 'hash' +else + is_format_valid 'user' +fi +is_type_valid "api ssh" "$type" +is_system_enabled "$DNS_SYSTEM" 'DNS_SYSTEM' +is_password_valid +is_dnshost_new +is_dnshost_alive + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Generating timestamp +time_n_date=$(date +'%T %F') +time=$(echo "$time_n_date" | cut -f 1 -d \ ) +date=$(echo "$time_n_date" | cut -f 2 -d \ ) + +if [ -z "$password" ]; then + # Concatentating dns host string + str="HOST='$host' PORT='$port' HASH='$hash'" + str="$str DNS_USER='$dns_user' TYPE='$type' SUSPENDED='no'" + str="$str TIME='$time' DATE='$date'" +else + # Concatentating dns host string + str="HOST='$host' PORT='$port' USER='$user' PASSWORD='$password'" + str="$str DNS_USER='$dns_user' TYPE='$type' SUSPENDED='no'" + str="$str TIME='$time' DATE='$date'" +fi + +# Adding host to dns-cluster.conf +echo "$str" >> $HESTIA/conf/dns-cluster.conf +chmod 660 $HESTIA/conf/dns-cluster.conf + +# Enabling DNS_CLUSTER +if [ -z "$(grep DNS_CLUSTER= $HESTIA/conf/hestia.conf)" ]; then + sed -i "s/^STATS_/DNS_CLUSTER='yes'\nSTATS_/g" $HESTIA/conf/hestia.conf +else + sed -i "s/DNS_CLUSTER=.*/DNS_CLUSTER='yes'/g" $HESTIA/conf/hestia.conf +fi + +# Enabling remote dns-cluster queue +cluster_cmd v-add-cron-restart-job +check_result $? "$HOST connection failed" "$E_CONNECT" + +# Loop trough domains to generate new serial +for dns_user in $($BIN/v-list-sys-users plain); do + for dns_domain in $($BIN/v-list-dns-domains $dns_user plain | cut -f1); do + $BIN/v-rebuild-dns-domain $dns_user $dns_domain "no" "yes" + done +done + +# Syncing all domains +$BIN/v-sync-dns-cluster +check_result $? "$HOST sync failed" "$E_CONNECT" + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Adding local dns-cluster cron job +cmd="sudo $BIN/v-update-sys-queue dns-cluster" +check_cron=$(grep "$cmd" $HESTIA/data/users/admin/cron.conf 2> /dev/null) +if [ -z "$check_cron" ] && [ ! -z "$CRON_SYSTEM" ]; then + $BIN/v-add-cron-job admin '*/5' '*' '*' '*' '*' "$cmd" +fi + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-add-remote-dns-record b/bin/v-add-remote-dns-record new file mode 100755 index 0000000..76d2e6b --- /dev/null +++ b/bin/v-add-remote-dns-record @@ -0,0 +1,98 @@ +#!/bin/bash +# info: add remote dns domain record +# options: USER DOMAIN ID +# +# example: v-add-remote-dns-record bob acme.com 23 +# +# This function synchronise dns domain with the remote server. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +id=$3 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/remote.sh +source $HESTIA/func/remote.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '3' "$#" 'USER DOMAIN ID' +is_format_valid 'user' 'domain' 'id' +is_system_enabled "$DNS_CLUSTER" 'DNS_CLUSTER' +is_object_valid 'user' 'USER' "$user" +is_object_valid 'dns' 'DOMAIN' "$domain" +is_procces_running +remote_dns_health_check + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Parsing record +str=$(grep "ID='$id'" $USER_DATA/dns/$domain.conf) +if [ -z "$str" ]; then + pipe="$HESTIA/data/queue/dns-cluster.pipe" + queue_str=$(grep -n "$SCRIPT $1 $2 $3$" $pipe | cut -f1 -d: | head -n1) + if [ -n "$queue_str" ]; then + sed -i "$queue_str d" $pipe + fi + exit +fi +# $DNS_CLUSTER_SYSTEM = "hestia-zone" doesn't need to be uopdated + +if [ "$DNS_CLUSTER_SYSTEM" != "hestia-zone" ]; then + IFS=$'\n' + for cluster in $(grep "SUSPENDED='no'" $HESTIA/conf/dns-cluster.conf); do + + # Reset user, password and hash vars + clear_dns_cluster_settings + + # Parsing remote host parameters + parse_object_kv_list "$cluster" + + # Syncing serial + str=$(grep "DOMAIN='$domain'" $USER_DATA/dns.conf) + # Parsing domain parameters + parse_object_kv_list "$str" + + cluster_cmd v-insert-dns-domain $DNS_USER "$str" $HOSTNAME 'domain' 'no' + check_result $? "$HOST connection failed (soa sync)" "$E_CONNECT" + + # Syncing record + str=$(grep "ID='$id'" $USER_DATA/dns/$domain.conf) + cluster_cmd v-insert-dns-record $DNS_USER $domain "$str" 'no' + check_result $? "$HOST connection failed (record sync)" "$E_CONNECT" + + # Rebuilding dns zone + cluster_cmd v-rebuild-dns-domain $DNS_USER $domain 'yes' 'no' + check_result $? "$HOST connection failed (rebuild)" "$E_CONNECT" + done +fi +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Updating pipe +pipe="$HESTIA/data/queue/dns-cluster.pipe" +str=$(grep -n "$SCRIPT $1 $2 $3$" $pipe | cut -f1 -d: | head -n1) +if [ -n "$str" ]; then + sed -i "$str d" $pipe +fi + +exit diff --git a/bin/v-add-sys-api-ip b/bin/v-add-sys-api-ip new file mode 100755 index 0000000..af01c2d --- /dev/null +++ b/bin/v-add-sys-api-ip @@ -0,0 +1,49 @@ +#!/bin/bash +# info: add IP address to API allow list +# options: IP +# +# example: v-add-sys-api-ip 1.1.1.1 + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +ip46=${1// /} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/ip.sh +source $HESTIA/func/ip.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'IP' +is_format_valid 'ip46' + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +if [ "$API_ALLOWED_IP" != "" ]; then + $BIN/v-change-sys-config-value 'API_ALLOWED_IP' "$API_ALLOWED_IP,$ip46" +else + $BIN/v-change-sys-config-value 'API_ALLOWED_IP' "$ip46" +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +$BIN/v-log-action "system" "Warning" "System" "Added new IP address added to Allowed IP API (IP: $ip46)" +log_event "$OK" "$ARGUMENTS" diff --git a/bin/v-add-sys-dependencies b/bin/v-add-sys-dependencies new file mode 100755 index 0000000..5f5b86d --- /dev/null +++ b/bin/v-add-sys-dependencies @@ -0,0 +1,109 @@ +#!/bin/bash +# Add php dependencies to Hestia +# options: [MODE] +# +# This function install PHPMailer and quoteshellarg as via composer + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" +# upgrade config file +source "$HESTIA/install/upgrade/upgrade.conf" + +MODE=$1 +user="admin" + +PM_INSTALL_DIR="$HESTIA/web/inc" +QUICK_INSTALL_DIR="$HESTIA/web/src" +COMPOSER_BIN="$HOMEDIR/$user/.composer/composer" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +# Checking root permissions +if [ "x$(id -u)" != 'x0' ]; then + echo "ERROR: v-add-sys-dependencies can be run executed only by root user" + exit 10 +fi + +# Ensure that $HESTIA (/usr/local/hestia/) and other variables are valid. +if [ -z "$HESTIA" ]; then + HESTIA="/usr/local/hestia" +fi + +if [ -z "$HOMEDIR" ] || [ -z "$HESTIA_INSTALL_DIR" ]; then + echo "ERROR: Environment variables not present, installation aborted." + exit 2 +fi + +# Ensure that Composer is installed for the user before continuing as it is a dependency of the PHPMailer. +if [ ! -f "$COMPOSER_BIN" ]; then + $BIN/v-add-user-composer "$user" + if [ $? -ne 0 ]; then + $BIN/v-add-user-notification admin 'Composer installation failed!' '

Hestia will not work without Composer.

Please try running the installer manually from a shell session:
v-add-sys-dependencies

If this continues, open an issue on GitHub.

' + exit 1 + fi +fi + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +cd "$PM_INSTALL_DIR" +rm --recursive --force ${PM_INSTALL_DIR}/vendor +mkdir -p ${PM_INSTALL_DIR}/vendor +chown $user: -R ${PM_INSTALL_DIR}/vendor + +openssl_installed=$(/usr/local/hestia/php/bin/php -m | grep openssl) +if [ -z "$openssl_installed" ]; then + COMPOSER_HOME="$HOMEDIR/$user/.config/composer" user_exec /usr/bin/php $COMPOSER_BIN --quiet --no-dev install +else + COMPOSER_HOME="$HOMEDIR/$user/.config/composer" user_exec $HESTIA_PHP $COMPOSER_BIN --quiet --no-dev install +fi + +# Check if installation was successful, if not abort script and throw error message notification and clean-up +if [ $? -ne 0 ]; then + echo "ERROR: PHPMailer installation failed!" + echo "Please report this to our development team:" + echo "https://github.com/hestiacp/hestiacp/issues" + $BIN/v-add-user-notification admin 'Hestia PHP dependencies installation failed!' '

Please open an issue on GitHub to report this to our development team.

' + # Installation failed, clean up files + rm --recursive --force ${PM_INSTALL_DIR}/vendor + $BIN/v-change-sys-config-value 'USE_SERVER_SMTP' 'n' + $BIN/v-log-action "system" "Error" "Plugins" "PHP dependencies installation failed" + exit 1 +fi + +cd "$QUICK_INSTALL_DIR" +rm --recursive --force ${QUICK_INSTALL_DIR}/vendor +mkdir -p ${QUICK_INSTALL_DIR}/vendor +chown $user: -R ${QUICK_INSTALL_DIR}/vendor + +if [ -z "$openssl_installed" ]; then + COMPOSER_HOME="$HOMEDIR/$user/.config/composer" user_exec /usr/bin/php $COMPOSER_BIN --quiet --no-dev install +else + COMPOSER_HOME="$HOMEDIR/$user/.config/composer" user_exec $HESTIA_PHP $COMPOSER_BIN --quiet --no-dev install +fi + +# Set permissions +chown root: -R "${PM_INSTALL_DIR}/vendor" +chown root: -R "${QUICK_INSTALL_DIR}/vendor" + +#----------------------------------------------------------# +# Logging # +#----------------------------------------------------------# + +$BIN/v-log-action "system" "Info" "Plugins" "PHPMailer enabled (Version: $pm_v)." +log_event "$OK" "$ARGUMENTS" diff --git a/bin/v-add-sys-filemanager b/bin/v-add-sys-filemanager new file mode 100755 index 0000000..1e3bd35 --- /dev/null +++ b/bin/v-add-sys-filemanager @@ -0,0 +1,119 @@ +#!/bin/bash +# info: add file manager functionality to Hestia Control Panel +# options: [MODE] +# +# This function installs the File Manager on the server +# for access through the Web interface. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" +# load config file +source_conf "$HESTIA/install/upgrade/upgrade.conf" + +MODE=$1 +user="admin" + +FM_INSTALL_DIR="$HESTIA/web/fm" +FM_FILE="filegator_latest" +FM_URL="https://github.com/filegator/static/raw/master/builds/filegator_latest.zip" +COMPOSER_BIN="$HOMEDIR/$user/.composer/composer" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +# Checking root permissions +if [ "x$(id -u)" != 'x0' ]; then + echo "ERROR: v-add-sys-filemanager can be run executed only by root user" + exit 10 +fi + +# Ensure that $HESTIA (/usr/local/hestia/) and other variables are valid. +if [ -z "$HESTIA" ]; then + HESTIA="/usr/local/hestia" +fi + +if [ -z "$HOMEDIR" ] || [ -z "$HESTIA_INSTALL_DIR" ]; then + echo "ERROR: Environment variables not present, installation aborted." + exit 2 +fi + +# Ensure that Composer is installed for the user before continuing as it is a dependency of the File Manager. +if [ ! -f "$COMPOSER_BIN" ]; then + $BIN/v-add-user-composer "$user" + if [ $? -ne 0 ]; then + $BIN/v-add-user-notification admin 'Composer installation failed!' '

The File Manager will not work without Composer.

Please try running the installer manually from a shell session:
v-add-sys-filemanager

If this continues, open an issue on GitHub.

' + exit 1 + fi +fi + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +openssl_installed=$(/usr/local/hestia/php/bin/php -m | grep openssl) + +rm --recursive --force "$FM_INSTALL_DIR" +mkdir -p "$FM_INSTALL_DIR" +cd "$FM_INSTALL_DIR" + +[ ! -f "${FM_INSTALL_DIR}/${FM_FILE}" ] && wget "$FM_URL" --quiet -O "${FM_INSTALL_DIR}/${FM_FILE}.zip" + +unzip -qq "${FM_INSTALL_DIR}/${FM_FILE}.zip" +mv --force ${FM_INSTALL_DIR}/filegator/* "${FM_INSTALL_DIR}" +rm --recursive --force ${FM_INSTALL_DIR}/${FM_FILE} +[[ -f "${FM_INSTALL_DIR}/${FM_FILE}" ]] && rm "${FM_INSTALL_DIR}/${FM_FILE}" + +cp --recursive --force ${HESTIA_INSTALL_DIR}/filemanager/filegator/* "${FM_INSTALL_DIR}" + +chown $user: -R "${FM_INSTALL_DIR}" + +if [ -z "$openssl_installed" ]; then + COMPOSER_HOME="$HOMEDIR/$user/.config/composer" user_exec /usr/bin/php $COMPOSER_BIN --quiet --no-dev install +else + COMPOSER_HOME="$HOMEDIR/$user/.config/composer" user_exec /usr/local/hestia/php/bin/php $COMPOSER_BIN --quiet --no-dev install +fi + +# Check if installation was successful, if not abort script and throw error message notification and clean-up +if [ $? -ne 0 ]; then + echo "ERROR: File Manager installation failed!" + echo "Please report this to our development team:" + echo "https://github.com/hestiacp/hestiacp/issues" + $BIN/v-add-user-notification admin 'File Manager installation failed!' '

Please open an issue on GitHub to report this to our development team.

' + # Installation failed, clean up files + rm --recursive --force ${FM_INSTALL_DIR} + $BIN/v-change-sys-config-value 'FILE_MANAGER' 'false' + $BIN/v-log-action "system" "Error" "Plugins" "File Manager installation failed (Version: $fm_v)." + exit 1 +fi + +# Add configuration file +cp -f $HESTIA_INSTALL_DIR/filemanager/filegator/configuration.php $HESTIA/web/fm/configuration.php + +echo "$fm_v" > "${FM_INSTALL_DIR}/version" +# Set permissions +chown root: -R "${FM_INSTALL_DIR}" +chown $user: "${FM_INSTALL_DIR}/private" +chown $user: "${FM_INSTALL_DIR}/private/logs" +chown $user: "${FM_INSTALL_DIR}/repository" + +$BIN/v-change-sys-config-value 'FILE_MANAGER' 'true' + +#----------------------------------------------------------# +# Logging # +#----------------------------------------------------------# + +$BIN/v-log-action "system" "Info" "Plugins" "File Manager enabled (Version: $fm_v)." +log_event "$OK" "$ARGUMENTS" diff --git a/bin/v-add-sys-firewall b/bin/v-add-sys-firewall new file mode 100755 index 0000000..a7924bd --- /dev/null +++ b/bin/v-add-sys-firewall @@ -0,0 +1,56 @@ +#!/bin/bash +# info: add system firewall +# options: NONE +# +# example: v-add-sys-firewall +# +# This function enables the system firewall. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +if [ "$FIREWALL_SYSTEM" = 'iptables' ]; then + exit +fi + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Adding default ruleset +if [ -z "$(ls -A $HESTIA/data/firewall 2> /dev/null)" ]; then + cp -rf $HESTIA_COMMON_DIR/firewall $HESTIA/data/ + rm -f $HESTIA/data/firewall/ipset/blacklist.sh $HESTIA/data/firewall/ipset/blacklist.ipv6.sh +fi + +# Updating FIREWAL_SYSTEM value +$BIN/v-change-sys-config-value "FIREWALL_SYSTEM" "iptables" + +# Updating firewall rules +$BIN/v-update-firewall + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +$BIN/v-log-action "system" "Info" "Firewall" "System firewall enabled." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-add-sys-ip b/bin/v-add-sys-ip new file mode 100755 index 0000000..9711b1d --- /dev/null +++ b/bin/v-add-sys-ip @@ -0,0 +1,234 @@ +#!/bin/bash +# info: add system IP address +# options: IP NETMASK [INTERFACE] [USER] [IP_STATUS] [IP_NAME] [NAT_IP] +# +# example: v-add-sys-ip 203.0.113.1 255.255.255.0 +# +# This function adds IP address into a system. It also creates rc scripts. You +# can specify IP name which will be used as root domain for temporary aliases. +# For example, if you set a1.myhosting.com as name, each new domain created on +# this IP will automatically receive alias $domain.a1.myhosting.com. Of course +# you must have wildcard record *.a1.myhosting.com pointed to IP. This feature +# is very handy when customer wants to test domain before dns migration. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +ip="${1// /}" +netmask="$2" + +# Get interface name +# First try to detect which interface the IP address resides on +iface="$(ip -d -j addr show | jq --arg IP "$ip" -r '.[] | if .addr_info[].local == $IP then .ifname else empty end')" +# If that fails, detect the default interface as a fallback +if [ -z "$iface" ]; then + iface="$(ip -d -j route show | jq -r '.[] | if .dst == "default" then .dev else empty end')" +fi + +iface="${3-$iface}" +user="${4-admin}" +ip_status="${5-shared}" +ip_name="$6" +nat_ip="$7" + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/ip.sh +source $HESTIA/func/ip.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'IP NETMASK [INTERFACE] [USER] [STATUS] [NAME] [NATED_IP]' +is_format_valid 'ip' 'netmask' 'iface' 'user' 'ip_status' +is_ip_free +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +if [ -n "$ip_name" ]; then + is_format_valid 'ip_name' +fi +if [ -n "$nat_ip" ]; then + is_format_valid 'nat_ip' +fi +if [ "$user" != "admin" ]; then + ip_status="dedicated" +fi + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +cidr="$(convert_netmask "$netmask")" +broadcast="$(get_broadcast "$ip" "$netmask")" + +sys_ip_check="$(ip addr | grep -w "$ip")" +if [ -z "$sys_ip_check" ]; then + # Adding system IP + ip addr add "$ip/$cidr" dev "$iface" broadcast "$broadcast" label "$iface" + + # Check if netplan is in use and generate configuration file + if [ -n "$(netplan generate --mapping "$iface" 2> /dev/null | grep networkd)" ]; then + netplan="true" + else + netplan="false" + fi + + if [ "$netplan" = "true" ]; then + if [ -f "/etc/netplan/60-hestia.yaml" ]; then + sys_ip=" - $ip/$cidr" + else + sys_ip="# Added by Hestia, please do not edit the file manually!" + sys_ip="$sys_ip\nnetwork:" + sys_ip="$sys_ip\n version: 2" + sys_ip="$sys_ip\n renderer: networkd" + sys_ip="$sys_ip\n ethernets:" + sys_ip="$sys_ip\n $iface:" + sys_ip="$sys_ip\n addresses:" + sys_ip="$sys_ip\n - $ip/$cidr" + fi + IFS='%' + echo -e "$sys_ip" >> /etc/netplan/60-hestia.yaml + unset IFS + else + sys_ip="\n# Added by Hestia Control Panel" + sys_ip="$sys_ip\nauto $iface" + sys_ip="$sys_ip\niface $iface inet static" + sys_ip="$sys_ip\naddress $ip" + sys_ip="$sys_ip\nnetmask $netmask" + echo -e $sys_ip >> /etc/network/interfaces + fi +fi + +# Generating timestamp +new_timestamp + +# Adding Hestia IP +echo "OWNER='$user' +STATUS='$ip_status' +NAME='$ip_name' +U_SYS_USERS='' +U_WEB_DOMAINS='0' +INTERFACE='$iface' +NETMASK='$netmask' +NAT='$nat_ip' +TIME='$time' +DATE='$date'" > $HESTIA/data/ips/$ip +chmod 660 $HESTIA/data/ips/$ip + +# WEB support +if [ -n "$WEB_SYSTEM" ]; then + web_conf="/etc/$WEB_SYSTEM/conf.d/$ip.conf" + rm -f "$web_conf" + + if [ "$WEB_SYSTEM" = 'httpd' ] || [ "$WEB_SYSTEM" = 'apache2' ]; then + if [ -z "$(/usr/sbin/apachectl -v | grep Apache/2.4)" ]; then + echo "NameVirtualHost $ip:$WEB_PORT" > "$web_conf" + fi + echo "Listen $ip:$WEB_PORT" >> "$web_conf" + cat $HESTIA_INSTALL_DIR/apache2/unassigned.conf >> "$web_conf" + sed -i 's/directIP/'$ip'/g' "$web_conf" + sed -i 's/directPORT/'$WEB_PORT'/g' "$web_conf" + + elif [ "$WEB_SYSTEM" = 'nginx' ]; then + cp -f $HESTIA_INSTALL_DIR/nginx/unassigned.inc "$web_conf" + sed -i 's/directIP/'$ip'/g' "$web_conf" + process_http2_directive "$web_conf" + fi + + if [ "$WEB_SSL" = 'mod_ssl' ]; then + if [ -z "$(/usr/sbin/apachectl -v | grep Apache/2.4)" ]; then + sed -i "1s/^/NameVirtualHost $ip:$WEB_SSL_PORT\n/" "$web_conf" + fi + sed -i "1s/^/Listen $ip:$WEB_SSL_PORT\n/" "$web_conf" + sed -i 's/directSSLPORT/'$WEB_SSL_PORT'/g' "$web_conf" + fi +fi + +# Proxy support +if [ -n "$PROXY_SYSTEM" ]; then + cat $WEBTPL/$PROXY_SYSTEM/proxy_ip.tpl \ + | sed -e "s/%ip%/$ip/g" \ + -e "s/%web_port%/$WEB_PORT/g" \ + -e "s/%proxy_port%/$PROXY_PORT/g" \ + -e "s/%proxy_ssl_port%/$PROXY_SSL_PORT/g" \ + > /etc/$PROXY_SYSTEM/conf.d/$ip.conf + + process_http2_directive "/etc/$PROXY_SYSTEM/conf.d/$ip.conf" + + # mod_extract_forwarded + fw_conf="/etc/$WEB_SYSTEM/conf.d/mod_extract_forwarded.conf" + if [ -e "$fw_conf" ]; then + ips=$(grep 'MEFaccept ' "$fw_conf" | grep -v '#' | head -n1) + sed -i "s/$ips/$ips $ip/g" "$fw_conf" + fi + + # mod_rpaf + rpaf_conf="/etc/$WEB_SYSTEM/mods-enabled/rpaf.conf" + if [ -e "$rpaf_conf" ]; then + rpaf_str="$(grep RPAFproxy_ips "$rpaf_conf")" + [ -z "$rpaf_str" ] && sed -i 's||RPAFproxy_ips\n|' "$rpaf_conf" && rpaf_str='RPAFproxy_ips' + rpaf_str="$rpaf_str $ip" + sed -i "s/.*RPAFproxy_ips.*/$rpaf_str/" "$rpaf_conf" + fi + + # mod_remoteip + remoteip_conf="/etc/$WEB_SYSTEM/mods-enabled/remoteip.conf" + if [ -e "$remoteip_conf" ]; then + if [ "$(grep -ic "$ip" "$remoteip_conf")" -eq "0" ]; then + sed -i "s/<\/IfModule>/RemoteIPInternalProxy $ip\n<\/IfModule>/g" "$remoteip_conf" + fi + fi +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Updating user counters +increase_user_value "$user" '$IP_OWNED' +if [ "$user" = 'admin' ]; then + if [ "$ip_status" = 'shared' ]; then + for hestia_user in $($BIN/v-list-sys-users plain); do + increase_user_value "$hestia_user" '$IP_AVAIL' + done + else + increase_user_value 'admin' '$IP_AVAIL' + fi +else + increase_user_value "$user" '$IP_AVAIL' + increase_user_value 'admin' '$IP_AVAIL' +fi + +# Restarting web server +$BIN/v-restart-web +check_result $? "Web restart failed" > /dev/null + +# Restarting proxy server +if [ -n "$PROXY_SYSTEM" ]; then + $BIN/v-restart-proxy + check_result $? "Proxy restart failed" > /dev/null +fi + +# Restarting firewall +if [ -n "$FIREWALL_SYSTEM" ]; then + $BIN/v-update-firewall +fi + +# Logging +$BIN/v-log-action "system" "Info" "Network" "Added new IP address to the system (IP: $ip)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-add-sys-pma-sso b/bin/v-add-sys-pma-sso new file mode 100755 index 0000000..82ffa27 --- /dev/null +++ b/bin/v-add-sys-pma-sso @@ -0,0 +1,120 @@ +#!/bin/bash +# info: enables support for single sign on phpMyAdmin +# options: [mode] +# +# example: v-add-sys-pma-sso +# +# This function enables support for SSO to phpMyAdmin + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +MODE=$1 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +PMA_INSTALL="/usr/share/phpmyadmin" +PMA_CONFIG="/etc/phpmyadmin" + + +WWW_USER="www-data" +if [ -f /etc/redhat-release ]; then + WWW_USER="apache" +fi + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +# Checking root permissions +if [ "x$(id -u)" != 'x0' ]; then + echo "Error: Script can be run executed only by root" + exit 10 +fi + +if [ -n "$PHPMYADMIN_KEY" ] && [ "$PHPMYADMIN_KEY" != "" ]; then + echo "Error: SSO has been installed before to reenable it please run v-delete-sys-pma-sso first" + exit 1 +fi + +if [ -f "/usr/share/phpmyadmin/hestia-sso.php" ]; then + echo "Error: hestia-sso.php is already installed" + exit 2 +fi + +if [ -f "/usr/local/hesta/web/api/index.php" ]; then + echo "Error: API script not installed" + exit 2 +fi + +if [ "API_SYSTEM" = "0" ]; then + echo "Error: API is not enabled" + exit 2 +fi + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Generate the keys to secure everything +phpmyadminkey=$(generate_password) +apikey=$($BIN/v-add-access-key 'admin' 'phpmyadmin-sso' 'phpMyAdmin' 'plain') + +# copy config dir to /usr/share/phpmyadmin/ +cp -f $HESTIA_COMMON_DIR/phpmyadmin/hestia-sso.php $PMA_INSTALL/hestia-sso.php +chmod 640 $PMA_INSTALL/hestia-sso.php +chown root:$WWW_USER $PMA_INSTALL/hestia-sso.php + +sed -i "s/%PHPMYADMIN_KEY%/$phpmyadminkey/g" $PMA_INSTALL/hestia-sso.php +sed -i "s/%API_KEY%/$apikey/g" $PMA_INSTALL/hestia-sso.php +sed -i "s/%API_HOST_NAME%/$(hostname)/g" $PMA_INSTALL/hestia-sso.php +sed -i "s/%API_HESTIA_PORT%/$BACKEND_PORT/g" $PMA_INSTALL/hestia-sso.php + +# Check if config already contains the keys +touch $PMA_CONFIG/hestia-sso.inc.php +chmod 640 $PMA_CONFIG/hestia-sso.inc.php +chown root:$WWW_USER $PMA_CONFIG/hestia-sso.inc.php + +echo "" >> $PMA_CONFIG/hestia-sso.inc.php + +file=$(cat $PMA_CONFIG/config.inc.php) +if ! [[ "$file" =~ hestia-sso.inc.php ]]; then + if [[ $file =~ "//Add Hestia SSO code here" ]]; then + sed -i "s|//Add Hestia SSO code here|//Add Hestia SSO code here\n include ('$PMA_CONFIG/hestia-sso.inc.php');|g" $PMA_CONFIG/config.inc.php + else + echo "include ('$PMA_CONFIG/hestia-sso.inc.php');" >> $PMA_CONFIG/config.inc.php + fi +fi + +$BIN/v-change-sys-config-value 'PHPMYADMIN_KEY' "$phpmyadminkey" + +if [ -z "$(echo $API_ALLOWED_IP | grep 127.0.0.1)" ]; then + $BIN/v-add-sys-api-ip "127.0.0.1" +fi + +#----------------------------------------------------------# +# Logging # +#----------------------------------------------------------# + +if [ "$MODE" != "quiet" ]; then + echo "PMA Hestia-SSO plugin has been successfully installed" +fi +$BIN/v-log-action "system" "Info" "Plugins" "phpMyAdmin Single Sign-On has been enabled." +log_event "$OK" "$ARGUMENTS" diff --git a/bin/v-add-sys-quota b/bin/v-add-sys-quota new file mode 100755 index 0000000..811eaae --- /dev/null +++ b/bin/v-add-sys-quota @@ -0,0 +1,106 @@ +#!/bin/bash +# info: add system quota +# options: NONE +# +# example: v-add-sys-quota +# +# This function enables filesystem quota on /home partition +# Some kernels do require additional packages to be installed first + +#----------------------------------------------------------# +# Variable & Function # +#----------------------------------------------------------# + +# Includes +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +# Ensure that quota kernel modules are installed +kernel_module_check=$(find /lib/modules/$(uname -r) -type f -name '*quota_v*.ko*' | egrep '.*' && [ $? -eq 0 ]) +if [ -z "$kernel_module_check" ]; then + # Install kernel modules for quota support. + # Requires reboot to activate updated kernel. + echo "Installing required kernel modules for quota support..." + reboot_req="Y" + apt-get -qq install linux-image-extra-virtual -y + check_result $? "kernel module installation failed" "$E_UPDATE" +fi + +# Checking quota package +quota=$(which --skip-alias --skip-functions quota 2> /dev/null) +if [ $? -ne 0 ]; then + if [ -f "/etc/redhat-release" ]; then + dnf -y install quota > /dev/null 2>&1 + else + export DEBIAN_FRONTEND=noninteractive + apt-get -y install quota > /dev/null 2>&1 + fi + check_result $? "quota package installation failed" "$E_UPDATE" +fi + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Adding group and user quota on /home partition +mnt=$(df -P /home | awk '{print $6}' | tail -n1) +lnr=$(cat -n /etc/fstab | grep -v "#" | awk '{print $1,$3}' | grep "$mnt$" | cut -f 1 -d ' ') +opt=$(sed -n ${lnr}p /etc/fstab | awk '{print $4}') +fnd='usrquota\|grpquota\|usrjquota=aquota.user\|grpjquota=aquota.group\|jqfmt=vfsv0' +if [ $(echo $opt | tr ',' '\n' | grep -x $fnd | wc -l) -ne 5 ]; then + old=$(echo $(echo $opt | tr ',' '\n' | grep -v 'usrquota\|grpquota\|usrjquota=\|grpjquota=\|jqfmt=') | tr ' ' ',') + new='usrquota,grpquota,usrjquota=aquota.user,grpjquota=aquota.group,jqfmt=vfsv0' + sed -i "$lnr s/$opt/$old,$new/" /etc/fstab + mount -o remount "$mnt" +fi + +# Adding v2 group and user quota index +if [ ! -e "$mnt/aquota.user" ] || [ ! -e "$mnt/aquota.group" ]; then + quotacheck -avcugm > /dev/null 2>&1 +fi + +# Adding quotacheck on reboot +touch /forcequotacheck + +# Adding cron job +echo '#!/bin/bash' > /etc/cron.daily/quotacheck +echo 'touch /forcequotacheck' >> /etc/cron.daily/quotacheck +chmod a+x /etc/cron.daily/quotacheck + +# Enabling group and user quota +if [ -n "$(quotaon -pa | grep " $mnt " | grep 'user\|group' | grep 'is off')" ]; then + quotaon -v $mnt + check_result $? "quota can't be enabled in $mnt" "$E_DISK" +fi + +# Updating hestia.conf value +if [ -z "$(grep DISK_QUOTA $HESTIA/conf/hestia.conf)" ]; then + echo "DISK_QUOTA='yes'" >> $HESTIA/conf/hestia.conf +else + sed -i "s/DISK_QUOTA=.*/DISK_QUOTA='yes'/g" $HESTIA/conf/hestia.conf +fi + +# Rebuilding user quota +for user in $($BIN/v-list-sys-users plain); do + $BIN/v-update-user-quota "$user" +done + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +$BIN/v-log-action "system" "Info" "Plugins" "System Quota enforcement enabled." +log_history "system quota enforcement enabled" +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-add-sys-roundcube b/bin/v-add-sys-roundcube new file mode 100755 index 0000000..a16a530 --- /dev/null +++ b/bin/v-add-sys-roundcube @@ -0,0 +1,216 @@ +#!/bin/bash +# info: Install Roundcube webmail client +# options: [MODE] +# +# This function installs the Roundcube webmail client. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +source $HESTIA/func/db.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" +# upgrade config file +source "$HESTIA/install/upgrade/upgrade.conf" + +MODE=$2 +UPDATE="no" +# Version and Download paths +RC_FILE="roundcubemail-$rc_v-complete.tar.gz" +RC_EXTRACT="roundcubemail-$rc_v" +# Downloading full version +RC_URL="https://github.com/roundcube/roundcubemail/releases/download/$rc_v/roundcubemail-$rc_v-complete.tar.gz" + +# Folder paths +RC_INSTALL_DIR="/var/lib/roundcube" +RC_CONFIG_DIR="/etc/roundcube" +RC_LOG="/var/log/roundcube" + +WWW_USER="www-data" +if [ -f /etc/redhat-release ]; then + WWW_USER="apache" +fi + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +# Checking root permissions +if [ "x$(id -u)" != 'x0' ]; then + echo "ERROR: v-add-sys-roundcube can be run executed only by root user" + exit 10 +fi + +# Ensure that $HESTIA (/usr/local/hestia/) and other variables are valid. +if [ -z "$HESTIA" ]; then + HESTIA="/usr/local/hestia" +fi + +if [ -z "$HOMEDIR" ] || [ -z "$HESTIA_COMMON_DIR" ]; then + echo "ERROR: Environment variables not present, installation aborted." + exit 2 +fi + +if [ -z "$(echo "$DB_SYSTEM" | grep -w 'mysql')" ]; then + echo "ERROR: Mysql not available. Installation aborted" + exit 2 +fi + +if [ -d "/usr/share/roundcube" ]; then + echo "ERROR: Install done from apt source, unable to continue" + exit 2 +fi + +# Get current version +if [ -f "/var/lib/roundcube/index.php" ]; then + version=$(cat $RC_INSTALL_DIR/index.php | grep -o -E '[0-9].[0-9].[0-9]+' | head -1) + if [ "$version" == "$rc_v" ]; then + echo "Error: Installed version ($version) is equal to the available version ($rc_v)" + exit 2 + else + UPDATE="yes" + fi +fi + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +if [ "$UPDATE" == "no" ]; then + rm -f -r $RC_INSTALL_DIR + rm -f -r $RC_CONFIG_DIR + + mkdir -p $RC_INSTALL_DIR/ + mkdir -p $RC_CONFIG_DIR/ + + cd "$RC_INSTALL_DIR" + [ ! -f "${RC_INSTALL_DIR}/${RC_FILE}" ] && wget "$RC_URL" --retry-connrefused --quiet -O "${RC_INSTALL_DIR}/${RC_FILE}" + + tar xzf $RC_FILE + cp -rT $RC_EXTRACT $RC_INSTALL_DIR + + # Delete old config folder + cp $RC_INSTALL_DIR/config/defaults.inc.php $RC_CONFIG_DIR/defaults.inc.php + rm -f -r $RC_INSTALL_DIR/config/ + ln -s $RC_CONFIG_DIR/ ./config + # Replace with Hestia config + cp -f $HESTIA_COMMON_DIR/roundcube/main.inc.php $RC_CONFIG_DIR/config.inc.php + cp -f $HESTIA_COMMON_DIR/roundcube/mimetypes.php $RC_CONFIG_DIR/mimetypes.php + chmod 644 $RC_CONFIG_DIR/*.php + + cp -f $HESTIA_COMMON_DIR/roundcube/hestia.php $RC_INSTALL_DIR/plugins/password/drivers/ + mkdir -p $RC_CONFIG_DIR/plugins/password + mkdir -p $RC_CONFIG_DIR/plugins/newmail_notifier + mkdir -p $RC_CONFIG_DIR/plugins/zipdownload + + # Allow changes to the respective config / Create symlinks to /etc/roundcube/ + cp -f $HESTIA_COMMON_DIR/roundcube/config.inc.php $RC_CONFIG_DIR/plugins/password/config.inc.php + ln -s $RC_CONFIG_DIR/plugins/password/config.inc.php ./plugins/password/config.inc.php + cp -f $HESTIA_COMMON_DIR/roundcube/plugins/config_newmail_notifier.inc.php $RC_CONFIG_DIR/plugins/newmail_notifier/config.inc.php + ln -s $RC_CONFIG_DIR/plugins/newmail_notifier/config.inc.php ./plugins/newmail_notifier/config.inc.php + cp -f $HESTIA_COMMON_DIR/roundcube/plugins/config_zipdownload.inc.php $RC_CONFIG_DIR/plugins/zipdownload/config.inc.php + ln -s $RC_CONFIG_DIR/plugins/zipdownload/config.inc.php ./plugins/zipdownload/config.inc.php + + # Set up correct permissions roundcube + chown -R root:$WWW_USER $RC_CONFIG_DIR/ + chmod 751 -R $RC_CONFIG_DIR + chmod 644 $RC_CONFIG_DIR/config.inc.php + chmod 644 $RC_CONFIG_DIR/plugins/password/config.inc.php + chmod 644 $RC_CONFIG_DIR/plugins/newmail_notifier/config.inc.php + chmod 644 $RC_CONFIG_DIR/plugins/zipdownload/config.inc.php + + # Add robots.txt + echo "User-agent: *" > /var/lib/roundcube/robots.txt + echo "Disallow: /" >> /var/lib/roundcube/robots.txt + + chown -R root:$WWW_USER $RC_INSTALL_DIR + + # Log file + if [ ! -d $RC_LOG ]; then + mkdir $RC_LOG + fi + chown apache:$WWW_USER $RC_LOG + chmod 751 $RC_LOG + + if [ ! -z "$(echo "$DB_SYSTEM" | grep -E 'mysql|pgsql')" ]; then + host='localhost' + database='roundcube' + dbuser="$database" + dbpass=$(generate_password) + charset='UTF8' + sed -i "s/%password%/$dbpass/g" $RC_CONFIG_DIR/config.inc.php + + if [ ! -z "$(echo "$DB_SYSTEM" | grep -w 'mysql')" ]; then + add_mysql_database + mysql_query "USE $database; $(< /var/lib/roundcube/SQL/mysql.initial.sql)" + else + add_pgsql_database + psql_query "USE $database; $(< /var/lib/roundcube/SQL/postgres.initial.sql)" + fi + fi + + # TODO: Add support for PostgreSQL + + rcDesKey="$(openssl rand -base64 30 | tr -d "/" | cut -c1-24)" + sed -i "s/%des_key%/$rcDesKey/g" $RC_CONFIG_DIR/config.inc.php + # Update server hostname in password change plugin + sed -i "s/localhost/$(hostname)/g" $RC_CONFIG_DIR/plugins/password/config.inc.php + + # Clean up + rm -f -r $RC_INSTALL_DIR/installer + rm -f -r $RC_INSTALL_DIR/$RC_FILE + rm -f -r $RC_INSTALL_DIR/$RC_EXTRACT + + # Updating hestia.conf + if [ -z "$(grep WEBMAIL_SYSTEM $HESTIA/conf/hestia.conf)" ]; then + $BIN/v-change-sys-config-value 'WEBMAIL_SYSTEM' 'roundcube' + else + if [ -z "$(echo "$WEBMAIL_SYSTEM" | grep -w 'roundcube')" ]; then + if [ ! -z "$WEBMAIL_SYSTEM" ]; then + $BIN/v-change-sys-config-value 'WEBMAIL_SYSTEM' "roundcube,$WEBMAIL_SYSTEM" + else + $BIN/v-change-sys-config-value 'WEBMAIL_SYSTEM' "roundcube" + fi + fi + fi + + phpenmod mcrypt > /dev/null 2>&1 +else + cd "$RC_INSTALL_DIR" + [ ! -f "${RC_INSTALL_DIR}/${RC_FILE}" ] && wget "$RC_URL" --quiet -O "${RC_INSTALL_DIR}/${RC_FILE}" + + tar xzf $RC_FILE + + # Run Roundcube upgrade script + $RC_INSTALL_DIR/$RC_EXTRACT/bin/installto.sh -y $RC_INSTALL_DIR > /dev/null 2>&1 + $RC_INSTALL_DIR/bin/update.sh --version "$version" > /dev/null 2>&1 + $RC_INSTALL_DIR/bin/indexcontacts.sh > /dev/null 2>&1 + chown -R root:$WWW_USER $RC_INSTALL_DIR + + #clean up the mess + if [ -d "$RC_INSTALL_DIR/installer" ]; then + rm -f -r $RC_INSTALL_DIR/installer + fi + rm -f -r $RC_INSTALL_DIR/$RC_FILE + rm -f -r $RC_INSTALL_DIR/$RC_EXTRACT +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +if [ "$UPDATE" = "yes" ]; then + $BIN/v-log-action "system" "Info" "Plugins" "Roundcube updated (Version: $version)." +else + $BIN/v-log-action "system" "Info" "Plugins" "Roundcube enabled (Version: $version)." +fi +log_event "$OK" "$ARGUMENTS" diff --git a/bin/v-add-sys-sftp-jail b/bin/v-add-sys-sftp-jail new file mode 100755 index 0000000..d81db06 --- /dev/null +++ b/bin/v-add-sys-sftp-jail @@ -0,0 +1,99 @@ +#!/bin/bash +# info: add system sftp jail +# options: [RESTART] +# +# example: v-add-sys-sftp-jail yes +# +# This function enables sftp jailed environment. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +restart=$1 + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Checking sshd directives +config='/etc/ssh/sshd_config' +sftp_n=$(grep -n "Subsystem.*sftp" $config | grep -v internal | grep -v ":#") +sftp_i=$(grep -n "^# Hestia SFTP Chroot" $config) + +# Disabling normal sftp +if [ -n "$sftp_n" ]; then + fline=$(echo $sftp_n | cut -f 1 -d :) + sed -i "${fline}s/Subsystem.*sftp/#Subsystem sftp/" $config + restart='yes' +fi + +# Enabling jailed sftp +if [ -z "$sftp_i" ]; then + echo " " >> $config + echo "# Hestia SFTP Chroot" >> $config + echo "Match User sftp_dummy99" >> $config + echo "ChrootDirectory %h" >> $config + echo " X11Forwarding no" >> $config + echo " AllowTCPForwarding no" >> $config + echo " ForceCommand internal-sftp" >> $config + restart='yes' +fi + +# Validating opensshd config +if [ "$restart" = 'yes' ]; then + subj="OpenSSH restart failed" + email=$(grep CONTACT $HESTIA/data/users/admin/user.conf | cut -f 2 -d \') + /usr/sbin/sshd -t > /dev/null 2>&1 + if [ "$?" -ne 0 ]; then + mail_text="OpenSSH can not be restarted. Please check config: + \n\n$(/usr/sbin/sshd -t)" + echo -e "$mail_text" | $SENDMAIL -s "$subj" $email + else + service ssh restart > /dev/null 2>&1 + fi +fi + +# Checking users +shells="rssh|nologin" +for user in $(grep "$HOMEDIR" /etc/passwd | egrep "$shells" | cut -f 1 -d:); do + # Include all users v-add-user-sftp-jail will handle it + $BIN/v-add-user-sftp-jail "$user" "no" +done + +# Restart ssh service +if [ "$restart" = 'no' ]; then + # Skip restart of SSH daemon + echo "" > /dev/null 2>&1 +else + service ssh restart > /dev/null 2>&1 +fi + +# Add v-add-sys-sftp-jail to startup +if [ ! -e "/etc/cron.d/hestia-sftp" ]; then + echo "@reboot root sleep 60 && /usr/local/hestia/bin/v-add-sys-sftp-jail > /dev/null" > /etc/cron.d/hestia-sftp +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-add-sys-smtp b/bin/v-add-sys-smtp new file mode 100755 index 0000000..951cf84 --- /dev/null +++ b/bin/v-add-sys-smtp @@ -0,0 +1,63 @@ +#!/bin/bash +# info: Add SMTP Account for logging, notification and internal mail +# options: DOMAIN PORT SMTP_SECURITY USERNAME PASSWORD EMAIL +# +# example: v-add-sys-smtp example.com 587 STARTTLS test@domain.com securepassword test@example.com +# +# This function allows configuring a SMTP account for the server to use +# for logging, notification and warn emails etc. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +domain=$1 +port=$2 +smtp_security=$3 +username=$4 +password=$5 +email=$6 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '6' "$#" 'DOMAIN PORT SMTP_SECURITY USERNAME PASSWORD EMAIL' +is_format_valid 'domain' 'port' 'email' 'password' +is_username_format_valid "$username" 'username' +format_no_quotes "$password" 'passowrd' +is_common_format_valid "$smtp_security" "SMTP_SECURITY" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +change_sys_value "USE_SERVER_SMTP" 'true' +change_sys_value "SERVER_SMTP_HOST" "$domain" +change_sys_value "SERVER_SMTP_PORT" "$port" +change_sys_value "SERVER_SMTP_SECURITY" "$smtp_security" +change_sys_value "SERVER_SMTP_USER" "$username" +change_sys_value "SERVER_SMTP_PASSWD" "$password" +change_sys_value "SERVER_SMTP_ADDR" "$email" + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +$BIN/v-log-action "system" "Info" "Mail" "Server SMTP enabled." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-add-sys-smtp-relay b/bin/v-add-sys-smtp-relay new file mode 100755 index 0000000..5fbf94d --- /dev/null +++ b/bin/v-add-sys-smtp-relay @@ -0,0 +1,64 @@ +#!/bin/bash +# info: add system wide smtp relay support +# options: HOST [USERNAME] [PASSWORD] [PORT] +# +# example: v-add-sys-smtp-relay srv.smtprelay.tld uname123 pass12345 +# +# This function adds system wide smtp relay support. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +host=$1 +username=$2 +password=$3 +port=${4-587} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'HOST [USERNAME] [PASSWORD] [PORT]' +is_format_valid 'port' 'host' 'password' +is_username_format_valid "$username" 'username' +format_no_quotes "$password" 'passowrd' +is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM' + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +change_sys_value 'SMTP_RELAY' 'true' +change_sys_value 'SMTP_RELAY_HOST' "$host" +change_sys_value 'SMTP_RELAY_PORT' "$port" +change_sys_value 'SMTP_RELAY_USER' "$username" + +cat > /etc/exim4/smtp_relay.conf << EOL +host:$host +port:$port +user:$username +pass:$password +EOL + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +$BIN/v-log-action "system" "Info" "Mail" "Server-wide SMTP Relay enabled (Host: $host, Port: $port)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-add-sys-snappymail b/bin/v-add-sys-snappymail new file mode 100755 index 0000000..8d45c90 --- /dev/null +++ b/bin/v-add-sys-snappymail @@ -0,0 +1,174 @@ +#!/bin/bash +# info: Install SnappyMail webmail client +# options: [MODE] +# +# This function installs the SnappyMail webmail client. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" +# upgrade config file +source "$HESTIA/install/upgrade/upgrade.conf" + +MODE=$1 +UPDATE="no" +# Version and Download paths +# Version to be moved to upgrade script +SM_FILE="snappymail-latest.tar.gz" +# For removal of folder +SM_EXTRACT_MAIN="snappymail" + +# Downloading full version +SM_URL="https://snappymail.eu/repository/latest.tar.gz" + +# Folder paths +SM_INSTALL_DIR="/var/lib/snappymail" +SM_CONFIG_DIR="/etc/snappymail" +SM_LOG="/var/log/snappymail" + +WWW_USER="www-data" +if [ -f /etc/redhat-release ]; then + WWW_USER="apache" +fi + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +# Checking root permissions +if [ "x$(id -u)" != 'x0' ]; then + echo "ERROR: v-add-sys-snappymail can only be executed by the root user" + exit 10 +fi + +# Ensure that $HESTIA (/usr/local/hestia/) and other variables are valid. +if [ -z "$HESTIA" ]; then + HESTIA="/usr/local/hestia" +fi + +if [ -z "$HOMEDIR" ] || [ -z "$HESTIA_INSTALL_DIR" ]; then + echo "ERROR: Environment variables not present, installation aborted." + exit 2 +fi + +if [ -z "$(echo "$DB_SYSTEM" | grep -w 'mysql')" ]; then + echo "ERROR: Mysql not available. Installation aborted" + exit 2 +fi + +# Get current version +if [ -f "/var/lib/snappymail/data/VERSION" ]; then + version=$(cat $SM_INSTALL_DIR/data/VERSION) + if [ "$version" == "$sm_v" ]; then + echo "Error: Installed version ($version) is equal to the available version ($sm_v)" + exit 2 + else + UPDATE="yes" + fi +fi + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +if [ "$UPDATE" == "no" ]; then + rm -f -r $SM_INSTALL_DIR + rm -f -r $SM_CONFIG_DIR + + mkdir $SM_INSTALL_DIR + mkdir $SM_CONFIG_DIR + + cd "$SM_INSTALL_DIR" + [ ! -f "${SM_INSTALL_DIR}/${SM_FILE}" ] && wget "$SM_URL" --retry-connrefused --quiet -O "${SM_INSTALL_DIR}/${SM_FILE}" + + if [ ! -f "${SM_INSTALL_DIR}/${SM_FILE}" ]; then + echo "ERROR: Download failed, installation aborted." + exit 2 + fi + + # Get current version + + key=$(openssl rand -hex 4) + + admin_account="admin_$key" + admin_password=$(generate_password) + + echo "Username: admin_$key" > ~/.snappymail + echo "Password: $admin_password" >> ~/.snappymail + echo "Secret key: admin_$key" >> ~/.snappymail + + tar -xzf ${SM_INSTALL_DIR}/${SM_FILE} + + mv ./data $SM_CONFIG_DIR/ + ln -s $SM_CONFIG_DIR/data/ ./data + + if [ -f '/usr/bin/mariadb' ]; then + mariadb -e "CREATE DATABASE snappymail" 2>&1 + r=$(generate_password) + mariadb -e "GRANT ALL ON snappymail.* + TO snappymail@localhost IDENTIFIED BY '$r'" + else + mysql -e "CREATE DATABASE snappymail" 2>&1 + r=$(generate_password) + mysql -e "GRANT ALL ON snappymail.* + TO snappymail@localhost IDENTIFIED BY '$r'" + fi + php -f $HESTIA_COMMON_DIR/snappymail/install.php "admin_$key" "$admin_password" "$r" "$BACKEND_PORT" + + chown -R $WWW_USER:$WWW_USER ./data + chown -R $WWW_USER:$WWW_USER $SM_CONFIG_DIR/ + + rm ${SM_INSTALL_DIR}/${SM_FILE} + # Add robots.txt + echo "User-agent: *" > $SM_INSTALL_DIR/robots.txt + echo "Disallow: /" >> $SM_INSTALL_DIR/robots.txt + + # Updating hestia.conf + if [ -z "$(grep WEBMAIL_SYSTEM $HESTIA/conf/hestia.conf)" ]; then + $BIN/v-change-sys-config-value 'WEBMAIL_SYSTEM' 'snappymail' + else + if [ -z "$(echo "$WEBMAIL_SYSTEM" | grep -w 'snappymail')" ]; then + if [ -n "$WEBMAIL_SYSTEM" ]; then + $BIN/v-change-sys-config-value 'WEBMAIL_SYSTEM' "snappymail,$WEBMAIL_SYSTEM" + else + $BIN/v-change-sys-config-value 'WEBMAIL_SYSTEM' "snappymail" + fi + fi + fi + +else + [ ! -f "${SM_INSTALL_DIR}/${SM_FILE}" ] && wget "$SM_URL" --quiet -O "${SM_INSTALL_DIR}/${SM_FILE}" + version=$(cat $SM_INSTALL_DIR/data/VERSION) + + tar -xzf snappymail-latest.tar.gz "data/VERSION" $SM_INSTALL_DIR/ + version_source=$(cat $SM_INSTALL_DIR/VERSION) + + # Check version inside .tar.gz file in case hestia didn't update yet + if [ "$version" != "$version_source" ]; then + tar -xzf ${SM_INSTALL_DIR}/${SM_FILE} + rm $SM_INSTALL_DIR/$SM_FILE + fi + rm ${SM_INSTALL_DIR}/VERSION +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +if [ "$UPDATE" = "yes" ]; then + $BIN/v-log-action "system" "Info" "Plugins" "SnappyMail updated (Version: $version)." +else + $BIN/v-log-action "system" "Info" "Plugins" "SnappyMail enabled (Version: $version)." +fi +log_event "$OK" "$ARGUMENTS" diff --git a/bin/v-add-user b/bin/v-add-user new file mode 100755 index 0000000..299958a --- /dev/null +++ b/bin/v-add-user @@ -0,0 +1,286 @@ +#!/bin/bash +# info: add system user +# options: USER PASSWORD EMAIL [PACKAGE] [NAME] [LASTNAME] +# +# example: v-add-user admin2 P4$$w@rD bgates@aol.com +# +# This function creates new user account. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +password=$2 +HIDE=2 +email=$3 +package=${4-default} +name=$5 +# Last name has been added for backward compatibility with WHMCS / Blesta VestaCP Plugins +if [ -n "$6" ]; then + name="$name $6" +fi +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +is_user_free() { + # these names may cause issues with MariaDB/MySQL database names and should be reserved: + # sudo has been added due to Privilege escalation as sudo group has always sudo permission + check_sysuser=$(php -r '$reserved_names=array("aria", "aria_log", "mysql", "mysql_upgrade", "ib", "ib_buffer", + "ddl", "ddl_recovery", "performance", "sudo"); if(in_array(strtolower($argv[1]), $reserved_names, true)){echo implode(", ", $reserved_names);}' "$user") + if [ -n "$check_sysuser" ]; then + check_result "$E_INVALID" "The user name '$user' is reserved and cannot be used. List of reserved names: $check_sysuser" + return + fi + check_sysuser=$(cut -f 1 -d : /etc/passwd | grep "^$user$") + if [ -n "$check_sysuser" ] || [ -e "$USER_DATA" ]; then + check_result "$E_EXISTS" "user $user exists" + fi +} + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '3' "$#" 'USER PASSWORD EMAIL [PACKAGE] [NAME] ' +is_format_valid 'user' 'email' 'package' +if [ -n "$name" ]; then + is_format_valid 'name' +fi + +is_user_free "$user" +is_password_valid +is_package_valid + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Parsing package data +pkg_data=$(cat $HESTIA/data/packages/$package.pkg | egrep -v "TIME|DATE") + +# Checking shell +shell_conf=$(echo "$pkg_data" | grep 'SHELL' | cut -f 2 -d \') +shell=$(grep -w "$shell_conf" /etc/shells | head -n1) + +# Adding user +/usr/sbin/useradd "$user" -s "$shell" -c "$email" -m -d "$HOMEDIR/$user" -U +check_result $? "user creation failed" "$E_INVALID" + +# Adding password +echo "$user:$password" | /usr/sbin/chpasswd + +if [ $? -ne 0 ]; then + # Delete user on failure + /usr/sbin/deluser "$user" > /dev/null 2>&1 + echo "Error: Password not accepted due to PAM restrictions" + exit 2 +fi + +# Add a general group for normal users created by Hestia +if [ -z "$(grep ^hestia-users: /etc/group)" ]; then + groupadd --system "hestia-users" +fi + +# Add membership to hestia-users group to non-admin users +if [ "$user" = "admin" ]; then + setfacl -m "g:admin:r-x" "$HOMEDIR/$user" +else + usermod -a -G "hestia-users" "$user" + setfacl -m "u:$user:r-x" "$HOMEDIR/$user" +fi +setfacl -m "g:hestia-users:---" "$HOMEDIR/$user" + +# Building directory tree +mkdir $HOMEDIR/$user/conf + +if [ -n "$WEB_SYSTEM" ]; then + mkdir $HOMEDIR/$user/conf/web $HOMEDIR/$user/web $HOMEDIR/$user/tmp + chmod 751 $HOMEDIR/$user/conf/web + chmod 700 $HOMEDIR/$user/tmp + chown $user:$user $HOMEDIR/$user/tmp + chown root:$user $HOMEDIR/$user/web/ +fi + +if [ -n "$MAIL_SYSTEM" ]; then + mkdir $HOMEDIR/$user/conf/mail $HOMEDIR/$user/mail + chmod 751 $HOMEDIR/$user/mail + chmod 755 $HOMEDIR/$user/conf/mail +fi + +if [ -n "$DNS_SYSTEM" ]; then + if [ "$DNS_SYSTEM" = 'named' ]; then + dns_group='named' + else + dns_group='bind' + fi + mkdir $HOMEDIR/$user/conf/dns + chmod 771 $HOMEDIR/$user/conf/dns + chown root:$dns_group $HOMEDIR/$user/conf/dns +fi + +# Create default writeable folders +mkdir $HOMEDIR/$user/.config \ + $HOMEDIR/$user/.cache \ + $HOMEDIR/$user/.local \ + $HOMEDIR/$user/.composer \ + $HOMEDIR/$user/.vscode-server \ + $HOMEDIR/$user/.ssh \ + $HOMEDIR/$user/.npm + +chown $user:$user \ + $HOMEDIR/$user/.config \ + $HOMEDIR/$user/.cache \ + $HOMEDIR/$user/.local \ + $HOMEDIR/$user/.composer \ + $HOMEDIR/$user/.vscode-server \ + $HOMEDIR/$user/.ssh \ + $HOMEDIR/$user/.npm + +# Set permissions +chmod a+x $HOMEDIR/$user +chattr +i $HOMEDIR/$user/conf > /dev/null 2>&1 + +# Adding user dir +mkdir -p $USER_DATA/ssl $USER_DATA/dns $USER_DATA/mail + +# Creating configuration files and pipes +touch $USER_DATA/backup.conf \ + $USER_DATA/history.log \ + $USER_DATA/stats.log \ + $USER_DATA/web.conf \ + $USER_DATA/dns.conf \ + $USER_DATA/mail.conf \ + $USER_DATA/db.conf \ + $USER_DATA/cron.conf + +chmod 770 $USER_DATA \ + $USER_DATA/ssl \ + $USER_DATA/dns \ + $USER_DATA/mail + +chmod 660 $USER_DATA/backup.conf \ + $USER_DATA/history.log \ + $USER_DATA/stats.log \ + $USER_DATA/web.conf \ + $USER_DATA/dns.conf \ + $USER_DATA/mail.conf \ + $USER_DATA/db.conf \ + $USER_DATA/cron.conf + +# Updating queue pipes +echo "$BIN/v-update-user-disk $user" >> $HESTIA/data/queue/disk.pipe +if [ -n "$WEB_SYSTEM" ]; then + echo "$BIN/v-update-web-domains-traff $user" \ + >> $HESTIA/data/queue/traffic.pipe + echo "$BIN/v-update-web-domains-disk $user" >> $HESTIA/data/queue/disk.pipe +fi +if [ -n "$MAIL_SYSTEM" ]; then + echo "$BIN/v-update-mail-domains-disk $user" >> $HESTIA/data/queue/disk.pipe +fi + +if [ -n "$DB_SYSTEM" ]; then + echo "$BIN/v-update-databases-disk $user" >> $HESTIA/data/queue/disk.pipe +fi + +# Generating timestamp +time_n_date=$(date +'%T %F') +time=$(echo "$time_n_date" | cut -f 1 -d \ ) +date=$(echo "$time_n_date" | cut -f 2 -d \ ) + +# Filling user config +if [ "$user" != 'admin' ]; then + ip_avail=$($BIN/v-list-user-ips admin plain | grep -w shared | wc -l) + u_users=0 +else + ip_avail=0 + u_users=1 +fi + +echo "NAME='$name' +PACKAGE='$package' +$pkg_data +CONTACT='$email' +CRON_REPORTS='yes' +MD5='$(awk -v user=$user -F : 'user == $1 {print $2}' /etc/shadow)' +RKEY='$(generate_password)' +TWOFA='' +QRCODE='' +PHPCLI='' +ROLE='user' +SUSPENDED='no' +SUSPENDED_USERS='0' +SUSPENDED_WEB='0' +SUSPENDED_DNS='0' +SUSPENDED_MAIL='0' +SUSPENDED_DB='0' +SUSPENDED_CRON='0' +IP_AVAIL='$ip_avail' +IP_OWNED='0' +U_USERS='$u_users' +U_DISK='0' +U_DISK_DIRS='0' +U_DISK_WEB='0' +U_DISK_MAIL='0' +U_DISK_DB='0' +U_BANDWIDTH='0' +U_WEB_DOMAINS='0' +U_WEB_SSL='0' +U_WEB_ALIASES='0' +U_DNS_DOMAINS='0' +U_DNS_RECORDS='0' +U_MAIL_DOMAINS='0' +U_MAIL_DKIM='0' +U_MAIL_ACCOUNTS='0' +U_MAIL_SSL='0' +U_DATABASES='0' +U_CRON_JOBS='0' +U_BACKUPS='0' +LANGUAGE='' +THEME='' +NOTIFICATIONS='no' +PREF_UI_SORT='name' +LOGIN_DISABLED='no' +LOGIN_USE_IPLIST='no' +LOGIN_ALLOW_IPS='' +TIME='$time' +DATE='$date'" > $USER_DATA/user.conf +chmod 660 $USER_DATA/user.conf + +# Updating quota +if [ "$DISK_QUOTA" = 'yes' ]; then + $BIN/v-update-user-quota "$user" +fi + +# Updating admin counter +if [ "$user" != 'admin' ]; then + increase_user_value 'admin' '$U_USERS' +fi + +# Run template trigger +if [ -x "$HESTIA/data/packages/$package.sh" ]; then + $HESTIA/data/packages/$package.sh "$user" "$email" "$name" +fi + +# Adding jailed sftp env +$BIN/v-add-user-sftp-jail $user + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +$BIN/v-log-action "system" "Info" "Users" "User account added (Name: $user)." +$BIN/v-log-action "$user" "Info" "System" "Welcome!" +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-add-user-2fa b/bin/v-add-user-2fa new file mode 100755 index 0000000..be3aa99 --- /dev/null +++ b/bin/v-add-user-2fa @@ -0,0 +1,64 @@ +#!/bin/bash +# info: add 2fa to existing user +# options: USER +# +# example: v-add-user-2fa admin +# +# This function creates a new 2fa token for user. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'USER' +is_format_valid 'user' 'system' +is_object_valid 'user' 'USER' "$user" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Reading user values +source $USER_DATA/user.conf + +# Check if 2FA is already enabled +if [ -n "$TWOFA" ]; then + echo "Error: 2FA already enabled" + exit "$E_EXISTS" +fi + +# Get secret and qr code from 2fa library +data=$($HESTIA_PHP $HESTIA/web/inc/2fa/secret.php) + +# Split to secret and qrcode using delimiter +IFS='-' read -r -a array <<< "$data" +secret=${array[0]} +qrcode=${array[1]} + +# Save the secret in user config (needs encryption?) +update_user_value "$user" '$TWOFA' "$secret" +update_user_value "$user" '$QRCODE' "$qrcode" + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-add-user-composer b/bin/v-add-user-composer new file mode 100755 index 0000000..c3cfe64 --- /dev/null +++ b/bin/v-add-user-composer @@ -0,0 +1,95 @@ +#!/bin/bash +# info: add composer (php dependency manager) for a user +# options: USER +# +# example: v-add-user-composer user [version] +# +# This function adds support for composer (php dependency manager) +# Homepage: + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +version=${2-2} + +if [ -z "$HESTIA" ]; then + HESTIA="/usr/local/hestia" +fi + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'USER [VERSION]' +is_format_valid 'user' +is_number_format_valid "$version" "version" +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" + +[ -z "$HOMEDIR" ] && check_result "$E_NOTEXIST" "Hestia environment vars not present" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +COMPOSER_DIR="$HOMEDIR/$user/.composer" +COMPOSER_BIN="$COMPOSER_DIR/composer" + +if [ -f "$COMPOSER_BIN" ]; then + echo "Composer already available" + exit +fi + +[ -z "$(readlink -m "$COMPOSER_DIR" | egrep "^$HOMEDIR/$user/")" ] && check_result "$E_FORBIDEN" "Path outside of user homedir (Composer dir)" +[ -z "$(readlink -m "$COMPOSER_BIN" | egrep "^$HOMEDIR/$user/")" ] && check_result "$E_FORBIDEN" "Path outside of user homedir (Composer bin)" +[ -z "$(readlink -m "$HOMEDIR/$user/.config/" | egrep "^$HOMEDIR/$user/")" ] && check_result "$E_FORBIDEN" "Path outside of user homedir (.conf)" + +mkdir -p "$COMPOSER_DIR" +chown $user: "$COMPOSER_DIR" +mkdir -p "$HOMEDIR/$user/.config" +chown $user: "$HOMEDIR/$user/.config" +echo "alias composer=/home/"$user"/.composer/composer" >> /home/$user/.bash_aliases + +COMPOSER_SETUP_FILE=$(mktemp) +check_result $? "Create temp file" +chown $user: "$COMPOSER_SETUP_FILE" + +signature="$(curl --silent --show-error https://composer.github.io/installer.sig)" +check_result $? "Download signature" + +user_exec wget --tries=3 --timeout=15 --read-timeout=15 --waitretry=3 --no-dns-cache https://getcomposer.org/installer --quiet -O "$COMPOSER_SETUP_FILE" +check_result $? "Download composer installer" + +if [[ "$signature" != $(sha384sum "$COMPOSER_SETUP_FILE" | cut -f 1 -d " ") ]]; then + rm -f "$COMPOSER_SETUP_FILE" + check_result "$E_INVALID" "Composer signature does not match" +fi + +COMPOSER_HOME="$HOMEDIR/$user/.config/composer" user_exec /usr/bin/php "$COMPOSER_SETUP_FILE" --quiet "--$version" --install-dir="$COMPOSER_DIR" --filename=composer +check_result $? "Composer install failed" + +[ -f "$COMPOSER_SETUP_FILE" ] && rm -f "$COMPOSER_SETUP_FILE" + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +$BIN/v-log-action "$user" "Info" "Plugins" "Composer support enabled." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-add-user-notification b/bin/v-add-user-notification new file mode 100755 index 0000000..96b1de9 --- /dev/null +++ b/bin/v-add-user-notification @@ -0,0 +1,79 @@ +#!/bin/bash +# info: add user notification +# options: USER TOPIC NOTICE [TYPE] +# +# This function adds a new user notification to the panel. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +topic=$(echo $2 | sed "s/'/%quote%/g") +notice=$(echo $3 | sed "s/'/%quote%/g") +type=$4 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER TOPIC NOTICE [TYPE]' +is_format_valid 'user' 'topic' 'notice' +is_object_valid 'user' 'USER' "$user" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Defining notification id +if [ -e "$USER_DATA/notifications.conf" ]; then + nid=$(grep "NID=" $USER_DATA/notifications.conf | cut -f 2 -d \') + nid=$(echo "$nid" | sort -n | tail -n1) + if [ -n "$nid" ]; then + nid="$((nid + 1))" + else + nid=1 + fi +else + nid=1 +fi + +# Generating timestamp +time_n_date=$(date +'%T %F') +time=$(echo "$time_n_date" | cut -f 1 -d \ ) +date=$(echo "$time_n_date" | cut -f 2 -d \ ) + +# Concatenating string +str="NID='$nid' TOPIC='$topic' NOTICE='$notice' TYPE='$type'" +str="$str ACK='no' TIME='$time' DATE='$date'" + +# Adding to config +echo "$str" >> $USER_DATA/notifications.conf + +# Changing permissions +chmod 660 $USER_DATA/notifications.conf + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Updating notification counter +if [ -z "$(grep NOTIFICATIONS $USER_DATA/user.conf)" ]; then + sed -i "s/^TIME/NOTIFICATIONS='yes'\nTIME/g" $USER_DATA/user.conf +else + update_user_value "$user" '$NOTIFICATIONS' "yes" +fi + +exit diff --git a/bin/v-add-user-package b/bin/v-add-user-package new file mode 100755 index 0000000..4dac30b --- /dev/null +++ b/bin/v-add-user-package @@ -0,0 +1,154 @@ +#!/bin/bash +# info: adding user package +# options: tmpfile PACKAGE [REWRITE] +# +# This function adds new user package to the system. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +tmpfile=$1 +package=$2 +rewrite=$3 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +is_package_consistent() { + source_conf "$tmpfile" + if [ "$WEB_DOMAINS" != 'unlimited' ]; then + is_int_format_valid "$WEB_DOMAINS" 'WEB_DOMAINS' + fi + if [ "$WEB_ALIASES" != 'unlimited' ]; then + is_int_format_valid "$WEB_ALIASES" 'WEB_ALIASES' + fi + if [ "$DNS_DOMAINS" != 'unlimited' ]; then + is_int_format_valid "$DNS_DOMAINS" 'DNS_DOMAINS' + fi + if [ "$DNS_RECORDS" != 'unlimited' ]; then + is_int_format_valid "$DNS_RECORDS" 'DNS_RECORDS' + fi + if [ "$MAIL_DOMAINS" != 'unlimited' ]; then + is_int_format_valid "$MAIL_DOMAINS" 'MAIL_DOMAINS' + fi + if [ "$MAIL_ACCOUNTS" != 'unlimited' ]; then + is_int_format_valid "$MAIL_ACCOUNTS" 'MAIL_ACCOUNTS' + fi + if [ "$DATABASES" != 'unlimited' ]; then + is_int_format_valid "$DATABASES" 'DATABASES' + fi + if [ "$CRON_JOBS" != 'unlimited' ]; then + is_int_format_valid "$CRON_JOBS" 'CRON_JOBS' + fi + + is_int_format_valid "$RATE_LIMIT" 'RATE_LIMIT' + + if [ "$DISK_QUOTA" != 'unlimited' ]; then + is_int_format_valid "$DISK_QUOTA" 'DISK_QUOTA' + fi + if [ "$BANDWIDTH" != 'unlimited' ]; then + is_int_format_valid "$BANDWIDTH" 'BANDWIDTH' + fi + is_int_format_valid "$BACKUPS" 'BACKUPS' + if [ -n "$WEB_TEMPLATE" ]; then + is_web_template_valid "$WEB_TEMPLATE" + fi + if [ -n "$BACKEND_TEMPLATE" ]; then + is_backend_template_valid "$BACKEND_TEMPLATE" + fi + if [ -n "$PROXY_TEMPLATE" ]; then + is_proxy_template_valid "$PROXY_TEMPLATE" + fi + if [ -n "$DNS_TEMPLATE" ]; then + is_dns_template_valid "$DNS_TEMPLATE" + fi + if [ -n "$NS" ]; then + IFS=',' read -r -a nameservers <<< "$NS" + i=1 + for ns in "${nameservers[@]}"; do + is_domain_format_valid "$ns" "ns$i" + i=$((i + 1)) + done + fi + + is_format_valid_shell "$SHELL" +} + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'PKG_DIR PACKAGE' 'rewrite' +is_format_valid 'package' +if [ "$rewrite" != 'yes' ]; then + is_package_new "$package" +else + is_package_valid "$package" +fi + +if [ ! -f "$tmpfile" ]; then + echo "$tmpfile does not exists" + exit "$E_NOTEXIST" +fi + +is_package_consistent + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Generating timestamp +time_n_date=$(date +'%T %F') +time=$(echo "$time_n_date" | cut -f 1 -d \ ) +date=$(echo "$time_n_date" | cut -f 2 -d \ ) + +SHELL=$(basename $SHELL) +echo "WEB_TEMPLATE='$WEB_TEMPLATE' +PROXY_TEMPLATE='$PROXY_TEMPLATE' +BACKEND_TEMPLATE='$BACKEND_TEMPLATE' +DNS_TEMPLATE='$DNS_TEMPLATE' +WEB_DOMAINS='$WEB_DOMAINS' +WEB_ALIASES='$WEB_ALIASES' +DNS_DOMAINS='$DNS_DOMAINS' +DNS_RECORDS='$DNS_RECORDS' +MAIL_DOMAINS='$MAIL_DOMAINS' +MAIL_ACCOUNTS='$MAIL_ACCOUNTS' +RATE_LIMIT='$RATE_LIMIT' +DATABASES='$DATABASES' +CRON_JOBS='$CRON_JOBS' +DISK_QUOTA='$DISK_QUOTA' +BANDWIDTH='$BANDWIDTH' +NS='$NS' +SHELL='$SHELL' +BACKUPS='$BACKUPS' +TIME='$time' +DATE='$date' +" > "$HESTIA/data/packages/$package.pkg" + +chmod 644 "$HESTIA/data/packages/$package.pkg" + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +if [ "$rewrite" != 'yes' ]; then + $BIN/v-log-action "system" "Info" "Packages" "Package added (Name: $package)." +else + $BIN/v-log-action "system" "Info" "Packages" "Package limits updated (Name: $package)." +fi +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-add-user-sftp-jail b/bin/v-add-user-sftp-jail new file mode 100755 index 0000000..8abbf22 --- /dev/null +++ b/bin/v-add-user-sftp-jail @@ -0,0 +1,94 @@ +#!/bin/bash +# info: add user sftp jail +# options: USER [RESTART] +# +# example: v-add-user-sftp-jail admin +# +# This function enables sftp jailed environment + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +restart=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'USER' +is_format_valid 'user' +check=$(is_object_valid 'user' 'USER' "$user") +if [ $? -ne 0 ]; then + user_str=$(grep "^$user:" /etc/passwd | egrep "rssh|nologin") + #try to detect "owner" of the ftp_user if not found dont set it up + user_owner=$(echo $user_str | cut -f6 -d : | cut -f3 -d /) + is_object_valid 'user' 'USER' "$user_owner" +fi +user_str=$(grep "^$user:" /etc/passwd | egrep "rssh|nologin") +if [ -z "$user_str" ]; then + exit +fi + +# Get current users and split into array +ssh_users=$(grep -A1 "^# Hestia SFTP Chroot" /etc/ssh/sshd_config | sed -n 2p | sed 's/Match User //') +IFS=',' read -r -a users <<< "$ssh_users" + +# Check if jail exist +match_string="$ssh_users," +if [[ "$match_string" =~ ,$user, ]]; then + if [[ -d /home/$user && -z "$(find /home/$user -user root -print -prune -o -prune)" ]]; then + chown root:root /home/$user + fi + exit +fi + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Add user to array +users+=($user) + +# Write new user list to config +users=$( + IFS=',' + echo "${users[*]// /|}" + IFS=$' \t\n' +) +sed -i "s/$ssh_users/$users/g" /etc/ssh/sshd_config + +# Set home folder permission to root +if [ -d "/home/$user" ]; then + chown root:root /home/$user +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Restart ssh service +if [ "$restart" = 'no' ]; then + # Skip restart of SSH daemon + echo "" > /dev/null 2>&1 +else + service ssh restart > /dev/null 2>&1 +fi + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-add-user-sftp-key b/bin/v-add-user-sftp-key new file mode 100755 index 0000000..1df7993 --- /dev/null +++ b/bin/v-add-user-sftp-key @@ -0,0 +1,82 @@ +#!/bin/bash +# info: add user sftp key +# options: USER [TTL] +# +# This function creates and updates SSH keys for used with the File Manager. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +ttl=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'USER [TTL]' +is_format_valid 'user' 'ttl' +is_object_valid 'user' 'USER' "$user" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +PRVKEY_FILE="$HOMEDIR/$user/.ssh/hst-filemanager-key" +PUBKEY_FILE="$HOMEDIR/$user/.ssh/hst-filemanager-key.pub" +AUTHKEY_FILE="$HOMEDIR/$user/.ssh/authorized_keys" + +[ -z "$(readlink -f "$PRVKEY_FILE" | egrep "^$HOMEDIR/$user/.ssh/")" ] && check_result "$E_FORBIDEN" "Invalid private key file path" +[ -z "$(readlink -f "$PUBKEY_FILE" | egrep "^$HOMEDIR/$user/.ssh/")" ] && check_result "$E_FORBIDEN" "Invalid public key file path" +[ -z "$(readlink -f "$AUTHKEY_FILE" | egrep "^$HOMEDIR/$user/.ssh/")" ] && check_result "$E_FORBIDEN" "Invalid authorized keys path" + +if [ ! -f "${PRVKEY_FILE}" ]; then + ssh-keygen -q -b 1024 -t rsa -f "${PRVKEY_FILE}" -N "" + rm "${PUBKEY_FILE}" + new_privkey=true +fi + +if [ ! -f "${AUTHKEY_FILE}" ] || [ "$new_privkey" = true ]; then + pubkey_str="$(ssh-keygen -y -f ${PRVKEY_FILE})" + pubkey_desc="filemanager.ssh.key" + + if grep --quiet --no-messages -F "$pubkey_desc" "${AUTHKEY_FILE}"; then + sed -i "/filemanager\.ssh\.key\$/d" "${AUTHKEY_FILE}" + fi + + # make sure authorized_keys is ending with EOL + [ -f "${AUTHKEY_FILE}" ] && sed -i '$a\' "${AUTHKEY_FILE}" + + expire=0 + if [[ "$ttl" -gt 0 ]]; then + expire=$(date +%s -d "+${ttl} min") + echo "rm ${PRVKEY_FILE}" | at "now +${ttl} minute" > /dev/null 2>&1 + fi + echo "from=\"127.0.0.1\",command=\"internal-sftp\",restrict ${pubkey_str} TS:${expire} ${pubkey_desc}" >> "${AUTHKEY_FILE}" +fi + +# +chown ${user}: "${AUTHKEY_FILE}" +chown admin: "${PRVKEY_FILE}" + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-add-user-ssh-key b/bin/v-add-user-ssh-key new file mode 100755 index 0000000..38f1de9 --- /dev/null +++ b/bin/v-add-user-ssh-key @@ -0,0 +1,73 @@ +#!/bin/bash +# info: add ssh key +# options: USER KEY +# +# example: v-add-user-ssh-key user 'valid ssh key' +# +# Function check if $user/.ssh/authorized_keys exists and create it. +# After that it append the new key(s) + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +key=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER SSH_PUBLIC_KEY' +is_format_valid 'user' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Reading user values +source $USER_DATA/user.conf + +AUTHKEY_FILE="$HOMEDIR/$user/.ssh/authorized_keys" +[ -z "$(readlink -f "$AUTHKEY_FILE" | egrep "^$HOMEDIR/$user/.ssh/")" ] && check_result "$E_FORBIDEN" "Invalid authorized keys path" + +# Check if file exits +if [ ! -f "$AUTHKEY_FILE" ]; then + v-add-fs-file "$user" "${AUTHKEY_FILE}" +fi + +[ -z "$key" ] && check_result "$E_NOTEXIST" "Empty ssh public key" + +if ! echo "$key" | ssh-keygen -l -f - > /dev/null 2>&1; then + check_result "$E_PARSING" "Validating user private key" +fi + +# Make sure authorized_keys ends with EOL +[ -f "${AUTHKEY_FILE}" ] && sed -i '$a\' "${AUTHKEY_FILE}" + +# Append key data to file +echo "$key" >> "$AUTHKEY_FILE" + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +$BIN/v-log-action "$user" "Info" "System" "Added a new SSH key." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-add-user-wp-cli b/bin/v-add-user-wp-cli new file mode 100755 index 0000000..360e251 --- /dev/null +++ b/bin/v-add-user-wp-cli @@ -0,0 +1,69 @@ +#!/bin/bash +# info: add wp-cli for a user +# options: USER +# +# example: v-add-user-wp-cli user +# +# This function adds support for wp-cli to the user account + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 + +if [ -z "$HESTIA" ]; then + HESTIA="/usr/local/hestia" +fi + +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'USER' +is_format_valid 'user' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +WPCLI_DIR="/home/$user/.wp-cli" +WPCLI_BIN="$WPCLI_DIR/wp" + +if [ -f "$WPCLI_BIN" ]; then + check_result "$E_EXISTS" "For user name '$user' WP-CLI already available!" + exit +fi + +[ -z "$(readlink -m "$WPCLI_DIR" | egrep "^$HOMEDIR/$user/")" ] && check_result "$E_FORBIDEN" "Path outside of user homedir (WP Cli dir)" +[ -z "$(readlink -m "$WPCLI_BIN" | egrep "^$HOMEDIR/$user/")" ] && check_result "$E_FORBIDEN" "Path outside of user homedir (WP Cli bin)" + +mkdir -p "$WPCLI_DIR" +chown $user:$user "$WPCLI_DIR" + +user_exec wget --tries=3 --timeout=15 --read-timeout=15 --waitretry=3 --no-dns-cache --quiet -O "$WPCLI_BIN" https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar +user_exec chmod +x "$WPCLI_BIN" +user_exec echo -e "#add wp-cli alias for user\nalias wp='php $WPCLI_BIN'" >> ~/.bashrc + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +$BIN/v-log-action "$user" "Info" "Plugins" "WP-CLI support enabled." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-add-web-domain b/bin/v-add-web-domain new file mode 100755 index 0000000..b565828 --- /dev/null +++ b/bin/v-add-web-domain @@ -0,0 +1,257 @@ +#!/bin/bash +# info: add web domain +# options: USER DOMAIN [IP] [RESTART] [ALIASES] [PROXY_EXTENSIONS] +# +# example: v-add-web-domain admin wonderland.com 192.18.22.43 yes www.wonderland.com +# +# This function adds virtual host to a server. In cases when ip is +# undefined in the script, "default" template will be used. The alias of +# www.domain.tld type will be automatically assigned to the domain unless +# "none" is transmited as argument. If ip have associated dns name, this +# domain will also get the alias domain-tpl.$ipname. An alias with the ip +# name is useful during the site testing while dns isn't moved to server yet. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 +ip=$3 +restart=$4 # will be moved to the end soon +aliases=$5 +proxy_ext=$6 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# shellcheck source=/usr/local/hestia/func/ip.sh +source $HESTIA/func/ip.sh +# shellcheck source=/usr/local/hestia/func/syshealth.sh +source $HESTIA/func/syshealth.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn +format_aliases +domain_utf=$(idn2 --quiet -d "$domain_idn") + + +WWW_USER="www-data" +if [ -f /etc/redhat-release ]; then + WWW_USER="apache" +fi + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +is_system_enabled "$WEB_SYSTEM" 'WEB_SYSTEM' +check_args '2' "$#" 'USER DOMAIN [IP] [RESTART] [ALIASES] [PROXY_EXTENSIONS]' +is_format_valid 'user' 'domain' 'aliases' 'ip' 'proxy_ext' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_package_full 'WEB_DOMAINS' + +if [ "$aliases" != "none" ]; then + ALIAS="$aliases" + is_package_full 'WEB_ALIASES' +fi + +if [ "$($BIN/v-list-web-domain $user $domain_utf plain | cut -f 1) " != "$domain" ]; then + is_domain_new 'web' "$domain_utf,$aliases" +fi +if [ "$($BIN/v-list-web-domain $user $domain_idn plain | cut -f 1) " != "$domain" ]; then + is_domain_new 'web' "$domain_idn,$aliases" +else + is_domain_new 'web' "$domain,$aliases" +fi +if [ -z "$(is_ip_format_valid $domain)" ]; then + echo "Error: Invalid domain format. IP address detected as input." + exit 1 +fi + +is_dir_symlink "$HOMEDIR/$user/web" +is_dir_symlink "$HOMEDIR/$user/web/$domain" + +is_base_domain_owner "$domain,$aliases" + +if [ -n "$ip" ]; then + is_ip_valid "$ip" "$user" +else + get_user_ip +fi + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Reading user values +source_conf "$USER_DATA/user.conf" + +[[ -e "$HOMEDIR/$user/web/$domain" ]] && check_result "$E_EXISTS" "Web domain folder for $domain should not exist" + +# Creating domain directories +mkdir $HOMEDIR/$user/web/$domain +chown $user:$user $HOMEDIR/$user/web/$domain +$BIN/v-add-fs-directory "$user" "$HOMEDIR/$user/web/$domain/public_html" +$BIN/v-add-fs-directory "$user" "$HOMEDIR/$user/web/$domain/document_errors" +$BIN/v-add-fs-directory "$user" "$HOMEDIR/$user/web/$domain/cgi-bin" +$BIN/v-add-fs-directory "$user" "$HOMEDIR/$user/web/$domain/private" +$BIN/v-add-fs-directory "$user" "$HOMEDIR/$user/web/$domain/stats" +$BIN/v-add-fs-directory "$user" "$HOMEDIR/$user/web/$domain/logs" + +# Creating domain logs +touch /var/log/$WEB_SYSTEM/domains/$domain.bytes \ + /var/log/$WEB_SYSTEM/domains/$domain.log \ + /var/log/$WEB_SYSTEM/domains/$domain.error.log +ln -f -s /var/log/$WEB_SYSTEM/domains/$domain.*log \ + $HOMEDIR/$user/web/$domain/logs/ + +# Adding domain skeleton +user_exec cp -r $WEBTPL/skel/* "$HOMEDIR/$user/web/$domain/" > /dev/null 2>&1 +for file in $(find "$HOMEDIR/$user/web/$domain/" -type f); do + sed -i "s/%domain%/$domain/g" $file +done + +# Changing file owner & permission +chown -R $user:$user $HOMEDIR/$user/web/$domain +chown root:$user /var/log/$WEB_SYSTEM/domains/$domain.* $conf +chmod 640 /var/log/$WEB_SYSTEM/domains/$domain.* +user_exec chmod 751 $HOMEDIR/$user/web/$domain/* +user_exec chmod 551 $HOMEDIR/$user/web/$domain/stats $HOMEDIR/$user/web/$domain/logs +user_exec chmod 644 $HOMEDIR/$user/web/$domain/public_*html/* +user_exec chmod 551 $HOMEDIR/$user/web/$domain +chown --no-dereference $user:$WWW_USER $HOMEDIR/$user/web/$domain/public_*html + +# Adding PHP-FPM backend +if [ -n "$WEB_BACKEND" ]; then + if [ -z "$BACKEND_TEMPLATE" ]; then + BACKEND_TEMPLATE='default' + if [ -z "$(grep BACKEND_TEMPLATE $USER_DATA/user.conf)" ]; then + sed -i "s/^DNS_TEMPL/BACKEND_TEMPLATE='default'\nDNS_TEMPL/g" \ + $USER_DATA/user.conf + else + update_user_value "$user" '$BACKEND_TEMPLATE' "default" + fi + fi + export BACKEND="$BACKEND_TEMPLATE" + $BIN/v-add-web-domain-backend "$user" "$domain" "$BACKEND_TEMPLATE" "$restart" + check_result $? "Backend error" > /dev/null +fi + +# Preparing domain aliases +if [ "$aliases" = 'none' ]; then + ALIAS='' +else + ALIAS="www.$domain" + if [ -z "$aliases" ]; then + # Check and skip www alias for subdomains. + IFS='.' read -r -a domain_elements <<< "$domain" + if [ "${#domain_elements[@]}" -gt 2 ]; then + is_valid_2_part_extension $domain + if [ $? -ne 0 ]; then + ALIAS="" + else + ALIAS="www.$domain" + fi + else + ALIAS="www.$domain" + fi + else + ALIAS="$aliases" + fi + + ip_alias=$(get_ip_alias "$domain") + if [ -n "$ip_alias" ]; then + ALIAS="$ALIAS,$ip_alias" + fi +fi + +# Preparing domain variables +prepare_web_domain_values + +if [ -z "$WEB_TEMPLATE" ]; then + WEB_TEMPLATE='default' + update_user_value "$user" '$WEB_TEMPLATE' "default" +fi + +# Adding web server config +add_web_config "$WEB_SYSTEM" "$WEB_TEMPLATE.tpl" + +# Adding proxy config +if [ -n "$PROXY_SYSTEM" ]; then + PROXY_EXT="$proxy_ext" + if [ -z "$proxy_ext" ]; then + # Code + PROXY_EXT="css,htm,html,js,json,xml" + # Image (from https://developer.mozilla.org/en-US/docs/Web/Media/Formats/Image_types) + PROXY_EXT="$PROXY_EXT,apng,avif,bmp,cur,gif,ico,jfif,jpg,jpeg,pjp,pjpeg,png,svg,tif,tiff,webp" + # Audio from (https://developer.mozilla.org/en-US/docs/Web/Media/Formats/Audio_codecs) + PROXY_EXT="$PROXY_EXT,aac,caf,flac,m4a,midi,mp3,ogg,opus,wav" + # Video (from https://developer.mozilla.org/en-US/docs/Web/Media/Formats/Video_codecs) + PROXY_EXT="$PROXY_EXT,3gp,av1,avi,m4v,mkv,mov,mpg,mpeg,mp4,mp4v,webm" + # Fonts + PROXY_EXT="$PROXY_EXT,otf,ttf,woff,woff2" + # Productivity + PROXY_EXT="$PROXY_EXT,doc,docx,odf,odp,ods,odt,pdf,ppt,pptx,rtf,txt,xls,xlsx" + # Archive + PROXY_EXT="$PROXY_EXT,7z,bz2,gz,rar,tar,tgz,zip" + # Binaries + PROXY_EXT="$PROXY_EXT,apk,appx,bin,dmg,exe,img,iso,jar,msi" + fi + if [ -z "$PROXY_TEMPLATE" ]; then + PROXY_TEMPLATE='default' + update_user_value "$user" '$PROXY_TEMPLATE' "default" + fi + + add_web_config "$PROXY_SYSTEM" "$PROXY_TEMPLATE.tpl" +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Increasing counters +increase_ip_value "$local_ip" +increase_user_value "$user" '$U_WEB_DOMAINS' +increase_user_value "$user" '$U_WEB_ALIASES' "$alias_number" + +# Generating timestamp +time_n_date=$(date +'%T %F') +time=$(echo "$time_n_date" | cut -f 1 -d \ ) +date=$(echo "$time_n_date" | cut -f 2 -d \ ) + +# Adding domain in web.conf +echo "DOMAIN='$domain' IP='$ip' IP6='' CUSTOM_DOCROOT='' ALIAS='$ALIAS' TPL='$WEB_TEMPLATE'\ + SSL='no' SSL_FORCE='no' SSL_HOME='same' LETSENCRYPT='no' FTP_USER='' FTP_MD5=''\ + BACKEND='$BACKEND_TEMPLATE' PROXY='$PROXY_TEMPLATE' PROXY_EXT='$PROXY_EXT'\ + STATS='' STATS_USER='' STATS_CRYPT='' U_DISK='0' U_BANDWIDTH='0'\ + SUSPENDED='no' TIME='$time' DATE='$date'" >> $USER_DATA/web.conf + +syshealth_repair_web_config + +# Restarting web server +$BIN/v-restart-web "$restart" +check_result $? "Web restart failed" > /dev/null + +# Restarting proxy server +$BIN/v-restart-proxy "$restart" +check_result $? "Proxy restart failed" > /dev/null + +# Logging +$BIN/v-log-action "$user" "Info" "Web" "Added new web domain (Name: $domain)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-add-web-domain-alias b/bin/v-add-web-domain-alias new file mode 100755 index 0000000..b32a7fc --- /dev/null +++ b/bin/v-add-web-domain-alias @@ -0,0 +1,114 @@ +#!/bin/bash +# info: add web domain alias +# options: USER DOMAIN ALIASES [RESTART] +# +# example: v-add-web-domain-alias admin acme.com www.acme.com yes +# +# This function adds one or more aliases to a domain (it is also called +# "domain parking"). This function supports wildcards *.domain.tpl. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 +aliases=$3 +restart="$4" + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# shellcheck source=/usr/local/hestia/func/ip.sh +source $HESTIA/func/ip.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn +# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ? +format_aliases + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +if [ -z "$aliases" ]; then + check_result "$E_INVALID" "Invalid alias format: empty" +fi + +check_args '3' "$#" 'USER DOMAIN ALIASES [RESTART]' +is_format_valid 'user' 'domain' 'aliases' +is_system_enabled "$WEB_SYSTEM" 'WEB_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'web' 'DOMAIN' "$domain" +is_object_unsuspended 'web' 'DOMAIN' "$domain" +is_domain_new 'web' "$aliases" +is_base_domain_owner "$aliases" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +get_domain_values 'web' + +# Preparing domain values for the template substitution +local_ip=$(get_real_ip $IP) +if [ -z "$ALIAS" ]; then + ALIAS="$aliases" +else + ALIAS="$ALIAS,$aliases" +fi +prepare_web_domain_values + +is_package_full 'WEB_ALIASES' + +# Rebuilding vhost +del_web_config "$WEB_SYSTEM" "$TPL.tpl" +add_web_config "$WEB_SYSTEM" "$TPL.tpl" +if [ "$SSL" = 'yes' ]; then + del_web_config "$WEB_SYSTEM" "$TPL.stpl" + add_web_config "$WEB_SYSTEM" "$TPL.stpl" +fi + +# Rebuilding proxy configuration +if [ -n "$PROXY_SYSTEM" ] && [ -n "$PROXY" ]; then + del_web_config "$PROXY_SYSTEM" "$PROXY.tpl" + add_web_config "$PROXY_SYSTEM" "$PROXY.tpl" + if [ "$SSL" = 'yes' ]; then + del_web_config "$PROXY_SYSTEM" "$PROXY.stpl" + add_web_config "$PROXY_SYSTEM" "$PROXY.stpl" + fi +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Adding new alias +update_object_value 'web' 'DOMAIN' "$domain" '$ALIAS' "$ALIAS" +increase_user_value "$user" '$U_WEB_ALIASES' + +# Restarting web server +$BIN/v-restart-web "$restart" +check_result $? "Web restart failed" > /dev/null + +# Restarting proxy server +$BIN/v-restart-proxy "$restart" +check_result $? "Proxy restart failed" > /dev/null + +$BIN/v-log-action "$user" "Info" "Web" "Added new web domain alias (Alias: $aliases, Domain: $domain)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-add-web-domain-allow-users b/bin/v-add-web-domain-allow-users new file mode 100755 index 0000000..b22757c --- /dev/null +++ b/bin/v-add-web-domain-allow-users @@ -0,0 +1,71 @@ +#!/bin/bash +# info: Allow other users create subdomains +# options: USER DOMAIN +# +# example: v-add-web-domain-allow-users admin admin.com +# +# Bypass the rule check for Enforce subdomain ownership for a specific domain. +# Enforce subdomain ownership setting in /edit/server/ set to no will always overwrite this behaviour +# eg: admin adds admin.com +# user can create user.admin.com + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# shellcheck source=/usr/local/hestia/func/ip.sh +source $HESTIA/func/ip.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DOMAIN' +is_format_valid 'user' 'domain' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'web' 'DOMAIN' "$domain" +is_object_unsuspended 'web' 'DOMAIN' "$domain" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Load domain data +parse_object_kv_list $(grep "DOMAIN='$domain'" $USER_DATA/web.conf) + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +if [ -z "$ALLOW_USERS" ]; then + add_object_key "web" 'DOMAIN' "$domain" 'ALLOW_USERS' 'TIME' +fi + +# Adding new alias +update_object_value 'web' 'DOMAIN' "$domain" '$ALLOW_USERS' "yes" + +$BIN/v-log-action "$user" "Warning" "Web" "Subdomain ownership enforcement disabled (Domain: $domain)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-add-web-domain-backend b/bin/v-add-web-domain-backend new file mode 100755 index 0000000..bd3c1d1 --- /dev/null +++ b/bin/v-add-web-domain-backend @@ -0,0 +1,97 @@ +#!/bin/bash +# info: add web domain backend +# options: USER DOMAIN [TEMPLATE] [RESTART] +# +# example: v-add-web-domain-backend admin example.com default yes +# +# This function is used to add the web backend configuration. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +template=${3-default} +restart=$4 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# shellcheck source=/usr/local/hestia/conf/hestia.conf +source $HESTIA/conf/hestia.conf +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DOMAIN [TEMPLATE] [RESTART]' +is_format_valid 'user' 'domain' +is_system_enabled "$WEB_BACKEND" 'WEB_BACKEND' +is_object_valid 'user' 'USER' "$user" +is_backend_template_valid "$template" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Defining pool directory +prepare_web_backend +get_domain_values 'web' + +if [[ -n "$BACKEND" && "$BACKEND" != "$template" ]]; then + check_result "$E_EXISTS" "Pool already exists" +fi + +# Allocating backend port +backend_port=9000 +ports=$(grep -v '^;' $pool/* 2> /dev/null | grep listen | grep -o :[0-9].*) +ports=$(echo "$ports" | sed "s/://" | sort -n) +for port in $ports; do + if [ "$backend_port" -eq "$port" ]; then + backend_port=$((backend_port + 1)) + fi +done + +# Adding backend config +cat $WEBTPL/$WEB_BACKEND/$template.tpl \ + | sed -e "s|%backend_port%|$backend_port|" \ + -e "s|%user%|$user|g" \ + -e "s|%domain%|$domain|g" \ + -e "s|%backend%|$backend_type|g" \ + -e "s|%backend_version%|$backend_version|g" > $pool/$backend_type.conf + +# Set correct document root path +if [ -n "$CUSTOM_DOCROOT" ]; then + docroot="$CUSTOM_DOCROOT" + if [ -n "$CUSTOM_PHPROOT" ]; then + docroot="$CUSTOM_PHPROOT" + fi + sed -i "s|/home\/$user\/web\/$domain\/public_html|$docroot|g" $pool/$backend_type.conf +else + docroot="$HOMEDIR/$user/web/$domain/public_html/" +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Restart php interpreter +$BIN/v-restart-web-backend "$restart" "$backend_version" +check_result $? "PHP restart failed" > /dev/null + +# Logging +$BIN/v-log-action "$user" "Info" "Web" "Web domain configuration applied (Domain: $domain, Backend: $WEB_BACKEND)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-add-web-domain-ftp b/bin/v-add-web-domain-ftp new file mode 100755 index 0000000..b6c96b8 --- /dev/null +++ b/bin/v-add-web-domain-ftp @@ -0,0 +1,140 @@ +#!/bin/bash +# info: add ftp account for web domain. +# options: USER DOMAIN FTP_USER FTP_PASSWORD [FTP_PATH] +# +# example: v-add-web-domain-ftp alice wonderland.com alice_ftp p4$$vvOrD +# +# This function creates additional ftp account for web domain. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 +ftp_user=${1}_${3} +password=$4 +HIDE=4 +ftp_path=$5 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn +# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ? + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '4' "$#" 'USER DOMAIN FTP_USER FTP_PASSWORD [FTP_PATH]' +is_format_valid 'user' 'domain' 'ftp_user' +is_system_enabled "$WEB_SYSTEM" 'WEB_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'web' 'DOMAIN' "$domain" +is_object_unsuspended 'web' 'DOMAIN' "$domain" +check_ftp_user=$(grep "^$ftp_user:" /etc/passwd) +if [ -n "$check_ftp_user" ] && [ "$FTP_USER" != "$ftp_user" ]; then + echo "Error: ftp user $ftp_user already exists" + log_event "$E_EXISTS" "$ARGUMENTS" + exit "$E_EXISTS" +fi +is_password_valid + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Get domain values +get_domain_values 'web' + +# Defining ftp user shell +shell=$(which nologin) +if [ -n "$FTP_SHELL" ]; then + shell=$FTP_SHELL +fi + +# Defining path +if [ -z "$ftp_path" ]; then + ftp_path_a="$HOMEDIR/$user/web/$domain" +else + # Validating absolute path + ftp_path_a=$(readlink -f "$HOMEDIR/$user/web/$domain/$ftp_path") + if [ -z "$(echo $ftp_path_a | grep $HOMEDIR/$user/web/$domain)" ]; then + echo "Error: absolute path $ftp_path_a is invalid" + log_event "$E_INVALID" "$ARGUMENTS" + exit "$E_INVALID" + fi + # Creating ftp user home directory + if [ ! -e "$ftp_path_a" ]; then + $BIN/v-add-fs-directory "$user" "$ftp_path_a" + chown $user:$user "$ftp_path_a" + chmod 751 "$ftp_path_a" + fi +fi + +# Adding ftp user +/usr/sbin/useradd $ftp_user \ + -s $shell \ + -o -u $(id -u $user) \ + -g $(id -g $user) \ + -G hestia-users \ + -M -d "$ftp_path_a" > /dev/null 2>&1 + +# Set ftp user password +echo "$ftp_user:$password" | /usr/sbin/chpasswd + +if [ $? -ne 0 ]; then + # Delete user on failure again + /usr/sbin/deluser "$ftp_user" > /dev/null 2>&1 + echo "Error: Password not accepted due to PAM restrictions" + exit 2 +fi + +ftp_md5=$(awk -v user=$ftp_user -F : 'user == $1 {print $2}' /etc/shadow) + +# Adding jailed sftp env +$BIN/v-add-user-sftp-jail "$ftp_user" + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Transforming absolute path to relative +ftp_path_r=$(echo $ftp_path_a | sed "s%$HOMEDIR/$user/web/$domain%%") + +# Concatenating ftp variables +if [ ! -z "$FTP_USER" ]; then + ftp_user="$FTP_USER:$ftp_user" + ftp_md5="$FTP_MD5:$ftp_md5" + ftp_path="$FTP_PATH:$ftp_path_r" +fi + +# Adding new key into web.conf +add_object_key "web" 'DOMAIN' "$domain" 'FTP_PATH' 'PROXY' + +# Updating config +update_object_value 'web' 'DOMAIN' "$domain" '$FTP_USER' "$ftp_user" +update_object_value 'web' 'DOMAIN' "$domain" '$FTP_MD5' "$ftp_md5" +update_object_value 'web' 'DOMAIN' "$domain" '$FTP_PATH' "$ftp_path" + +# Logging +$BIN/v-log-action "$user" "Info" "Web" "Added new FTP account (Name: ${1}_${3}@$domain)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-add-web-domain-httpauth b/bin/v-add-web-domain-httpauth new file mode 100755 index 0000000..3d03c14 --- /dev/null +++ b/bin/v-add-web-domain-httpauth @@ -0,0 +1,125 @@ +#!/bin/bash +# info: add password protection for web domain +# options: USER DOMAIN AUTH_USER AUTH_PASSWORD [RESTART] +# +# example: v-add-web-domain-httpauth admin acme.com user02 super_pass +# +# This function is used for securing web domain with http auth + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +auth_user=$3 +password=$4 +HIDE=4 +restart=${5-yes} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Defining htpasswd file +htpasswd="$HOMEDIR/$user/conf/web/$domain/htpasswd" +docroot="$HOMEDIR/$user/web/$domain/public_html" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '4' "$#" 'USER DOMAIN AUTH_USER AUTH_PASSWORD [RESTART]' +is_format_valid 'user' 'domain' +is_system_enabled "$WEB_SYSTEM" 'WEB_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'web' 'DOMAIN' "$domain" +is_object_unsuspended 'web' 'DOMAIN' "$domain" +is_password_valid +get_domain_values 'web' +is_user_format_valid "$auth_user" "Auth user" +if [ -n "$(echo "$AUTH_USER" | tr : '\n' | grep ^$auth_user$)" ]; then + echo "Error: auth user $auth_user already exists" + log_event "$E_EXISTS" "$ARGUMENTS" + exit "$E_EXISTS" +fi + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Adding htaccess password protection +if [ "$WEB_SYSTEM" = "nginx" ] || [ "$PROXY_SYSTEM" = "nginx" ]; then + htaccess="$HOMEDIR/$user/conf/web/$domain/nginx.conf_htaccess" + shtaccess="$HOMEDIR/$user/conf/web/$domain/nginx.ssl.conf_htaccess" + if [ ! -f "$htaccess" ]; then + echo "auth_basic \"$domain password access\";" > $htaccess + echo "auth_basic_user_file $htpasswd;" >> $htaccess + ln -s $htaccess $shtaccess + restart_required='yes' + fi +else + htaccess="$HOMEDIR/$user/conf/web/$domain/apache2.conf_htaccess" + shtaccess="$HOMEDIR/$user/conf/web/$domain/apache2.ssl.conf_htaccess" + if [ ! -f "$htaccess" ]; then + echo "" > $htaccess + echo " AuthUserFile $htpasswd" >> $htaccess + echo " AuthName \"$domain access\"" >> $htaccess + echo " AuthType Basic" >> $htaccess + echo " Require valid-user" >> $htaccess + echo "" >> $htaccess + ln -s $htaccess $shtaccess + restart_required='yes' + fi +fi + +# Adding httpasswd user +auth_hash=$($BIN/v-generate-password-hash htpasswd htpasswd $password) +touch $htpasswd +chmod 644 $htpasswd $htaccess +chgrp $user $htpasswd $htaccess +sed -i "/^$auth_user:/d" $htpasswd +echo "$auth_user:$auth_hash" >> $htpasswd + +# Restarting web server +if [ "$restart" != 'no' ] && [ "$restart_required" = 'yes' ]; then + $BIN/v-restart-web + if [ -n "$PROXY_SYSTEM" ]; then + $BIN/v-restart-proxy + fi +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Preparing web.conf keys +if [ -n "$AUTH_USER" ]; then + auth_user="$AUTH_USER:$auth_user" + auth_hash="$AUTH_HASH:$auth_hash" +else + # Adding new key into web.conf + add_object_key "web" 'DOMAIN' "$domain" 'AUTH_USER' 'U_DISK' + add_object_key "web" 'DOMAIN' "$domain" 'AUTH_HASH' 'U_DISK' +fi + +# Updating config +update_object_value 'web' 'DOMAIN' "$domain" '$AUTH_USER' "$auth_user" +update_object_value 'web' 'DOMAIN' "$domain" '$AUTH_HASH' "$auth_hash" + +# Logging +$BIN/v-log-action "$user" "Info" "Web" "Password protection enabled (Domain: $domain, Username: $httpauth_user)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-add-web-domain-proxy b/bin/v-add-web-domain-proxy new file mode 100755 index 0000000..743f8ca --- /dev/null +++ b/bin/v-add-web-domain-proxy @@ -0,0 +1,88 @@ +#!/bin/bash +# info: add webdomain proxy support +# options: USER DOMAIN [TEMPLATE] [EXTENTIONS] [RESTART] +# +# example: v-add-web-domain-proxy admin example.com +# +# This function enables proxy support for a domain. This can significantly +# improve website speed. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +template=$3 +default_extentions="jpg,jpeg,gif,png,webp,ico,svg,css,zip,tgz,gz,rar,bz2,doc,xls,\ +exe,pdf,ppt,txt,odt,ods,odp,odf,tar,wav,bmp,rtf,js,mp3,avi,mpeg,flv,html,htm" +extentions=${4-$default_extentions} +restart="$5" + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# shellcheck source=/usr/local/hestia/func/ip.sh +source $HESTIA/func/ip.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DOMAIN [TEMPLATE] [EXTENTIONS] [RESTART]' +is_format_valid 'user' 'domain' 'extentions' +is_system_enabled "$PROXY_SYSTEM" 'PROXY_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'web' 'DOMAIN' "$domain" +is_object_unsuspended 'web' 'DOMAIN' "$domain" +is_object_value_empty 'web' 'DOMAIN' "$domain" '$PROXY' +if [ -z $template ]; then + template=$(get_user_value '$PROXY_TEMPLATE') +fi +is_proxy_template_valid $template + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Defining domain parameters +get_domain_values 'web' +prepare_web_domain_values +local_ip=$(get_real_ip "$IP") + +# Preparing domain values for the template substitution +PROXY_EXT="$extentions" +add_web_config "$PROXY_SYSTEM" "$template.tpl" + +# Adding proxy for ssl +if [ "$SSL" = 'yes' ]; then + add_web_config "$PROXY_SYSTEM" "$template.stpl" +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Update config +update_object_value 'web' 'DOMAIN' "$domain" '$PROXY' "$template" +update_object_value 'web' 'DOMAIN' "$domain" '$PROXY_EXT' "$extentions" + +# Restarting web server +$BIN/v-restart-proxy "$restart" +check_result $? "Proxy restart failed" > /dev/null + +$BIN/v-log-action "$user" "Info" "Web" "Proxy enabled (Domain: $domain)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-add-web-domain-redirect b/bin/v-add-web-domain-redirect new file mode 100755 index 0000000..71f9a6f --- /dev/null +++ b/bin/v-add-web-domain-redirect @@ -0,0 +1,162 @@ +#!/bin/bash +# info: Adding force redirect to domain +# options: USER DOMAIN REDIRECT HTTPCODE [RESTART] +# +# example: v-add-web-domain-redirect user domain.tld domain.tld +# example: v-add-web-domain-redirect user domain.tld www.domain.tld +# example: v-add-web-domain-redirect user domain.tld shop.domain.tld +# example: v-add-web-domain-redirect user domain.tld different-domain.com +# example: v-add-web-domain-redirect user domain.tld shop.different-domain.com +# example: v-add-web-domain-redirect user domain.tld different-domain.com 302 +# +# Function creates a forced redirect to a domain + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +redirect=$3 +code=${4-301} +restart=${5-no} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '3' "$#" 'USER DOMAIN REDIRECT [HTTP-CODE] [RESTART]' +is_format_valid 'user' 'domain' +is_number_format_valid "$code" "code" +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'web' 'DOMAIN' "$domain" +is_object_unsuspended 'web' 'DOMAIN' "$domain" + +requesturi=0 +if [[ "$3" =~ http://|https:// ]]; then + scheme_check=1 + scheme=$($HESTIA_PHP -r '$url=parse_url($argv[1]); echo $url["scheme"];' "$redirect") + host=$($HESTIA_PHP -r '$url=parse_url($argv[1]); echo $url["host"];' "$redirect") + path=$($HESTIA_PHP -r '$url=parse_url($argv[1]); if(!empty($url["path"])){echo $url["path"];}' "$redirect") + port=$($HESTIA_PHP -r '$url=parse_url($argv[1]); if(!empty($url["port"])){echo $url["port"];}' "$redirect") + + host=$(idn2 --quiet "$host") + redirect="$scheme://$host$path" + if [ -n "$port" ]; then + redirect="$scheme://$host:$port$path" + fi + + isValidUrl=$(php -r '$url=$argv[1]; $url=filter_var($url,FILTER_VALIDATE_URL); echo $url;' "$redirect") + if [ -z "$isValidUrl" ]; then + check_result $E_INVALID "Invalid redirect" + fi +else + host=$($HESTIA_PHP -r '$url=parse_url($argv[1]); echo $url["host"];' "http://$redirect") + path=$($HESTIA_PHP -r '$url=parse_url($argv[1]); if(!empty($url["path"])){echo $url["path"];}' "http://$redirect") + port=$($HESTIA_PHP -r '$url=parse_url($argv[1]); if(!empty($url["port"])){echo $url["port"];}' "$redirect") + + host=$(idn2 --quiet "$host") + + redirect="$host$path" + if [ -n "$port" ]; then + redirect="$host:$port$path" + fi + + isValidUrl=$(php -r '$url=$argv[1]; $url=filter_var($url,FILTER_VALIDATE_URL); echo $url;' "http://$redirect") + if [ -z "$isValidUrl" ]; then + check_result $E_INVALID "Invalid redirect" + fi +fi + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Check if proxy is active +if [ "$WEB_SYSTEM" = 'nginx' ] || [ "$PROXY_SYSTEM" = 'nginx' ]; then + conf="$HOMEDIR/$user/conf/web/$domain/nginx.conf_redirect" + sconf="$HOMEDIR/$user/conf/web/$domain/nginx.ssl.conf_redirect" +fi + +# Prevent $request_uri being added if ends in .html +requesturi=0 +if [ -n "$path" ]; then + lastchr=${path#${path%?}} + if [ "$lastchr" = "/" ]; then + requesturi=1 + redirect=${redirect:0:-1} + fi +else + requesturi=1 +fi + +# Insert redirect commands +if [ -n "$PROXY_SYSTEM" ] || [ "$WEB_SYSTEM" = 'nginx' ]; then + if [ "$scheme_check" = 1 ]; then + if [ "$requesturi" = 1 ]; then + echo " return $code $redirect\$request_uri;" > $conf + else + echo " return $code $redirect;" > $conf + fi + if [ ! -e "$sconf" ]; then + ln -s "$conf" "$sconf" + fi + else + echo "if (\$host != \"$redirect\") {" > $conf + if [ "$requesturi" = 1 ]; then + echo " return $code \$scheme://$redirect\$request_uri;" >> $conf + else + echo " return $code \$scheme://$redirect;" >> $conf + fi + echo "}" >> $conf + + if [ ! -e "$sconf" ]; then + ln -s "$conf" "$sconf" + fi + fi +else + echo "Non supported please use .htaccess instead" + exit 2 +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Update object keys +if [ -z "$REDIRECT" ]; then + add_object_key "web" 'DOMAIN' "$domain" 'REDIRECT' 'U_DISK' + add_object_key "web" 'DOMAIN' "$domain" 'REDIRECT_CODE' 'U_DISK' +fi + +# Update values for domain +update_object_value 'web' 'DOMAIN' "$domain" '$REDIRECT' "$redirect" +update_object_value 'web' 'DOMAIN' "$domain" '$REDIRECT_CODE' "$code" + +if [ "$restart" = "yes" ]; then + # Restarting web server + $BIN/v-restart-web "$restart" + check_result $? "Web restart failed" > /dev/null + + $BIN/v-restart-proxy "$restart" + check_result $? "Proxy restart failed" > /dev/null +fi + +# Logging +$BIN/v-log-action "$user" "Info" "Web" "Domain redirection enabled (Domain: $domain, Redirect to: $redirect)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-add-web-domain-ssl b/bin/v-add-web-domain-ssl new file mode 100755 index 0000000..15f4954 --- /dev/null +++ b/bin/v-add-web-domain-ssl @@ -0,0 +1,143 @@ +#!/bin/bash +# info: adding ssl for domain +# options: USER DOMAIN SSL_DIR [SSL_HOME] [RESTART] +# +# example: v-add-web-domain-ssl admin example.com /home/admin/conf/example.com/web +# +# This function turns on SSL support for a domain. Parameter ssl_dir is a path +# to directory where 2 or 3 ssl files can be found. Certificate file +# domain.tld.crt and its key domain.tld.key are mandatory. Certificate +# authority domain.tld.ca file is optional. If home directory parameter +# (ssl_home) is not set, https domain uses public_shtml as separate +# documentroot directory. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +ssl_dir=$3 +ssl_home=${4-same} +restart="$5" + +domain=$domain +domain_idn=$(idn2 --quiet "$domain") + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# shellcheck source=/usr/local/hestia/func/ip.sh +source $HESTIA/func/ip.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '3' "$#" 'USER DOMAIN SSL_DIR [SSL_HOME] [RESTART]' +is_format_valid 'user' 'domain' 'ssl_dir' +is_system_enabled "$WEB_SYSTEM" 'WEB_SYSTEM' +is_system_enabled "$WEB_SSL" 'SSL_SUPPORT' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'web' 'DOMAIN' "$domain" +is_object_unsuspended 'web' 'DOMAIN' "$domain" +is_object_value_empty 'web' 'DOMAIN' "$domain" '$SSL' +is_web_domain_cert_valid + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Adding certificate to user data directory +cp -f $ssl_dir/$domain.crt $USER_DATA/ssl/$domain.crt +cp -f $ssl_dir/$domain.key $USER_DATA/ssl/$domain.key +cp -f $ssl_dir/$domain.crt $USER_DATA/ssl/$domain.pem +if [ -e "$ssl_dir/$domain.ca" ]; then + cp -f $ssl_dir/$domain.ca $USER_DATA/ssl/$domain.ca + echo >> $USER_DATA/ssl/$domain.pem + cat $USER_DATA/ssl/$domain.ca >> $USER_DATA/ssl/$domain.pem +fi +chmod 660 $USER_DATA/ssl/$domain.* + +# Ensure SSL directory exists +if [ ! -d "$HOMEDIR/$user/conf/web/$domain/ssl" ]; then + mkdir -p $HOMEDIR/$user/conf/web/$domain/ssl/ +fi + +# Adding certificate to user dir +cp -f $USER_DATA/ssl/$domain.crt $HOMEDIR/$user/conf/web/$domain/ssl/$domain.crt +cp -f $USER_DATA/ssl/$domain.key $HOMEDIR/$user/conf/web/$domain/ssl/$domain.key +cp -f $USER_DATA/ssl/$domain.pem $HOMEDIR/$user/conf/web/$domain/ssl/$domain.pem +if [ -e "$USER_DATA/ssl/$domain.ca" ]; then + cp -f $USER_DATA/ssl/$domain.ca $HOMEDIR/$user/conf/web/$domain/ssl/$domain.ca +fi + +if [ "$SSL_FORCE" == "yes" ]; then + # Enabling SSL redirection on demand + $BIN/v-add-web-domain-ssl-force "$user" "$domain" +fi +# Parsing domain values +get_domain_values 'web' +local_ip=$(get_real_ip "$IP") + +# Preparing domain values for the template substitution +SSL_HOME="$ssl_home" +prepare_web_domain_values + +# Adding domain to the web config +add_web_config "$WEB_SYSTEM" "$TPL.stpl" + +# Checking proxy config +if [ -n "$PROXY_SYSTEM" ] && [ -n "$PROXY" ]; then + add_web_config "$PROXY_SYSTEM" "$PROXY.stpl" +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Increasing domain value +increase_user_value "$user" '$U_WEB_SSL' + +# Adding ssl values +update_object_value 'web' 'DOMAIN' "$domain" '$SSL_HOME' "$SSL_HOME" +update_object_value 'web' 'DOMAIN' "$domain" '$SSL' "yes" + +# Restarting web server +$BIN/v-restart-web "$restart" +check_result $? "Web restart failed" > /dev/null + +$BIN/v-restart-proxy "$restart" +check_result $? "Proxy restart failed" > /dev/null + +if [ -n "$UPDATE_HOSTNAME_SSL" ] && [ "$UPDATE_HOSTNAME_SSL" = "yes" ]; then + hostname=$(hostname -f) + if [ "$hostname" = "$domain" ]; then + $BIN/v-update-host-certificate "$user" "$domain" + fi +fi + +if [ -n "$UPDATE_SSL_SCRIPT" ]; then + eval "$UPDATE_SSL_SCRIPT $user $domain" +fi + +# Logging +$BIN/v-log-action "$user" "Info" "Web" "Added certificate and enabled SSL (Domain: $domain)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-add-web-domain-ssl-force b/bin/v-add-web-domain-ssl-force new file mode 100755 index 0000000..db9d8f9 --- /dev/null +++ b/bin/v-add-web-domain-ssl-force @@ -0,0 +1,97 @@ +#!/bin/bash +# info: Adding force SSL for a domain +# options: USER DOMAIN [RESTART] [QUIET] +# +# example: v-add-web-domain-ssl-force admin acme.com +# +# This function forces SSL for the requested domain. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +restart="$3" +quiet="$4" + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DOMAIN' +is_format_valid 'user' 'domain' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'web' 'DOMAIN' "$domain" +is_object_unsuspended 'web' 'DOMAIN' "$domain" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Load domain data +parse_object_kv_list $(grep "DOMAIN='$domain'" $USER_DATA/web.conf) + +# Check if SSL is enabled +if [ "$SSL" != 'yes' ]; then + echo "Error: SSL is not enabled" + exit "$E_NOTEXIST" +fi + +# Check if proxy is active +if [ -n "$PROXY_SYSTEM" ]; then + forcessl="$HOMEDIR/$user/conf/web/$domain/$PROXY_SYSTEM.forcessl.conf" +else + forcessl="$HOMEDIR/$user/conf/web/$domain/$WEB_SYSTEM.forcessl.conf" +fi + +# Insert redirect commands +if [ -n "$PROXY_SYSTEM" ] || [ "$WEB_SYSTEM" = 'nginx' ]; then + echo 'return 301 https://$host$request_uri;' > $forcessl +else + echo 'RewriteEngine On' > $forcessl + echo 'RewriteRule ^(.*)$ https://%{HTTP_HOST}$1 [R=301,L]' >> $forcessl +fi + +chown root:$user $forcessl +chmod 640 $forcessl + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +if [ -z "$SSL_FORCE" ]; then + add_object_key "web" 'DOMAIN' "$domain" 'SSL_FORCE' 'SSL_HOME' +fi + +# Set forcessl flag to enabled +update_object_value 'web' 'DOMAIN' "$domain" '$SSL_FORCE' 'yes' + +# Restart web server +$BIN/v-restart-web "$restart" +check_result $? "Web restart failed" > /dev/null + +# Restart proxy +$BIN/v-restart-proxy "$restart" +check_result $? "Proxy restart failed" > /dev/null + +# Logging +if [ "$quiet" != "yes" ]; then + $BIN/v-log-action "$user" "Info" "Web" "Automatic HTTPS redirection enabled (Domain: $domain)." +fi +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-add-web-domain-ssl-hsts b/bin/v-add-web-domain-ssl-hsts new file mode 100755 index 0000000..5b307ba --- /dev/null +++ b/bin/v-add-web-domain-ssl-hsts @@ -0,0 +1,89 @@ +#!/bin/bash +# info: Adding hsts to a domain +# options: USER DOMAIN [RESTART] [QUIET] +# +# This function enables HSTS for the requested domain. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +restart="$3" +quiet="$4" + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DOMAIN' +is_format_valid 'user' 'domain' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'web' 'DOMAIN' "$domain" +is_object_unsuspended 'web' 'DOMAIN' "$domain" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Load domain data +parse_object_kv_list $(grep "DOMAIN='$domain'" $USER_DATA/web.conf) + +# Check if SSL is enabled +if [ "$SSL" != 'yes' ]; then + echo "Error: SSL is not enabled" + exit "$E_NOTEXIST" +fi + +# Check for Apache/Nginx or Nginx/PHP-FPM configuration +if [ -z "$PROXY_SYSTEM" ]; then + hstsconf="$HOMEDIR/$user/conf/web/$domain/$WEB_SYSTEM.hsts.conf" +else + hstsconf="$HOMEDIR/$user/conf/web/$domain/$PROXY_SYSTEM.hsts.conf" +fi + +echo 'add_header Strict-Transport-Security "max-age=31536000;" always;' > $hstsconf + +chown root:$user $hstsconf +chmod 640 $hstsconf + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +if [ -z "$SSL_HSTS" ]; then + add_object_key "web" 'DOMAIN' "$domain" 'SSL_HSTS' 'SSL_FORCE' +fi + +# Set forcessl flag to enabled +update_object_value 'web' 'DOMAIN' "$domain" '$SSL_HSTS' 'yes' + +# Restart web server +$BIN/v-restart-web "$restart" +check_result $? "Web restart failed" > /dev/null + +# Restart proxy +$BIN/v-restart-proxy "$restart" +check_result $? "Proxy restart failed" > /dev/null + +# Logging +if [ "$quiet" != "yes" ]; then + $BIN/v-log-action "$user" "Info" "Web" "HTTP Strict Transport Security (HSTS) enabled (Domain: $domain)." +fi +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-add-web-domain-ssl-preset b/bin/v-add-web-domain-ssl-preset new file mode 100755 index 0000000..6a7587e --- /dev/null +++ b/bin/v-add-web-domain-ssl-preset @@ -0,0 +1,60 @@ +#!/bin/bash +# info: Adding force SSL for a domain +# options: USER DOMAIN [SSL] +# +# example: v-add-web-domain-ssl-preset +# +# Up on creating an web domain set the SSL Force values due to the delay of LE due to DNS propergation over DNS cluster +# When LE has been activated it will set the actions + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +ssl=$3 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DOMAIN [SSL]' +is_format_valid 'user' 'domain' 'ssl' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'web' 'DOMAIN' "$domain" +is_object_unsuspended 'web' 'DOMAIN' "$domain" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Load domain data +parse_object_kv_list $(grep "DOMAIN='$domain'" $USER_DATA/web.conf) + +if [ "$ssl" = "yes" ]; then + if [ -z "$SSL_FORCE" ]; then + add_object_key "web" 'DOMAIN' "$domain" 'SSL_FORCE' 'SSL_HOME' + fi + + # Set forcessl flag to enabled + update_object_value 'web' 'DOMAIN' "$domain" '$SSL_FORCE' 'yes' +fi + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-add-web-domain-stats b/bin/v-add-web-domain-stats new file mode 100755 index 0000000..4c47e73 --- /dev/null +++ b/bin/v-add-web-domain-stats @@ -0,0 +1,109 @@ +#!/bin/bash +# info: add log analyser to generate domain statistics +# options: USER DOMAIN TYPE +# +# example: v-add-web-domain-stats admin example.com awstats +# +# This function is used for enabling log analyser system to a domain. For viewing +# the domain statistics use link. Access this page +# is not protected by default. If you want to secure it with passwords you +# should use v-add-web-domain_stat_auth script. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 +type=$3 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '3' "$#" 'USER DOMAIN TYPE' +is_format_valid 'user' 'domain' +is_system_enabled "$WEB_SYSTEM" 'WEB_SYSTEM' +is_type_valid "$STATS_SYSTEM" "$type" +is_object_valid 'user' 'USER' "$user" "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'web' 'DOMAIN' "$domain" +is_object_unsuspended 'web' 'DOMAIN' "$domain" +is_object_value_empty 'web' 'DOMAIN' "$domain" '$STATS' + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Parse aliases +get_domain_values 'web' + +# Adding statistic config +prepare_web_domain_values + +if [ -z "${aliases//,/ }" ]; then + stats_alias="localhost" +else + stats_alias=${aliases_idn//,/ } +fi + +cat $WEBTPL/$type/$type.tpl \ + | sed -e "s|%ip%|$ip|g" \ + -e "s|%web_port%|$WEB_PORT|g" \ + -e "s|%web_system%|$WEB_SYSTEM|g" \ + -e "s|%web_ssl_port%|$WEB_SSL_PORT|g" \ + -e "s|%rgroups%|$WEB_RGROUPs|g" \ + -e "s|%proxy_system%|$PROXY_SYSTEM|g" \ + -e "s|%proxy_port%|$PROXY_PORT|g" \ + -e "s|%proxy_ssl_port%|$PROXY_SSL_PORT|g" \ + -e "s|%domain_idn%|$domain_idn|g" \ + -e "s|%domain%|$domain|g" \ + -e "s|%user%|$user|g" \ + -e "s|%home%|$HOMEDIR|g" \ + -e "s|%alias%|$stats_alias|g" \ + -e "s|%alias_idn%|$stats_alias|g" \ + > $HOMEDIR/$user/conf/web/$domain/$type.conf + +if [ "$type" == 'awstats' ]; then + rm -f /etc/awstats/$type.$domain_idn.conf + ln -s $HOMEDIR/$user/conf/web/$domain/$type.conf \ + /etc/awstats/$type.$domain_idn.conf +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Schedule statistic processing +echo "$BIN/v-update-web-domain-stat $user $domain" >> $HESTIA/data/queue/webstats.pipe + +# Update config +update_object_value 'web' 'DOMAIN' "$domain" '$STATS' "$type" + +# Logging +$BIN/v-log-action "$user" "Info" "Web" "Web traffic analyzer enabled (Domain: $domain)." +log_event "$OK" "$ARGUMENTS" + +# Build stats +exec $BIN/v-update-web-domain-stat "$user" "$domain" + +exit diff --git a/bin/v-add-web-domain-stats-user b/bin/v-add-web-domain-stats-user new file mode 100755 index 0000000..0ab52f2 --- /dev/null +++ b/bin/v-add-web-domain-stats-user @@ -0,0 +1,89 @@ +#!/bin/bash +# info: add password protection to web domain statistics +# options: USER DOMAIN STATS_USER STATS_PASSWORD [RESTART] +# +# example: v-add-web-domain-stats-user admin example.com watchdog your_password +# +# This function is used for securing the web statistics page. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +stats_user=$3 +password=$4 +HIDE=4 +restart=$5 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '4' "$#" 'USER DOMAIN STATS_USER STATS_PASS [RESTART]' +is_format_valid 'user' 'domain' 'stats_user' +is_system_enabled "$WEB_SYSTEM" 'WEB_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'web' 'DOMAIN' "$domain" +is_object_unsuspended 'web' 'DOMAIN' "$domain" +is_password_valid + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Defining statistic dir +stats_dir="$HOMEDIR/$user/web/$domain/stats" +conf_dir="$HOMEDIR/$user/conf/web" + +# Adding htaccess file +if [ "$WEB_SYSTEM" = 'nginx' ]; then + echo "auth_basic \"Web Statistics\";" > $stats_dir/auth.conf + echo "auth_basic_user_file $stats_dir/.htpasswd;" >> $stats_dir/auth.conf +else + echo "AuthUserFile $stats_dir/.htpasswd" > $stats_dir/.htaccess + echo "AuthName \"Web Statistics\"" >> $stats_dir/.htaccess + echo "AuthType Basic" >> $stats_dir/.htaccess + echo "Require valid-user" >> $stats_dir/.htaccess +fi + +# Generating htaccess user and password +salt=$(generate_password "$PW_MATRIX" "8") +stats_pass=$($BIN/v-generate-password-hash md5 $salt $password) +echo "$stats_user:$stats_pass" > $stats_dir/.htpasswd + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Adding stats user in config +update_object_value 'web' 'DOMAIN' "$domain" '$STATS_USER' "$stats_user" +update_object_value 'web' 'DOMAIN' "$domain" '$STATS_CRYPT' "$stats_pass" + +# Restarting web server +if [ "$WEB_SYSTEM" = 'nginx' ]; then + $BIN/v-restart-web "$restart" + check_result $? "Web restart failed" > /dev/null +fi + +# Logging +$BIN/v-log-action "$user" "Info" "Web" "Web traffic analyzer password enabled (Username: $stats_user, Domain: $domain)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-add-web-php b/bin/v-add-web-php new file mode 100755 index 0000000..bba1d77 --- /dev/null +++ b/bin/v-add-web-php @@ -0,0 +1,194 @@ +#!/bin/bash +# info: add php fpm version +# options: VERSION +# +# example: v-add-web-php 8.0 +# +# Install php-fpm for provided version. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +version=$1 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" +source_conf "$HESTIA/install/upgrade/upgrade.conf" +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'VERSION' + +if [ -z "$WEB_BACKEND" ]; then + echo "Multiple php versions are not supported for modphp" +fi + +# Set file locations +php_fpm="/etc/init.d/php$version-fpm" + +# Verify php version format +if [ -f /etc/redhat-release ]; then + if [[ ! $version =~ ^[0-9][0-9]+ ]]; then + echo "The specified PHP version format is invalid, it should look like [0-9][0-9]." + echo "Example: 70, 74, 80" + exit "$E_INVALID" + fi +else + if [[ ! $version =~ ^[0-9].[0-9]+ ]]; then + echo "The specified PHP version format is invalid, it should look like [0-9].[0-9]." + echo "Example: 7.0, 7.4, 8.0" + exit "$E_INVALID" + fi +fi + +# Check if php version already exists +if [ -f "$php_fpm" ] && [ -f "$HESTIA/data/templates/web/php-fpm/PHP-${version/\./_}.tpl" ]; then + echo "ERROR: Specified PHP version is already installed." + exit "$E_INVALID" +fi + +# Check if php version is supported +if [[ ! "$multiphp_v" =~ $version ]]; then + echo "ERROR: Specified PHP version is not supported or does not exist." + exit "$E_INVALID" +fi + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +mph="php$version-common php$version-mbstring php$version-bcmath php$version-cli php$version-curl + php$version-fpm php$version-gd php$version-intl php$version-mysql + php$version-soap php$version-xml php$version-zip php$version-json php$version-bz2 + php$version-pspell php$version-imagick php$version-pgsql php$version-imap php$version-ldap" +if [ -f /etc/redhat-release ]; then + # Packages in Remi repo have names with php$version-php- prefixes + mph="php$version-php-fpm php$version-php-cgi php$version-php-mysqlnd php$version-php-pgsql + php$version-php-pdo php$version-php-common php$version-php-pecl-imagick php$version-php-imap + php$version-php-ldap php$version-php-pecl-apcu php$version-php-pecl-zip php$version-php-cli + php$version-php-opcache php$version-php-xml php$version-php-gd php$version-php-intl + php$version-php-mbstring php$version-php-pspell php$version-php-readline" + if [ "$version" = "56" ]; then + mph=$(sed -e "s/php$version-php-pecl-apcu//") + fi +fi + +# Check is version is 7.1 or below to add mcrypt +if [[ $(echo "$version 7.2" | awk '{print ($1 < $2)}') == 1 ]]; then + mph="$mph php$version-mcrypt" +fi + +# Check if version is 8.0 or higher and drop php json. +if [[ ${version:0:1} == "8" ]]; then + mph=$(echo "$mph" | sed -e "s/php$version\(-php\)\{0,1\}-json//") +fi + +if ! echo "$DB_SYSTEM" | grep -w 'mysql' > /dev/null; then + mph=$(echo "$mph" | sed -e "s/php$version\(-php\)\{0,1\}-mysql//") +fi + +if ! echo "$DB_SYSTEM" | grep -w 'pgsql' > /dev/null; then + mph=$(echo "$mph" | sed -e "s/php$version\(-php\)\{0,1\}-pgsql//") +fi + +# Install php packages +if [ -f '/etc/redhat-release' ]; then + dnf install -q -y $mph > /dev/null 2>&1 & +else + apt-get -qq update + apt-get -y -qq -o Dpkg::Options::="--force-confold" install $mph > /dev/null 2>&1 & +fi +BACK_PID=$! + +# Check if package installation is done, print a spinner +echo "Installing PHP-$version, please wait..." +spinner="/-\|" +spin_i=1 +while kill -0 $BACK_PID > /dev/null 2>&1; do + printf "\b${spinner:spin_i++%${#spinner}:1}" + sleep 0.5 +done + +# Do a blank echo to get the \n back +echo + +# Check if installation was successful +if [ ! -f "$php_fpm" ]; then + echo "ERROR: Installation failed, please run the following command manually for debugging:" + if [ -f '/etc/redhat-release' ]; then + echo "dnf install $mph" + else + echo "apt-get install $mph" + fi +fi + +# Check if required modules for apache2 are enabled +if [ "$WEB_SYSTEM" = "apache2" ]; then + if [ -f /etc/redhat-release ]; then + if ! httpd -M | grep 'proxy_fcgi_module' ; then + sed 's/#LoadModule proxy_fcgi_module/LoadModule proxy_fcgi_module/' -i /etc/httpd/conf.modules.d/00-proxy.conf + sed 's/#LoadModule proxy_module/LoadModule proxy_module/' -i /etc/httpd/conf.modules.d/00-proxy.conf + fi + if ! httpd -M | grep 'setenvif_module' ; then + sed 's/#LoadModule setenvif_module/LoadModule setenvif_module/' -i /etc/httpd/conf.modules.d/00-base.conf + fi + else + if ! a2query -q -m proxy_fcgi; then + a2enmod -q proxy_fcgi + fi + if ! a2query -q -m setenvif; then + a2enmod -q setenvif + fi + fi + $BIN/v-restart-web "yes" +fi + +# Configure fpm +v_tpl=${version//./} +if [ -f /etc/redhat-release ]; then + systemctl enable php${version}-php-fpm + rm -f /etc/opt/remi/php${version}/php-fpm.d/* + cp -f $HESTIA_INSTALL_DIR/php-fpm/dummy.conf /etc/opt/remi/php${version}/php-fpm.d/ + sed -i "s/9999/99$v_tpl/g" /etc/opt/remi/php${version}/php-fpm.d/dummy.conf + + # Increase max upload and max post size + sed -i "s/upload_max_filesize = 2M/upload_max_filesize = 100M/g" /etc/opt/remi/php${version}/php.ini + sed -i "s/post_max_size = 8M/post_max_size = 100M/g" /etc/opt/remi/php${version}/php.ini + sed -i "s/max_execution_time = 30/max_execution_time = 60/g" /etc/opt/remi/php${version}/php.ini +else + update-rc.d php$version-fpm defaults > /dev/null 2>&1 + rm -f /etc/php/$version/fpm/pool.d/* + cp -f $HESTIA_INSTALL_DIR/php-fpm/dummy.conf /etc/php/$version/fpm/pool.d/ + sed -i "s/9999/99$v_tpl/g" /etc/php/$version/fpm/pool.d/dummy.conf + cp -f $HESTIA_INSTALL_DIR/php-fpm/php-fpm.conf /etc/php/$version/fpm/ + sed -i "s/fpm_v/$version/g" /etc/php/$version/fpm/php-fpm.conf + + # Increase max upload and max post size + sed -i "s/upload_max_filesize = 2M/upload_max_filesize = 100M/g" /etc/php/$version/fpm/php.ini + sed -i "s/post_max_size = 8M/post_max_size = 100M/g" /etc/php/$version/fpm/php.ini + sed -i "s/max_execution_time = 30/max_execution_time = 60/g" /etc/php/$version/fpm/php.ini +fi +# Install backend template +cp -f $HESTIA_INSTALL_DIR/php-fpm/multiphp.tpl \ + $HESTIA/data/templates/web/php-fpm/PHP-${version/\./_}.tpl + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +$BIN/v-log-action "system" "Info" "System" "Installed PHP $version." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-backup-user b/bin/v-backup-user new file mode 100755 index 0000000..fee80d9 --- /dev/null +++ b/bin/v-backup-user @@ -0,0 +1,800 @@ +#!/bin/bash +# info: backup system user with all its objects +# options: USER NOTIFY +# +# example: v-backup-user admin yes +# +# This function is used for backing up user with all its domains and databases. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +notify=${2-no} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# shellcheck source=/usr/local/hestia/func/db.sh +source $HESTIA/func/db.sh +# shellcheck source=/usr/local/hestia/func/backup.sh +source $HESTIA/func/backup.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Return Disk Usage +get_user_disk_usage() { + u_usage=0 + web_exclusions='' + mail_exclusions='' + db_exclusions='' + user_exclusions='' + + # Parsing excludes + if [ -e "$USER_DATA/backup-excludes.conf" ]; then + web_exclusions=$(grep 'WEB=' $USER_DATA/backup-excludes.conf \ + | awk -F "WEB='" '{print $2}' | cut -f 1 -d \') + mail_exclusions=$(grep 'MAIL=' $USER_DATA/backup-excludes.conf \ + | awk -F "MAIL='" '{print $2}' | cut -f 1 -d \') + db_exclusions=$(grep 'DB=' $USER_DATA/backup-excludes.conf \ + | awk -F "DB='" '{print $2}' | cut -f 1 -d \') + user_exclusions=$(grep 'USER=' $USER_DATA/backup-excludes.conf \ + | awk -F "USER='" '{print $2}' | cut -f 1 -d \') + fi + + if [ -f "$USER_DATA/web.conf" ] && [ "$web_exclusions" != '*' ]; then + usage=0 + domains=$(grep 'DOMAIN=' $USER_DATA/web.conf \ + | awk -F "DOMAIN='" '{print $2}' | cut -f 1 -d \') + + for domain in $domains; do + exclusion=$(echo -e "$web_exclusions" | tr ',' '\n' | grep "^$domain\|\*$") + if [ -z "$exclusion" ]; then + # Defining home directory + home_dir="$HOMEDIR/$user/web/$domain/" + exclusion=$(echo -e "$web_exclusions" | tr ',' '\n' | grep "^$domain\|\*:") + fargs=() + + if [ -n "$exclusion" ]; then + xdirs=$(echo -e "$exclusion" | tr ':' '\n' | grep -v "$domain\|\*") + for xpath in $xdirs; do + fargs+=(--exclude="$xpath") + done + fi + + # Checking home directory exist + if [ -e "$home_dir" ]; then + disk_usage=$(nice -n 19 du -shm "$home_dir" "${fargs[@]}" | cut -f 1) + u_usage=$((u_usage + disk_usage)) + fi + fi + done + fi + + if [ -f "$USER_DATA/mail.conf" ] && [ "$mail_exclusions" != '*' ]; then + usage=0 + domains=$(grep 'DOMAIN=' "$USER_DATA/mail.conf" \ + | awk -F "DOMAIN='" '{print $2}' | cut -f 1 -d \') + + for domain in $domains; do + check_exl=$(echo "$mail_exclusions" | tr ',' '\n' | grep "^$domain$") + if [ -f "$USER_DATA/mail/$domain.conf" ] && [ -z "$check_exl" ]; then + accounts=$(grep 'ACCOUNT=' "$USER_DATA/mail/$domain.conf" \ + | awk -F "ACCOUNT='" '{print $2}' | cut -f 1 -d \') + + for account in $accounts; do + home_dir=$HOMEDIR/$user/mail/$domain/$account + exclusion=$(echo "$mail_exclusions" | tr ',' '\n' | grep "$domain:") + exclusion=$(echo "$exclusion" | tr ':' '\n' | grep -E "^$account|\*") + + if [ -z "$exclusion" ] && [ -e "$home_dir" ]; then + disk_usage=$(nice -n 19 du -shm "$home_dir" | cut -f 1) + u_usage=$((u_usage + disk_usage)) + fi + done + fi + done + fi + + if [ -f "$USER_DATA/db.conf" ] && [ "$db_exclusions" != '*' ]; then + usage=0 + databases=$(grep 'DB=' "$USER_DATA/db.conf" \ + | awk -F "DB='" '{print $2}' | cut -f 1 -d \') + for database in $databases; do + exclusion=$(echo "$db_exclusions" | tr ',' '\n' | grep "^$database$") + if [ -z "$exclusion" ]; then + # Get database values + get_database_values + + # Switching on db type + case $DB_SYSTEM in + mysql) get_mysql_disk_usage ;; + pgsql) get_pgsql_disk_usage ;; + esac + u_usage=$((u_usage + usage)) + fi + done + fi + + if [ "$user_exclusions" != '*' ]; then + fargs=() + for xpath in $(echo "$user_exclusions" | tr ',' '\n'); do + fargs+=(--exclude="$xpath") + done + usage=$(du -shm "$HOMEDIR/$user" --exclude "$HOMEDIR/$user/web" --exclude "$HOMEDIR/$user/mail" --exclude "$HOMEDIR/$user/conf" "${fargs[@]}" | cut -f 1) + u_usage=$((u_usage + usage)) + fi + + echo ${u_usage} +} + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'USER [NOTIFY]' +is_format_valid 'user' +is_system_enabled "$BACKUP_SYSTEM" 'BACKUP_SYSTEM' +is_object_valid 'user' 'USER' "$user" +if [ "$POLICY_BACKUP_SUSPENDED_USERS" != "yes" ]; then + is_object_unsuspended 'user' 'USER' "$user" +fi +is_backup_enabled + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +check_backup_conditions + +# Set backup directory if undefined +if [ -z "$BACKUP" ]; then + BACKUP=/backup +fi + +# Check if backup folder exists and have the correct permission +if [[ ! -d "$BACKUP" ]]; then + mkdir -p $BACKUP +fi +if [ "$(stat -c %a "$BACKUP")" != 755 ]; then + chmod 755 $BACKUP +fi + +# Get current time +start_time=$(date '+%s') + +# Set notification email and subject +subj="$user → backup failed" +email=$(grep CONTACT "$HESTIA/data/users/admin/user.conf" | cut -f 2 -d \') + +# Validate available disk space (take usage * 2, due to the backup handling) +let u_disk=$(($(get_user_disk_usage) * 2)) +let v_disk=$(($(stat -f --format="%a*%S" $BACKUP)))/1024/1024 + +if [ "$u_disk" -gt "$v_disk" ]; then + let u_disk_original=$(get_user_disk_usage) + # Always notify on failure + echo "Not enough disk space available ($v_disk mb) to perform the backup of $user. ( $u_disk_original mb * 2 = $u_disk mb). https://hestiacp.com/docs/server-administration/backup-restore.html" | $SENDMAIL -s "$subj" "$email" "yes" + # Deleting task from queue + sed -i "/v-backup-user $user /d" $HESTIA/data/queue/backup.pipe + check_result "$E_LIMIT" "not enough disk space available ($v_disk mb) to perform the backup of $user. ( $u_disk_original mb * 2 = $u_disk mb)." +fi + +if [ -z "$BACKUP_TEMP" ]; then + BACKUP_TEMP=$BACKUP +fi + +# Creating temporary directory +tmpdir=$(mktemp -p $BACKUP_TEMP -d) + +if [ "$?" -ne 0 ]; then + echo "Can't create tmp dir $tmpdir" | $SENDMAIL -s "$subj" "$email" "yes" + # Deleting task from queue + sed -i "/v-backup-user $user /d" $HESTIA/data/queue/backup.pipe + check_result "$E_NOTEXIST" "can't create tmp dir" +fi + +# Backup sys configs +echo "-- SYSTEM --" | tee $BACKUP/$user.log +mkdir $tmpdir/hestia + +echo -e "$(date "+%F %T") $user.conf" | tee -a $BACKUP/$user.log +cp -r $USER_DATA/user.conf $tmpdir/hestia/ +cp -r $USER_DATA/ssl $tmpdir/hestia/ + +if [ -e "$USER_DATA/stats.log" ]; then + echo -e "$(date "+%F %T") stats.log" | tee -a $BACKUP/$user.log + cp -r $USER_DATA/stats.log $tmpdir/hestia/ +fi + +if [ -e "$USER_DATA/history.log" ]; then + echo -e "$(date "+%F %T") history.log" | tee -a $BACKUP/$user.log + cp -r $USER_DATA/history.log $tmpdir/hestia/ +fi + +if [ -e "$USER_DATA/backup-excludes.conf" ]; then + echo -e "$(date "+%F %T") backup-excludes.conf" | tee -a $BACKUP/$user.log + cp -r $USER_DATA/backup-excludes.conf $tmpdir/hestia/ +fi + +# Backup PAM +mkdir $tmpdir/pam +echo -e "$(date "+%F %T") pam" | tee -a $BACKUP/$user.log +grep "^$user:" /etc/passwd > $tmpdir/pam/passwd +grep "^$user:" /etc/shadow > $tmpdir/pam/shadow +grep "^$user:" /etc/group > $tmpdir/pam/group +echo + +# Parsing excludes +if [ -e "$USER_DATA/backup-excludes.conf" ]; then + source $USER_DATA/backup-excludes.conf +fi + +# WEB domains +if [ -n "$WEB_SYSTEM" ] && [ "$WEB" != '*' ]; then + echo -e "\n-- WEB --" | tee -a $BACKUP/$user.log + mkdir $tmpdir/web/ + + # Parsing domain exclusions + conf="$USER_DATA/web.conf" + for domain in $(search_objects 'web' 'SUSPENDED' "*" 'DOMAIN'); do + exclusion=$(echo -e "$WEB" | tr ',' '\n' | grep "^$domain$\|^\*$") + if [ -z "$exclusion" ]; then + web_list="$web_list $domain" + else + echo "$(date "+%F %T") excluding $domain" | tee -a $BACKUP/$user.log + fi + done + web_list=$(echo "$web_list" | sed -e "s/ */\ /g" -e "s/^ //") + + i=0 + + for domain in $web_list; do + check_backup_conditions + ((i++)) + echo -e "$(date "+%F %T") $domain" | tee -a $BACKUP/$user.log + mkdir -p $tmpdir/web/$domain/conf + mkdir -p $tmpdir/web/$domain/hestia + + # Get domain variables + domain_idn=$domain + format_domain_idn + get_domain_values 'web' + + # Backup web.conf + cd $tmpdir/web/$domain/ + conf="$USER_DATA/web.conf" + grep "DOMAIN='$domain'" $conf > hestia/web.conf + + # Backup vhost config + if [ -e "$HOMEDIR/$user/conf/web/$domain/$WEB_SYSTEM.conf" ]; then + cp $HOMEDIR/$user/conf/web/$domain/$WEB_SYSTEM.conf* conf/ + elif [ -e "$HOMEDIR/$user/conf/web/$domain.$WEB_SYSTEM.conf" ]; then + cp $HOMEDIR/$user/conf/web/$domain.$WEB_SYSTEM.conf* conf/ + else + # legacy format: all domain configs in single file + tpl_file="$WEBTPL/$WEB_SYSTEM/$WEB_BACKEND/$TPL.tpl" + conf="$HOMEDIR/$user/conf/web/$WEB_SYSTEM.conf" + get_web_config_lines "$tpl_file" "$conf" + sed -n "$top_line,$bottom_line p" $conf > conf/$WEB_SYSTEM.conf + fi + + # Backup ssl vhost + if [ "$SSL" = 'yes' ]; then + if [ -e "$HOMEDIR/$user/conf/web/$domain/$WEB_SYSTEM.ssl.conf" ]; then + cp $HOMEDIR/$user/conf/web/$domain/$WEB_SYSTEM.ssl.conf* conf/ + elif [ -e "$HOMEDIR/$user/conf/web/$domain.$WEB_SYSTEM.ssl.conf" ]; then + cp $HOMEDIR/$user/conf/web/$domain.$WEB_SYSTEM.ssl.conf* conf/ + else + # legacy format: all domain configs in single file + tpl_file="$WEBTPL/$WEB_SYSTEM/$WEB_BACKEND/$TPL.stpl" + conf="$HOMEDIR/$user/conf/web/s$WEB_SYSTEM.conf" + get_web_config_lines "$tpl_file" "$conf" + sed -n "$top_line,$bottom_line p" $conf > conf/s$WEB_SYSTEM.conf + fi + fi + + # Backup proxy config + if [ -n "$PROXY_SYSTEM" ] && [ -n "$PROXY" ]; then + if [ -e "$HOMEDIR/$user/conf/web/$domain/$PROXY_SYSTEM.conf" ]; then + cp $HOMEDIR/$user/conf/web/$domain/$PROXY_SYSTEM.conf* conf/ + elif [ -e "$HOMEDIR/$user/conf/web/$domain.$PROXY_SYSTEM.conf" ]; then + cp $HOMEDIR/$user/conf/web/$domain.$PROXY_SYSTEM.conf* conf/ + else + # legacy format: all domain configs in single file + tpl_file="$WEBTPL/$PROXY_SYSTEM/$PROXY.tpl" + conf="$HOMEDIR/$user/conf/web/$PROXY_SYSTEM.conf" + get_web_config_lines "$tpl_file" "$conf" + sed -n "$top_line,$bottom_line p" $conf > conf/$PROXY_SYSTEM.conf + fi + fi + + # Backup ssl proxy config + if [ -n "$PROXY_SYSTEM" ] && [ -n "$PROXY" ] && [ "$SSL" = 'yes' ]; then + if [ -e "$HOMEDIR/$user/conf/web/$domain/$PROXY_SYSTEM.ssl.conf" ]; then + cp $HOMEDIR/$user/conf/web/$domain/$PROXY_SYSTEM.ssl.conf* conf/ + elif [ -e "$HOMEDIR/$user/conf/web/$domain.$PROXY_SYSTEM.ssl.conf" ]; then + cp $HOMEDIR/$user/conf/web/$domain.$PROXY_SYSTEM.ssl.conf* conf/ + else + # legacy format: all domain configs in single file + tpl_file="$WEBTPL/$PROXY_SYSTEM/$PROXY.stpl" + conf="$HOMEDIR/$user/conf/web/s$PROXY_SYSTEM.conf" + get_web_config_lines "$tpl_file" "$conf" + sed -n "$top_line,$bottom_line p" $conf > conf/s$PROXY_SYSTEM.conf + fi + fi + + domain_conf=$(grep "DOMAIN='$domain'" $conf) + parse_object_kv_list_non_eval domain_conf + + mkdir -p template/$WEB_SYSTEM/ + mkdir template/php-fpm/ + + if [ $WEB_BACKEND == 'php-fpm' ]; then + cp $HESTIA/data/templates/web/$WEB_SYSTEM/php-fpm/$TPL.tpl template/$WEB_SYSTEM/ + cp $HESTIA/data/templates/web/$WEB_SYSTEM/php-fpm/$TPL.stpl template/$WEB_SYSTEM/ + cp $HESTIA/data/templates/web/php-fpm/$BACKEND.tpl template/php-fpm/ + else + cp $HESTIA/data/templates/web/$WEB_SYSTEM/$TPL.tpl template/$WEB_SYSTEM/ + cp $HESTIA/data/templates/web/$WEB_SYSTEM/$TPL.stpl template/$WEB_SYSTEM/ + fi + if [ -n "$PROXY_SYSTEM" ] && [ -n "$PROXY" ]; then + mkdir template/$PROXY_SYSTEM + cp $HESTIA/data/templates/web/$PROXY_SYSTEM/$PROXY.tpl template/$PROXY_SYSTEM/ + cp $HESTIA/data/templates/web/$PROXY_SYSTEM/$PROXY.stpl template/$PROXY_SYSTEM/ + fi + + # Backup ssl certificates + if [ "$SSL" = 'yes' ]; then + cp $HOMEDIR/$user/conf/web/$domain/ssl/$domain.* conf/ + cp $USER_DATA/ssl/$domain.* hestia/ + fi + + # Changin dir to documentroot + cd $HOMEDIR/$user/web/$domain + + # Define exclude arguments + exclusion=$(echo -e "$WEB" | tr ',' '\n' | grep "^$domain\|\*:") + set -f + fargs=() + fargs+=(--exclude='./logs/*') + if [ -n "$exclusion" ]; then + + if [[ "$exclusion" =~ '*' ]]; then + exclusion="${exclusion/\*/$domain}" + fi + + xdirs="$(echo -e "$exclusion" | tr ':' '\n' | grep -v $domain)" + for xpath in $xdirs; do + if [ -d "$xpath" ]; then + fargs+=(--exclude=$xpath/*) + echo "$(date "+%F %T") excluding directory $xpath" + msg="$msg\n$(date "+%F %T") excluding directory $xpath" + else + echo "$(date "+%F %T") excluding file $xpath" + msg="$msg\n$(date "+%F %T") excluding file $xpath" + fargs+=(--exclude=$xpath) + fi + done + fi + set +f + + # Backup files + if [ "$BACKUP_MODE" = 'zstd' ]; then + tar "${fargs[@]}" -cpf- * | pzstd -"$BACKUP_GZIP" - > $tmpdir/web/$domain/domain_data.tar.zst + else + tar "${fargs[@]}" -cpf- * | gzip -"$BACKUP_GZIP" - > $tmpdir/web/$domain/domain_data.tar.gz + fi + done + + # Print total + if [ "$i" -eq 1 ]; then + echo -e "$(date "+%F %T") *** $i domain ***" | tee -a $BACKUP/$user.log + else + echo -e "$(date "+%F %T") *** $i domains ***" | tee -a $BACKUP/$user.log + fi +fi + +# DNS domains +if [ -n "$DNS_SYSTEM" ] && [ "$DNS" != '*' ]; then + echo -e "\n-- DNS --" | tee -a $BACKUP/$user.log + mkdir $tmpdir/dns/ + + # Parsing domain exclusions + for domain in $(search_objects 'dns' 'SUSPENDED' "*" 'DOMAIN'); do + exclusion=$(echo "$DNS" | tr ',' '\n' | grep "^$domain$") + if [ -z "$exclusion" ]; then + dns_list="$dns_list $domain" + else + echo "$(date "+%F %T") excluding $domain" + msg="$msg\n$(date "+%F %T") excluding $domain" + fi + done + dns_list=$(echo "$dns_list" | sed -e "s/ */\ /g" -e "s/^ //") + + i=0 + for domain in $dns_list; do + ((i++)) + echo -e "$(date "+%F %T") $domain" | tee -a $BACKUP/$user.log + domain_idn="$domain" + # Building directory tree + mkdir -p $tmpdir/dns/$domain/conf + mkdir -p $tmpdir/dns/$domain/conf/keys + mkdir -p $tmpdir/dns/$domain/hestia + + # Backup dns.conf + cd $tmpdir/dns/$domain/ + conf="$USER_DATA/dns.conf" + grep "DOMAIN='$domain'" $conf > hestia/dns.conf + + # Backup dns recods + cp $USER_DATA/dns/$domain.conf hestia/$domain.conf + if [ "$DNS_SYSTEM" != 'remote' ]; then + cp $HOMEDIR/$user/conf/dns/$domain.db conf/$domain.db + fi + # Backup DNSSEC public and private key if enabled + dnssec=$(grep "DOMAIN='$domain'" $USER_DATA/dns.conf | grep "DNSSEC='yes'") + if [ -n "$dnssec" ]; then + format_domain_idn + cp $USER_DATA/keys/K$domain_idn*.* $tmpdir/dns/$domain/conf/keys + fi + done + + # Print total + if [ "$i" -eq 1 ]; then + echo -e "$(date "+%F %T") *** $i domain ***" | tee -a $BACKUP/$user.log + else + echo -e "$(date "+%F %T") *** $i domains ***" | tee -a $BACKUP/$user.log + fi +fi + +# Mail domains +if [ -n "$MAIL_SYSTEM" ] && [ "$MAIL" != '*' ]; then + echo -e "\n-- MAIL --" | tee -a $BACKUP/$user.log + mkdir $tmpdir/mail/ + + # Parsing domain exclusions + conf="$USER_DATA/mail.conf" + for domain in $(search_objects 'mail' 'SUSPENDED' "*" 'DOMAIN'); do + check_exl=$(echo "$MAIL" | tr ',' '\n' | grep "^$domain$") + if [ -z "$check_exl" ]; then + mail_list="$mail_list $domain" + else + echo "$(date "+%F %T") excluding $domain" | tee -a $BACKUP/$user.log + fi + done + mail_list=$(echo "$mail_list" | sed -e "s/ */\ /g" -e "s/^ //") + + i=0 + for domain in $mail_list; do + check_backup_conditions + ((i++)) + echo -e "$(date "+%F %T") $domain" | tee -a $BACKUP/$user.log + mkdir -p $tmpdir/mail/$domain/conf + mkdir -p $tmpdir/mail/$domain/hestia + domain_idn=$domain + format_domain_idn + + # Backup exim config + if [[ "$MAIL_SYSTEM" =~ exim ]]; then + cd $tmpdir/mail/$domain/ + cp -r $HOMEDIR/$user/conf/mail/$domain/* conf/ + fi + + # Backup mail.conf + conf="$USER_DATA/mail.conf" + grep "DOMAIN='$domain'" $conf > hestia/mail.conf + cp $USER_DATA/mail/$domain.* hestia/ + if [ -n "$(ls $USER_DATA/mail/ | grep *@$domain)" ]; then + cp $USER_DATA/mail/*@$domain.* hestia/ + fi + + # Backup emails + cd $HOMEDIR/$user/mail/$domain_idn + accounts=() + for account in *; do + exclusion=$(echo "$MAIL" | tr ',' '\n' | grep "$domain:") + exclusion=$(echo "$exclusion" | tr ':' '\n' | grep -E "^$account|\*") + + # Checking exclusions + if [ -z "$exclusion" ] && [[ "$MAIL_SYSTEM" =~ exim ]]; then + accounts+=($account) + else + echo "$(date "+%F %T") excluding mail account $account" \ + | tee -a $BACKUP/$user.log + fi + done + # Compress archive + if [ ${#accounts[@]} -gt 0 ]; then + if [ "$BACKUP_MODE" = 'zstd' ]; then + tar -cpf- "${accounts[@]}" | pzstd -"$BACKUP_GZIP" - > $tmpdir/mail/$domain/accounts.tar.zst + else + tar -cpf- "${accounts[@]}" | gzip -"$BACKUP_GZIP" - > $tmpdir/mail/$domain/accounts.tar.gz + fi + fi + done + + # Print total + if [ "$i" -eq 1 ]; then + echo -e "$(date "+%F %T") *** $i domain ***" | tee -a $BACKUP/$user.log + else + echo -e "$(date "+%F %T") *** $i domains ***" | tee -a $BACKUP/$user.log + fi +fi + +# Databases +if [ -n "$DB_SYSTEM" ] && [ "$DB" != '*' ]; then + echo -e "\n-- DB --" | tee -a $BACKUP/$user.log + mkdir $tmpdir/db/ + + # Parsing database exclusions + for database in $(search_objects 'db' 'SUSPENDED' "*" 'DB'); do + exclusion=$(echo "$DB" | tr ',' '\n' | grep "^$database$") + if [ -z "$exclusion" ]; then + db_list="$db_list $database" + else + echo "$(date "+%F %T") excluding $database" \ + | tee -a $BACKUP/$user.log + fi + done + + i=0 + conf="$USER_DATA/db.conf" + db_list=$(echo "$db_list" | sed -e "s/ */\ /g" -e "s/^ //") + for database in $db_list; do + check_backup_conditions + ((i++)) + get_database_values + + echo -e "$(date "+%F %T") $database ($TYPE)" | tee -a $BACKUP/$user.log + mkdir -p $tmpdir/db/$database/conf + mkdir -p $tmpdir/db/$database/hestia + + cd $tmpdir/db/$database/ + grep "DB='$database'" $conf > hestia/db.conf + + dump="$tmpdir/db/$database/$database.$TYPE.sql" + if [ "$BACKUP_MODE" = 'zstd' ]; then + dumpgz="$tmpdir/db/$database/$database.$TYPE.sql.zst" + else + dumpgz="$tmpdir/db/$database/$database.$TYPE.sql.gz" + fi + + grants="$tmpdir/db/$database/conf/$database.$TYPE.$DBUSER" + if [ ! -f "$dumpgz" ]; then + + WAIT_LOOP_ENTERED=0 + while true; do + if pgrep -x "mysqldump" > /dev/null; then + WAIT_LOOP_ENTERED=1 + echo "Wait other mysqldump to finish" + sleep 1 + else + if [ "$WAIT_LOOP_ENTERED" -eq 1 ]; then + echo "We can use mysqldump now" + fi + break + fi + done + + case $TYPE in + mysql) dump_mysql_database ;; + pgsql) dump_pgsql_database ;; + esac + + # Compress dump + if [ "$BACKUP_MODE" = 'zstd' ]; then + pzstd -$BACKUP_GZIP $dump + rm $dump + else + gzip -$BACKUP_GZIP $dump + fi + fi + done + + # Print total + if [ "$i" -eq 1 ]; then + echo -e "$(date "+%F %T") *** $i database ***" \ + | tee -a $BACKUP/$user.log + else + echo -e "$(date "+%F %T") *** $i databases ***" \ + | tee -a $BACKUP/$user.log + fi +fi + +# Cron jobs +if [ -n "$CRON_SYSTEM" ] && [ "$CRON" != '*' ]; then + echo -e "\n-- CRON --" | tee -a $BACKUP/$user.log + mkdir $tmpdir/cron/ + + # Backup cron.conf + cp $USER_DATA/cron.conf $tmpdir/cron/ + cron_record=$(wc -l $USER_DATA/cron.conf | cut -f 1 -d ' ') + + if [ -e "/var/spool/cron/$user" ]; then + cron_list="$cron_record" + cp /var/spool/cron/$user $tmpdir/cron/ + fi + + # Print total + if [ "$cron_record" -eq 1 ]; then + echo -e "$(date "+%F %T") *** $cron_record job ***" \ + | tee -a $BACKUP/$user.log + else + echo -e "$(date "+%F %T") *** $cron_record jobs ***" \ + | tee -a $BACKUP/$user.log + fi +fi + +# User Directories +if [ "$USER" != '*' ]; then + echo -e "\n-- User Dir --" | tee -a $BACKUP/$user.log + mkdir $tmpdir/user_dir + cd $HOMEDIR/$user + + # Parsing directory exclusions + USER='' + if [ -e "$USER_DATA/backup-excludes.conf" ]; then + source $USER_DATA/backup-excludes.conf + fi + fargs=() + for xpath in $(echo "$USER" | tr ',' '\n'); do + if [ -d "$xpath" ]; then + fargs+=(--exclude="$xpath"/*) + echo "$(date "+%F %T") excluding directory $xpath" \ + | tee -a $BACKUP/$user.log + else + echo "$(date "+%F %T") excluding file $xpath" \ + | tee -a $BACKUP/$user.log + fargs+=(--exclude="$xpath") + fi + done + + IFS=$'\n' + set -f + i=0 + + for udir in $(ls -a | egrep -v "^conf$|^web$|^dns$|^tmp$|^mail$|^\.\.$|^\.$"); do + exclusion=$(echo "$USER" | tr ',' '\n' | grep "^$udir$") + if [ -z "$exclusion" ]; then + ((i++)) + udir_list="$udir_list $udir" + echo -e "$(date "+%F %T") adding $udir" | tee -a $BACKUP/$user.log + + check_backup_conditions + + # Backup files and dirs + if [ "$BACKUP_MODE" = 'zstd' ]; then + tar --anchored -cpf- "${fargs[@]}" $udir | pzstd -"$BACKUP_GZIP" - > $tmpdir/user_dir/$udir.tar.zst + else + tar --anchored -cpf- "${fargs[@]}" $udir | gzip -"$BACKUP_GZIP" - > $tmpdir/user_dir/$udir.tar.gz + fi + + fi + done + set +f + udir_list=$(echo "$udir_list" | sed -e "s/ */\ /g" -e "s/^ //") + + # Print total + if [ "$i" -eq 1 ]; then + echo -e "$(date "+%F %T") *** $i user directory ***" \ + | tee -a $BACKUP/$user.log + else + echo -e "$(date "+%F %T") *** $i directories ***" \ + | tee -a $BACKUP/$user.log + fi +fi + +if [ "$BACKUP_MODE" = 'zstd' ]; then + touch $tmpdir/.zstd +fi + +# Get backup size +size="$(du -shm $tmpdir | cut -f 1)" + +# Get current time +end_time=$(date '+%s') +time_n_date=$(date +'%T %F') +time=$(echo "$time_n_date" | cut -f 1 -d \ ) +date=$(echo "$time_n_date" | cut -f 2 -d \ ) +backup_new_date=$(date +"%Y-%m-%d_%H-%M-%S") + +echo -e "\n-- SUMMARY --" | tee -a $BACKUP/$user.log + +errorcode="0" +# Switching on backup system types +for backup_type in $(echo -e "${BACKUP_SYSTEM//,/\\n}"); do + case $backup_type in + local) local_backup ;; + ftp) ftp_backup ;; + sftp) sftp_backup ;; + b2) b2_backup ;; + rclone) rclone_backup ;; + esac +done + +# Removing tmpdir +rm -rf $tmpdir +if [[ "$errorcode" != "0" ]]; then + if [[ "$BACKUP_SYSTEM" =~ "local" ]]; then + echo -e "$(date "+%F %T") *** Local backup was successfully executed. Remote backup failed ***" \ + | tee -a $BACKUP/$user.log + BACKUP_SYSTEM="local" + else + echo -e "$(date "+%F %T") *** Remote backup failed ***" \ + | tee -a $BACKUP/$user.log + + exit $error_code + fi +fi +# Calculation run time +run_time=$((end_time - start_time)) +run_time=$((run_time / 60)) +current_time=$(date "+%T") +if [ "$run_time" -lt 1 ]; then + run_time=1 +fi +min=minutes +if [ "$run_time" -eq 1 ]; then + min=minute +fi + +echo "$(date "+%F %T") Size: $size MB" | tee -a $BACKUP/$user.log +echo "$(date "+%F %T") Runtime: $run_time $min" | tee -a $BACKUP/$user.log + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Removing duplicate +touch $USER_DATA/backup.conf +sed -i "/$user.$backup_new_date.tar/d" $USER_DATA/backup.conf + +# Registering new backup +backup_str="BACKUP='$user.$backup_new_date.tar'" +backup_str="$backup_str TYPE='$BACKUP_SYSTEM' SIZE='$size'" +backup_str="$backup_str WEB='${web_list// /,}'" +backup_str="$backup_str DNS='${dns_list// /,}'" +backup_str="$backup_str MAIL='${mail_list// /,}'" +backup_str="$backup_str DB='${db_list// /,}'" +backup_str="$backup_str CRON='$cron_list'" +backup_str="$backup_str UDIR='${udir_list// /,}'" +backup_str="$backup_str RUNTIME='$run_time' TIME='$time' DATE='$date'" +echo "$backup_str" >> $USER_DATA/backup.conf + +# Removing old backups +tail -n $BACKUPS $USER_DATA/backup.conf > $USER_DATA/backup.conf_ +mv -f $USER_DATA/backup.conf_ $USER_DATA/backup.conf +chmod 660 $USER_DATA/backup.conf +chmod 660 $BACKUP/$user.log + +# Deleting task from queue +sed -i "/v-backup-user $user /d" $HESTIA/data/queue/backup.pipe + +U_BACKUPS=$(grep BACKUP $USER_DATA/backup.conf | wc -l) +update_user_value "$user" '$U_BACKUPS' "$U_BACKUPS" +cd $BACKUP + +# Send notification +if [ -e "$BACKUP/$user.log" ] && [ "$notify" = "yes" ]; then + subj="$user → backup has been completed" + email=$(get_user_value '$CONTACT') + cat $BACKUP/$user.log | $SENDMAIL -s "$subj" "$email" "$notify" + $BIN/v-add-user-notification "$user" "Backup created successfully" "

Archive: $user.$backup_new_date.tar

" +fi + +# Logging +$BIN/v-log-action "$user" "Info" "Backup" "Backup created (Archive: $backup_new_date.tar)." +$BIN/v-log-action "system" "Info" "Backup" "Backup created (User: $user, Archive: $backup_new_date.tar)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-backup-users b/bin/v-backup-users new file mode 100755 index 0000000..d66e120 --- /dev/null +++ b/bin/v-backup-users @@ -0,0 +1,56 @@ +#!/bin/bash +# info: backup all users +# options: NONE +# +# example: v-backup-users +# +# This function backups all system users. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Auto-repair all databases before backuping all accounts +mysqlrepair --all-databases --check --auto-repair > /dev/null 2>&1 + +if [ -z "$BACKUP_SYSTEM" ]; then + exit +fi +for user in $($BIN/v-list-sys-users plain); do + check_suspend=$(grep "SUSPENDED='no'" $HESTIA/data/users/$user/user.conf) + log=$HESTIA/log/backup.log + if [ ! -f "$HESTIA/data/users/$user/user.conf" ]; then + continue + fi + check_backup_conditions + check_suspend=$(grep "SUSPENDED='no'" $HESTIA/data/users/$user/user.conf) + log=$HESTIA/log/backup.log + if [ -n "$check_suspend" ]; then + echo -e "================================" >> $log + echo -e "$user" >> $log + echo -e "--------------------------------\n" >> $log + nice -n 19 ionice -c2 -n7 $BIN/v-backup-user $user >> $log 2>&1 + echo -e "\n--------------------------------\n\n" >> $log + fi +done + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-change-cron-job b/bin/v-change-cron-job new file mode 100755 index 0000000..14c8641 --- /dev/null +++ b/bin/v-change-cron-job @@ -0,0 +1,85 @@ +#!/bin/bash +# info: change cron job +# options: USER JOB MIN HOUR DAY MONTH WDAY COMMAND +# +# example: v-change-cron-job admin 7 * * * * * * /usr/bin/uptime +# +# This function is used for changing existing job. It fully replace job +# parameters with new one but with same id. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +job=$2 +min=$3 +hour=$4 +day=$5 +month=$6 +wday=$7 +command=$8 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '7' "$#" 'USER JOB MIN HOUR DAY MONTH WDAY COMMAND' +is_format_valid 'user' 'job' 'min' 'hour' 'day' 'month' 'wday' 'command' +is_system_enabled "$CRON_SYSTEM" 'CRON_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'cron' 'JOB' "$job" +is_object_unsuspended 'cron' 'JOB' "$job" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Generating timestamp +time_n_date=$(date +'%T %F') +time=$(echo "$time_n_date" | cut -f 1 -d \ ) +date=$(echo "$time_n_date" | cut -f 2 -d \ ) + +# Concatenating cron string +command=$(echo $command | sed -e "s/'/%quote%/g") +str="JOB='$job' MIN='$min' HOUR='$hour' DAY='$day' MONTH='$month' WDAY='$wday'" +str="$str CMD='$command' SUSPENDED='no' TIME='$time' DATE='$date'" + +# Deleting old job +sed -i "/JOB='$job' /d" $USER_DATA/cron.conf + +# Adding new +echo "$str" >> $USER_DATA/cron.conf + +# Sorting jobs by id +sort_cron_jobs + +# Sync system cron with user +sync_cron_jobs + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Restarting crond +$BIN/v-restart-cron +check_result $? "Cron restart failed" > /dev/null + +# Logging +$BIN/v-log-action "$user" "Info" "Cron Jobs" "Cron job updated (Job: $job, Command: $command)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-change-database-host-password b/bin/v-change-database-host-password new file mode 100755 index 0000000..7bdd154 --- /dev/null +++ b/bin/v-change-database-host-password @@ -0,0 +1,78 @@ +#!/bin/bash +# info: change database server password +# options: TYPE HOST USER PASSWORD +# +# example: v-change-database-host-password mysql localhost wp_user pA$$w@rD +# +# This function changes database server password. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +type=$1 +host=$2 +dbuser=$3 +password=$4 +HIDE=4 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/db.sh +source $HESTIA/func/db.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +args_usage='TYPE HOST DBUSER DBPASS' +check_args '4' "$#" "$args_usage" +is_format_valid 'host' 'dbuser' +is_object_valid "../../conf/$type" 'HOST' "$host" +dbpass="$password" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Define email +email=$(grep CONTACT $HESTIA/data/users/admin/user.conf | cut -f2 -d \') +subj="v-change-database-host-password $*" + +case $type in + mysql) + mysql_connect "$host" + query="USE mysql; UPDATE user SET" + query="$query password=PASSWORD('$dbpass')" + query="$query WHERE User='$dbuser';" + query="$query FLUSH PRIVILEGES;" + mysql_query "$query" + if [ "$dbuser" == "root" ]; then + echo -e "[client]\npassword='$dbpass'\n" > /root/.my.cnf + chmod 600 /root/.my.cnf + fi + ;; + pgsql) echo "TBD" > /dev/null ;; +esac + +update_object_value "../../conf/$type" 'HOST' "$host" '$USER' "$dbuser" +update_object_value "../../conf/$type" 'HOST' "$host" '$PASSWORD' "$dbpass" + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +$BIN/v-log-action "system" "Warning" "Database" "Password changed for remote database host (Host: $host)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-change-database-owner b/bin/v-change-database-owner new file mode 100755 index 0000000..bae2138 --- /dev/null +++ b/bin/v-change-database-owner @@ -0,0 +1,133 @@ +#!/bin/bash +# info: change database owner +# options: DATABASE USER +# +# example: v-change-database-owner mydb alice +# +# This function for changing database owner. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +database=$1 +user=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/db.sh +source $HESTIA/func/db.sh +# shellcheck source=/usr/local/hestia/func/rebuild.sh +source $HESTIA/func/rebuild.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'DATABASE USER' +is_format_valid 'database' 'user' +is_system_enabled "$DB_SYSTEM" 'DB_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" + +# Check owner existence +owner=$(echo $database | cut -f 1 -d '_') +if [ ! -d "$HESTIA/data/users/$owner" ]; then + echo "Error: database owner doesn't exist" + log_event "$E_NOTEXIST" "$ARGUMENTS" + exit "$E_NOTEXIST" +fi + +# Check if owner is the same as the dst user +if [ "$owner" = "$user" ]; then + exit +fi + +# Check db existence +db_data=$(grep "DB='$database'" $HESTIA/data/users/$owner/db.conf) +if [ -z "$db_data" ]; then + echo "Error: database $database doesn't exist" + log_event "$E_NOTEXIST" "$ARGUMENTS" + exit "$E_NOTEXIST" +fi + +parse_object_kv_list "$db_data" +#Fix issue #1084 with "Upper case not allowed with PGSQL" +if [ "$TYPE" == "pgsql" ]; then + usersmall=$(echo "$user" | tr '[:upper:]' '[:lower:]') +else + usersmall=$user +fi + +# Check if database name is uniqe +new_db=$(echo $database | sed "s/^${owner}_/${usersmall}_/") +check_db=$(grep "DB='$new_db'" $HESTIA/data/users/$user/db.conf) +if [ -n "$check_db" ]; then + echo "Error: $new_db database exists" + log_event "$E_EXISTS" "$ARGUMENTS" + exit "$E_EXISTS" +fi + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Creating temporary directory +tmpdir=$(mktemp -p $BACKUP -d "tmp.$database.XXXXXXXXXX") + +# Suspend database +$BIN/v-suspend-database $owner $database > /dev/null 2>&1 + +# Dump database +dump="$tmpdir/$database.$TYPE.sql" +grants="$tmpdir/$database.$TYPE.$DBUSER" +case $TYPE in + mysql) dump_mysql_database ;; + pgsql) dump_pgsql_database ;; +esac + +# Import configuration +db_data=$(echo "$db_data" | sed "s/'${owner}_/'${usersmall}_/g") +echo "$db_data" >> $HESTIA/data/users/$user/db.conf +parse_object_kv_list "$db_data" + +# Unsuspend db +$BIN/v-unsuspend-database "$user" "$new_db" > /dev/null 2>&1 + +# Rebuild databases +$BIN/v-rebuild-databases "$user" + +# Import dump +case $TYPE in + mysql) import_mysql_database "$dump" ;; + pgsql) import_pgsql_database "$dump" ;; +esac + +# Deleting tmpdir +rm -rf $tmpdir + +# Remove old database +$BIN/v-unsuspend-database "$owner" "$database" > /dev/null 2>&1 +$BIN/v-delete-database "$owner" "$database" > /dev/null 2>&1 + +# Update counters +$BIN/v-update-user-counters "$owner" +$BIN/v-update-user-counters "$user" + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-change-database-password b/bin/v-change-database-password new file mode 100755 index 0000000..52cc6b2 --- /dev/null +++ b/bin/v-change-database-password @@ -0,0 +1,69 @@ +#!/bin/bash +# info: change database password +# options: USER DATABASE DBPASS +# +# example: v-change-database-password admin wp_db neW_pAssWorD +# +# This function for changing database user password to a database. It uses the +# full name of database as argument. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +database=$2 +password=$3 +HIDE=3 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/db.sh +source $HESTIA/func/db.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '3' "$#" 'USER DATABASE DBPASS' +is_format_valid 'user' 'database' +is_system_enabled "$DB_SYSTEM" 'DB_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'db' 'DB' "$database" +is_object_unsuspended 'db' 'DB' "$database" +is_password_valid +dbpass="$password" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# +# Get database values +get_database_values + +case $TYPE in + mysql) change_mysql_password ;; + pgsql) change_pgsql_password ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Update config value +update_object_value 'db' 'DB' "$database" '$MD5' "$md5" + +# Logging +$BIN/v-log-action "$user" "Info" "Database" "Database password changed (Database: $database)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-change-database-user b/bin/v-change-database-user new file mode 100755 index 0000000..2963dca --- /dev/null +++ b/bin/v-change-database-user @@ -0,0 +1,109 @@ +#!/bin/bash +# info: change database username +# options: USER DATABASE DBUSER [DBPASS] +# +# example: v-change-database-user admin my_db joe_user +# +# This function for changing database user. It uses the + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +database=$2 +dbuser="$user"_"$3" +password=$4 +HIDE=4 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/db.sh +source $HESTIA/func/db.sh +# shellcheck source=/usr/local/hestia/func/rebuild.sh +source $HESTIA/func/rebuild.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '3' "$#" 'USER DATABASE DBUSER [DBPASS]' +is_format_valid 'user' 'database' 'dbuser' +is_system_enabled "$DB_SYSTEM" 'DB_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'db' 'DB' "$database" +is_object_new 'db' 'DBUSER' "$dbuser" +is_object_unsuspended 'db' 'DB' "$database" +is_password_valid +dbpass="$password" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Compare old and new user +old_dbuser=$(get_object_value 'db' 'DB' "$database" '$DBUSER') +if [ "$old_dbuser" = "$dbuser" ]; then + exit +fi + +# Set new dbuser +update_object_value 'db' 'DB' "$database" '$DBUSER' "$dbuser" + +# Get database values +get_database_values + +#Fix issue #1084 with "Upper case not allowed with PGSQL" +if [ "$TYPE" = "pgsql" ]; then + dbuser=$(echo $dbuser | tr '[:upper:]' '[:lower:]') + exclude="-" + if [[ "$dbuser" =~ $exclude ]]; then + check_result "$E_INVALID" "invalid database user format" + fi +fi + +# Rebuild database +case $TYPE in + mysql) rebuild_mysql_database ;; + pgsql) rebuild_pgsql_database ;; +esac + +# Change password +if [ -n "$dbpass" ]; then + case $TYPE in + mysql) change_mysql_password ;; + pgsql) change_pgsql_password ;; + esac + + # Update config value + update_object_value 'db' 'DB' "$database" '$MD5' "$md5" +fi + +# Remove old user +check_old_dbuser=$(grep "DBUSER='$old_dbuser'" $USER_DATA/db.conf) +if [ -z "$check_old_dbuser" ]; then + case $TYPE in + mysql) delete_mysql_user ;; + pgsql) delete_pgsql_user ;; + esac +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +$BIN/v-log-action "$user" "Info" "Database" "Database user changed (Database: $database, User: $dbuser)" +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-change-dns-domain-dnssec b/bin/v-change-dns-domain-dnssec new file mode 100755 index 0000000..b3232ad --- /dev/null +++ b/bin/v-change-dns-domain-dnssec @@ -0,0 +1,107 @@ +#!/bin/bash +# info: change dns domain dnssec status +# options: USER DOMAIN STATUS +# +# example: v-change-dns-domain-dnssec admin domain.pp.ua yes + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 +status=$3 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/rebuild.sh +source $HESTIA/func/rebuild.sh +# shellcheck source=/usr/local/hestia/func/syshealth.sh +source $HESTIA/func/syshealth.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '3' "$#" 'USER DOMAIN STATUS' +is_format_valid 'user' 'domain' '' +is_system_enabled "$DNS_SYSTEM" 'DNS_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'dns' 'DOMAIN' "$domain" +is_object_unsuspended 'dns' 'DOMAIN' "$domain" + +if [ -n "$status" ]; then + is_boolean_format_valid "$status" 'status' +fi + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +if [ "$DNS_CLUSTER_SYSTEM" != 'hestia-zone' ]; then + check_result "$E_DISABLED" "DNSSEC is not supported when DNS_CLUSTER_SYSTEM is not set to hestia-zone" +fi + +version=$(named -v | awk 'NR==1{print $2}') +if version_ge '9.16.18' $version; then + check_result "$E_DISABLED" "DNSSEC is not supported when bind / named version <= 9.16.18" +fi + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +if [ -f "$HESTIA/data/queue/dns-cluster.pipe" ]; then + bash $HESTIA/data/queue/dns-cluster.pipe +fi + +syshealth_repair_dns_config + +# Changing exp +update_object_value 'dns' 'DOMAIN' "$domain" '$DNSSEC' "$status" + +# Update serial +update_domain_serial +# Rebuild DNS config +rebuild_dns_domain_conf + +if [ $status = "no" ]; then + update_object_value 'dns' 'DOMAIN' "$domain" '$KEY' "" + # Delete existing keys + rm -fr $HOMEDIR/$user/conf/dns/$domain.db.* + rm -fr /var/cache/bind/K$domain_idn.* + rm -fr $USER_DATA/keys/K$domain_idn.* +fi + +# Updating dns-cluster queue +if [ "$DNS_CLUSTER" = "yes" ]; then + # Check for first sync + dlock=$(grep "domain $user $domain" $HESTIA/data/queue/dns-cluster.pipe) + if [ -z "$dlock" ]; then + cmd="$BIN/v-add-remote-dns-domain $user $domain yes" + echo "$cmd" >> $HESTIA/data/queue/dns-cluster.pipe + fi +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +$BIN/v-log-action "$user" "Info" "DNS" "Updated DNS SOA expiration date (Domain: $domain, Value: $exp)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-change-dns-domain-exp b/bin/v-change-dns-domain-exp new file mode 100755 index 0000000..85f82f1 --- /dev/null +++ b/bin/v-change-dns-domain-exp @@ -0,0 +1,73 @@ +#!/bin/bash +# info: change dns domain expiration date +# options: USER DOMAIN EXP +# +# example: v-change-dns-domain-exp admin domain.pp.ua 2020-11-20 +# +# This function of changing the term of expiration domain's registration. The +# serial number will be refreshed automatically during update. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 +exp=$3 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn +# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ? + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '3' "$#" 'USER DOMAIN EXP' +is_format_valid 'user' 'domain' 'exp' +is_system_enabled "$DNS_SYSTEM" 'DNS_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'dns' 'DOMAIN' "$domain" +is_object_unsuspended 'dns' 'DOMAIN' "$domain" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Changing exp +update_object_value 'dns' 'DOMAIN' "$domain" '$EXP' "$exp" + +# Updating dns-cluster queue +if [ "$DNS_CLUSTER" = "yes" ]; then + # Check for first sync + dlock=$(grep "domain $user $domain" $HESTIA/data/queue/dns-cluster.pipe) + if [ -z "$dlock" ]; then + cmd="$BIN/v-change-remote-dns-domain-exp $user $domain $exp" + echo "$cmd" >> $HESTIA/data/queue/dns-cluster.pipe + fi +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +$BIN/v-log-action "$user" "Info" "DNS" "Updated DNS SOA expiration date (Domain: $domain, Value: $exp)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-change-dns-domain-ip b/bin/v-change-dns-domain-ip new file mode 100755 index 0000000..745e833 --- /dev/null +++ b/bin/v-change-dns-domain-ip @@ -0,0 +1,95 @@ +#!/bin/bash +# info: change dns domain ip address +# options: USER DOMAIN IP [RESTART] +# +# example: v-change-dns-domain-ip admin domain.com 123.212.111.222 +# +# This function for changing the main ip of DNS zone. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 +ip=$3 +restart=$4 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# shellcheck source=/usr/local/hestia/func/rebuild.sh +source $HESTIA/func/rebuild.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn +# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ? + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '3' "$#" 'USER DOMAIN IP [RESTART]' +is_format_valid 'user' 'domain' 'ip' +is_system_enabled "$DNS_SYSTEM" 'DNS_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'dns' 'DOMAIN' "$domain" +is_object_unsuspended 'dns' 'DOMAIN' "$domain" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Get old ip +get_domain_values 'dns' +old=$IP + +# Changing ip +update_object_value 'dns' 'DOMAIN' "$domain" '$IP' "$ip" + +# Changing records +sed -i "s/$old/$ip/g" $USER_DATA/dns/$domain.conf + +# Update serial +update_domain_serial +# Updating zone +if [[ "$DNS_SYSTEM" =~ named|bind ]]; then + rebuild_dns_domain_conf +fi + +# Updating dns-cluster queue +if [ "$DNS_CLUSTER" = "yes" ]; then + # Check for first sync + dlock=$(grep "domain $user $domain" $HESTIA/data/queue/dns-cluster.pipe) + if [ -z "$dlock" ]; then + cmd="$BIN/v-add-remote-dns-domain $user $domain yes" + echo "$cmd" >> $HESTIA/data/queue/dns-cluster.pipe + fi +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Restarting named +$BIN/v-restart-dns "$restart" +check_result $? "DNS restart failed" > /dev/null + +# Logging +$BIN/v-log-action "$user" "Info" "DNS" "IP address for DNS domain changed (IP: $ip, Domain: $domain)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-change-dns-domain-soa b/bin/v-change-dns-domain-soa new file mode 100755 index 0000000..d84fb6a --- /dev/null +++ b/bin/v-change-dns-domain-soa @@ -0,0 +1,89 @@ +#!/bin/bash +# info: change dns domain soa record +# options: USER DOMAIN SOA [RESTART] +# +# example: v-change-dns-domain-soa admin acme.com d.ns.domain.tld +# +# This function for changing SOA record. This type of records can not be +# modified by v-change-dns-record call. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 +soa=$(echo $3 | sed -e 's/\.*$//g' -e 's/^\.*//g') +restart=$4 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# shellcheck source=/usr/local/hestia/func/rebuild.sh +source $HESTIA/func/rebuild.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn +# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ? + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '3' "$#" 'USER DOMAIN SOA [RESTART]' +is_format_valid 'user' 'domain' 'soa' +is_system_enabled "$DNS_SYSTEM" 'DNS_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'dns' 'DOMAIN' "$domain" +is_object_unsuspended 'dns' 'DOMAIN' "$domain" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Changing soa +update_object_value 'dns' 'DOMAIN' "$domain" '$SOA' "$soa" + +# Update serial +update_domain_serial +# Updating zone +if [[ "$DNS_SYSTEM" =~ named|bind ]]; then + rebuild_dns_domain_conf +fi + +# Updating dns-cluster queue +if [ "$DNS_CLUSTER" = "yes" ]; then + # Check for first sync + dlock=$(grep "domain $user $domain" $HESTIA/data/queue/dns-cluster.pipe) + if [ -z "$dlock" ]; then + cmd="$BIN/v-change-remote-dns-domain-soa $user $domain $soa" + echo "$cmd" >> $HESTIA/data/queue/dns-cluster.pipe + fi +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Restarting named +$BIN/v-restart-dns "$restart" +check_result $? "DNS restart failed" > /dev/null + +# Logging +$BIN/v-log-action "$user" "Info" "DNS" "SOA record for DNS domain changed (SOA: $soa, Domain: $domain)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-change-dns-domain-tpl b/bin/v-change-dns-domain-tpl new file mode 100755 index 0000000..d7219c2 --- /dev/null +++ b/bin/v-change-dns-domain-tpl @@ -0,0 +1,172 @@ +#!/bin/bash +# info: change dns domain template +# options: USER DOMAIN TEMPLATE [RESTART] +# +# example: v-change-dns-domain-tpl admin example.com child-ns yes +# +# This function for changing the template of records. By updating old records +# will be removed and new records will be generated in accordance with +# parameters of new template. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 +template=$3 +restart=$4 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# shellcheck source=/usr/local/hestia/func/rebuild.sh +source $HESTIA/func/rebuild.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '3' "$#" 'USER DOMAIN TEMPLATE [RESTART]' +is_format_valid 'user' 'domain' 'template' +is_system_enabled "$DNS_SYSTEM" 'DNS_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'dns' 'DOMAIN' "$domain" +is_object_unsuspended 'dns' 'DOMAIN' "$domain" +is_dns_template_valid "$template" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Defining variables +get_domain_values 'dns' +i=1 +ns=$(get_user_value '$NS') +for nameserver in ${ns//,/ }; do + eval ns$i=$nameserver + ((++i)) +done + +# Reading template +template_data=$(cat "$DNSTPL/$template.tpl") + +# Deleting unused nameservers +if [ -z "$ns3" ]; then + template_data=$(echo "$template_data" | grep -v %ns3%) +fi +if [ -z "$ns4" ]; then + template_data=$(echo "$template_data" | grep -v %ns4%) +fi +if [ -z "$ns5" ]; then + template_data=$(echo "$template_data" | grep -v %ns5%) +fi +if [ -z "$ns6" ]; then + template_data=$(echo "$template_data" | grep -v %ns6%) +fi +if [ -z "$ns7" ]; then + template_data=$(echo "$template_data" | grep -v %ns7%) +fi +if [ -z "$ns8" ]; then + template_data=$(echo "$template_data" | grep -v %ns8%) +fi + +# Changing tpl +echo "$template_data" \ + | sed -e "s/%ip%/$IP/g" \ + -e "s/%domain_idn%/$domain_idn/g" \ + -e "s/%domain%/$domain/g" \ + -e "s/%ns1%/$ns1/g" \ + -e "s/%ns2%/$ns2/g" \ + -e "s/%ns3%/$ns3/g" \ + -e "s/%ns4%/$ns4/g" \ + -e "s/%ns5%/$ns5/g" \ + -e "s/%ns6%/$ns6/g" \ + -e "s/%ns7%/$ns7/g" \ + -e "s/%ns8%/$ns8/g" \ + -e "s/%time%/$TIME/g" \ + -e "s/%date%/$DATE/g" > $USER_DATA/dns/$domain.conf +records="$(wc -l $USER_DATA/dns/$domain.conf | cut -f 1 -d ' ')" + +# Refresh DKIM records in DNS if signing key exists for domain +if [ "$template" = "default" ] || [ "$template" = "child-ns" ]; then + if [ -n "$MAIL_SYSTEM" ] && [ -f "$HOMEDIR/$user/conf/mail/$domain/dkim.pem" ]; then + check_dns_domain=$(is_object_valid 'dns' 'DOMAIN' "$domain") + if [ "$?" -eq 0 ]; then + p=$(cat "$USER_DATA/mail/$domain.pub" | grep -v ' KEY---' | tr -d '\n') + record='_domainkey' + policy="\"t=y; o=~;\"" + $BIN/v-add-dns-record "$user" "$domain" "$record" TXT "$policy" '' '' 'no' + + record='mail._domainkey' + selector="\"v=DKIM1\; k=rsa\; p=$p\"" + $BIN/v-add-dns-record "$user" "$domain" "$record" TXT "$selector" + fi + fi +fi + +# Set correct domain name formatting for Office 365/Microsoft 365 MX records +if [ "$template" = "office365" ]; then + check_dns_domain=$(is_object_valid 'dns' 'DOMAIN' "$domain") + if [ "$?" -eq 0 ]; then + record='@' + formatted_domain=$(echo "$domain" | sed 's/\./-/g') + $BIN/v-add-dns-record "$user" "$domain" "$record" MX "${formatted_domain}.mail.protection.outlook.com." '0' '' "$restart" + fi +fi + +# Update serial +update_domain_serial +# Updating zone +if [[ "$DNS_SYSTEM" =~ named|bind ]]; then + rebuild_dns_domain_conf +fi + +# Updating dns-cluster queue +if [ "$DNS_CLUSTER" = "yes" ]; then + # Check for first sync + dlock=$(grep "domain $user $domain" $HESTIA/data/queue/dns-cluster.pipe) + if [ -z "$dlock" ]; then + cmd="$BIN/v-add-remote-dns-domain $user $domain domain" + echo "$cmd" >> $HESTIA/data/queue/dns-cluster.pipe + fi +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Updating hestia config +update_object_value 'dns' 'DOMAIN' "$domain" '$TPL' "$template" +update_object_value 'dns' 'DOMAIN' "$domain" '$RECORDS' "$records" + +# Rebuild DNS zone and update counters to ensure that it has updated correctly +$BIN/v-rebuild-dns-domain "$user" "$domain" no +$BIN/v-update-user-stats "$user" +$BIN/v-update-user-counters "$user" + +# Restarting named +$BIN/v-restart-dns "$restart" +check_result $? "DNS restart failed" > /dev/null + +# Logging +$BIN/v-log-action "system" "Info" "DNS" "Template for DNS domain changed (Template: $template, Domain: $domain)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-change-dns-domain-ttl b/bin/v-change-dns-domain-ttl new file mode 100755 index 0000000..ca66aeb --- /dev/null +++ b/bin/v-change-dns-domain-ttl @@ -0,0 +1,88 @@ +#!/bin/bash +# info: change dns domain ttl +# options: USER DOMAIN TTL [RESTART] +# +# example: v-change-dns-domain-ttl alice example.com 14400 +# +# This function for changing the time to live TTL parameter for all records. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 +ttl=$3 +restart=$4 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# shellcheck source=/usr/local/hestia/func/rebuild.sh +source $HESTIA/func/rebuild.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn +# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ? + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '3' "$#" 'USER DOMAIN TTL [RESTART]' +is_format_valid 'user' 'domain' 'ttl' +is_system_enabled "$DNS_SYSTEM" 'DNS_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'dns' 'DOMAIN' "$domain" +is_object_unsuspended 'dns' 'DOMAIN' "$domain" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Changing ttl +update_object_value 'dns' 'DOMAIN' "$domain" '$TTL' "$ttl" + +# Update serial +update_domain_serial +# Updating zone +if [[ "$DNS_SYSTEM" =~ named|bind ]]; then + rebuild_dns_domain_conf +fi + +# Updating dns-cluster queue +if [ "$DNS_CLUSTER" = "yes" ]; then + # Check for first sync + dlock=$(grep "domain $user $domain" $HESTIA/data/queue/dns-cluster.pipe) + if [ -z "$dlock" ]; then + cmd="$BIN/v-change-remote-dns-domain-ttl $user $domain $ttl" + echo "$cmd" >> $HESTIA/data/queue/dns-cluster.pipe + fi +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Restarting named +$BIN/v-restart-dns "$restart" +check_result $? "DNS restart failed" > /dev/null + +# Logging +$BIN/v-log-action "$user" "Info" "DNS" "TTL for DNS domain changed (TTL: $ttl, Domain: $domain)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-change-dns-record b/bin/v-change-dns-record new file mode 100755 index 0000000..b0d0434 --- /dev/null +++ b/bin/v-change-dns-record @@ -0,0 +1,168 @@ +#!/bin/bash +# info: change dns domain record +# options: USER DOMAIN ID RECORD TYPE VALUE [PRIORITY] [RESTART] [TTL] +# +# example: v-change-dns-record admin domain.ua 42 192.18.22.43 +# +# This function for changing DNS record. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 +id=$3 +record=$4 +rtype=$5 +dvalue=$6 +priority=$7 +restart=$8 +ttl=$9 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# shellcheck source=/usr/local/hestia/func/rebuild.sh +source $HESTIA/func/rebuild.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn +# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ? + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '6' "$#" 'USER DOMAIN ID RECORD TYPE VALUE [PRIORITY] [RESTART] [TTL]' +is_format_valid 'user' 'domain' 'id' 'record' +is_system_enabled "$DNS_SYSTEM" 'DNS_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'dns' 'DOMAIN' "$domain" +is_object_unsuspended 'dns' 'DOMAIN' "$domain" +is_object_valid "dns/$domain" 'ID' "$id" +is_format_valid 'ttl' + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +if [ "$record" = "@" ] && [ "$rtype" = "CNAME" ]; then + check_result $E_INVALID "CNAME on root is not allowed" +fi + +# Make sure the variable for the optional parameter TTL is empty before parsing +# We depend on that later on +unset TTL + +# Parsing domain config +line=$(grep "ID='$id'" $USER_DATA/dns/$domain.conf) +parse_object_kv_list "$line" + +if [ -z "$rtype" ]; then + rtype=$TYPE +fi + +if [ -z "$priority" ]; then + priority=$PRIORITY +fi + +# Null priority for none MX/SRV records +if [ "$rtype" != 'MX' ] && [ "$rtype" != 'SRV' ]; then + priority='' +fi + +# Add trailing dot at the end of NS/CNAME/MX/PTR/SRV record +if [[ $rtype =~ ^NS|CNAME|MX|PTR|SRV ]]; then + trailing_dot=$(echo "$dvalue" | grep "\.$") + if [ -z "$trailing_dot" ]; then + dvalue="$dvalue." + fi +fi + +if [[ $rtype =~ NS|CNAME|MX|PTR|SRV ]]; then + dvalue=$(idn2 --quiet "$dvalue") + record=$(idn2 --quiet "$record") +fi + +if [ "$rtype" != "CAA" ]; then + dvalue=${dvalue//\"/} + + if [ "$rtype" != 'SRV' ] && [[ "$dvalue" =~ [\;[:space:]] ]]; then + dvalue='"'"$dvalue"'"' + fi +fi + +#RTYPE wasn't checked make sure to do it now correctly +is_format_valid 'user' 'domain' 'id' 'record' 'rtype' 'dvalue' + +# Additional verifications +is_dns_fqnd "$TYPE" "$dvalue" +is_dns_nameserver_valid "$domain" "$TYPE" "$dvalue" + +if [[ "$RECORD" == "$record" ]] && [[ "$TYPE" == "$rtype" ]] && [[ "$PRIORITY" -eq "$priority" ]] \ + && [[ "$VALUE" == "$dvalue" ]] && [[ "$SUSPENDED" == 'no' ]] && [[ "$TTL" -eq "$ttl" ]]; then + echo "No pending changes in DNS entry." + exit "$E_EXISTS" +fi + +# Generating timestamp +time_n_date=$(date +'%T %F') +time=$(echo "$time_n_date" | cut -f 1 -d \ ) +date=$(echo "$time_n_date" | cut -f 2 -d \ ) + +# Adding record +dns_rec="ID='$id' RECORD='$record' TYPE='$rtype' PRIORITY='$priority'" +dns_rec="$dns_rec VALUE='$dvalue' SUSPENDED='no' TIME='$time' DATE='$date'" +[ -n "$ttl" ] && dns_rec="$dns_rec TTL='$ttl'" +# Deleting old record +sed -i "/^ID='$id'/d" $USER_DATA/dns/$domain.conf +# Add new entry +echo "$dns_rec" >> $USER_DATA/dns/$domain.conf + +# Sorting records +sort_dns_records + +# Update serial +update_domain_serial +# Updating zone +if [[ "$DNS_SYSTEM" =~ named|bind ]]; then + rebuild_dns_domain_conf +fi + +# Updating dns-cluster queue +if [ "$DNS_CLUSTER" = "yes" ]; then + # Check for first sync + dlock=$(grep "domain $user $domain" $HESTIA/data/queue/dns-cluster.pipe) + if [ -z "$dlock" ]; then + cmd="$BIN/v-add-remote-dns-domain $user $domain records" + echo "$cmd" >> $HESTIA/data/queue/dns-cluster.pipe + fi +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Restarting named +$BIN/v-restart-dns "$restart" +check_result $? "DNS restart failed" > /dev/null + +# Logging +$BIN/v-log-action "$user" "Info" "DNS" "DNS record value changed (Type: $rtype, Record: $record, Value: $dvalue, Domain: $domain)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-change-dns-record-id b/bin/v-change-dns-record-id new file mode 100755 index 0000000..5085277 --- /dev/null +++ b/bin/v-change-dns-record-id @@ -0,0 +1,93 @@ +#!/bin/bash +# info: change dns domain record id +# options: USER DOMAIN ID NEWID [RESTART] +# +# example: v-change-dns-record-id admin acme.com 24 42 yes +# +# This function for changing internal record id. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 +id=$3 +newid=$4 +restart=$5 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# shellcheck source=/usr/local/hestia/func/rebuild.sh +source $HESTIA/func/rebuild.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn +# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ? + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '4' "$#" 'USER DOMAIN ID NEWID [RESTART]' +is_format_valid 'user' 'domain' 'id' 'newid' +is_system_enabled "$DNS_SYSTEM" 'DNS_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'dns' 'DOMAIN' "$domain" +is_object_unsuspended 'dns' 'DOMAIN' "$domain" +is_object_valid "dns/$domain" 'ID' "$id" +is_object_new "dns/$domain" 'ID' "$newid" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Change id +sed -i "s/^ID='$id'/ID='$newid'/" $USER_DATA/dns/$domain.conf + +# Sorting records +sort_dns_records + +# Update serial +update_domain_serial +# Updating zone +if [[ "$DNS_SYSTEM" =~ named|bind ]]; then + rebuild_dns_domain_conf +fi + +# Updating dns-cluster queue +if [ "$DNS_CLUSTER" = "yes" ]; then + # Check for first sync + dlock=$(grep "domain $user $domain" $HESTIA/data/queue/dns-cluster.pipe) + if [ -z "$dlock" ]; then + cmd="$BIN/v-add-remote-dns-domain $user $domain records" + echo "$cmd" >> $HESTIA/data/queue/dns-cluster.pipe + fi +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Restarting named +$BIN/v-restart-dns "$restart" +check_result $? "DNS restart failed" > /dev/null + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-change-domain-owner b/bin/v-change-domain-owner new file mode 100755 index 0000000..41f9bf4 --- /dev/null +++ b/bin/v-change-domain-owner @@ -0,0 +1,317 @@ +#!/bin/bash +# info: change domain owner +# options: DOMAIN USER +# +# example: v-change-domain-owner www.example.com bob +# +# This function of changing domain ownership. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +domain=$1 +user=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/ip.sh +source $HESTIA/func/ip.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'DOMAIN USER' +is_format_valid 'domain' 'user' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +owner=$($BIN/v-search-domain-owner "$domain") +if [ -z "$owner" ]; then + check_result "$E_NOTEXIST" "domain $domain doesn't exist" +fi +if [ "$owner" = "$user" ]; then + echo "ERROR: $domain is already owned by $user." + exit +fi + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +echo "Moving $domain from $owner to $user, please wait..." + +# WEB domain +web_data=$(grep "DOMAIN='$domain'" $HESTIA/data/users/$owner/web.conf) +if [ -n "$web_data" ]; then + echo "[*] Moving web domain..." + $BIN/v-suspend-web-domain "$owner" "$domain" >> /dev/null 2>&1 + parse_object_kv_list "$web_data" + + if [ -n "$CUSTOM_DOCROOT" ]; then + if [ -z $(echo $CUSTOM_DOCROOT | grep -i "/home/$owner/web/$domain") ]; then + docdomain=$(echo "$CUSTOM_DOCROOT" | cut -d'/' -f5) + $BIN/v-list-web-domain $user $docdomain > /dev/null + if [ "$?" != 0 ]; then + echo "Error: Target domain doesn't belong to the new user" + exit $E_NOTEXIST + fi + new_docroot=$(echo $CUSTOM_DOCROOT | sed "s/\/home\/$owner/\/home\/$user/") + new_php_docroot=$(echo $CUSTOM_PHPROOT | sed "s/\/home\/$owner/\/home\/$user/") + + else + new_docroot=$(echo $CUSTOM_DOCROOT | sed "s/\/home\/$owner/\/home\/$user/") + new_php_docroot=$(echo $CUSTOM_PHPROOT | sed "s/\/home\/$owner/\/home\/$user/") + fi + fi + + if [ -z "$(echo $(get_user_ips) | grep $IP)" ]; then + echo "[*] IP dedicated to $owner select new ip address..." + get_user_ip + fi + old_ip=$IP + new_ip=$ip + echo $ip + + # Change IP + if [ -n "$ip" ]; then + web_data=$(echo "$web_data" | sed "s/IP='$IP'/IP='$ip'/") + fi + if [ -n "$new_docroot" ]; then + web_data=$(echo "$web_data" | sed "s|CUSTOM_DOCROOT='$CUSTOM_DOCROOT'|CUSTOM_DOCROOT='$new_docroot'|") + web_data=$(echo "$web_data" | sed "s|CUSTOM_PHPROOT='$CUSTOM_PHPROOT'|CUSTOM_PHPROOT='$new_php_docroot'|") + fi + web_data=$(echo "$web_data" | sed "s/SUSPENDED='no'/SUSPENDED='yes'/") + + # Check SSL + if [ "$SSL" = 'yes' ]; then + ssl_crt=$HESTIA/data/users/$owner/ssl/$domain.crt + ssl_key=$HESTIA/data/users/$owner/ssl/$domain.key + ssl_ca=$HESTIA/data/users/$owner/ssl/$domain.ca + ssl_pem=$HESTIA/data/users/$owner/ssl/$domain.pem + mv $ssl_crt $HESTIA/data/users/$user/ssl/ + mv $ssl_key $HESTIA/data/users/$user/ssl/ + mv $ssl_ca $HESTIA/data/users/$user/ssl/ >> /dev/null 2>&1 + mv $ssl_pem $HESTIA/data/users/$user/ssl/ >> /dev/null 2>&1 + rm -f $HOMEDIR/$owner/conf/web/ssl.$domain.* + fi + + # Check ftp user account + if [ -n "$FTP_USER" ]; then + /usr/sbin/userdel -f "$FTP_USER" >> /dev/null 2>&1 + old_str="FTP_USER='$FTP_USER'" + new_str=$(echo "$old_str" | sed "s/${owner}_/${user}_/") + web_data=$(echo "$web_data" | sed "s/$old_str/$new_str/") + fi + + # Move config + sed -i "/DOMAIN='$domain'/d" $HESTIA/data/users/$owner/web.conf + echo "$web_data" >> $HESTIA/data/users/$user/web.conf + + # Move data + mv $HOMEDIR/$owner/web/$domain $HOMEDIR/$user/web/ + + # Change ownership + find "$HOMEDIR/$user/web/$domain" -user "$owner" \ + -exec chown -h $user:$user {} \; + + # Rebuild config + $BIN/v-unsuspend-web-domain "$user" "$domain" no >> /dev/null 2>&1 + $BIN/v-rebuild-web-domains "$owner" no + $BIN/v-rebuild-web-domains "$user" + + # Cleanup old config + rm -rf "$HOMEDIR/$owner/conf/web/$domain/" +fi + +# DNS domain +dns_data=$(grep "DOMAIN='$domain'" $HESTIA/data/users/$owner/dns.conf) +if [ -n "$dns_data" ]; then + echo "[*] Moving DNS zone and records..." + parse_object_kv_list "$dns_data" + + # Change IP + if [ -n "$ip" ]; then + dns_data=$(echo "$dns_data" | sed "s/IP='$IP'/IP='$ip'/") + sed -i "s/$IP/$ip/g" $HESTIA/data/users/$owner/dns/$domain.conf + fi + + # Move config + sed -i "/DOMAIN='$domain'/d" $HESTIA/data/users/$owner/dns.conf + echo "$dns_data" >> $HESTIA/data/users/$user/dns.conf + + # Move dns records + mv $HESTIA/data/users/$owner/dns/$domain.conf \ + $HESTIA/data/users/$user/dns/ + + # Rebuild config + $BIN/v-unsuspend-dns-domain "$user" "$domain" no >> /dev/null 2>&1 + $BIN/v-rebuild-dns-domains "$owner" no + $BIN/v-rebuild-dns-domains "$user" + + # Cleanup old config + rm -f $HOMEDIR/$owner/conf/dns/$domain.db + + # Resync dns cluster + if [ "$DNS_CLUSTER" = "yes" ]; then + $BIN/v-sync-dns-cluster + fi +fi + +# MAIL domain +mail_data=$(grep "DOMAIN='$domain'" $HESTIA/data/users/$owner/mail.conf) +if [ -n "$mail_data" ]; then + $BIN/v-suspend-mail-domain "$owner" "$domain" >> /dev/null 2>&1 + echo "[*] Moving mail domain and accounts..." + + parse_object_kv_list "$mail_data" + + # Ensure mail configuration directory exists for receiving user + if [ ! -e "$HOMEDIR/$user/conf/mail/$domain/" ]; then + mkdir -p $HOMEDIR/$user/conf/mail/$domain/ + fi + + # Move config + sed -i "/DOMAIN='$domain'/d" $HESTIA/data/users/$owner/mail.conf + mail_data=$(echo "$mail_data" | sed "s/SUSPENDED='no'/SUSPENDED='yes'/") + echo "$mail_data" >> $HESTIA/data/users/$user/mail.conf + mv -f $HESTIA/data/users/$owner/mail/$domain.conf \ + $HESTIA/data/users/$user/mail/ + + # Move DKIM + if [ -e "$HESTIA/data/users/$owner/mail/$domain.pem" ]; then + mv -f $HESTIA/data/users/$owner/mail/$domain.pem \ + $HESTIA/data/users/$user/mail/ + mv -f $HESTIA/data/users/$owner/mail/$domain.pub \ + $HESTIA/data/users/$user/mail/ + fi + + # Move SSL certificates + if [ "$SSL" = 'yes' ]; then + # Ensure that SSL directory exists and move certificates + mkdir -p $HESTIA/data/users/$user/ssl/ + mkdir -p $HOMEDIR/$user/conf/mail/$domain/ssl/ + + ssl_crt=$HESTIA/data/users/$owner/ssl/mail.$domain.crt + ssl_key=$HESTIA/data/users/$owner/ssl/mail.$domain.key + ssl_ca=$HESTIA/data/users/$owner/ssl/mail.$domain.ca + ssl_pem=$HESTIA/data/users/$owner/ssl/mail.$domain.pem + mv $ssl_crt $HESTIA/data/users/$user/ssl/ + mv $ssl_key $HESTIA/data/users/$user/ssl/ + mv $ssl_ca $HESTIA/data/users/$user/ssl/ >> /dev/null 2>&1 + mv $ssl_pem $HESTIA/data/users/$user/ssl/ >> /dev/null 2>&1 + + # Add certificate to user home directory + cp -f $HESTIA/data/users/$user/ssl/mail.$domain.crt $HOMEDIR/$user/conf/mail/$domain/ssl/$domain.crt + cp -f $HESTIA/data/users/$user/ssl/mail.$domain.key $HOMEDIR/$user/conf/mail/$domain/ssl/$domain.key + cp -f $HESTIA/data/users/$user/ssl/mail.$domain.pem $HOMEDIR/$user/conf/mail/$domain/ssl/$domain.pem + if [ -e "$HESTIA/data/users/$user/ssl/mail.$domain.ca" ]; then + cp -f $HESTIA/data/users/$user/ssl/mail.$domain.ca $HOMEDIR/$user/conf/mail/$domain/ssl/$domain.ca + fi + + # Add domain SSL configuration to dovecot + if [ -f "/etc/dovecot/conf.d/domains/$domain.conf" ]; then + rm -f /etc/dovecot/conf.d/domains/$domain.conf + fi + + echo "" >> /etc/dovecot/conf.d/domains/$domain.conf + echo "local_name mail.$domain {" >> /etc/dovecot/conf.d/domains/$domain.conf + echo " ssl_cert = <$HOMEDIR/$user/conf/mail/$domain/ssl/$domain.pem" >> /etc/dovecot/conf.d/domains/$domain.conf + echo " ssl_key = <$HOMEDIR/$user/conf/mail/$domain/ssl/$domain.key" >> /etc/dovecot/conf.d/domains/$domain.conf + echo "}" >> /etc/dovecot/conf.d/domains/$domain.conf + + # Add domain SSL configuration to exim4 + # Cleanup symlinks + find /usr/local/hestia/ssl/mail -xtype l -delete + + ln -s -f $HOMEDIR/$user/conf/mail/$domain/ssl/$domain.pem /usr/local/hestia/ssl/mail/mail.$domain.crt + ln -s -f $HOMEDIR/$user/conf/mail/$domain/ssl/$domain.key /usr/local/hestia/ssl/mail/mail.$domain.key + + # Set correct permissions on certificates + chmod 750 $HOMEDIR/$user/conf/mail/$domain/ssl + chown -R $MAIL_USER:mail $HOMEDIR/$user/conf/mail/$domain/ssl + chmod 0644 $HOMEDIR/$user/conf/mail/$domain/ssl/* + chown -h $user:mail $HOMEDIR/$user/conf/mail/$domain/ssl/* + chmod -R 0644 /usr/local/hestia/ssl/mail/* + chown -h $user:mail /usr/local/hestia/ssl/mail/* + fi + + # Move data + mv $HOMEDIR/$owner/mail/$domain $HOMEDIR/$user/mail/ + + # Change ownership + find $HOMEDIR/$user/mail/$domain -user $owner \ + -exec chown -h $user {} \; + + # Checking exim username for later chowning + exim_user="exim" + check_exim_username=$(grep -c '^Debian-exim:' /etc/passwd) + if [ "$check_exim_username" -eq 1 ]; then + exim_user="Debian-exim" + fi + # Chowning mail conf files to exim user + if [ -d "$HOMEDIR/$user/conf/mail/$domain" ]; then + find $HOMEDIR/$user/conf/mail/$domain -user root \ + -exec chown $exim_user {} \; + fi + + # Remove old mail directory from original owner + if [ -e "$HOMEDIR/$owner/mail/$domain" ]; then + rm -rf "$HOMEDIR/$owner/mail/$domain" + fi + + # Remove old mail configuration directory from original owner + if [ -e "$HOMEDIR/$owner/conf/mail/$domain" ]; then + rm -rf "$HOMEDIR/$owner/conf/mail/$domain" + fi + if [ -e "$HESTIA/data/users/$owner/mail/$domain.conf" ]; then + rm -f "$HESTIA/data/users/$owner/mail/$domain.conf" + fi + + # Rebuild config + $BIN/v-unsuspend-mail-domain "$user" "$domain" no + $BIN/v-rebuild-mail-domains "$owner" no + $BIN/v-rebuild-mail-domains "$user" +fi + +# Update counters +$BIN/v-update-user-counters "$owner" +$BIN/v-update-user-counters "$user" + +# Mail domains currently don't have the IP variable set see #2306 +if [ -n "$old_ip" ]; then + # Recalculate ip usage + if [ -n "$ip" ]; then + decrease_ip_value $old_ip $owner + increase_ip_value $new_ip + else + # recalculate ip + decrease_ip_value $old_ip $owner + increase_ip_value $old_ip + fi +fi +# Send notification to panel +if [ -n "$web_data" ] || [ -n "$dns_data" ] || [ -n "$mail_data" ]; then + $BIN/v-add-user-notification "$user" "$domain has been added to your account" '' +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +$BIN/v-log-action "system" "Info" "System" "Domain moved between users (Domain: $domain, Old user: $owner, New User: $user)." +$BIN/v-log-action "$user" "Info" "System" "New domain added to account (Domain: $domain)." +$BIN/v-log-action "$owner" "Info" "System" "Domain removed from account (Domain: $domain)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-change-firewall-rule b/bin/v-change-firewall-rule new file mode 100755 index 0000000..f74d311 --- /dev/null +++ b/bin/v-change-firewall-rule @@ -0,0 +1,95 @@ +#!/bin/bash +# info: change firewall rule +# options: RULE ACTION IP PORT [PROTOCOL] [COMMENT] +# +# example: v-change-firewall-rule 3 ACCEPT 5.188.123.17 443 +# +# This function is used for changing existing firewall rule. +# It fully replace rule with new one but keeps same id. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +rule=$1 +action=$(echo $2 | tr '[:lower:]' '[:upper:]') +ip=$3 +port_ext=$4 +protocol=${5-TCP} +protocol=$(echo $protocol | tr '[:lower:]' '[:upper:]') +comment=$6 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Sort function +sort_fw_rules() { + cat $HESTIA/data/firewall/rules.conf \ + | sort -n -k 2 -t \' > $HESTIA/data/firewall/rules.conf.tmp + mv -f $HESTIA/data/firewall/rules.conf.tmp \ + $HESTIA/data/firewall/rules.conf +} + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '4' "$#" 'RULE ACTION IP PORT [PROTOCOL] [COMMENT]' +is_format_valid 'rule' 'action' 'protocol' 'port_ext' +if [ ! -z "$comment" ]; then + is_format_valid 'comment' +fi +is_system_enabled "$FIREWALL_SYSTEM" 'FIREWALL_SYSTEM' +is_object_valid '../../data/firewall/rules' 'RULE' "$rule" + +if [[ "$ip" =~ ^ipset: ]]; then + ipset_name="${ip#ipset:}" + $BIN/v-list-firewall-ipset plain | grep "^$ipset_name\s" > /dev/null + check_result $? 'ipset object not found' "$E_NOTEXIST" +else + is_format_valid 'ip' +fi + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Generating timestamp +time_n_date=$(date +'%T %F') +time=$(echo "$time_n_date" | cut -f 1 -d \ ) +date=$(echo "$time_n_date" | cut -f 2 -d \ ) + +# Concatenating firewall rule +str="RULE='$rule' ACTION='$action' PROTOCOL='$protocol' PORT='$port_ext'" +str="$str IP='$ip' COMMENT='$comment' SUSPENDED='no'" +str="$str TIME='$time' DATE='$date'" + +# Deleting old rule +sed -i "/RULE='$rule' /d" $HESTIA/data/firewall/rules.conf + +# Adding new +echo "$str" >> $HESTIA/data/firewall/rules.conf + +# Sorting firewall rules by id number +sort_fw_rules + +# Updating system firewall +$BIN/v-update-firewall + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +$BIN/v-log-action "system" "Info" "Firewall" "Firewall rule changed (Rule: $rule, Action: $action, Protocol: $protocol, Port: $port_ext)." +log_event "$OK" "$ARGUMENTS" +exit diff --git a/bin/v-change-fs-file-permission b/bin/v-change-fs-file-permission new file mode 100755 index 0000000..6528822 --- /dev/null +++ b/bin/v-change-fs-file-permission @@ -0,0 +1,62 @@ +#!/bin/bash +# info: change file permission +# options: USER FILE PERMISSIONS +# +# example: v-change-fs-file-permission admin readme.txt 0777 +# +# This function changes file access permissions on the file system + +user=$1 +src_file=$2 +permissions=$3 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '3' "$#" 'USER FILE PERMISSIONS' +is_format_valid 'user' +is_object_valid 'user' 'USER' "$user" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +# Checking user homedir +homedir=$(grep "^$user:" /etc/passwd | cut -f 6 -d :) +if [ -z "$homedir" ]; then + echo "Error: user home directory doesn't exist" + exit 12 +fi + +# Checking source file +if [ ! -f "$src_file" ]; then + echo "Error: source file doesn't exist $src_file" + exit 3 +fi + +# Checking source path +rpath=$(readlink -f "$src_file") +if [ -z "$(echo $rpath | egrep "^/tmp|^$homedir")" ]; then + echo "Error: invalid source path $src_file" + exit 2 +fi + +# Changing file permissions +user_exec chmod -R $permissions "$src_file" > /dev/null 2>&1 +if [ $? -ne 0 ]; then + echo "Error: access permission on $src_file was not changed" + exit 3 +fi + +$BIN/v-log-action "system" "Info" "System" "File system permissions changed (User: $user, File: $src_file, Permissions: $permissions)." + +# Exiting +exit diff --git a/bin/v-change-mail-account-password b/bin/v-change-mail-account-password new file mode 100755 index 0000000..30016c5 --- /dev/null +++ b/bin/v-change-mail-account-password @@ -0,0 +1,94 @@ +#!/bin/bash +# info: change mail account password +# options: USER DOMAIN ACCOUNT PASSWORD +# +# example: v-change-mail-account-password admin mydomain.tld user p4$$vvOrD +# +# This function changes email account password. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 +account=$3 +password=$4 +HIDE=4 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hest +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn +# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ? + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '4' "$#" 'USER DOMAIN ACCOUNT PASSWORD' +is_format_valid 'user' 'domain' 'account' +is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'mail' 'DOMAIN' "$domain" +is_object_unsuspended 'mail' 'DOMAIN' "$domain" +is_object_valid "mail/$domain" 'ACCOUNT' "$account" +is_object_unsuspended "mail/$domain" 'ACCOUNT' "$account" +is_password_valid + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Generating hashed password +if [ -n "$(doveadm pw -l | grep BLF-CRYPT)" ]; then + set +H # disable ! style history substitution + md5="$(doveadm pw -s BLF-CRYPT -p "$password")" +elif [ -n "$(doveadm pw -l | grep ARGON2ID)" ]; then + # Fall back on Argon2id if bcrypt is not available + set +H # disable ! style history substitution + md5="$(doveadm pw -s ARGON2ID -p "$password")" +else + # Fall back on MD5 if neither bcrypt nor argon2id is available + salt=$(generate_password "$PW_MATRIX" "8") + md5="{MD5}$($BIN/v-generate-password-hash md5 $salt <<< $password)" +fi + +if [[ "$MAIL_SYSTEM" =~ exim ]]; then + quota=$(get_object_value "mail/$domain" 'ACCOUNT' "$account" '$QUOTA') + if [ "$quota" = 'unlimited' ]; then + quota=0 + fi + sed -i "/^$account:/d" $HOMEDIR/$user/conf/mail/$domain/passwd + str="$account:$md5:$user:mail::$HOMEDIR/$user:${quota}:userdb_quota_rule=*:storage=${quota}M" + echo "$str" >> $HOMEDIR/$user/conf/mail/$domain/passwd +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Update md5 +update_object_value "mail/$domain" 'ACCOUNT' "$account" '$MD5' "$md5" + +# Logging +$BIN/v-log-action "$user" "Info" "Mail" "Mail account password changed (Account: $account@$domain)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-change-mail-account-quota b/bin/v-change-mail-account-quota new file mode 100755 index 0000000..379d7ff --- /dev/null +++ b/bin/v-change-mail-account-quota @@ -0,0 +1,84 @@ +#!/bin/bash +# info: change mail account quota +# options: USER DOMAIN ACCOUNT QUOTA +# +# example: v-change-mail-account-quota admin mydomain.tld user01 unlimited +# +# This function changes email account disk quota. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 +account=$3 +quota=$4 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn +# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ? + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '4' "$#" 'USER DOMAIN ACCOUNT QUOTA' +is_format_valid 'user' 'domain' 'account' +if [ "$quota" != 'unlimited' ]; then + is_format_valid 'quota' +fi +is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'mail' 'DOMAIN' "$domain" +is_object_unsuspended 'mail' 'DOMAIN' "$domain" +is_object_valid "mail/$domain" 'ACCOUNT' "$account" +is_object_unsuspended "mail/$domain" 'ACCOUNT' "$account" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +md5=$(get_object_value "mail/$domain" 'ACCOUNT' "$account" '$MD5') +if [[ "$MAIL_SYSTEM" =~ exim ]]; then + if [ "$quota" = 'unlimited' ]; then + quota=0 + fi + sed -i "/^$account:/d" "$HOMEDIR/$user/conf/mail/$domain/passwd" + str="$account:$md5:$user:mail::$HOMEDIR/$user:${quota}:userdb_quota_rule=*:storage=${quota}M" + echo "$str" >> "$HOMEDIR/$user/conf/mail/$domain/passwd" +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +if [[ "$quota" -eq 0 ]]; then + quota='unlimited' +fi + +# Update quota +update_object_value "mail/$domain" 'ACCOUNT' "$account" '$QUOTA' "$quota" + +# Logging +$BIN/v-log-action "$user" "Info" "Mail" "Mail account quota changed (Quota: $quota, Account: $account@$domain)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-change-mail-account-rate-limit b/bin/v-change-mail-account-rate-limit new file mode 100755 index 0000000..e95c90a --- /dev/null +++ b/bin/v-change-mail-account-rate-limit @@ -0,0 +1,96 @@ +#!/bin/bash +# info: change mail account rate limit +# options: USER DOMAIN ACCOUNT RATE +# +# example: v-change-mail-account-rate-limit admin mydomain.tld user01 100 +# +# This function changes email account rate limit. Use system to use domain or "server" setting + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 +account=$3 +rate=$4 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# shellcheck source=/usr/local/hestia/func/syshealth.sh +source $HESTIA/func/syshealth.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn +# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ? + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '4' "$#" 'USER DOMAIN ACCOUNT RATE' +is_format_valid 'user' 'domain' 'account' +if [ "$rate" != 'system' ]; then + is_format_valid 'rate' +fi +is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'mail' 'DOMAIN' "$domain" +is_object_unsuspended 'mail' 'DOMAIN' "$domain" +is_object_valid "mail/$domain" 'ACCOUNT' "$account" +is_object_unsuspended "mail/$domain" 'ACCOUNT' "$account" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +md5=$(get_object_value "mail/$domain" 'ACCOUNT' "$account" '$MD5') +if [[ "$MAIL_SYSTEM" =~ exim ]]; then + if [ "$rate" = "system" ]; then + user_rate_limit=$(get_object_value 'mail' 'DOMAIN' "$domain" '$RATE_LIMIT') + if [ -n "$user_rate_limit" ]; then + sed -i "/^$account@$domain_idn:/ d" $HOMEDIR/$user/conf/mail/$domain/limits + echo "$account@$domain_idn:$user_rate_limit" >> $HOMEDIR/$user/conf/mail/$domain/limits + else + system=$(cat /etc/exim4/limit.conf) + sed -i "/^$account@$domain_idn:/ d" $HOMEDIR/$user/conf/mail/$domain/limits + echo "$account@$domain_idn:$system" >> $HOMEDIR/$user/conf/mail/$domain/limits + fi + else + sed -i "/^$account@$domain_idn:/ d" $HOMEDIR/$user/conf/mail/$domain/limits + echo "$account@$domain_idn:$rate" >> $HOMEDIR/$user/conf/mail/$domain/limits + fi +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +if [[ "$rate" = "system" ]]; then + rate='' +fi + +syshealth_repair_mail_account_config + +# Update quota +update_object_value "mail/$domain" 'ACCOUNT' "$account" '$RATE_LIMIT' "$rate" + +# Logging +$BIN/v-log-action "$user" "Info" "Mail" "Mail account rate limit changed (Rate: $rate, Account: $account@$domain)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-change-mail-domain-catchall b/bin/v-change-mail-domain-catchall new file mode 100755 index 0000000..928640a --- /dev/null +++ b/bin/v-change-mail-domain-catchall @@ -0,0 +1,69 @@ +#!/bin/bash +# info: change mail domain catchall email +# options: USER DOMAIN EMAIL +# +# example: v-change-mail-domain-catchall user01 mydomain.tld master@mydomain.tld +# +# This function changes mail domain catchall. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 +email=$3 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '3' "$#" 'USER DOMAIN EMAIL' +is_format_valid 'user' 'domain' 'email' +is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'mail' 'DOMAIN' "$domain" +is_object_unsuspended 'mail' 'DOMAIN' "$domain" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Change cathcall alias +if [[ "$MAIL_SYSTEM" =~ exim ]]; then + sed -i "/*@$domain_idn:/d" "$HOMEDIR/$user/conf/mail/$domain/aliases" + echo "*@$domain_idn:$email" >> "$HOMEDIR/$user/conf/mail/$domain/aliases" +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Change catchall in config +update_object_value 'mail' 'DOMAIN' "$domain" '$CATCHALL' "$email" + +# Logging +$BIN/v-log-action "$user" "Info" "Mail" "Mail domain catch-all address changed (Domain: $domain, Send to: $email)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-change-mail-domain-rate-limit b/bin/v-change-mail-domain-rate-limit new file mode 100755 index 0000000..4623156 --- /dev/null +++ b/bin/v-change-mail-domain-rate-limit @@ -0,0 +1,72 @@ +#!/bin/bash +# info: change mail domain rate limit +# options: USER DOMAIN RATE +# +# example: v-change-mail-domain-rate-limit admin mydomain.tld 100 +# +# This function changes email account rate limit for the domain. Account specific setting will overwrite domain setting! + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 +rate=$3 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn +# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ? + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '3' "$#" 'USER DOMAIN RATE' +is_format_valid 'user' 'domain' +if [ "$rate" != 'system' ]; then + is_format_valid 'rate' +fi +is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'mail' 'DOMAIN' "$domain" +is_object_unsuspended 'mail' 'DOMAIN' "$domain" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +if [[ "$rate" = "system" ]]; then + rate='' +fi + +# Update quota +update_object_value "mail" 'DOMAIN' "$domain" '$RATE_LIMIT' "$rate" +$BIN/v-rebuild-mail-domain "$user" "$domain" + +# Logging +$BIN/v-log-action "$user" "Info" "Mail" "Mail domain rate limit has changed ($rate)" +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-change-mail-domain-sslcert b/bin/v-change-mail-domain-sslcert new file mode 100755 index 0000000..06512a3 --- /dev/null +++ b/bin/v-change-mail-domain-sslcert @@ -0,0 +1,72 @@ +#!/bin/bash +# info: change domain ssl certificate +# options: USER DOMAIN SSL_DIR [RESTART] +# +# This function changes SSL domain certificate and the key. If ca file present +# it will be replaced as well. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 +restart=$3 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '3' "$#" 'USER DOMAIN SSL_DIR [RESTART]' +is_format_valid 'user' 'domain' 'ssl_dir' +is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'mail' 'DOMAIN' "$domain_idn" +is_object_unsuspended 'mail' 'DOMAIN' "$domain_idn" +is_object_value_empty 'mail' 'DOMAIN' "$domain_idn" '$SSL' +is_web_domain_cert_valid + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Remove old configuration +del_mail_ssl_config + +# Create new configuration +add_mail_ssl_config + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Restarting mail server +$BIN/v-restart-mail "$restart" + +check_result $? "Mail restart failed" > /dev/null + +# Logging +$BIN/v-log-action "$user" "Info" "Mail" "SSL certificate changed (Domain: $domain)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-change-remote-dns-domain-exp b/bin/v-change-remote-dns-domain-exp new file mode 100755 index 0000000..5ab35a5 --- /dev/null +++ b/bin/v-change-remote-dns-domain-exp @@ -0,0 +1,83 @@ +#!/bin/bash +# info: change remote dns domain expiration date +# options: USER DOMAIN +# +# This function synchronise dns domain with the remote server. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/remote.sh +source $HESTIA/func/remote.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DOMAIN' +is_format_valid 'user' 'domain' +is_system_enabled "$DNS_CLUSTER" 'DNS_CLUSTER' +is_object_valid 'user' 'USER' "$user" +is_object_valid 'dns' 'DOMAIN' "$domain" +is_procces_running +remote_dns_health_check + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +IFS=$'\n' +for cluster in $(grep "SUSPENDED='no'" $HESTIA/conf/dns-cluster.conf); do + + # Reset user, password and hash vars + clear_dns_cluster_settings + + # Parsing remote host parameters + parse_object_kv_list "$cluster" + + # Syncing domain + str=$(grep "DOMAIN='$domain'" $USER_DATA/dns.conf) + if [ "$DNS_CLUSTER_SYSTEM" = "hestia-zone" ]; then + str=$(echo "$str" | sed "s/SLAVE='no'/SLAVE='yes'/g") + ip=$($BIN/v-list-sys-ips plain | cut -f1) + str=$(echo "$str" | sed "s/MASTER='*'/MASTER='$ip'/g") + + # Syncing domain data + cluster_cmd v-insert-dns-domain $DNS_USER "$str" $HOSTNAME $flush 'no' + check_result $? "$HOST connection failed" "$E_CONNECT" + + rndc notify $domain > /dev/null 2>&1 + else + cluster_cmd v-insert-dns-domain "$DNS_USER" "$str" "$HOSTNAME" 'no' + check_result $? "$HOST connection failed (exp insert)" "$E_CONNECT" + fi + +done + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Updating pipe +pipe="$HESTIA/data/queue/dns-cluster.pipe" +str=$(grep -n "$SCRIPT $1 $2 $3$" $pipe | cut -f1 -d: | head -n1) +if [ -n "$str" ]; then + sed -i "$str d" $pipe +fi + +exit diff --git a/bin/v-change-remote-dns-domain-soa b/bin/v-change-remote-dns-domain-soa new file mode 100755 index 0000000..31508e8 --- /dev/null +++ b/bin/v-change-remote-dns-domain-soa @@ -0,0 +1,91 @@ +#!/bin/bash +# info: change remote dns domain SOA +# options: USER DOMAIN +# +# example: v-change-remote-dns-domain-soa admin example.org.uk +# +# This function synchronise dns domain with the remote server. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/remote.sh +source $HESTIA/func/remote.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DOMAIN' +is_format_valid 'user' 'domain' +is_system_enabled "$DNS_CLUSTER" 'DNS_CLUSTER' +is_object_valid 'user' 'USER' "$user" +is_object_valid 'dns' 'DOMAIN' "$domain" +is_procces_running +remote_dns_health_check + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +IFS=$'\n' +for cluster in $(grep "SUSPENDED='no'" $HESTIA/conf/dns-cluster.conf); do + + # Reset user, password and hash vars + clear_dns_cluster_settings + + # Parsing remote host parameters + parse_object_kv_list "$cluster" + + if [ "$DNS_CLUSTER_SYSTEM" = "hestia-zone" ]; then + str=$(echo "$str" | sed "s/SLAVE='no'/SLAVE='yes'/g") + ip=$($BIN/v-list-sys-ips plain | cut -f1) + str=$(echo "$str" | sed "s/MASTER='*'/MASTER='$ip'/g") + + # Syncing domain data + cluster_cmd v-insert-dns-domain $DNS_USER "$str" $HOSTNAME $flush 'no' + check_result $? "$HOST connection failed" "$E_CONNECT" + + cluster_cmd v-rebuild-dns-domain $DNS_USER $domain 'yes' 'no' + check_result $? "$HOST connection failed" "$E_CONNECT" + + rndc notify $domain > /dev/null 2>&1 + else + # Syncing SOA + str=$(grep "DOMAIN='$domain'" $USER_DATA/dns.conf) + cluster_cmd v-insert-dns-domain "$DNS_USER" "$str" "$HOSTNAME" 'domain' 'no' + check_result $? "$HOST connection failed (sync)" "$E_CONNECT" + + # Rebuilding dns zone + cluster_cmd v-rebuild-dns-domain "$DNS_USER" "$domain" 'yes' 'no' + check_result $? "$HOST connection failed (rebuild)" "$E_CONNECT" + fi +done + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Updating pipe +pipe="$HESTIA/data/queue/dns-cluster.pipe" +str=$(grep -n "$SCRIPT $1 $2 $3$" $pipe | cut -f1 -d: | head -n1) +if [ -n "$str" ]; then + sed -i "$str d" $pipe +fi + +exit diff --git a/bin/v-change-remote-dns-domain-ttl b/bin/v-change-remote-dns-domain-ttl new file mode 100755 index 0000000..60c6a57 --- /dev/null +++ b/bin/v-change-remote-dns-domain-ttl @@ -0,0 +1,91 @@ +#!/bin/bash +# info: change remote dns domain TTL +# options: USER DOMAIN +# +# example: v-change-remote-dns-domain-ttl admin domain.tld +# +# This function synchronise dns domain with the remote server. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/remote.sh +source $HESTIA/func/remote.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DOMAIN' +is_format_valid 'user' 'domain' +is_system_enabled "$DNS_CLUSTER" 'DNS_CLUSTER' +is_object_valid 'user' 'USER' "$user" +is_object_valid 'dns' 'DOMAIN' "$domain" +is_procces_running +remote_dns_health_check + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +IFS=$'\n' +for cluster in $(grep "SUSPENDED='no'" $HESTIA/conf/dns-cluster.conf); do + + # Reset user, password and hash vars + clear_dns_cluster_settings + + # Parsing remote host parameters + parse_object_kv_list "$cluster" + + # Syncing TTL + str=$(grep "DOMAIN='$domain'" $USER_DATA/dns.conf) + if [ "$DNS_CLUSTER_SYSTEM" = "hestia-zone" ]; then + str=$(echo "$str" | sed "s/SLAVE='no'/SLAVE='yes'/g") + ip=$($BIN/v-list-sys-ips plain | cut -f1) + str=$(echo "$str" | sed "s/MASTER='*'/MASTER='$ip'/g") + + # Syncing domain data + cluster_cmd v-insert-dns-domain $DNS_USER "$str" $HOSTNAME $flush 'no' + check_result $? "$HOST connection failed" "$E_CONNECT" + + cluster_cmd v-rebuild-dns-domain $DNS_USER $domain 'yes' 'no' + check_result $? "$HOST connection failed" "$E_CONNECT" + + rndc notify $domain > /dev/null 2>&1 + else + cluster_cmd v-insert-dns-domain "$DNS_USER" "$str" "$HOSTNAME" 'domain' 'no' + check_result $? "$HOST connection failed (sync)" "$E_CONNECT" + + # Rebuilding dns zone + cluster_cmd v-rebuild-dns-domain "$DNS_USER" "$domain" 'yes' 'no' + check_result $? "$HOST connection failed (rebuild)" "$E_CONNECT" + fi +done + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Updating pipe +pipe="$HESTIA/data/queue/dns-cluster.pipe" +str=$(grep -n "$SCRIPT $1 $2 $3$" $pipe | cut -f1 -d: | head -n1) +if [ -n "$str" ]; then + sed -i "$str d" "$pipe" +fi + +exit diff --git a/bin/v-change-sys-api b/bin/v-change-sys-api new file mode 100755 index 0000000..fdd53fb --- /dev/null +++ b/bin/v-change-sys-api @@ -0,0 +1,86 @@ +#!/bin/bash +# info: Enable / Disable API access +# options: STATUS +# +# example: v-change-sys-api enable legacy +# # Enable legacy api currently default on most of api based systems +# example: v-change-sys-api enable api +# # Enable api +# +# example: v-change-sys-api disable +# # Disable API +# +# Enabled / Disable API + +status=$1 +version=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +check_args '1' "$#" "STATUS" "VERSION" +is_type_valid "enable,disable,remove" "$status" +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +if [ "$status" = "enable" ]; then + if [ ! -f "$HESTIA/web/api/index.php" ]; then + wget -q https://raw.githubusercontent.com/hestiacp/hestiacp/$RELEASE_BRANCH/web/api/index.php -O $HESTIA/web/api/index.php + if [ ! -s "$HESTIA/web/api/index.php" ]; then + wget -q https://raw.githubusercontent.com/hestiacp/hestiacp/release/web/api/index.php -O $HESTIA/web/api/index.php + if [ ! -s "$HESTIA/web/api/index.php" ]; then + # Throw error message to user + echo "ERROR: API installation failed." + # Remove empty file created by wget output + rm -f "$HESTIA/web/api/index.php" + exit 1 + fi + fi + else + sed -i 's|die("Error: Disabled");|//die("Error: Disabled");|g' $HESTIA/web/api/index.php + sed -i 's|////|//|g' $HESTIA/web/api/index.php + fi + if [ "$version" = "legacy" ] || [ "$version" = "all" ]; then $BIN/v-change-sys-config-value "API" "yes"; fi + if [ "$version" = "api" ] || [ "$version" = "all" ]; then $BIN/v-change-sys-config-value "API_SYSTEM" "1"; fi +else + $BIN/v-change-sys-config-value "API" "no" + $BIN/v-change-sys-config-value "API_ALLOWED_IP" "" + $BIN/v-change-sys-config-value "API_SYSTEM" "0" + if [ "$status" != "remove" ]; then + sed -i 's|//die("Error: Disabled");|die("Error: Disabled");|g' $HESTIA/web/api/index.php + fi +fi + +if [ "$status" = "remove" ]; then + if [ ! -f "$HESTIA/web/api/index.php" ]; then + echo "ERROR: API is not installed." + exit 1 + else + rm -f "$HESTIA/web/api/index.php" + fi +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +if [ "$status" = "enable" ]; then + $BIN/v-log-action "system" "Warning" "System" "System API access enabled." +else + $BIN/v-log-action "system" "Info" "System" "System API access disabled." +fi +log_event "$OK" "$ARGUMENTS" diff --git a/bin/v-change-sys-config-value b/bin/v-change-sys-config-value new file mode 100755 index 0000000..0fef26a --- /dev/null +++ b/bin/v-change-sys-config-value @@ -0,0 +1,56 @@ +#!/bin/bash +# info: change sysconfig value +# options: KEY VALUE +# +# example: v-change-sys-config-value VERSION 1.0 +# +# This function is for changing main config settings such as COMPANY_NAME or +# COMPANY_EMAIL and so on. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +key=$(echo "$1" | tr '[:lower:]' '[:upper:]') +value=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'KEY VALUE' +is_common_format_valid "$key" 'key' +format_no_quotes "$value" 'value' +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +change_sys_value "$key" "$value" + +# Sort configuration file in alphabetical order on change +sort $HESTIA/conf/hestia.conf -o /tmp/updconf +mv $HESTIA/conf/hestia.conf $HESTIA/conf/hestia.conf.bak +mv /tmp/updconf $HESTIA/conf/hestia.conf +rm -f $HESTIA/conf/hestia.conf.bak + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +$BIN/v-log-action "system" "Info" "System" "System configuration value changed (Key: $key, Value: $value)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-change-sys-db-alias b/bin/v-change-sys-db-alias new file mode 100755 index 0000000..816db87 --- /dev/null +++ b/bin/v-change-sys-db-alias @@ -0,0 +1,108 @@ +#!/bin/bash +# info: change phpmyadmin/phppgadmin alias url +# options: TYPE ALIAS +# +# example: v-change-sys-db-alias pma phpmyadmin +# # Sets phpMyAdmin alias to phpmyadmin +# +# example: v-change-sys-db-alias pga phppgadmin +# # Sets phpPgAdmin alias to phppgadmin +# +# This function changes the database editor url in +# apache2 or nginx configuration. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +type=$1 +alias=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'type alias' + +is_common_format_valid "$alias" "Alias" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Detect common allowed entries for phpMyAdmin +if [ "$type" = "pma" ] || [ "$type" = "PMA" ] || [ "$type" = "phpmyadmin" ]; then + # Set database editor friendly name + db_editor="phpMyAdmin" + # Set new alias value + $BIN/v-change-sys-config-value 'DB_PMA_ALIAS' "$alias" + + # Replace old configuration files and update alias + if [ -e "/etc/apache2/conf.d/phpmyadmin.inc" ]; then + rm -f /etc/apache2/conf.d/phpmyadmin.inc + cp -f $HESTIA_INSTALL_DIR/pma/apache.conf /etc/apache2/conf.d/phpmyadmin.inc + sed -i "s|%pma_alias%|$alias|g" /etc/apache2/conf.d/phpmyadmin.inc + + # Restart services + $BIN/v-restart-service apache2 + fi + + if [ -e "/etc/nginx/conf.d/phpmyadmin.inc" ]; then + rm -f /etc/nginx/conf.d/phpmyadmin.inc + cp -f $HESTIA_INSTALL_DIR/nginx/phpmyadmin.inc /etc/nginx/conf.d/phpmyadmin.inc + sed -i "s|%pma_alias%|$alias|g" /etc/nginx/conf.d/phpmyadmin.inc + + # Restart services + $BIN/v-restart-service nginx + fi +fi + +# Detect common allowed entries for phpPgAdmin +if [ "$type" = "pga" ] || [ "$type" = "PGA" ] || [ "$type" = "phppgadmin" ]; then + # Set database editor friendly name + db_editor="phpPgAdmin" + + # Set new alias value + $BIN/v-change-sys-config-value 'DB_PGA_ALIAS' "$alias" + + # Replace old configuration files and update alias + if [ -e "/etc/apache2/conf.d/phppgadmin.inc" ]; then + rm -f /etc/apache2/conf.d/phppgadmin.inc + cp -f $HESTIA_INSTALL_DIR/pga/phppgadmin.conf /etc/apache2/conf.d/phppgadmin.inc + sed -i "s|%pga_alias%|$alias|g" /etc/apache2/conf.d/phppgadmin.inc + + # Restart services + $BIN/v-restart-service apache2 + fi + + if [ -e "/etc/nginx/conf.d/phppgadmin.inc" ]; then + rm -f /etc/nginx/conf.d/phppgadmin.inc + cp -f $HESTIA_INSTALL_DIR/nginx/phppgadmin.inc /etc/nginx/conf.d/phppgadmin.inc + sed -i "s|%pga_alias%|$alias|g" /etc/nginx/conf.d/phppgadmin.inc + + # Restart services + $BIN/v-restart-service nginx + fi +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +$BIN/v-log-action "system" "Info" "System" "System access alias changed (Tool: $db_editor, Alias: $alias)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-change-sys-demo-mode b/bin/v-change-sys-demo-mode new file mode 100755 index 0000000..293d0f8 --- /dev/null +++ b/bin/v-change-sys-demo-mode @@ -0,0 +1,68 @@ +#!/bin/bash +# info: enable or disable demo mode +# options: ACTIVE +# +# This function will set the demo mode variable, +# which will prevent usage of certain v-scripts in the backend +# and prevent modification of objects in the control panel. +# It will also disable virtual hosts for Apache and NGINX +# for domains which have been created. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +active=$1 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'ACTIVE' +is_format_valid 'active' + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +if [ "$active" = "yes" ]; then + #TO-DO: Instructions for disabling vhosts + # Disable API for Demo server + $BIN/v-change-sys-api 'disable' + $BIN/v-change-sys-config-value 'DEMO_MODE' 'yes' +elif [ "$active" = "no" ]; then + # Note even v-change-sys-demo-mode can be called v-change-sys-config-value is protected to disable demo mode call + # Use sed -i "s|^DEMO_MODE=.*'|DEMO_MODE='no'|g" $HESTIA/conf/hestia.conf + #TODO: Instructions for enabling vhosts + $BIN/v-change-sys-config-value 'DEMO_MODE' 'no' +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Restarting web server +$BIN/v-restart-web "yes" +check_result $? "restart" > /dev/null 2>&1 + +$BIN/v-restart-proxy "yes" +check_result $? "restart" > /dev/null 2>&1 + +# Logging +if [ "$active" = "yes" ]; then + $BIN/v-log-action "system" "Warning" "System" "Demonstration mode (restricted access) enabled." +else + $BIN/v-log-action "system" "Warning" "Info" "Demonstration mode (restricted access) disabled." +fi + +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-change-sys-hestia-ssl b/bin/v-change-sys-hestia-ssl new file mode 100755 index 0000000..07e1608 --- /dev/null +++ b/bin/v-change-sys-hestia-ssl @@ -0,0 +1,76 @@ +#!/bin/bash +# info: change hestia ssl certificate +# options: SSL_DIR [RESTART] +# +# example: v-change-sys-hestia-ssl /home/new/dir/path yes +# +# This function changes hestia SSL certificate and the key. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +domain='certificate' +ssl_dir=$1 +restart=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'SSL_DIR [RESTART]' +is_format_valid 'ssl_dir' + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Checking new certificate +certificate=$(cat $ssl_dir/$domain.crt | grep -n END) +certificate_count=$(echo "$certificate" | wc -l) +if [ "$certificate_count" -gt 1 ]; then + crt_end=$(echo "$certificate" | head -n1 | cut -f 1 -d :) + crt_lines=$(wc -l $ssl_dir/$domain.crt | cut -f1 -d ' ') + pem_begin=$((crt_lines - crt_end)) + mv $ssl_dir/$domain.crt $ssl_dir/$domain.crt_full + head -n $crt_end $ssl_dir/$domain.crt_full > $ssl_dir/$domain.crt + tail -n $pem_begin $ssl_dir/$domain.crt_full > $ssl_dir/$domain.ca + is_web_domain_cert_valid + mv -f $ssl_dir/$domain.crt_full $ssl_dir/$domain.crt + rm -f $ssl_dir/$domain.ca +else + is_web_domain_cert_valid +fi + +# Adding new certificate +cp -f $ssl_dir/certificate.crt $HESTIA/ssl/certificate.crt +cp -f $ssl_dir/certificate.key $HESTIA/ssl/certificate.key + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Restarting web server +if [ "$restart" != 'no' ]; then + kill -HUP $(cat /run/hestia-nginx.pid) + $BIN/v-restart-mail "$restart" +fi + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-change-sys-hostname b/bin/v-change-sys-hostname new file mode 100755 index 0000000..1c62323 --- /dev/null +++ b/bin/v-change-sys-hostname @@ -0,0 +1,79 @@ +#!/bin/bash +# info: change hostname +# options: HOSTNAME +# +# example: v-change-sys-hostname mydomain.tld +# +# This function for changing system hostname. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +domain=$1 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'HOSTNAME' +is_format_valid 'domain' + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +hostname "$domain" + +if [ -d "/etc/sysconfig" ]; then + # RHEL/CentOS/Amazon + touch /etc/sysconfig/network + if [ -z "$(grep HOSTNAME /etc/sysconfig/network)" ]; then + echo "HOSTNAME='$domain'" >> /etc/sysconfig/network + else + sed -i "s/HOSTNAME=.*/HOSTNAME='$domain'/" /etc/sysconfig/network + fi +else + # Debian/Ubuntu + hostnamectl set-hostname "$domain" + echo "$domain" > /etc/hostname +fi + +# Update Roundcube password plugin configuration +if [ -d /etc/roundcube/ ]; then + sed -i "/password_hestia_host/c\$rcmail_config['password_hestia_host'] = '$domain';" /etc/roundcube/plugins/password/config.inc.php +fi +if [ -d /etc/rainloop/ ]; then + sed -i "/hestia_host/c\hestia_host = \"$domain\"" /etc/rainloop/data/_data_/_default_/configs/plugin-hestia-change-password.ini +fi +if [ -d /etc/snappymail/ ]; then + sed -i "/\"hestia_host\":/c\\\"hestia_host\": \"$domain\"," /etc/snappymail/data/_data_/_default_/configs/plugin-change-password.json +fi + +if [ -f /etc/hosts ]; then + if ! cat /etc/hosts | grep $domain > /dev/null; then + echo "127.0.0.1 $domain" >> /etc/hosts + fi +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +$BIN/v-log-action "system" "Warning" "System" "System hostname changed (Host: $domain)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-change-sys-ip-name b/bin/v-change-sys-ip-name new file mode 100755 index 0000000..c08a454 --- /dev/null +++ b/bin/v-change-sys-ip-name @@ -0,0 +1,54 @@ +#!/bin/bash +# info: change IP name +# options: IP NAME +# +# example: v-change-sys-ip-name 203.0.113.1 acme.com +# +# This function for changing dns domain associated with IP. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +ip="$1" +ip_name="$2" + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/ip.sh +source $HESTIA/func/ip.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'IP IP_NAME' +is_format_valid 'ip' +is_format_valid 'ip_name' +is_ip_valid "$ip" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Changing IP name +update_ip_value '$NAME' "$ip_name" + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +$BIN/v-log-action "system" "Info" "System" "Changed associated DNS on $ip to $ip_name." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-change-sys-ip-nat b/bin/v-change-sys-ip-nat new file mode 100755 index 0000000..94a933d --- /dev/null +++ b/bin/v-change-sys-ip-nat @@ -0,0 +1,119 @@ +#!/bin/bash +# info: change NAT IP address +# options: IP NAT_IP [RESTART] +# +# example: v-change-sys-ip-nat 10.0.0.1 203.0.113.1 +# +# This function for changing NAT IP associated with IP. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +ip="$1" +nat_ip="$2" +restart="$3" + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/ip.sh +source $HESTIA/func/ip.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'IP NAT_IP [RESTART]' +is_format_valid 'ip' +is_format_valid 'nat_ip' +is_ip_valid "$ip" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Updating IP +if [ -z "$(grep NAT= $HESTIA/data/ips/$ip)" ]; then + sed -i "s/^TIME/NAT='$nat_ip'\nTIME/g" $HESTIA/data/ips/$ip + old='' + new="$nat_ip" +else + old="$(get_ip_value '$NAT')" + new="$nat_ip" + sed -i "s/NAT=.*/NAT='$new'/" $HESTIA/data/ips/$ip + if [ -z "$nat_ip" ]; then + new="$ip" + fi +fi + +# Updating WEB configs +if [ -n "$old" ] && [ -n "$WEB_SYSTEM" ]; then + for user in $($BIN/v-list-sys-users plain); do + sed -i "s/$old/$new/" $HESTIA/data/users/$user/web.conf + $BIN/v-rebuild-web-domains "$user" no + done + $BIN/v-restart-dns "$restart" +fi + +# Updating DNS configs +if [ -n "$old" ] && [ -n "$DNS_SYSTEM" ]; then + for user in $($BIN/v-list-sys-users plain); do + sed -i "s/$old/$new/" "$HESTIA/data/users/$user/dns.conf" + if ls $HESTIA/data/users/$user/dns/*.conf > /dev/null 2>&1; then + sed -i "s/$old/$new/" $HESTIA/data/users/$user/dns/*.conf + fi + $BIN/v-rebuild-dns-domains "$user" no + done + $BIN/v-restart-dns "$restart" +fi + +# Updating FTP +if [ -n "$old" ] && [ -n "$FTP_SYSTEM" ]; then + ftp_conf="$(find /etc -maxdepth 2 -name "$FTP_SYSTEM.conf")" + if [ -e "$ftp_conf" ]; then + sed -i "s/$old/$new/g" "$ftp_conf" + if [ "$FTP_SYSTEM" = 'vsftpd' ]; then + check_pasv="$(grep pasv_address "$ftp_conf")" + if [ -z "$check_pasv" ] && [ -n "$nat_ip" ]; then + echo "pasv_address=$nat_ip" >> "$ftp_conf" + fi + if [ -n "$check_pasv" ] && [ -z "$nat_ip" ]; then + sed -i "/pasv_address/d" "$ftp_conf" + fi + if [ -n "$check_pasv" ] && [ -n "$nat_ip" ]; then + sed -i "s/pasv_address=.*/pasv_address='$nat_ip'/g" "$ftp_conf" + fi + fi + fi + if [ "$FTP_SYSTEM" = 'proftpd' ]; then + ext_ip_conf="/etc/$FTP_SYSTEM/conf.d/external_ip.conf" + content="MasqueradeAddress ${nat_ip}" + echo "$content" > "$ext_ip_conf" + fi + $BIN/v-restart-ftp "$restart" +fi + +# Updating firewall +if [ -n "$old" ] && [ -n "$FIREWALL_SYSTEM" ]; then + sed -i "s/$old/$new/g" $HESTIA/data/firewall/*.conf + $BIN/v-update-firewall +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +$BIN/v-log-action "system" "Info" "System" "IP NAT address changed (IP: $ip, NAT IP: $nat_ip)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-change-sys-ip-owner b/bin/v-change-sys-ip-owner new file mode 100755 index 0000000..bf95b4a --- /dev/null +++ b/bin/v-change-sys-ip-owner @@ -0,0 +1,94 @@ +#!/bin/bash +# info: change IP owner +# options: IP USER +# +# example: v-change-sys-ip-owner 203.0.113.1 admin +# +# This function of changing IP address ownership. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +ip="$1" +user="$2" + +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/ip.sh +source $HESTIA/func/ip.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'IP USER' +is_format_valid 'ip' 'user' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_ip_valid "$ip" +is_ip_key_empty '$U_WEB_DOMAINS' +is_ip_key_empty '$U_SYS_USERS' + +ip_status="$(get_ip_value '$STATUS')" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Changing IP owner +ip_owner=$(get_ip_value '$OWNER') +if [ "$ip_owner" != "$user" ]; then + update_ip_value '$OWNER' "$user" + decrease_user_value "$ip_owner" '$IP_OWNED' + if [ "$ip_owner" = 'admin' ]; then + if [ "$ip_status" = 'shared' ]; then + for hestia_user in $($BIN/v-list-sys-users plain); do + decrease_user_value "$hestia_user" '$IP_AVAIL' + done + else + decrease_user_value 'admin' '$IP_AVAIL' + fi + else + decrease_user_value "$ip_owner" '$IP_AVAIL' + decrease_user_value 'admin' '$IP_AVAIL' + fi + + increase_user_value "$user" '$IP_OWNED' + if [ "$user" = 'admin' ]; then + if [ "$ip_status" = 'shared' ]; then + for hestia_user in $($BIN/v-list-sys-users plain); do + increase_user_value "$hestia_user" '$IP_AVAIL' + done + else + increase_user_value 'admin' '$IP_AVAIL' + fi + else + increase_user_value "$user" '$IP_AVAIL' + increase_user_value 'admin' '$IP_AVAIL' + fi +fi + +# Set status to dedicated if owner is not admin +ip_status="$(get_ip_value '$STATUS')" +if [ "$user" != 'admin' ] && [ "$ip_status" = 'shared' ]; then + $BIN/v-change-sys-ip-status "$ip" 'dedicated' +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +$BIN/v-log-action "system" "Info" "System" "IP address owner changed (IP: $ip, Owner: $user)" +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-change-sys-ip-status b/bin/v-change-sys-ip-status new file mode 100755 index 0000000..86c26d3 --- /dev/null +++ b/bin/v-change-sys-ip-status @@ -0,0 +1,65 @@ +#!/bin/bash +# info: change IP status +# options: IP IP_STATUS +# +# example: v-change-sys-ip-status 203.0.113.1 yourstatus +# +# This function of changing an IP address's status. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +ip="$1" +ip_status="$2" + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/ip.sh +source $HESTIA/func/ip.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'IP IP_STATUS' +is_format_valid 'ip' 'ip_status' +is_ip_valid "$ip" +if [ "$ip_status" = "$(get_ip_value '$STATUS')" ]; then + check_result "$E_EXISTS" "status $ip_status is already set" +fi +web_domains=$(get_ip_value '$U_WEB_DOMAINS') +sys_user=$(get_ip_value '$U_SYS_USERS') +ip_owner=$(get_ip_value '$OWNER') +if [ "$web_domains" -ne '0' ] && [ "$sys_user" != "$ip_owner" ]; then + check_result "$E_INUSE" "IP $ip is used" +fi +if [ "$ip_owner" != "admin" ] && [ "$ip_status" = "shared" ]; then + $BIN/v-change-sys-ip-owner "$ip" "admin" +fi + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Changing IP status +update_ip_value '$STATUS' "$ip_status" + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +$BIN/v-log-action "system" "Info" "System" "IP address status changed (Status: $ip_status, IP: $ip)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-change-sys-language b/bin/v-change-sys-language new file mode 100755 index 0000000..165db97 --- /dev/null +++ b/bin/v-change-sys-language @@ -0,0 +1,78 @@ +#!/bin/bash +# info: change sys language +# options: LANGUAGE [UPDATE_USERS] +# +# example: v-change-sys-language ru +# +# This function for changing system language. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +language=$1 +update_users=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +is_language_valid() { + # English is always allowed + if [ "$1" != "en" ]; then + if ! [[ "$1" =~ ^[[:alnum:]_-]+$ ]]; then + echo "Error: language $1 is not valid" + log_event "$E_INVALID" "$ARGUMENTS" + exit $E_INVALID + fi + if [ ! -d "$HESTIA/web/locale/$1" ]; then + echo "Error: language $1 doesn't exist" + log_event "$E_NOTEXIST" "$ARGUMENTS" + exit $E_NOTEXIST + fi + fi +} + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'LANGUAGE [UPDATE_USERS]' +is_format_valid 'language' +is_language_valid "$language" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Change language +if [ -z "$(grep LANGUAGE $HESTIA/conf/hestia.conf)" ]; then + echo "LANGUAGE='$language'" >> $HESTIA/conf/hestia.conf +else + sed -i "s/LANGUAGE=.*/LANGUAGE='$language'/g" $HESTIA/conf/hestia.conf +fi + +# Update language for all existing users if specified +if [ "$update_users" = "yes" ]; then + for user in $($BIN/v-list-sys-users plain); do + $BIN/v-change-user-language "$user" "$language" + done +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +$BIN/v-log-action "system" "Info" "System" "System language changed (Language: $language)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-change-sys-php b/bin/v-change-sys-php new file mode 100755 index 0000000..acfaae0 --- /dev/null +++ b/bin/v-change-sys-php @@ -0,0 +1,67 @@ +#!/bin/bash +# info: Change default php version server wide +# options: VERSION + +# example: v-change-sys-php 8.0 + +version=$1 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +check_args '1' "$#" 'VERSION' + +# Verify php version format +if [[ ! $version =~ ^[0-9]\.[0-9]+ ]]; then + echo "The specified PHP version format is invalid, it should look like [0-9].[0-9]." + echo "Example: 7.0, 7.4, 8.0" + exit "$E_INVALID" +fi + +# Check if php version exists +version_check=$($BIN/v-list-sys-php plain | grep "$version") +if [ -z "$version_check" ]; then + echo "ERROR: Specified PHP version is not installed." + exit "$E_INVALID" +fi + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Set file locations +php_fpm="/etc/init.d/php$version-fpm" + +rm -f /etc/php/*/fpm/pool.d/www.conf +cp -f $HESTIA/install/deb/php-fpm/www.conf /etc/php/$version/fpm/pool.d/www.conf + +for user in $($BIN/v-list-sys-users plain); do + $BIN/v-rebuild-web-domains "$user" 'no' > /dev/null 2>&1 + $BIN/v-rebuild-mail-domains "$user" 'no' > /dev/null 2>&1 +done + +# Reload "current" php version before reload everthing +$BIN/v-restart-web-backend '' $(multiphp_default_version) +$BIN/v-restart-web-backend +$BIN/v-restart-web +$BIN/v-restart-proxy + +update-alternatives --set php /usr/bin/php$version + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +log_event "$OK" "$ARGUMENTS" diff --git a/bin/v-change-sys-port b/bin/v-change-sys-port new file mode 100755 index 0000000..903f16b --- /dev/null +++ b/bin/v-change-sys-port @@ -0,0 +1,107 @@ +#!/bin/bash +# info: change system backend port +# options: PORT +# +# example: v-change-sys-port 5678 +# +# This function for changing the system backend port in NGINX configuration. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +PORT=$1 +NGINX_CONFIG="$HESTIA/nginx/conf/nginx.conf" + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Functions +is_port_valid() { + # Check if PORT is numeric + if [[ ! "$PORT" =~ ^[0-9]+$ ]]; then + echo "Port should contains a numeric value only!" + log_event "$E_INVALID" "$ARGUMENTS" + exit "$E_INVALID" + fi + + # Check if PORT is already used + BUSY_PORT=$(lsof -i:"$PORT") + if [ -n "$BUSY_PORT" ] && [ "$PORT" != "$BACKEND_PORT" ]; then + echo "Port is already used by Hestia, please set anotherone!" + log_event "$E_INUSE" "$ARGUMENTS" + exit "$E_INUSE" + fi +} + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'PORT' +is_port_valid + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Get original port +LISTEN_ROWS=$(cat ${NGINX_CONFIG} | grep -c "listen") +ORIGINAL_PORT=$(cat ${NGINX_CONFIG} | grep -m1 "listen" | sed 's/[^0-9]*//g') + +# Check if port is different to nginx.conf +if [ "$ORIGINAL_PORT" = "$PORT" ]; then + # Nothing to do, exit + exit +else + # Set new port in config via v-change-sys-config-value + $BIN/v-change-sys-config-value "BACKEND_PORT" "$PORT" + # Replace port in config files. + sed -i "s/\(listen[ \t]*.*[: \t]\)[0-9][0-9]*\([^0-9]*ssl\;$\)/\1$PORT\2/" ${NGINX_CONFIG} + if [ -d /etc/roundcube/ ]; then + sed -i "/password_hestia_port/c\$rcmail_config['password_hestia_port'] = '$PORT';" /etc/roundcube/plugins/password/config.inc.php + fi + if [ -d /etc/snappymail/ ]; then + sed -i "/\"hestia_port\":/c\\\"hestia_host\": $PORT" /etc/snappymail/data/_data_/_default_/configs/plugin-change-password.json + fi + + if [ -f "$HESTIA/data/firewall/rules.conf" ]; then + sed -i "/COMMENT='HESTIA'/c\RULE='2' ACTION='ACCEPT' PROTOCOL='TCP' PORT='$PORT' IP='0.0.0.0/0' COMMENT='HESTIA' SUSPENDED='no' TIME='07:40:16' DATE='2014-05-25'" $HESTIA/data/firewall/rules.conf + fi + + if [ -f $HESTIA/data/firewall/chains.conf ]; then + sed -i "/CHAIN='HESTIA'/c\CHAIN='HESTIA' PORT='$PORT' PROTOCOL='TCP'" $HESTIA/data/firewall/chains.conf + fi + + # Restart services + if [ -n "$FIREWALL_SYSTEM" ] && [ "$FIREWALL_SYSTEM" != no ]; then + $BIN/v-restart-service iptables + fi + + # Check if Hestia is running + if [[ $(ps -eaf | grep -i hestia | sed '/^$/d' | wc -l) -gt 1 ]]; then + $BIN/v-restart-service hestia + fi +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +$BIN/v-log-action "system" "Warning" "System" "Hestia Control Panel backend port changed (New Value: $PORT, Old Value: $ORIGINAL_PORT)." +if [ $LISTEN_ROWS -gt 1 ]; then + $BIN/v-log-action "system" "Warning" "System" "Hestia Control Panel backend port: Use first of $LISTEN_ROWS listened ports in ${NGINX_CONFIG}" +fi +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-change-sys-release b/bin/v-change-sys-release new file mode 100755 index 0000000..b2ea28c --- /dev/null +++ b/bin/v-change-sys-release @@ -0,0 +1,71 @@ +#!/bin/bash +# info: update web templates +# options: [RESTART] +# +# This function for changing the release branch for the +# Hestia Control Panel. This allows the user to switch between +# stable and pre-release builds which will automaticlly update +# based on the appropriate release schedule if auto-update is +# turned on. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +branch=$1 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# +if [ -z "$branch" ]; then + echo "Error: no release branch specified." + echo "Usage: v-change-sys-release branchname" + echo "" + echo "Release branches:" + echo "- release: the latest stable release" + echo "- beta: beta and release candidate test releases" + echo "- main: work-in-progress code for the next release" + echo "" + echo "You can also specify another branch name from the" + echo "GitHub repository to install the code from that branch." + echo "" + exit +else + # Check that requested branch exists + echo "Checking for existence of $branch branch..." + branch_check=$(curl -s --head -w %{http_code} "https://raw.githubusercontent.com/hestiacp/hestiacp/$branch/src/deb/hestia/control" -o /dev/null) + if [ "$branch_check" -ne "200" ]; then + echo "Error: invalid branch name specified." + exit 1 + fi + + # Remove old branch variable + sed -i "/RELEASE_BRANCH/d" $HESTIA/conf/hestia.conf + + # Set new branch variable + echo "RELEASE_BRANCH='$branch'" >> $HESTIA/conf/hestia.conf + echo "Updated system to update from Git using branch: $branch" +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +$BIN/v-log-action "system" "Info" "System" "Update branch changed (Value: $branch)." +exit diff --git a/bin/v-change-sys-service-config b/bin/v-change-sys-service-config new file mode 100755 index 0000000..7c878f7 --- /dev/null +++ b/bin/v-change-sys-service-config @@ -0,0 +1,129 @@ +#!/bin/bash +# info: change service config +# options: CONFIG SERVICE [RESTART] +# +# example: v-change-sys-service-config /home/admin/dovecot.conf dovecot yes +# +# This function for changing service confguration. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +src=$1 +service=$2 +restart=$3 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'CONFIG SERVICE [RESTART]' +is_format_valid 'service' 'restart' + +if [ ! -e "$src" ]; then + check_result "$E_NOTEXIST" "$src config doesn't exist" +fi + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Defining dst config path +case $service in + nginx) dst='/etc/nginx/nginx.conf' ;; + httpd) dst='/etc/httpd/conf/httpd.conf' ;; + apache2) dst='/etc/apache2/apache2.conf' ;; + exim) dst='/etc/exim/exim.conf' ;; + exim4) dst='/etc/exim4/exim4.conf.template' ;; + vsftpd) dst=$(find /etc/vsftpd* -name 'vsftpd.conf') ;; + proftpd) dst=$(find /etc/proftpd* -name 'proftpd.conf') ;; + php) dst=$(find /etc/php* -name php.ini) ;; + mysql) dst=$(find /etc/my* -name my.cnf) ;; + mysqld) dst=$(find /etc/my* -name my.cnf) ;; + mariadb) dst=$(find /etc/my* -name my.cnf) ;; + postgresql) dst=$($BIN/v-list-sys-pgsql-config plain | cut -f 1) ;; + postgresql-hba) dst=$($BIN/v-list-sys-pgsql-config plain | cut -f 2) ;; + dovecot) dst=$(find /etc/dovecot* -name dovecot.conf) ;; + dovecot-1) dst='/etc/dovecot/conf.d/10-auth.conf' ;; + dovecot-2) dst='/etc/dovecot/conf.d/10-logging.conf' ;; + dovecot-3) dst='/etc/dovecot/conf.d/10-mail.conf' ;; + dovecot-4) dst='/etc/dovecot/conf.d/10-master.conf' ;; + dovecot-5) dst='/etc/dovecot/conf.d/10-ssl.conf' ;; + dovecot-6) dst='/etc/dovecot/conf.d/20-imap.conf' ;; + dovecot-7) dst='/etc/dovecot/conf.d/20-pop3.conf' ;; + dovecot-8) dst='/etc/dovecot/conf.d/auth-passwdfile.conf.ext' ;; + named) dst='/etc/named.conf' ;; + bind9) dst='/etc/bind/named.conf' ;; + bind9-opt) dst='/etc/bind/named.conf.options' ;; + spamd) dst=$($BIN/v-list-sys-spamd-config plain) ;; + spamassassin) dst=$($BIN/v-list-sys-spamd-config plain) ;; + clamd) dst=$($BIN/v-list-sys-clamd-config plain) ;; + fail2ban) dst='/etc/fail2ban/jail.local' ;; + ssh) dst='/etc/ssh/sshd_config' ;; + *) check_result $E_NOTEXIST "service $service doesn't exist" ;; +esac + +# Checking config path +for config in $dst; do + if [ ! -e "$config" ]; then + check_result "$E_NOTEXIST" "$service config doesn't exist" + fi +done + +# Checking diff between src and dst configs +for config in $dst; do + diff -q "$src" "$config" > /dev/null + + if [ $? -ne 0 ]; then + cp "$config" "$config.vst.back" + cp "$src" "$config" + update="yes" + fi +done + +# Restarting service +if [ "$update" = 'yes' ] && [ "$restart" != 'no' ]; then + if [[ "$service" =~ - ]]; then + service=$(echo ${service%-*}) + fi + + if [ "$service" = 'php' ]; then + if [ "$(multiphp_count)" -gt 0 ]; then + service="php-fpm" + elif [ "$WEB_SYSTEM" = 'apache2' ]; then + service="$WEB_SYSTEM" + fi + fi + + $BIN/v-restart-service "$service" > /dev/null 2>&1 + + if [ $? -ne 0 ]; then + for config in $dst; do + cat "$config.vst.back" > "$config" + rm -f "$config.vst.back" + done + check_result "$E_RESTART" "ERROR: $service failed to start with new configuration." + fi +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-change-sys-timezone b/bin/v-change-sys-timezone new file mode 100755 index 0000000..957898c --- /dev/null +++ b/bin/v-change-sys-timezone @@ -0,0 +1,78 @@ +#!/bin/bash +# info: change system timezone +# options: TIMEZONE +# +# example: v-change-sys-timezone Europe/Berlin +# +# This function for changing system timezone. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +timezone=$1 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +is_timezone_valid() { + if [ ! -e "/usr/share/zoneinfo/$timezone" ]; then + echo "Error: tz file $timezone doesn't exist" + log_event "$E_NOTEXIST" "$ARGUMENTS" + exit "$E_NOTEXIST" + fi +} + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'TIMEZONE' +is_timezone_valid + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Changing system timezone +which timedatectls > /dev/null 2>&1 +if [ "$?" -eq 0 ]; then + timedatectl set-timezone "$timezone" +else + if [ -e "/etc/sysconfig/clock" ]; then + sed -i "s/ZONE.*//" /etc/sysconfig/clock + echo "ZONE=\"$timezone\"" >> /etc/sysconfig/clock + fi + if [ -e "/etc/timezone" ]; then + echo "$timezone" > /etc/timezone + fi + rm -f /etc/localtime + ln -sf /usr/share/zoneinfo/$timezone /etc/localtime +fi + +# Chaning php timezone +if [ -n "$WEB_SYSTEM" ]; then + for conf in $(find /etc/php* -name php.ini); do + sed -i "s|;date.timezone =|date.timezone =|" $conf + sed -i "s|date.timezone =.*|date.timezone = $timezone|" $conf + done +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +$BIN/v-log-action "system" "Info" "System" "System time zone changed (Value: $timezone)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-change-sys-webmail b/bin/v-change-sys-webmail new file mode 100755 index 0000000..1a1cd92 --- /dev/null +++ b/bin/v-change-sys-webmail @@ -0,0 +1,70 @@ +#!/bin/bash +# info: change webmail alias url +# options: WEBMAIL +# +# example: v-change-sys-webmail YourtrickyURLhere +# +# This function changes the webmail url in apache2 or nginx configuration. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Get existing system webmail alias +export WEBMAIL_ALIAS="$WEBMAIL_ALIAS" + +# Define aliases +OLD_ALIAS=$WEBMAIL_ALIAS +NEW_ALIAS=$1 + +restart=${2-yes} + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Delete old webmail configuration +for user in $($BIN/v-list-sys-users plain); do + for domain in $($BIN/v-list-mail-domains "$user" plain | cut -f 1); do + $BIN/v-delete-mail-domain-webmail "$user" "$domain" + done +done + +# Set new webmail alias +$BIN/v-change-sys-config-value 'WEBMAIL_ALIAS' $NEW_ALIAS + +# Add new webmail configuration +for user in $($BIN/v-list-sys-users plain); do + for domain in $($BIN/v-list-mail-domains "$user" plain | cut -f 1); do + $BIN/v-add-mail-domain-webmail "$user" "$domain" + done +done + +if [ -d /etc/apache2/ ]; then + sed -i "s/IncludeOptional conf.d\/domains\/$WEBMAIL_ALIAS.*.conf/IncludeOptional conf.d\/domains\/$NEW_ALIAS.*.conf/g" /etc/apache2/apache2.conf +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Restart services +$BIN/v-restart-web "$restart" +$BIN/v-restart-proxy "$restart" + +# Logging +$BIN/v-log-action "system" "Info" "System" "Webmail access alias changed (Value: $NEW_ALIAS, Previous: $OLD_ALIAS)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-change-user-config-value b/bin/v-change-user-config-value new file mode 100755 index 0000000..60cd5b4 --- /dev/null +++ b/bin/v-change-user-config-value @@ -0,0 +1,54 @@ +#!/bin/bash +# info: changes user configuration value +# options: USER KEY VALUE +# +# example: v-change-user-config-value admin ROLE admin +# +# Changes key/value for specified user. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +key="$2" +value="$3" + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +is_format_valid 'user' 'key' +is_common_format_valid "$value" "$key" +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Set theme value +check_ckey=$(grep "^${key^^}" $USER_DATA/user.conf) +if [ -z "$check_ckey" ]; then + # Rebuild user configuration to repair missing value + $BIN/v-rebuild-user "$user" +fi +update_user_value "$user" "${key^^}" "$value" + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-change-user-contact b/bin/v-change-user-contact new file mode 100755 index 0000000..ec422e4 --- /dev/null +++ b/bin/v-change-user-contact @@ -0,0 +1,59 @@ +#!/bin/bash +# info: change user contact email +# options: USER EMAIL +# +# example: v-change-user-contact admin admin@yahoo.com +# +# This function for changing of e-mail associated with a certain user. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +email=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER EMAIL' +is_format_valid 'user' 'email' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Changing user contact email +old_email=$(get_user_value '$CONTACT') +update_user_value "$user" '$CONTACT' "$email" +pw_str=$(grep -n "^$user:" /etc/passwd) +str=$(echo "$pw_str" | cut -f 1 -d :) +sed -i "$str s/$old_email/$email/g" /etc/passwd + +# Update crontab email +$BIN/v-rebuild-cron-jobs "$user" > /dev/null 2>&1 + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +$BIN/v-log-action "$user" "Info" "System" "Email address changed (Value: $email)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-change-user-language b/bin/v-change-user-language new file mode 100755 index 0000000..b142bad --- /dev/null +++ b/bin/v-change-user-language @@ -0,0 +1,73 @@ +#!/bin/bash +# info: change user language +# options: USER LANGUAGE +# +# example: v-change-user-language admin en +# +# This function for changing language. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +language=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +is_language_valid() { + # English is always allowed + if [ "$1" != "en" ]; then + if ! [[ "$1" =~ ^[[:alnum:]_-]+$ ]]; then + echo "Error: language $1 is not valid" + log_event "$E_INVALID" "$ARGUMENTS" + exit $E_INVALID + fi + if [ ! -d "$HESTIA/web/locale/$1" ]; then + echo "Error: language $1 doesn't exist" + log_event "$E_NOTEXIST" "$ARGUMENTS" + exit $E_NOTEXIST + fi + fi +} + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER LANGUAGE' +is_format_valid 'user' 'language' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_language_valid "$language" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Change language +if [ -z "$(grep LANGUAGE $USER_DATA/user.conf)" ]; then + sed -i "s/^TIME/LANGUAGE='$language'\nTIME/g" $USER_DATA/user.conf +else + update_user_value "$user" '$LANGUAGE' "$language" +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +$BIN/v-log-action "$user" "Info" "System" "Display language changed (Value: $language)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-change-user-name b/bin/v-change-user-name new file mode 100755 index 0000000..efeeded --- /dev/null +++ b/bin/v-change-user-name @@ -0,0 +1,60 @@ +#!/bin/bash +# info: change user full name +# options: USER NAME [LAST_NAME] +# +# example: v-change-user-name admin John Smith +# +# This function allow to change user's full name. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +name=$2 +lname=$3 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER NAME [LAST_NAME]' +is_format_valid 'user' 'name' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +if [ -n "$lname" ]; then + is_common_format_valid "$name $lname" "last name" +fi + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Changing ns values +if [ -n "$lname" ]; then + update_user_value "$user" '$NAME' "$name $lname" +else + update_user_value "$user" '$NAME' "$name" +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +$BIN/v-log-action "$user" "Info" "System" "User display name changed (Value: $name)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-change-user-ns b/bin/v-change-user-ns new file mode 100755 index 0000000..f55d89f --- /dev/null +++ b/bin/v-change-user-ns @@ -0,0 +1,95 @@ +#!/bin/bash +# info: change user name servers +# options: USER NS1 NS2 [NS3] [NS4] [NS5] [NS6] [NS7] [NS8] +# +# example: v-change-user-ns ns1.domain.tld ns2.domain.tld +# +# This function for changing default name servers for specific user. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +ns1=$(echo $2 | sed -e 's/\.*$//g' -e 's/^\.*//g') +ns2=$(echo $3 | sed -e 's/\.*$//g' -e 's/^\.*//g') +ns3=$(echo $4 | sed -e 's/\.*$//g' -e 's/^\.*//g') +ns4=$(echo $5 | sed -e 's/\.*$//g' -e 's/^\.*//g') +ns5=$(echo $6 | sed -e 's/\.*$//g' -e 's/^\.*//g') +ns6=$(echo $7 | sed -e 's/\.*$//g' -e 's/^\.*//g') +ns7=$(echo $8 | sed -e 's/\.*$//g' -e 's/^\.*//g') +ns8=$(echo $9 | sed -e 's/\.*$//g' -e 's/^\.*//g') + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +# Checking args +check_args '3' "$#" 'USER NS1 NS2 [NS3] [NS4] [NS5] [NS6] [NS7] [NS8]' + +# Checking argument format +is_format_valid 'user' 'ns1' 'ns2' + +if [ "$ns1" = '' ]; then + check_result '3' "Usage: v-change-user-ns USER NS1 NS2 [NS3] [NS4] [NS5] [NS6] [NS7] [NS8]" +fi +if [ "$ns2" = '' ]; then + check_result '3' "Usage: v-change-user-ns USER NS1 NS2 [NS3] [NS4] [NS5] [NS6] [NS7] [NS8]" +fi + +ns="$ns1,$ns2" +if [ -n "$ns3" ]; then + is_format_valid 'ns3' + ns="$ns,$ns3" +fi +if [ -n "$ns4" ]; then + is_format_valid 'ns4' + ns="$ns,$ns4" +fi +if [ -n "$ns5" ]; then + is_format_valid 'ns5' + ns="$ns,$ns5" +fi +if [ -n "$ns6" ]; then + is_format_valid 'ns6' + ns="$ns,$ns6" +fi +if [ -n "$ns7" ]; then + is_format_valid 'ns7' + ns="$ns,$ns7" +fi +if [ -n "$ns8" ]; then + is_format_valid 'ns8' + ns="$ns,$ns8" +fi +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Changing ns values +update_user_value "$user" '$NS' "$ns" + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +$BIN/v-log-action "$user" "Info" "DNS" "Updated DNS nameservers ($ns1 $ns2 $ns3 $ns4 $ns5 $ns6 $ns7 $ns8)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-change-user-package b/bin/v-change-user-package new file mode 100755 index 0000000..c77dcd2 --- /dev/null +++ b/bin/v-change-user-package @@ -0,0 +1,195 @@ +#!/bin/bash +# info: change user package +# options: USER PACKAGE [FORCE] +# +# example: v-change-user-package admin yourpackage +# +# This function changes user's hosting package. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +package=$2 +force=$3 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +is_package_available() { + + source_conf "$USER_DATA/user.conf" + + WEB_DOMAINS='0' + DATABASES='0' + MAIL_DOMAINS='0' + DNS_DOMAINS='0' + DISK_QUOTA='0' + BANDWIDTH='0' + + source_conf "$HESTIA/data/packages/$package.pkg" + + # Checking usage agains package limits + if [ "$WEB_DOMAINS" != 'unlimited' ]; then + if [ "$WEB_DOMAINS" -lt "$U_WEB_DOMAINS" ]; then + check_result "$E_LIMIT" "Package doesn't cover WEB_DOMAIN usage" + fi + fi + if [ "$DNS_DOMAINS" != 'unlimited' ]; then + if [ "$DNS_DOMAINS" -lt "$U_DNS_DOMAINS" ]; then + check_result "$E_LIMIT" "Package doesn't cover DNS_DOMAIN usage" + fi + fi + if [ "$MAIL_DOMAINS" != 'unlimited' ]; then + if [ "$MAIL_DOMAINS" -lt "$U_MAIL_DOMAINS" ]; then + check_result "$E_LIMI"T "Package doesn't cover MAIL_DOMAIN usage" + fi + fi + if [ "$DATABASES" != 'unlimited' ]; then + if [ "$DATABASES" -lt "$U_DATABASES" ]; then + check_result "$E_LIMIT" "Package doesn't cover DATABASE usage" + fi + fi + if [ "$CRON_JOBS" != 'unlimited' ]; then + if [ "$CRON_JOBS" -lt "$U_CRON_JOBS" ]; then + check_result "$E_LIMIT" "Package doesn't cover CRON usage" + fi + fi + if [ "$DISK_QUOTA" != 'unlimited' ]; then + if [ "$DISK_QUOTA" -lt "$U_DISK" ]; then + check_result "$E_LIMIT" "Package doesn't cover DISK usage" + fi + fi + if [ "$BANDWIDTH" != 'unlimited' ]; then + if [ "$BANDWIDTH" -lt "$U_BANDWIDTH" ]; then + check_result "$E_LIMIT" "Package doesn't cover BANDWIDTH usage" + fi + fi +} + +change_user_package() { + source_conf "$USER_DATA/user.conf" + # Keep user creation date and time saved + time="$TIME" + date="$DATE" + source_conf "$HESTIA/data/packages/$package.pkg" + echo "NAME='$NAME' +PACKAGE='$package' +WEB_TEMPLATE='$WEB_TEMPLATE' +BACKEND_TEMPLATE='$BACKEND_TEMPLATE' +PROXY_TEMPLATE='$PROXY_TEMPLATE' +DNS_TEMPLATE='$DNS_TEMPLATE' +WEB_DOMAINS='$WEB_DOMAINS' +WEB_ALIASES='$WEB_ALIASES' +DNS_DOMAINS='$DNS_DOMAINS' +DNS_RECORDS='$DNS_RECORDS' +MAIL_DOMAINS='$MAIL_DOMAINS' +MAIL_ACCOUNTS='$MAIL_ACCOUNTS' +RATE_LIMIT='$RATE_LIMIT' +DATABASES='$DATABASES' +CRON_JOBS='$CRON_JOBS' +DISK_QUOTA='$DISK_QUOTA' +BANDWIDTH='$BANDWIDTH' +NS='$NS' +SHELL='$SHELL' +BACKUPS='$BACKUPS' +CONTACT='$CONTACT' +CRON_REPORTS='$CRON_REPORTS' +MD5='$MD5' +RKEY='$RKEY' +TWOFA='$TWOFA' +QRCODE='$QRCODE' +PHPCLI='$PHPCLI' +ROLE='$ROLE' +SUSPENDED='$SUSPENDED' +SUSPENDED_USERS='$SUSPENDED_USERS' +SUSPENDED_WEB='$SUSPENDED_WEB' +SUSPENDED_DNS='$SUSPENDED_DNS' +SUSPENDED_MAIL='$SUSPENDED_MAIL' +SUSPENDED_DB='$SUSPENDED_DB' +SUSPENDED_CRON='$SUSPENDED_CRON' +IP_AVAIL='$IP_AVAIL' +IP_OWNED='$IP_OWNED' +U_USERS='$U_USERS' +U_DISK='$U_DISK' +U_DISK_DIRS='$U_DISK_DIRS' +U_DISK_WEB='$U_DISK_WEB' +U_DISK_MAIL='$U_DISK_MAIL' +U_DISK_DB='$U_DISK_DB' +U_BANDWIDTH='$U_BANDWIDTH' +U_WEB_DOMAINS='$U_WEB_DOMAINS' +U_WEB_SSL='$U_WEB_SSL' +U_WEB_ALIASES='$U_WEB_ALIASES' +U_DNS_DOMAINS='$U_DNS_DOMAINS' +U_DNS_RECORDS='$U_DNS_RECORDS' +U_MAIL_DOMAINS='$U_MAIL_DOMAINS' +U_MAIL_DKIM='$U_MAIL_DKIM' +U_MAIL_ACCOUNTS='$U_MAIL_ACCOUNTS' +U_DATABASES='$U_DATABASES' +U_CRON_JOBS='$U_CRON_JOBS' +U_BACKUPS='$U_BACKUPS' +LANGUAGE='$LANGUAGE' +THEME='$THEME' +NOTIFICATIONS='$NOTIFICATIONS' +PREF_UI_SORT='$PREF_UI_SORT' +LOGIN_DISABLED='$LOGIN_DISABLED' +LOGIN_USE_IPLIST='$LOGIN_USE_IPLIST' +LOGIN_ALLOW_IPS='$LOGIN_ALLOW_IPS' +TIME='$time' +DATE='$date'" > $USER_DATA/user.conf +} + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER PACKAGE [FORCE]' +is_format_valid 'user' 'package' +is_object_valid 'user' 'USER' "$user" +is_package_valid +if [ "$force" != 'yes' ]; then + is_package_available +fi + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Changing user package +change_user_package + +# Update user shell +shell_conf=$(cat "$HESTIA/data/packages/$package.pkg" | grep 'SHELL' | cut -f 2 -d \') +$BIN/v-change-user-shell "$user" "$shell_conf" + +# Run template trigger +if [ -x "$HESTIA/data/packages/$package.sh" ]; then + $HESTIA/data/packages/$package.sh "$user" "$CONTACT" "$NAME" +fi + +# Update disk quota +source $HESTIA/conf/hestia.conf +if [ "$DISK_QUOTA" = 'yes' ]; then + $BIN/v-update-user-quota "$user" +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +$BIN/v-log-action "$user" "Info" "System" "You have been assigned a new package ($package)." +$BIN/v-log-action "system" "Info" "System" "Package limits applied to user (Package: $package, User: $user)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-change-user-password b/bin/v-change-user-password new file mode 100755 index 0000000..ab82989 --- /dev/null +++ b/bin/v-change-user-password @@ -0,0 +1,72 @@ +#!/bin/bash +# info: change user password +# options: USER PASSWORD +# +# example: v-change-user-password admin NewPassword123 +# +# This function changes user's password and updates RKEY value. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +password=$2 +HIDE=2 + +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'USER [PASSWORD]' +is_format_valid 'user' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" + +# Non-interactive (stdin not opened) +[[ -z "$password" && ! -t 0 ]] && read -r password + +# Password prompt +[[ -z "$password" ]] && read -r -s -p "Password:" password + +is_password_valid + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Changing user password +echo "$user:$password" | /usr/sbin/chpasswd + +if [ $? -ne 0 ]; then + echo "Error: Password not accepted due to PAM restrictions" + exit 2 +fi + +md5=$(awk -v user=$user -F : 'user == $1 {print $2}' /etc/shadow) + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Changing RKEY value +update_user_value "$user" '$RKEY' "$(generate_password)" +update_user_value "$user" '$MD5' "$md5" + +# Logging +$BIN/v-log-action "system" "Warning" "Security" "Password changed (User: $user)." +$BIN/v-log-action "$user" "Warning" "Security" "Password changed." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-change-user-php-cli b/bin/v-change-user-php-cli new file mode 100755 index 0000000..b6d150a --- /dev/null +++ b/bin/v-change-user-php-cli @@ -0,0 +1,81 @@ +#!/bin/bash +# info: add php version alias to .bash_aliases +# options: USER VERSION +# +# example: v-change-user-php-cli user 7.4 +# +# add line to .bash_aliases to set default php command line +# version when multi-php is enabled. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +version=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +FILE=$HOMEDIR/$user/.bash_aliases + +check_args '2' "$#" 'USER PHPVERSION' +is_format_valid 'user' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +# Reading user values +source $USER_DATA/user.conf + +versions=$($BIN/v-list-sys-php plain) +support=0 +for v in $versions; do + if [ "$v" == "$version" ]; then + support=1 + fi +done + +if [ "$support" = 0 ]; then + echo "Version is currently not supported or does not exist..." + exit 2 +fi + +# Create .bash_aliases is not exsists +if [ ! -f "$FILE" ]; then + touch $FILE + chown $user:$user $FILE +fi + +if grep -q "alias php='env php$version'" "$FILE"; then + echo "PHP CLI Already defined" + exit +fi + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +sed -i "/alias php='env/d" $FILE +echo "alias php='env php$version'" >> $FILE +update_user_value "$user" '$PHPCLI' "$version" + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +$BIN/v-log-action "system" "Info" "Users" "Default PHP CLI version changed (User: $user, Version: $version)." + +exit diff --git a/bin/v-change-user-rkey b/bin/v-change-user-rkey new file mode 100755 index 0000000..f4e20ca --- /dev/null +++ b/bin/v-change-user-rkey @@ -0,0 +1,67 @@ +#!/bin/bash +# info: change user random key +# options: USER [HASH] +# +# This function changes user's RKEY value thats has been used for security value to be used forgot password function only. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +hash=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'USER [HASH]' +is_format_valid 'user' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +if [ -n "$hash" ]; then + password=$hash + is_password_valid + hash=$password +else + hash=$(generate_password) +fi +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +d=$(date +%s) + +# Changing RKEY value +update_user_value "$user" '$RKEY' "$hash" + +#check if RKEYEXP exists +if [ -z "$(grep RKEYEXP $USER_DATA/user.conf)" ]; then + sed -i "s/^RKEY/RKEYEXP='$d'\nRKEY/g" $USER_DATA/user.conf +else + update_user_value "$user" '$RKEYEXP' "$d" +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +$BIN/v-log-action "system" "Warning" "Users" "Password reset requested (User: $user)." +$BIN/v-log-action "$user" "Warning" "System" "Password reset requested." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-change-user-role b/bin/v-change-user-role new file mode 100755 index 0000000..0f0eb18 --- /dev/null +++ b/bin/v-change-user-role @@ -0,0 +1,49 @@ +#!/bin/bash +# info: updates user role +# options: USER ROLE +# +# example: v-change-user-role user administrator +# +# Give/revoke user administrator rights to manage all accounts as admin + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +role=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +ROLE=$(get_user_value '$ROLE') + +is_format_valid 'user' 'role' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +$BIN/v-log-action "system" "Warning" "Security" "User privileges changed (User: $user, Role: $role, Previous: $ROLE)." +update_user_value "$user" '$ROLE' "$role" + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-change-user-shell b/bin/v-change-user-shell new file mode 100755 index 0000000..3715a47 --- /dev/null +++ b/bin/v-change-user-shell @@ -0,0 +1,66 @@ +#!/bin/bash +# info: change user shell +# options: USER SHELL +# +# example: v-change-user-shell admin nologin +# +# This function changes system shell of a user. Shell gives ability to use ssh. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +shell=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/conf/hestia.conf +source $HESTIA/conf/hestia.conf + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER SHELL' +is_format_valid 'user' 'shell' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Get shell full path +shell_path=$(grep -w "$shell" /etc/shells | head -n1) + +# Changing passwd file +/usr/bin/chsh -s "$shell_path" "$user" > /dev/null 2>&1 +shell=$(basename "$shell_path") + +# Adding jailed sftp env +if [[ "$shell" =~ nologin ]] || [[ "$shell" =~ rssh ]]; then + $BIN/v-add-user-sftp-jail "$user" > /dev/null 2>&1 +else + $BIN/v-delete-user-sftp-jail "$user" > /dev/null 2>&1 +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Changing user shell +update_user_value "$user" '$SHELL' "$shell" + +# Logging +$BIN/v-log-action "system" "Info" "System" "User SSH shell changed (Shell: $shell, User: $user)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-change-user-sort-order b/bin/v-change-user-sort-order new file mode 100755 index 0000000..25f9d9c --- /dev/null +++ b/bin/v-change-user-sort-order @@ -0,0 +1,51 @@ +#!/bin/bash +# info: updates user role +# options: USER SORT_ORDER +# +# example: v-change-user-sort-order user date +# +# Changes web UI display sort order for specified user. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +sort_order=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +is_format_valid 'user' +is_common_format_valid "$sort_order" "sort_order" +is_object_valid 'user' 'USER' "$user" + +is_object_unsuspended 'user' 'USER' "$user" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +$BIN/v-change-user-config-value "$user" 'PREF_UI_SORT' "$sort_order" + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +$BIN/v-log-action "$user" "Warning" "System" "Change user setting ($key)" + +exit diff --git a/bin/v-change-user-template b/bin/v-change-user-template new file mode 100755 index 0000000..cbc0c40 --- /dev/null +++ b/bin/v-change-user-template @@ -0,0 +1,72 @@ +#!/bin/bash +# info: change user default template +# options: USER TYPE TEMPLATE +# +# example: v-change-user-template admin WEB wordpress +# +# This function changes default user web template. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +type=$(echo "$2" | tr '[:lower:]' '[:upper:]') +template=$3 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '3' "$#" 'USER TYPE TEMPLATE' +is_format_valid 'user' 'template' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +case $type in + WEB) + is_web_template_valid "$template" + update_user_value "$user" '$WEB_TEMPLATE' "$template" + ;; + PROXY) + is_proxy_template_valid "$template" + update_user_value "$user" '$PROXY_TEMPLATE' "$template" + ;; + BACKEND) + is_backend_template_valid "$template" + update_user_value "$user" '$BACKEND_TEMPLATE' "$template" + ;; + DNS) + is_dns_template_valid "$template" + update_user_value "$user" '$DNS_TEMPLATE' "$template" + ;; + *) check_args '1' '0' 'USER TYPE TEMPLATE' ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +$BIN/v-log-action "$user" "Info" "Web" "Default domain template changed (Type: $type, Template: $template)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-change-user-theme b/bin/v-change-user-theme new file mode 100755 index 0000000..d7f372f --- /dev/null +++ b/bin/v-change-user-theme @@ -0,0 +1,66 @@ +#!/bin/bash +# info: updates user theme +# options: USER THEME +# +# example: v-change-user-theme admin dark +# example: v-change-user-theme peter vestia +# +# Changes web UI display theme for specified user. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +theme=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/conf/hestia.conf +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +is_format_valid 'user' 'theme' +is_common_format_valid "$theme" "theme" +is_object_valid 'user' 'USER' "$user" + +is_object_unsuspended 'user' 'USER' "$user" + +themes=$($BIN/v-list-sys-themes plain) + +if ! echo "$themes" | grep -q -x "$theme"; then + echo "Theme does not exists" + exit "$E_NOTEXIST" +fi + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Set theme value +check_ckey=$(grep "THEME" $USER_DATA/user.conf) +if [ -z "$check_ckey" ]; then + # Rebuild user configuration to repair missing value + $BIN/v-rebuild-user "$user" +fi +update_user_value "$user" '$THEME' "$theme" + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +$BIN/v-log-action "$user" "Info" "System" "Applied theme to user interface (Theme: $theme)." + +exit diff --git a/bin/v-change-web-domain-backend-tpl b/bin/v-change-web-domain-backend-tpl new file mode 100755 index 0000000..2e021be --- /dev/null +++ b/bin/v-change-web-domain-backend-tpl @@ -0,0 +1,186 @@ +#!/bin/bash +# info: change web domain backend template +# options: USER DOMAIN TEMPLATE [RESTART] +# +# example: v-change-web-domain-backend-tpl admin acme.com PHP-7_4 +# +# This function changes backend template + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 +template=$3 +restart=$4 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# shellcheck source=/usr/local/hestia/func/ip.sh +source $HESTIA/func/ip.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '3' "$#" 'USER DOMAIN TEMPLATE [RESTART]' +is_format_valid 'user' 'domain' 'template' +is_system_enabled "$WEB_BACKEND" 'WEB_BACKEND' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'web' 'DOMAIN' "$domain" +is_object_unsuspended 'web' 'DOMAIN' "$domain" +is_backend_template_valid "$template" +get_domain_values 'web' + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Prepare new backend configuration +prepare_web_backend + +# Deleting current backend +delete_web_backend + +# Allocating backend port +backend_port=9000 +ports=$(grep -v '^;' $pool/* 2> /dev/null | grep listen | grep -o :[0-9].*) +ports=$(echo "$ports" | sed "s/://" | sort -n) +for port in $ports; do + if [ "$backend_port" -eq "$port" ]; then + backend_port=$((backend_port + 1)) + fi +done + +# Changing backend config +cat $WEBTPL/$WEB_BACKEND/$template.tpl \ + | sed -e "s|%backend_port%|$backend_port|" \ + -e "s|%user%|$user|g" \ + -e "s|%domain%|$domain|g" \ + -e "s|%domain_idn%|$domain_idn|" \ + -e "s|%backend%|$backend_type|g" \ + -e "s|%backend_version%|$backend_version|g" > $pool/$backend_type.conf + +# Set correct document root path +if [ -n "$CUSTOM_DOCROOT" ]; then + docroot="$CUSTOM_DOCROOT" + sed -i "s|/home\/$user\/web\/$domain\/public_html|$docroot|g" $pool/$backend_type.conf +fi + +# Checking backend pool configuration +if [[ "$backend_type" = "$user" && $WEB_BACKEND_POOL = 'user' ]]; then + conf=$USER_DATA/web.conf + fields='$DOMAIN' + nohead=1 + + for domain in $(shell_list); do + get_domain_values 'web' + local_ip=$(get_real_ip "$IP") + prepare_web_domain_values + + # Rebuilding vhost + del_web_config "$WEB_SYSTEM" "$TPL.tpl" + add_web_config "$WEB_SYSTEM" "$TPL.tpl" + if [ "$SSL" = 'yes' ]; then + del_web_config "$WEB_SYSTEM" "$TPL.stpl" + add_web_config "$WEB_SYSTEM" "$TPL.stpl" + fi + + # Rebuilding proxy configuration + if [ -n "$PROXY_SYSTEM" ] && [ ! -z "$PROXY" ]; then + del_web_config "$PROXY_SYSTEM" "$PROXY.tpl" + add_web_config "$PROXY_SYSTEM" "$PROXY.tpl" + if [ "$SSL" = 'yes' ]; then + del_web_config "$PROXY_SYSTEM" "$PROXY.stpl" + add_web_config "$PROXY_SYSTEM" "$PROXY.stpl" + fi + fi + + # Update config + add_object_key "web" 'DOMAIN' "$domain" 'BACKEND' 'PROXY' + update_object_value 'web' 'DOMAIN' "$domain" '$BACKEND' "$template" + done + + # Chaning template in user config + old_template=$(grep BACKEND_TEMPLATE "$USER_DATA/user.conf") + if [ -z "$old_template" ]; then + sed -i "s/^WEB_DOMAINS/BACKEND_TEMPLATE='$template'\nWEB_DOMAINS/g" \ + $USER_DATA/user.conf + else + update_user_value "$user" '$BACKEND_TEMPLATE' "$template" + fi +else + # Parsing domain values + get_domain_values 'web' + local_ip=$(get_real_ip "$IP") + BACKEND="$template" + prepare_web_domain_values + + # Rebuilding vhost + del_web_config "$WEB_SYSTEM" "$TPL.tpl" + add_web_config "$WEB_SYSTEM" "$TPL.tpl" + if [ "$SSL" = 'yes' ]; then + del_web_config "$WEB_SYSTEM" "$TPL.stpl" + add_web_config "$WEB_SYSTEM" "$TPL.stpl" + fi + + # Rebuilding proxy configuration + if [ -n "$PROXY_SYSTEM" ] && [ -n "$PROXY" ]; then + del_web_config "$PROXY_SYSTEM" "$PROXY.tpl" + add_web_config "$PROXY_SYSTEM" "$PROXY.tpl" + if [ "$SSL" = 'yes' ]; then + del_web_config "$PROXY_SYSTEM" "$PROXY.stpl" + add_web_config "$PROXY_SYSTEM" "$PROXY.stpl" + fi + fi + + # Update config + add_object_key "web" 'DOMAIN' "$domain" 'BACKEND' 'PROXY' + update_object_value 'web' 'DOMAIN' "$domain" '$BACKEND' "$template" +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Restarting web +$BIN/v-restart-web "$restart" +check_result $? "Web restart failed" > /dev/null + +# Detect prev version +if [[ $BACKEND =~ ^.*PHP-([0-9])\_([0-9])$ ]]; then + version="${BASH_REMATCH[1]}.${BASH_REMATCH[2]}" +else + version=$(multiphp_default_version) +fi + +$BIN/v-restart-web-backend "$restart" "$version" +if [ "$version" != "$backend_version" ]; then + $BIN/v-restart-web-backend "$restart" "$backend_version" +fi + +check_result $? "PHP restart failed" > /dev/null + +# Logging +$BIN/v-log-action "$user" "Info" "Web" "Backend template applied (Domain: $domain, Template: $template)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-change-web-domain-dirlist b/bin/v-change-web-domain-dirlist new file mode 100755 index 0000000..ff03202 --- /dev/null +++ b/bin/v-change-web-domain-dirlist @@ -0,0 +1,88 @@ +#!/bin/bash +# info: enable/disable directory listing +# options: USER DOMAIN MODE +# +# example: v-change-web-domain-dirlist user demo.com on +# +# This function is used for changing the directory list mode. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument defenition +user=$1 +domain=$2 +mode=$3 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '3' "$#" 'USER DOMAIN MODE' +is_format_valid 'user' 'domain' +is_system_enabled "$WEB_SYSTEM" 'WEB_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'web' 'DOMAIN' "$domain" +is_object_unsuspended 'web' 'DOMAIN' "$domain" +get_domain_values 'web' + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Fetching domain variables +get_domain_values 'web' + +if [ "$mode" = "on" ]; then + # Enable directory listing + sed -i "s/-Index/+Index/g" $HOMEDIR/$user/conf/web/$domain/$WEB_SYSTEM.conf + if [ "$SSL" == "yes" ]; then + # Enable directory listing for SSL-enforced domains + sed -i "s/-Index/+Index/g" $HOMEDIR/$user/conf/web/$domain/$WEB_SYSTEM.ssl.conf + fi + echo "Enabled directory browsing for $domain." +else + # Disable directory listing + sed -i "s/+Index/-Index/g" $HOMEDIR/$user/conf/web/$domain/$WEB_SYSTEM.conf + if [ "$SSL" == "yes" ]; then + # Enable directory listing for SSL-enforced domains + sed -i "s/+Index/-Index/g" $HOMEDIR/$user/conf/web/$domain/$WEB_SYSTEM.ssl.conf + fi + echo "Disabled directory browsing for $domain." +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Rebuilding vhosts +$BIN/v-restart-web + +# Logging +if [ "$mode" = "on" ]; then + $BIN/v-log-action "$user" "Warning" "Web" "Directory browsing enabled (Domain: $domain)." +else + $BIN/v-log-action "$user" "Info" "Web" "Directory browsing disabled (Domain: $domain)." +fi +log_event "$OK" "$EVENT" + +exit diff --git a/bin/v-change-web-domain-docroot b/bin/v-change-web-domain-docroot new file mode 100755 index 0000000..1d12abb --- /dev/null +++ b/bin/v-change-web-domain-docroot @@ -0,0 +1,137 @@ +#!/bin/bash +# info: Changes the document root for an existing web domain +# options: USER DOMAIN TARGET_DOMAIN [DIRECTORY] [PHP] +# +# example: v-change-web-domain-docroot admin domain.tld otherdomain.tld +# # add custom docroot +# # points domain.tld to otherdomain.tld's document root. +# +# example: v-change-web-domain-docroot admin test.local default +# # remove custom docroot +# # returns document root to default value for domain. +# +# This call changes the document root of a chosen web domain +# to another available domain under the user context. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 + +# Export target domain and directory +# so they are correctly passed through to domain.sh +export target_domain=$3 +export target_directory=$4 +export php=$5 +restart=$6 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DOMAIN [TARGET_DOMAIN] [DIRECTORY] [PHP-DOCROOT] [RESTART]' +is_system_enabled "$WEB_SYSTEM" 'WEB_SYSTEM' +# Check to ensure that target domain is valid if we're +# not setting the docroot value back to defaults +if [ "$target_domain" != "default" ]; then + is_format_valid 'user' 'domain' 'target_domain' 'restart' + is_object_valid 'web' 'DOMAIN' "$target_domain" +else + is_format_valid 'user' 'domain' 'restart' +fi +is_object_valid 'user' 'USER' "$user" "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'web' 'DOMAIN' "$domain" +is_object_unsuspended 'web' 'DOMAIN' "$domain" +is_object_value_empty 'web' 'DOMAIN' "$domain" '$docroot' +is_dir_symlink "$HOMEDIR/$user/web" +is_dir_symlink "$HOMEDIR/$user/web/$target_domain" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Unset existing custom document root path +if [ -n "$CUSTOM_DOCROOT" ]; then + update_object_value 'web' 'DOMAIN' "$domain" '$CUSTOM_DOCROOT' "" + update_object_value 'web' 'DOMAIN' "$domain" '$CUSTOM_PHPROOT' "" +fi + +# If target domain value is 'default', remove the custom document root +# value and rebuild web domain to restore default configuration. +# Otherwise, set target document root path accordingly based on passed values. +if [ "$target_domain" = "default" ]; then + update_object_value 'web' 'DOMAIN' "$domain" '$CUSTOM_DOCROOT' "" + update_object_value 'web' 'DOMAIN' "$domain" '$CUSTOM_PHPROOT' "" +else + # Check for existence of specified directory under target domain's public_html folder + target_domain_directory="$HOMEDIR/$user/web/$target_domain" + if [ -n "$target_directory" ]; then + # Checking destination path + real_target_directory="$(readlink -e "${target_domain_directory}/public_html/$target_directory/")" + if [ ! -e "$real_target_directory" ]; then + check_result "$E_NOTEXIST" "Directory $target_directory does not exist under $HOMEDIR/$user/web/$target_domain/public_html/." + elif [ -z "$(echo $real_target_directory | egrep "^$target_domain_directory\b")" ]; then + check_result "$E_FORBIDEN" "Target dir outside of target domain dir" + else + CUSTOM_DOCROOT="$real_target_directory" + if [ -n "$php" ]; then + custom_phproot="${target_domain_directory}/public_html/" + else + custom_phproot="$real_target_directory" + fi + fi + else + CUSTOM_DOCROOT="${target_domain_directory}/public_html/" + custom_phproot="${target_domain_directory}/public_html/" + fi + + add_object_key 'web' 'DOMAIN' "$domain" 'CUSTOM_DOCROOT' 'IP6' + add_object_key 'web' 'DOMAIN' "$domain" 'CUSTOM_PHPROOT' 'IP6' + + update_object_value 'web' 'DOMAIN' "$domain" '$CUSTOM_DOCROOT' "$CUSTOM_DOCROOT" + # CUSTOM_PHPROOT got overwriten by default + CUSTOM_PHPROOT=$custom_phproot + update_object_value 'web' 'DOMAIN' "$domain" '$CUSTOM_PHPROOT' "$CUSTOM_PHPROOT" +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Rebuild domain configuration +$BIN/v-rebuild-web-domain "$user" "$domain" "$restart" + +# Logging +if [ "$target_domain" = "default" ]; then + $BIN/v-log-action "$user" "Info" "Web" "Domain document root reset (Domain: $domain)." +else + $BIN/v-log-action "$user" "Info" "Web" "Domain document root updated (Domain: $domain, Target: $target_domain)." +fi + +log_event "$OK" "$ARGUMENTS" + +# Unset variables +unset target_domain +unset target_directory + +exit diff --git a/bin/v-change-web-domain-ftp-password b/bin/v-change-web-domain-ftp-password new file mode 100755 index 0000000..f5b4bc1 --- /dev/null +++ b/bin/v-change-web-domain-ftp-password @@ -0,0 +1,90 @@ +#!/bin/bash +# info: change ftp user password. +# options: USER DOMAIN FTP_USER FTP_PASSWORD +# +# example: v-change-web-domain-ftp-password admin example.com ftp_usr ftp_qwerty +# +# This function changes ftp user password. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 +ftp_user=$3 +password=$4 +HIDE=4 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn +# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ? + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '4' "$#" 'USER DOMAIN FTP_USER FTP_PASSWORD' +is_format_valid 'user' 'domain' 'ftp_user' +is_system_enabled "$WEB_SYSTEM" 'WEB_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'web' 'DOMAIN' "$domain" +is_object_unsuspended 'web' 'DOMAIN' "$domain" +is_password_valid +get_domain_values 'web' +if [ -z "$(echo $FTP_USER | tr ':' '\n' | grep ^$ftp_user$)" ]; then + echo "Error: account $ftp_user doesn't exist" + log_event "$E_NOTEXIST" "$ARGUMENTS" + exit "$E_NOTEXIST" +fi + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Changing ftp user password +echo "$ftp_user:$password" | /usr/sbin/chpasswd + +if [ $? -ne 0 ]; then + echo "Error: Password not accepted due to PAM restrictions" + exit 2 +fi + +ftp_md5=$(awk -v user=$ftp_user -F : 'user == $1 {print $2}' /etc/shadow) + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Rebuilding FTP variables +position=$(echo $FTP_USER | tr ':' '\n' | grep -n '' | grep ":$ftp_user$" \ + | cut -f 1 -d:) +ftp_md5=$(echo $FTP_MD5 | tr ':' '\n' | grep -n '' \ + | sed -e "s%^$position:.*%$position:$ftp_md5%" \ + | cut -f 2 -d : | sed -e "/^$/d" | sed -e ':a;N;$!ba;s/\n/:/g') + +# Updating config +update_object_value 'web' 'DOMAIN' "$domain" '$FTP_MD5' "$ftp_md5" + +# Logging +$BIN/v-log-action "$user" "Info" "Web" "FTP account password changed (User: $ftp_user, Domain: $domain)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-change-web-domain-ftp-path b/bin/v-change-web-domain-ftp-path new file mode 100755 index 0000000..1b9875c --- /dev/null +++ b/bin/v-change-web-domain-ftp-path @@ -0,0 +1,100 @@ +#!/bin/bash +# info: change path for ftp user. +# options: USER DOMAIN FTP_USER FTP_PATH +# +# example: v-change-web-domain-ftp-path admin example.com /home/admin/example.com +# +# This function changes ftp user path. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 +ftp_user=$3 +ftp_path=$4 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn +# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ? + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '4' "$#" 'USER DOMAIN FTP_USER FTP_PATH' +is_format_valid 'user' 'domain' 'ftp_user' +is_system_enabled "$WEB_SYSTEM" 'WEB_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'web' 'DOMAIN' "$domain" +is_object_unsuspended 'web' 'DOMAIN' "$domain" +get_domain_values 'web' +if [ -z "$(echo $FTP_USER | tr ':' '\n' | grep ^$ftp_user$)" ]; then + echo "Error: account $ftp_user doesn't exist" + log_event "$E_NOTEXIST" "$ARGUMENTS" + exit "$E_NOTEXIST" +fi +ftp_path_a=$(readlink -f "$HOMEDIR/$user/web/$domain/$ftp_path") +if [ -z "$(echo $ftp_path_a | grep $HOMEDIR/$user/web/$domain)" ]; then + echo "Error: absolute path $ftp_path_a is invalid" + log_event "$E_INVALID" "$ARGUMENTS" + exit "$E_INVALID" +fi + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# MKDIR if path doesn't exist +if [ ! -e "$ftp_path_a" ]; then + $BIN/v-add-fs-directory "$user" "$ftp_path_a" + chown $user:$user "$ftp_path_a" + chmod 751 "$ftp_path_a" +fi + +# Chaning ftp user path +pw_str=$(grep -n "^$ftp_user:" /etc/passwd) +str=$(echo "$pw_str" | cut -f 1 -d :) +old_path=$(echo "$pw_str" | cut -f 7 -d :) +sed -i "$str s%$old_path%$ftp_path_a%g" /etc/passwd + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Transforming absolute path to relative +ftp_path_r=$(echo $ftp_path_a | sed "s%$HOMEDIR/$user/web/$domain%%") + +# Rebuilding FTP variables +position=$(echo $FTP_USER | tr ':' '\n' | grep -n '' | grep ":$ftp_user$" \ + | cut -f 1 -d:) +ftp_path=$(echo $FTP_PATH | tr ':' '\n' | grep -n '' \ + | sed -e "s%^$position:.*%$position:$ftp_path_r%" \ + | cut -f 2 -d : | sed -e ':a;N;$!ba;s/\n/:/g') + +# Updating config +update_object_value 'web' 'DOMAIN' "$domain" '$FTP_PATH' "$ftp_path" + +# Logging +$BIN/v-log-action "$user" "Info" "Web" "FTP account path changed (User: $ftp_user@domain, Path: $ftp_path_a)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-change-web-domain-httpauth b/bin/v-change-web-domain-httpauth new file mode 100755 index 0000000..3377778 --- /dev/null +++ b/bin/v-change-web-domain-httpauth @@ -0,0 +1,84 @@ +#!/bin/bash +# info: change password for http auth user +# options: USER DOMAIN AUTH_USER AUTH_PASSWORD [RESTART] +# +# example: v-change-web-domain-httpauth admin acme.com alice white_rA$$bIt +# +# This function is used for changing http auth user password + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +auth_user=$3 +password=$4 +HIDE=4 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Defining htpasswd file +htpasswd="$HOMEDIR/$user/conf/web/$domain/htpasswd" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '4' "$#" 'USER DOMAIN AUTH_USER AUTH_PASSWORD [RESTART]' +is_format_valid 'user' 'domain' +is_system_enabled "$WEB_SYSTEM" 'WEB_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'web' 'DOMAIN' "$domain" +is_object_unsuspended 'web' 'DOMAIN' "$domain" +is_common_format_valid "$auth_user" "auth user" +is_password_valid +get_domain_values 'web' +if [ -z "$(echo "$AUTH_USER" | tr : '\n' | grep ^$auth_user$)" ]; then + echo "Error: auth user $auth_user doesn't exist" + log_event "$E_NOTEXIST" "$ARGUMENTS" + exit "$E_NOTEXIST" +fi + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Adding httpasswd user +auth_hash=$($BIN/v-generate-password-hash htpasswd htpasswd "$password") +touch $htpasswd +sed -i "/^$auth_user:/d" $htpasswd +echo "$auth_user:$auth_hash" >> $htpasswd + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Rebuilding AUTH_HASH variable +position=$(echo "$AUTH_USER" | tr ':' '\n' | grep -n '' | grep ":$auth_user$" \ + | cut -f 1 -d:) +auth_hash=$(echo "$AUTH_HASH" | tr ':' '\n' | grep -n '' \ + | sed -e "s%^$position:.*%$position:$auth_hash%" \ + | cut -f 2 -d : | sed -e "/^$/d" | sed -e ':a;N;$!ba;s/\n/:/g') + +# Updating config +update_object_value 'web' 'DOMAIN' "$domain" '$AUTH_HASH' "$auth_hash" + +# Logging +$BIN/v-log-action "$user" "Info" "Web" "Web domain password changed (User: $httpauth_user, Domain: $domain)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-change-web-domain-ip b/bin/v-change-web-domain-ip new file mode 100755 index 0000000..80ea029 --- /dev/null +++ b/bin/v-change-web-domain-ip @@ -0,0 +1,103 @@ +#!/bin/bash +# info: change web domain ip +# options: USER DOMAIN DOMAIN [RESTART] +# +# example: v-change-web-domain-ip admin example.com 167.86.105.230 yes +# +# This function is used for changing domain ip + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 +ip=$3 +restart=$4 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# shellcheck source=/usr/local/hestia/func/ip.sh +source $HESTIA/func/ip.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn +# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ? + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '3' "$#" 'USER DOMAIN IP [RESTART]' +is_format_valid 'user' 'domain' 'ip' +is_system_enabled "$WEB_SYSTEM" 'WEB_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'web' 'DOMAIN' "$domain" +is_object_unsuspended 'web' 'DOMAIN' "$domain" +is_ip_valid "$ip" "$user" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Preparing variables for vhost replace +get_domain_values 'web' +old=$(get_real_ip "$IP") +new=$(get_real_ip "$ip") + +# Replacing vhost +replace_web_config "$WEB_SYSTEM" "$TPL.tpl" +if [ "$SSL" = 'yes' ]; then + replace_web_config "$WEB_SYSTEM" "$TPL.stpl" +fi + +# Replacing proxy vhost +if [ -n "$PROXY_SYSTEM" ] && [ -n "$PROXY" ]; then + replace_web_config "$PROXY_SYSTEM" "$PROXY.tpl" + if [ "$SSL" = 'yes' ]; then + replace_web_config "$PROXY_SYSTEM" "$PROXY.stpl" + fi +fi + +# Check for webmail +if [ -n "$IMAP_SYSTEM" ]; then + $BIN/v-rebuild-mail-domain "$user" "$domain" +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Update config +update_object_value 'web' 'DOMAIN' "$domain" '$IP' "$3" + +# Update counters +increase_ip_value "$new" +decrease_ip_value "$old" + +# Restart web server +$BIN/v-restart-web "$restart" +check_result $? "WEB restart failed" > /dev/null + +$BIN/v-restart-proxy "$restart" +check_result $? "Proxy restart failed" > /dev/null + +# Logging +$BIN/v-log-action "$user" "Info" "Web" "Web domain IP address changed (IP: $3, Domain: $domain)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-change-web-domain-name b/bin/v-change-web-domain-name new file mode 100755 index 0000000..dee80ff --- /dev/null +++ b/bin/v-change-web-domain-name @@ -0,0 +1,130 @@ +#!/bin/bash +# info: change web domain name +# options: USER DOMAIN NEW_DOMAIN [RESTART] +# +# example: v-change-web-domain-name alice wonderland.com lookinglass.com yes +# +# This function is used for changing the domain name. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument defenition +user=$1 +domain=$2 +domain_idn=$2 +new_domain=$3 +restart=$4 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# shellcheck source=/usr/local/hestia/func/ip.sh +source $HESTIA/func/ip.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn +# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ? + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '3' "$#" 'USER DOMAIN NEW_DOMAIN [RESTART]' +is_format_valid 'user' 'domain' +is_domain_format_valid "$new_domain" +is_system_enabled "$WEB_SYSTEM" 'WEB_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'web' 'DOMAIN' "$domain" +is_object_unsuspended 'web' 'DOMAIN' "$domain" +check_new_domain=$(grep "DOMAIN='$new_domain'" $HESTIA/data/users/*/web.conf) +if [ -n "$check_new_domain" ]; then + check_result "$E_EXISTS" "$new_domain already exists" +fi + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Fetching domain variables +get_domain_values 'web' + +# Changing domain in web.conf +sed -i "s/DOMAIN='$domain'/DOMAIN='$new_domain'/" $USER_DATA/web.conf +new_alias=$(echo "$ALIAS,$domain" \ + | sed -e "s/,/\n/g" \ + | sed -e "s/^$new_domain$//g" \ + | sed -e "/^$/d" \ + | sed -e ':a;N;$!ba;s/\n/,/g') + +# Updating domain alias +if [ "$ALIAS" != "$new_alias" ]; then + sed -i "s/ALIAS='$ALIAS'/ALIAS='$new_alias'/" $USER_DATA/web.conf +fi + +# Moving document root and domain logs +mv "$HOMEDIR/$user/web/$domain" "$HOMEDIR/$user/web/$new_domain/" +cd /var/log/$WEB_SYSTEM/domains +mv "$domain.log" "$new_domain.log" +mv "$domain.error.log" "$new_domain.error.log" +mv "$domain.bytes" "$new_domain.bytes" +rm -f "$HOMEDIR/$user/web/$new_domain/logs/$domain.*" + +# Updating domain certificates +if [ -e "$USER_DATA/ssl/$domain.crt" ]; then + cd $USER_DATA/ssl + mv $USER_DATA/ssl/$domain.crt $USER_DATA/ssl/$new_domain.crt + mv $USER_DATA/ssl/$domain.ca $USER_DATA/ssl/$new_domain.ca + mv $USER_DATA/ssl/$domain.pem $USER_DATA/ssl/$new_domain.pem + mv $USER_DATA/ssl/$domain.key $USER_DATA/ssl/$new_domain.key + rm -f $HOMEDIR/$user/conf/web/$domain/ssl/$domain.* +fi + +# Deleting vhost configuration +del_web_config "$WEB_SYSTEM" "$TPL.tpl" +# Deleting SSL configuration and certificates +if [ "$SSL" = 'yes' ]; then + del_web_config "$WEB_SYSTEM" "$TPL.stpl" +fi + +# Deleting proxy +if [ -n "$PROXY_SYSTEM" ]; then + del_web_config "$PROXY_SYSTEM" "$PROXY.tpl" + if [ "$SSL" = 'yes' ]; then + del_web_config "$PROXY_SYSTEM" "$PROXY.stpl" + fi + if [ -e "/etc/$PROXY_SYSTEM/conf.d/01_caching_pool.conf" ]; then + sed -i "/=$domain:/d" /etc/$PROXY_SYSTEM/conf.d/01_caching_pool.conf + fi +fi + +# Delete backend +if [ -n "$BACKEND" ]; then + prepare_web_backend + delete_web_backend +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Rebuilding vhosts +$BIN/v-rebuild-web-domains "$user" "$restart" + +# Logging +$BIN/v-log-action "$user" "Info" "Web" "Renamed web domain (Old Domain: $domain, New Domain: $new_domain)." +log_event "$OK" "$EVENT" + +exit diff --git a/bin/v-change-web-domain-proxy-tpl b/bin/v-change-web-domain-proxy-tpl new file mode 100755 index 0000000..ef2cee3 --- /dev/null +++ b/bin/v-change-web-domain-proxy-tpl @@ -0,0 +1,97 @@ +#!/bin/bash +# info: change web domain proxy template +# options: USER DOMAIN TEMPLATE [EXTENTIONS] [RESTART] +# +# example: v-change-web-domain-proxy-tpl admin domain.tld hosting +# +# This function changes proxy template + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 +template=$3 +default_extentions="jpg,jpeg,gif,png,ico,svg,css,zip,tgz,gz,rar,bz2,doc,xls,\ +exe,pdf,ppt,txt,odt,ods,odp,odf,tar,wav,bmp,rtf,js,mp3,avi,mpeg,flv,html,htm" +extentions=${4-$default_extentions} +restart="$5" + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# shellcheck source=/usr/local/hestia/func/ip.sh +source $HESTIA/func/ip.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn +# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ? + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '3' "$#" 'USER DOMAIN TEMPLATE [EXTENTIONS] [RESTART]' +is_format_valid 'user' 'domain' 'template' +is_system_enabled "$PROXY_SYSTEM" 'PROXY_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'web' 'DOMAIN' "$domain" +is_object_unsuspended 'web' 'DOMAIN' "$domain" +is_object_value_exist 'web' 'DOMAIN' "$domain" '$PROXY' +is_proxy_template_valid $template + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Parsing domain values +get_domain_values 'web' +local_ip=$(get_real_ip "$IP") + +# Delete old vhost +del_web_config "$PROXY_SYSTEM" "$PROXY.tpl" +if [ "$SSL" = 'yes' ]; then + del_web_config "$PROXY_SYSTEM" "$PROXY.stpl" +fi + +# Add new vhost +PROXY="$template" +PROXY_EXT="$extentions" + +prepare_web_domain_values +add_web_config "$PROXY_SYSTEM" "$PROXY.tpl" +if [ "$SSL" = 'yes' ]; then + add_web_config "$PROXY_SYSTEM" "$PROXY.stpl" +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Updating config +update_object_value 'web' 'DOMAIN' "$domain" '$PROXY' "$PROXY" +update_object_value 'web' 'DOMAIN' "$domain" '$PROXY_EXT' "$extentions" + +# Restarting proxy +$BIN/v-restart-proxy "$restart" +check_result $? "Proxy restart failed" > /dev/null + +# Logging +$BIN/v-log-action "$user" "Info" "Web" "Proxy template changed (Domain: $domain, Template: $template)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-change-web-domain-sslcert b/bin/v-change-web-domain-sslcert new file mode 100755 index 0000000..09a597e --- /dev/null +++ b/bin/v-change-web-domain-sslcert @@ -0,0 +1,95 @@ +#!/bin/bash +# info: change domain ssl certificate +# options: USER DOMAIN SSL_DIR [RESTART] +# +# example: v-change-web-domain-sslcert admin example.com /home/admin/tmp +# +# This function changes SSL domain certificate and the key. If ca file present +# it will be replaced as well. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 +ssl_dir=$3 +restart=$4 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn +# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ? + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '3' "$#" 'USER DOMAIN SSL_DIR [RESTART]' +is_format_valid 'user' 'domain' 'ssl_dir' +is_system_enabled "$WEB_SYSTEM" 'WEB_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'web' 'DOMAIN' "$domain" +is_object_unsuspended 'web' 'DOMAIN' "$domain" +is_object_value_exist 'web' 'DOMAIN' "$domain" '$SSL' +is_web_domain_cert_valid + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Deleting old certificate +tmpdir=$(mktemp -p $HOMEDIR/$user/web/$domain/private -d) +rm -f $HOMEDIR/$user/conf/web/$domain/ssl/$domain.* +mv $USER_DATA/ssl/$domain.* $tmpdir +chown -R $user:$user $tmpdir + +# Adding new certificate to user data directory +cp -f $ssl_dir/$domain.crt $USER_DATA/ssl/$domain.crt +cp -f $ssl_dir/$domain.key $USER_DATA/ssl/$domain.key +cp -f $ssl_dir/$domain.crt $USER_DATA/ssl/$domain.pem +if [ -e "$ssl_dir/$domain.ca" ]; then + cp -f $ssl_dir/$domain.ca $USER_DATA/ssl/$domain.ca + cat $USER_DATA/ssl/$domain.ca >> $USER_DATA/ssl/$domain.pem +fi + +# Adding new certificate to user dir +cp -f $USER_DATA/ssl/$domain.crt $HOMEDIR/$user/conf/web/$domain/ssl/$domain.crt +cp -f $USER_DATA/ssl/$domain.key $HOMEDIR/$user/conf/web/$domain/ssl/$domain.key +cp -f $USER_DATA/ssl/$domain.pem $HOMEDIR/$user/conf/web/$domain/ssl/$domain.pem +if [ -e "$USER_DATA/ssl/$domain.ca" ]; then + cp -f $USER_DATA/ssl/$domain.ca $HOMEDIR/$user/conf/web/$domain/ssl/$domain.ca +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Restarting web server +$BIN/v-restart-web "$restart" +check_result $? "Web restart failed" > /dev/null + +$BIN/v-restart-proxy "$restart" +check_result $? "Proxy restart failed" > /dev/null + +# Logging +$BIN/v-log-action "$user" "Info" "Web" "SSL certificate changed (Domain: $domain)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-change-web-domain-sslhome b/bin/v-change-web-domain-sslhome new file mode 100755 index 0000000..ae1274e --- /dev/null +++ b/bin/v-change-web-domain-sslhome @@ -0,0 +1,104 @@ +#!/bin/bash +# info: changing domain ssl home +# options: USER DOMAIN SSL_HOME [RESTART] +# +# example: v-change-web-domain-sslhome admin acme.com single +# example: v-change-web-domain-sslhome admin acme.com same +# +# This function changes SSL home directory. Single will separate the both public_html / public_shtml. Same will always point to public_shtml + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 +ssl_home=$3 +restart=$4 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn +# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ? + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '3' "$#" 'USER DOMAIN SSL_HOME [RESTART]' +is_format_valid 'user' 'domain' +is_system_enabled "$WEB_SYSTEM" 'WEB_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'web' 'DOMAIN' "$domain" +is_object_unsuspended 'web' 'DOMAIN' "$domain" +is_object_value_exist 'web' 'DOMAIN' "$domain" '$SSL' + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Get domain values +get_domain_values 'web' +old_ssl_home=$SSL_HOME +SSL_HOME=$ssl_home + +# Parsing tpl_option +case $SSL_HOME in + single) + new="$HOMEDIR/$user/web/$domain/public_shtml" + old="$HOMEDIR/$user/web/$domain/public_html" + ;; + same) + new="$HOMEDIR/$user/web/$domain/public_html" + old="$HOMEDIR/$user/web/$domain/public_shtml" + ;; + *) check_args '3' "2" 'USER DOMAIN SSLHOME' ;; +esac + +if [ "$SSL_HOME" = 'single' ] && [ ! -d "$HOMEDIR/$user/web/$domain/public_shtml" ]; then + mkdir $HOMEDIR/$user/web/$domain/public_shtml + chown $user:$user $HOMEDIR/$user/web/$domain/public_shtml + user_exec cp $WEBTPL/skel/public_html/* "$HOMEDIR/$user/web/$domain/public_shtml" > /dev/null 2>&1 + for file in $(find "$HOMEDIR/$user/web/$domain/public_shtml" -type f); do + sed -i "s/%domain%/$domain/g" $file + done +fi + +# Changing sslhome directory +replace_web_config "$WEB_SYSTEM" "$TPL.stpl" + +# Changing proxy vhost +if [ -n "$PROXY_SYSTEM" ] && [ ! -z "$PROXY" ]; then + replace_web_config "$PROXY_SYSTEM" "$PROXY.stpl" +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Update config +update_object_value 'web' 'DOMAIN' "$domain" '$SSL_HOME' "$SSL_HOME" + +# Rebuild web +$BIN/v-rebuild-web-domain "$user" "$domain" "$restart" + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-change-web-domain-stats b/bin/v-change-web-domain-stats new file mode 100755 index 0000000..6c56297 --- /dev/null +++ b/bin/v-change-web-domain-stats @@ -0,0 +1,104 @@ +#!/bin/bash +# info: change web domain statistics +# options: USER DOMAIN TYPE +# +# example: v-change-web-domain-stats admin example.com awstats +# +# This function of deleting site's system of statistics. Its type is +# automatically chooses from client's configuration file. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 +type=$3 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" +# Additional argument formatting +format_domain +format_domain_idn + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '3' "$#" 'USER DOMAIN TYPE' +is_format_valid 'user' 'domain' +is_system_enabled "$WEB_SYSTEM" 'WEB_SYSTEM' +is_type_valid "$STATS_SYSTEM" "$type" +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'web' 'DOMAIN' "$domain" +is_object_unsuspended 'web' 'DOMAIN' "$domain" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Parse aliases +get_domain_values 'web' + +# Deleting config +rm -f $HOMEDIR/$user/conf/web/$domain/$type.conf + +# Adding statistic config +prepare_web_domain_values + +if [ -z "${aliases//,/ }" ]; then + stats_alias="localhost" +else + stats_alias=${aliases_idn//,/ } +fi + +cat $WEBTPL/$type/$type.tpl \ + | sed -e "s|%ip%|$ip|g" \ + -e "s|%web_port%|$WEB_PORT|g" \ + -e "s|%web_system%|$WEB_SYSTEM|g" \ + -e "s|%web_ssl_port%|$WEB_SSL_PORT|g" \ + -e "s|%rgroups%|$WEB_RGROUPs|g" \ + -e "s|%proxy_system%|$PROXY_SYSTEM|g" \ + -e "s|%proxy_port%|$PROXY_PORT|g" \ + -e "s|%proxy_ssl_port%|$PROXY_SSL_PORT|g" \ + -e "s|%domain_idn%|$domain_idn|g" \ + -e "s|%domain%|$domain|g" \ + -e "s|%user%|$user|g" \ + -e "s|%home%|$HOMEDIR|g" \ + -e "s|%alias%|${aliases//,/ }|g" \ + -e "s|%alias_idn%|$stats_alias|g" \ + > $HOMEDIR/$user/conf/web/$domain/$type.conf + +if [ "$type" == 'awstats' ]; then + rm -f /etc/awstats/$type.$domain_idn.conf + ln -s $HOMEDIR/$user/conf/web/$domain/$type.conf \ + /etc/awstats/$type.$domain_idn.conf +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Update config +update_object_value 'web' 'DOMAIN' "$domain" '$STATS' "$type" + +# Logging +log_event "$OK" "$ARGUMENTS" + +# Build stats +exec $BIN/v-update-web-domain-stat "$user" "$domain" + +exit diff --git a/bin/v-change-web-domain-tpl b/bin/v-change-web-domain-tpl new file mode 100755 index 0000000..4c97d8e --- /dev/null +++ b/bin/v-change-web-domain-tpl @@ -0,0 +1,91 @@ +#!/bin/bash +# info: change web domain template +# options: USER DOMAIN TEMPLATE [RESTART] +# +# example: v-change-web-domain-tpl admin acme.com opencart +# +# This function changes template of the web configuration file. The content +# of webdomain directories remains untouched. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 +template=$3 +restart=$4 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# shellcheck source=/usr/local/hestia/func/ip.sh +source $HESTIA/func/ip.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn +# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ? + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '3' "$#" 'USER DOMAIN TEMPLATE [RESTART]' +is_format_valid 'user' 'domain' 'template' +is_system_enabled "$WEB_SYSTEM" 'WEB_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'web' 'DOMAIN' "$domain" +is_object_unsuspended 'web' 'DOMAIN' "$domain" +is_web_template_valid "$template" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Parsing domain values +get_domain_values 'web' +local_ip=$(get_real_ip "$IP") +export local_ip + +# Deleting domain +del_web_config "$WEB_SYSTEM" "$TPL.tpl" +if [ "$SSL" = 'yes' ]; then + del_web_config "$WEB_SYSTEM" "$TPL.stpl" +fi + +# Defining variables for new vhost config +prepare_web_domain_values +add_web_config "$WEB_SYSTEM" "$template.tpl" +if [ "$SSL" = 'yes' ]; then + add_web_config "$WEB_SYSTEM" "$template.stpl" +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Changing tpl in config +update_object_value 'web' 'DOMAIN' "$domain" '$TPL' "$template" + +# Restarting web +$BIN/v-restart-web "$restart" +check_result $? "Web restart failed" > /dev/null + +# Logging +$BIN/v-log-action "$user" "Info" "Web" "Web domain template applied (Domain: $domain, Template: $template)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-check-access-key b/bin/v-check-access-key new file mode 100755 index 0000000..d4ce930 --- /dev/null +++ b/bin/v-check-access-key @@ -0,0 +1,114 @@ +#!/bin/bash +# info: check access key +# options: ACCESS_KEY_ID SECRET_ACCESS_KEY COMMAND [IP] [FORMAT] +# +# example: v-check-access-key key_id secret v-purge-nginx-cache 127.0.0.1 json +# +# * Checks if the key exists; +# * Checks if the secret belongs to the key; +# * Checks if the key user is suspended; +# * Checks if the key has permission to run the command. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +access_key_id="$(basename "$1")" +secret_access_key=$2 +hst_command=$3 +ip46=${4-127.0.0.1} +format=${5-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +time_n_date=$(date +'%T %F') +time=$(echo "$time_n_date" | cut -f 1 -d \ ) +date=$(echo "$time_n_date" | cut -f 2 -d \ ) + +# JSON list function +json_list() { + echo -n '{"USER": "'$user'"' + + if [[ -n "$user_arg_pos" ]]; then + echo -n ', "USER_ARG_POSITION": '$user_arg_pos'' + fi + + echo '}' +} + +# SHELL list function +shell_list() { + echo "USER: $user" + if [[ -n "$user_arg_pos" ]]; then + echo "USER_ARG_POSITION: $user_arg_pos" + fi +} + +# Callback to intercept invalid result validation +abort_missmatch() { + echo "Error: $2" + echo "$date $time ${access_key_id:-api} $ip46 failed to login" >> $HESTIA/log/auth.log + + # Add a log for user + if [[ "$1" == "$E_PASSWORD" && -n "$user" ]]; then + log_history "[$ip46] $access_key_id $2" "Error" "$user" "API" + fi + + if [[ "$1" == "$E_FORBIDEN" ]]; then + exit "$1" + fi + + exit "$E_PASSWORD" +} + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +# Add a callback to intercept invalid "check_result" results +CHECK_RESULT_CALLBACK="abort_missmatch" + +check_args '3' "$#" 'ACCESS_KEY_ID SECRET_ACCESS_KEY COMMAND [IP] [FORMAT]' +is_format_valid 'access_key_id' 'ip46' 'command' +is_object_valid 'key' 'KEY' "$access_key_id" +is_format_valid 'secret_access_key' +check_access_key_secret "$access_key_id" "$secret_access_key" user +check_access_key_cmd "$access_key_id" "$hst_command" user_arg_pos + +# Check if key owner is active +is_format_valid 'user' +is_object_valid 'user' 'USER' "$user" +export USER_DATA=$HESTIA/data/users/$user +is_object_unsuspended 'user' 'USER' "$user" + +# Remove the check_result callback +CHECK_RESULT_CALLBACK="" + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Listing data +case $format in + json) json_list ;; + shell) shell_list ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +log_history "[$ip46] Access key $access_key_id successfully launched with command $hst_command" "Info" "$user" "API" +echo "$date $time $access_key_id $ip46 $hst_command successfully launched" >> $HESTIA/log/auth.log + +exit diff --git a/bin/v-check-api-key b/bin/v-check-api-key new file mode 100755 index 0000000..863f7d8 --- /dev/null +++ b/bin/v-check-api-key @@ -0,0 +1,62 @@ +#!/bin/bash +# info: check api key +# options: KEY [IP] +# +# example: v-check-api-key random_key 127.0.0.1 +# +# This function checks a key file in $HESTIA/data/keys/ + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +new_timestamp + +abort_missmatch() { + echo "Error: key missmatch" + echo "$date $time api $ip failed to login" >> $HESTIA/log/auth.log + exit "$E_PASSWORD" +} + +ip=${2-127.0.0.1} +time_n_date=$(date +'%T %F') +time=$(echo "$time_n_date" | cut -f 1 -d \ ) +date=$(echo "$time_n_date" | cut -f 2 -d \ ) + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +key="$(basename "$1")" + +# Exit if Key is unset or to short +[[ -z $key || ${#key} -lt 16 ]] && abort_missmatch + +# Key file must exist +maybe_key_path="$(readlink -e "${HESTIA}/data/keys/${key}")" +[[ -z $maybe_key_path ]] && abort_missmatch + +# Key file cannot be the key store +[[ $maybe_key_path == "${HESTIA}/data/keys" ]] && abort_missmatch + +# Key file must be in the key store +[[ $maybe_key_path == "${HESTIA}/data/keys/"* ]] || abort_missmatch + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +echo "$date $time api $ip successfully launched" >> $HESTIA/log/auth.log + +exit diff --git a/bin/v-check-fs-permission b/bin/v-check-fs-permission new file mode 100755 index 0000000..3f0d78d --- /dev/null +++ b/bin/v-check-fs-permission @@ -0,0 +1,59 @@ +#!/bin/bash +# info: open file +# options: USER FILE +# +# example: v-check-fs-permission admin readme.txt +# +# This function opens/reads files on the file system + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +user=$1 +src=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER FILE' +is_format_valid 'user' +is_object_valid 'user' 'USER' "$user" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +# Checking user homedir +homedir=$(grep "^$user:" /etc/passwd | cut -f 6 -d :) +if [ -z "$homedir" ]; then + echo "Error: user home directory doesn't exist" + exit 12 +fi + +# Checking path +if [ -n "$src" ]; then + rpath=$(readlink -f "$src") + if [ -z "$(echo $rpath | egrep "^/tmp|^$homedir")" ]; then + echo "Error: invalid source path $user $src" + exit 2 + fi +fi + +# Checking if file has readable permission +user_exec ls "$src" > /dev/null 2>&1 +if [ $? -ne 0 ]; then + echo "Error: can't read $src" + exit 1 +fi + +# Exiting +exit diff --git a/bin/v-check-mail-account-hash b/bin/v-check-mail-account-hash new file mode 100755 index 0000000..149fc59 --- /dev/null +++ b/bin/v-check-mail-account-hash @@ -0,0 +1,65 @@ +#!/bin/bash +# info: check user password +# options: TYPE PASSWORD HASH +# +# example: v-check-mail-account-hash ARGONID2 PASS HASH +# +# This function verifies email account password hash + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +type=$1 +password=$2 +HIDE=2 +hash=$3 +HIDE=2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '3' "$#" 'TYPE PASS HASH' + +is_password_valid + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +if [ "$type" = "BCRYPT" ]; then + match=$(doveadm pw -s BLF-CRYPT -p "$password" -t $hash | grep "verified") + if [ -n "$match" ]; then + exit 0 + else + echo $match + exit 2 + fi +elif [ "$type" = "ARGONID2" ]; then + match=$(doveadm pw -s ARGON2ID -p "$password" -t $hash | grep "verified") + if [ -n "$match" ]; then + exit 0 + else + echo $match + exit 2 + fi +else + echo "unsupported hash type." + exit 2 +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-check-user-2fa b/bin/v-check-user-2fa new file mode 100755 index 0000000..d1a9e74 --- /dev/null +++ b/bin/v-check-user-2fa @@ -0,0 +1,57 @@ +#!/bin/bash +# info: check user token +# options: USER TOKEN +# +# example: v-check-user-2fa admin 493690 +# +# This function verifies user 2fa token. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +token=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER TOKEN' +is_format_valid 'user' 'system' +is_object_valid 'user' 'USER' "$user" + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Reading user values +source $USER_DATA/user.conf + +# Check if 2FA is enabled +if [ -z "$TWOFA" ]; then + echo "Error: Two-factor authentication is not enabled." + exit "$E_NOTEXIST" +fi + +# Check if token is valid +result=$($HESTIA_PHP $HESTIA/web/inc/2fa/check.php "$TWOFA" "$token") +if [ "$result" != "ok" ]; then + echo "Error: Authentication token mismatch." + exit 9 +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-check-user-hash b/bin/v-check-user-hash new file mode 100755 index 0000000..0fafc93 --- /dev/null +++ b/bin/v-check-user-hash @@ -0,0 +1,102 @@ +#!/bin/bash +# info: check user hash +# options: USER HASH [IP] +# +# example: v-check-user-hash admin CN5JY6SMEyNGnyCuvmK5z4r7gtHAC4mRZ... +# +# This function verifies user hash + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +hash=$2 +HIDE=2 +ip46=${3-127.0.0.1} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +time_n_date=$(date +'%T %F') +time=$(echo "$time_n_date" | cut -f 1 -d \ ) +date=$(echo "$time_n_date" | cut -f 2 -d \ ) + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER HASH' +is_format_valid 'user' 'ip46' + +# Checking user +if [ ! -d "$HESTIA/data/users/$user" ] && [ "$user" != 'root' ]; then + echo "Error: password missmatch" + echo "$date $time $user $ip failed to login" >> $HESTIA/log/auth.log + exit 9 +fi + +# Checking user hash +is_hash_valid + +# Checking empty hash +if [[ -z "$hash" ]]; then + echo "Error: password missmatch" + echo "$date $time $user $ip46 failed to login" >> $HESTIA/log/auth.log + exit 9 +fi + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Parsing user's salt +shadow=$(grep "^$user:" /etc/shadow | cut -f 2 -d :) + +if echo "$shadow" | grep -qE '^\$[0-9a-z]+\$[^\$]+\$'; then + salt=$(echo "$shadow" | cut -f 3 -d \$) + method=$(echo "$shadow" | cut -f 2 -d \$) + if [ "$method" = "y" ]; then + method="yescrypt" + elif [ "$method" -eq '1' ]; then + method='md5' + elif [ "$method" -eq '6' ]; then + method='sha-512' + else + echo "Error: password missmatch" + echo "$date $time $user $ip46 failed to login" >> $HESTIA/log/auth.log + exit 9 + fi +else + salt=${shadow:0:2} + method='des' +fi + +# Checking salt +if [ -z "$salt" ]; then + echo "Error: password missmatch" + echo "$date $time $user $ip46 failed to login" >> $HESTIA/log/auth.log + exit 9 +fi + +# Comparing hashes +if [[ "$shadow" != "$hash" ]]; then + echo "Error: password missmatch" + echo "$date $time $user $ip46 failed to login" >> $HESTIA/log/auth.log + exit 9 +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +echo "$date $time $user $ip46 successfully logged in" >> $HESTIA/log/auth.log + +exit diff --git a/bin/v-check-user-password b/bin/v-check-user-password new file mode 100755 index 0000000..e2556af --- /dev/null +++ b/bin/v-check-user-password @@ -0,0 +1,130 @@ +#!/bin/bash +# info: check user password +# options: USER PASSWORD [IP] [RETURN_HASH] +# +# example: v-check-user-password admin qwerty1234 +# +# This function verifies user password from file + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +password=$2 +HIDE=2 +ip46=${3-127.0.0.1} +return_hash=$4 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +time_n_date=$(date +'%T %F') +time=$(echo "$time_n_date" | cut -f 1 -d \ ) +date=$(echo "$time_n_date" | cut -f 2 -d \ ) + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER PASSWORD [IP] [RETURN_HASH]' +is_format_valid 'user' 'ip46' + +# Checking user +if [ ! -d "$HESTIA/data/users/$user" ]; then + echo "Error: password missmatch" + echo "$date $time $user $ip46 failed to login" >> $HESTIA/log/auth.log + exit 9 +fi + +is_password_valid + +# Checking empty password +if [[ -z "$password" ]]; then + echo "Error: password missmatch" + echo "$date $time $user $ip46 failed to login" >> $HESTIA/log/auth.log + exit 9 +fi + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Parsing user's salt +shadow=$(grep "^$user:" /etc/shadow | cut -f 2 -d :) + +if echo "$shadow" | grep -qE '^\$[0-9a-z]+\$[^\$]+\$'; then + salt=$(echo "$shadow" | cut -f 3 -d \$) + method=$(echo "$shadow" | cut -f 2 -d \$) + if [ "$method" = "y" ]; then + method="yescrypt" + elif [ "$method" -eq '1' ]; then + method='md5' + elif [ "$method" -eq '6' ]; then + method='sha-512' + else + echo "Error: password missmatch" + echo "$date $time $user $ip46 failed to login" >> $HESTIA/log/auth.log + exit 9 + fi +else + salt=${shadow:0:2} + method='des' +fi + +if [ -z "$salt" ]; then + echo "Error: password missmatch" + echo "$date $time $user $ip46 failed to login" >> $HESTIA/log/auth.log + exit 9 +fi + +if [ "$method" = "yescrypt" ]; then + if which python3 > /dev/null; then + export PASS="$password" SALT="$shadow" + hash=$(python3 -c 'import crypt, os; print(crypt.crypt(os.getenv("PASS"), os.getenv("SALT")))') + else + # Fall back to mkpasswd as fallback + hash=$(mkpasswd "$password" "$shadow") + fi + + if [ $? -ne 0 ]; then + echo "Error: password missmatch" + echo "$date $time $user $ip46 failed to login" >> $HESTIA/log/auth.log + exit 9 + fi +else + # Generating hash + set -o noglob + hash=$($BIN/v-generate-password-hash "$method" "$salt" <<< "$password") + if [[ -z "$hash" ]]; then + echo "Error: password missmatch" + echo "$date $time $user $ip46 failed to login" >> $HESTIA/log/auth.log + exit 9 + fi +fi + +# Checking hash +result=$(grep "^$user:$hash:" /etc/shadow 2> /dev/null) +if [[ -z "$result" ]]; then + echo "Error: password missmatch" + echo "$date $time $user $ip46 failed to login" >> $HESTIA/log/auth.log + exit 9 +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +if [ -n "$return_hash" ]; then + echo $hash +fi +# Logging +echo "$date $time $user $ip46 successfully logged in" >> $HESTIA/log/auth.log + +exit diff --git a/bin/v-copy-fs-directory b/bin/v-copy-fs-directory new file mode 100755 index 0000000..b69da12 --- /dev/null +++ b/bin/v-copy-fs-directory @@ -0,0 +1,69 @@ +#!/bin/bash +# info: copy directory +# options: USER SRC_DIRECTORY DST_DIRECTORY +# +# example: v-copy-fs-directory alice /home/alice/dir1 /home/bob/dir2 +# +# This function copies directory on the file system + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +user=$1 +src_dir=$2 +dst_dir=$3 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '3' "$#" 'USER SRC_DIRECTORY DST_DIRECTORY' +is_format_valid 'user' +is_object_valid 'user' 'USER' "$user" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +# Checking user homedir +homedir=$(grep "^$user:" /etc/passwd | cut -f 6 -d :) +if [ -z "$homedir" ]; then + echo "Error: user home directory doesn't exist" + exit 12 +fi + +# Checking source dir +if [ ! -e "$src_dir" ]; then + echo "Error: source directory $src_dir doesn't exist" + exit 3 +fi + +# Checking source path +rpath=$(readlink -f "$src_dir") +if [ -z "$(echo $rpath | egrep "^/tmp|^$homedir")" ]; then + echo "Error: invalid source path $src_dir" + exit 2 +fi + +# Checking destination path +rpath=$(readlink -f "$dst_dir") +if [ -z "$(echo $rpath | egrep "^/tmp|^$homedir")" ]; then + echo "Error: invalid destination path $dst_dir" + exit 2 +fi + +# Copying directory +user_exec cp -rf "$src_dir" "$dst_dir" > /dev/null 2>&1 +if [ $? -ne 0 ]; then + echo "Error: directory $src_dir was not copied" + exit 3 +fi + +# Exiting +exit diff --git a/bin/v-copy-fs-file b/bin/v-copy-fs-file new file mode 100755 index 0000000..22fbff7 --- /dev/null +++ b/bin/v-copy-fs-file @@ -0,0 +1,69 @@ +#!/bin/bash +# info: copy file +# options: USER SRC_FILE DST_FILE +# +# example: v-copy-fs-file admin readme.txt readme_new.txt +# +# This function copies file on the file system + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +user=$1 +src_file=$2 +dst_file=$3 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '3' "$#" 'USER SRC_FILE DST_FILE' +is_format_valid 'user' +is_object_valid 'user' 'USER' "$user" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +# Checking user homedir +homedir=$(grep "^$user:" /etc/passwd | cut -f 6 -d :) +if [ -z "$homedir" ]; then + echo "Error: user home directory doesn't exist" + exit 12 +fi + +# Checking source file +if [ ! -f "$src_file" ]; then + echo "Error: $src_file doesn't exist" + exit 3 +fi + +# Checking source path +rpath=$(readlink -f "$src_file") +if [ -z "$(echo $rpath | egrep "^/tmp|^$homedir")" ]; then + echo "Error: invalid source path $src_file" + exit 2 +fi + +# Checking destination path +rpath=$(readlink -f "$dst_file") +if [ -z "$(echo $rpath | egrep "^/tmp|^$homedir")" ]; then + echo "Error: invalid destination path $dst_file" + exit 2 +fi + +# Copying file +user_exec cp "$src_file" "$dst_file" > /dev/null 2>&1 +if [ $? -ne 0 ]; then + echo "Error: file $src_file was not copied" + exit 3 +fi + +# Exiting +exit diff --git a/bin/v-copy-user-package b/bin/v-copy-user-package new file mode 100755 index 0000000..222f2c5 --- /dev/null +++ b/bin/v-copy-user-package @@ -0,0 +1,68 @@ +#!/bin/bash +# info: duplicate existing package +# options: PACKAGE NEW_PACKAGE +# +# example: v-copy-user-package default new +# +# This function allows the user to duplicate an existing +# package file to facilitate easier configuration. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +package=$1 +new_package=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/conf/hestia.conf +source $HESTIA/conf/hestia.conf +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +is_package_valid "$package" +is_package_new "$new_package" +is_object_format_valid "$package" "Package" +is_object_format_valid "$new_package" "New package" + +if [ -n "$1" ]; then + if [ ! -f "$HESTIA/data/packages/$package.pkg" ]; then + echo "Error: package does not exist." + exit "$E_NOTEXIST" + fi + if [ -n "$2" ]; then + # Copy package + cp -f "$HESTIA/data/packages/$package.pkg" "$HESTIA/data/packages/$new_package.pkg" + # Don't leave the .sh file behind + if [ -f "$HESTIA/data/packages/$package.sh" ]; then + cp $HESTIA/data/packages/$package.sh $HESTIA/data/packages/$new_package.sh + fi + else + echo "Error: new package name not specified." + exit "$E_ARGS" + fi +else + echo "Error: package name not specified." + exit "$E_ARGS" +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +$BIN/v-log-action "system" "Info" "System" "Package copied (Package: $package, New Package: $new_package)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-delete-access-key b/bin/v-delete-access-key new file mode 100755 index 0000000..d13861a --- /dev/null +++ b/bin/v-delete-access-key @@ -0,0 +1,57 @@ +#!/bin/bash +# info: delete access key +# options: ACCESS_KEY_ID +# +# example: v-delete-access-key mykey +# +# This function removes a key from in $HESTIA/data/access-keys/ + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +access_key_id=$1 + +check_args '1' "$#" "ACCESS_KEY_ID" +is_format_valid 'access_key_id' +is_object_valid 'key' 'KEY' "$access_key_id" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +if [ ! -d "$HESTIA/data/access-keys/" ]; then + exit "$E_NOTEXIST" +fi + +if [[ -e "${HESTIA}/data/access-keys/${access_key_id}" ]]; then + source_conf "${HESTIA}/data/access-keys/${access_key_id}" + rm "${HESTIA}/data/access-keys/${access_key_id}" +else + exit "$E_NOTEXIST" +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +log_history "Access key $access_key_id deleted" "Info" "$USER" "API" +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-delete-backup-host b/bin/v-delete-backup-host new file mode 100755 index 0000000..209ef0b --- /dev/null +++ b/bin/v-delete-backup-host @@ -0,0 +1,62 @@ +#!/bin/bash +# info: delete backup ftp server +# options: TYPE [HOST] +# +# example: v-delete-backup-host sftp +# +# This function deletes ftp backup host + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +type=$1 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'TYPE [HOST]' +types=$(echo "$BACKUP_SYSTEM" | sed "s/,/\n/g" | grep "^$type$") +if [ -z "$types" ]; then + echo "Error: invalid backup type" + log_event "$E_INVALID" "$ARGUMENTS" + exit "$E_INVALID" +fi + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Deleting host config +rm -f $HESTIA/conf/$type.backup.conf + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Updating hestia.conf +bckp=$(echo "$BACKUP_SYSTEM" \ + | sed "s/,/\n/g" \ + | sed "s/^$type$//" \ + | sed "/^$/d" \ + | sed ':a;N;$!ba;s/\n/,/g') +sed -i "s/BACKUP_SYSTEM=.*/BACKUP_SYSTEM='$bckp'/g" $HESTIA/conf/hestia.conf + +# Logging +$BIN/v-log-action "system" "Info" "Backup" "Removed remote backup host (Host: $host, Type: $type)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-delete-cron-hestia-autoupdate b/bin/v-delete-cron-hestia-autoupdate new file mode 100755 index 0000000..833cfa7 --- /dev/null +++ b/bin/v-delete-cron-hestia-autoupdate @@ -0,0 +1,68 @@ +#!/bin/bash +# info: delete hestia autoupdate cron job +# options: NONE +# +# This function deletes hestia autoupdate cron job. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=admin + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +is_system_enabled "$CRON_SYSTEM" 'CRON_SYSTEM' +check_cron_apt=$(grep 'v-update-sys-hestia-all' $USER_DATA/cron.conf) +check_cron_git=$(grep 'v-update-sys-hestia-git' $USER_DATA/cron.conf) + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Deleting job +if [ -n "$check_cron_apt" ]; then + job=$(echo $check_cron_apt | tr ' ' "\n" | grep JOB | cut -f 2 -d "'") +fi +if [ -n "$check_cron_git" ]; then + job=$(echo $check_cron_git | tr ' ' "\n" | grep JOB | cut -f 2 -d "'") +fi + +sed -i "/JOB='$job' /d" $USER_DATA/cron.conf + +# Sorting jobs by id +sort_cron_jobs + +# Sync system cron with user +sync_cron_jobs + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Decreasing cron value +decrease_user_value "$user" '$U_CRON_JOBS' + +# Restarting crond +$BIN/v-restart-cron +check_result $? "Cron restart failed" > /dev/null + +# Logging +$BIN/v-log-action "system" "Warning" "System" "Automatic updates disabled." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-delete-cron-job b/bin/v-delete-cron-job new file mode 100755 index 0000000..58aa236 --- /dev/null +++ b/bin/v-delete-cron-job @@ -0,0 +1,73 @@ +#!/bin/bash +# info: delete cron job +# options: USER JOB +# +# example: v-delete-cron-job admin 9 +# +# This function deletes cron job. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +job=$2 +restart=$3 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER JOB [RESTART]' +is_format_valid 'user' 'job' +is_system_enabled "$CRON_SYSTEM" 'CRON_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_valid 'cron' 'JOB' "$job" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +suspended=$(grep "JOB='$job'" $USER_DATA/cron.conf | grep "SUSPENDED='yes'") +# Deleting job +sed -i "/JOB='$job' /d" $USER_DATA/cron.conf + +# Sorting jobs by id +sort_cron_jobs + +# Sync system cron with user +sync_cron_jobs + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Decreasing cron value +decrease_user_value "$user" '$U_CRON_JOBS' + +# Check if is suspended to decrease the suspended value +if [ -n "$suspended" ]; then + decrease_user_value "$user" '$SUSPENDED_CRON' +fi + +# Restarting cron +$BIN/v-restart-cron "$restart" +check_result $? "Restart restart failed" > /dev/null + +# Logging +$BIN/v-log-action "$user" "Info" "Cron Jobs" "Cron job deleted (ID: $job)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-delete-cron-reports b/bin/v-delete-cron-reports new file mode 100755 index 0000000..92c0ee3 --- /dev/null +++ b/bin/v-delete-cron-reports @@ -0,0 +1,60 @@ +#!/bin/bash +# info: delete cron reports +# options: USER +# +# example: v-delete-cron-reports admin +# +# This function for disabling reports on cron tasks and administrative +# notifications. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'USER' +is_format_valid 'user' +is_system_enabled "$CRON_SYSTEM" 'CRON_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Changing user report value +update_user_value "$user" '$CRON_REPORTS' 'no' + +# Sync system cron with user +sync_cron_jobs + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Restarting cron +$BIN/v-restart-cron +check_result $? "Cron restart failed" > /dev/null + +# Logging +$BIN/v-log-action "$user" "Info" "Warning" "Cron job notifications and reporting disabled." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-delete-cron-restart-job b/bin/v-delete-cron-restart-job new file mode 100755 index 0000000..0354e51 --- /dev/null +++ b/bin/v-delete-cron-restart-job @@ -0,0 +1,47 @@ +#!/bin/bash +# info: delete restart job +# options: NONE +# +# This function for disabling restart cron tasks + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +is_system_enabled "$CRON_SYSTEM" 'CRON_SYSTEM' + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Add cron job +cmd="sudo $BIN/v-update-sys-queue restart" +check_cron=$(grep "$cmd" $HESTIA/data/users/admin/cron.conf 2> /dev/null) +if [ -n "$check_cron" ]; then + parse_object_kv_list "$check_cron" + $BIN/v-delete-cron-job admin "$JOB" +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-delete-database b/bin/v-delete-database new file mode 100755 index 0000000..38ed0c0 --- /dev/null +++ b/bin/v-delete-database @@ -0,0 +1,78 @@ +#!/bin/bash +# info: delete database +# options: USER DATABASE +# +# example: v-delete-database admin wp_db +# +# This function for deleting the database. If database user have access to +# another database, he will not be deleted. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +database=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/db.sh +source $HESTIA/func/db.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DATABASE' +is_format_valid 'user' 'database' +is_system_enabled "$DB_SYSTEM" 'DB_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_valid 'db' 'DB' "$database" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Get database values +get_database_values +# Issues with $SUSPENDED overwritten when delete_mysql_database is called +suspended=$SUSPENDED + +# Switching on db type +case $TYPE in + mysql) delete_mysql_database ;; + pgsql) delete_pgsql_database ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Deleting database +sed -i "/DB='$database' /d" $USER_DATA/db.conf + +# Decreasing counters +decrease_dbhost_values +decrease_user_value "$user" '$U_DATABASES' + +# Check if is suspended to decrease the suspended value +if [ -n "$suspended" ]; then + if [ "$suspended" == "yes" ]; then + decrease_user_value "$user" '$SUSPENDED_DB' + fi +fi + +# Logging +$BIN/v-log-action "$user" "Info" "Database" "Deleted database (Name: $database)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-delete-database-host b/bin/v-delete-database-host new file mode 100755 index 0000000..908f7d7 --- /dev/null +++ b/bin/v-delete-database-host @@ -0,0 +1,60 @@ +#!/bin/bash +# info: delete database server +# options: TYPE HOST +# +# example: v-delete-database-host pgsql localhost +# +# This function for deleting the database host from hestia configuration. It will +# be deleted if there are no databases created on it only. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +type=$1 +host=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/db.sh +source $HESTIA/func/db.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'TYPE HOST' +is_format_valid 'type' 'host' +is_system_enabled "$DB_SYSTEM" 'DB_SYSTEM' +is_type_valid "$DB_SYSTEM" "$type" +is_object_valid "../../conf/$type" 'HOST' "$host" +is_dbhost_free + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Deleting server +sed -i "/HOST='$host' /d" "$HESTIA/conf/$type.conf" +# Delete RRD database +rm -fr $HESTIA'/web/rrd/db/'$type'_'$host'.rrd' +rm -fr $HESTIA'/web/rrd/db/'*-$type'_'$host'.*' + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +$BIN/v-log-action "system" "Info" "Database" "Removed remote database host (Host: $host, Type: $type)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-delete-database-temp-user b/bin/v-delete-database-temp-user new file mode 100755 index 0000000..476b969 --- /dev/null +++ b/bin/v-delete-database-temp-user @@ -0,0 +1,69 @@ +#!/bin/bash +# info: deletes temp database user +# options: USER DBUSER [TYPE] [HOST] +# +# example: v-add-database-temp-user wordress hestia_sso_user mysql +# +# Revokes "temp user" access to a database and removes the user +# To be used in combination with v-add-database-temp-user + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +database=$2 +dbuser=$3 +type=${4-mysql} +host=$5 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/db.sh +source $HESTIA/func/db.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '3' "$#" 'USER DATABASE DBUSER [TYPE] [HOST]' +is_format_valid 'user' 'database' 'dbuser' +is_system_enabled "$DB_SYSTEM" 'DB_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'db' 'DB' "$database" +is_object_unsuspended 'db' 'DB' "$database" +get_next_dbhost + +if [[ $dbuser != *"hestia_sso"* ]]; then + echo "DBUSER is invalid SSO user" + exit "$E_INVALID" +fi + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Get database values +get_database_values + +delete_mysql_database_temp_user + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +$BIN/v-log-action "$user" "Info" "Database" "Revoked user access (Database: $database, User: $dbuser)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-delete-databases b/bin/v-delete-databases new file mode 100755 index 0000000..bae7992 --- /dev/null +++ b/bin/v-delete-databases @@ -0,0 +1,52 @@ +#!/bin/bash +# info: delete user databases +# options: USER +# +# example: v-delete-databases admin +# +# This function deletes all user databases. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'USER' +is_format_valid 'user' +is_system_enabled "$DB_SYSTEM" 'DB_SYSTEM' +is_object_valid 'user' 'USER' "$user" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Starting delete loop +for database in $(search_objects 'db' 'SUSPENDED' "no" 'DB'); do + $BIN/v-delete-database "$user" "$database" +done + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-delete-dns-domain b/bin/v-delete-dns-domain new file mode 100755 index 0000000..9de8c86 --- /dev/null +++ b/bin/v-delete-dns-domain @@ -0,0 +1,105 @@ +#!/bin/bash +# info: delete dns domain +# options: USER DOMAIN +# +# example: v-delete-dns-domain alice acme.com +# +# This function for deleting DNS domain. By deleting it all records will also be +# deleted. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +restart="$3" + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +format_domain +format_domain_idn + +check_args '2' "$#" 'USER DOMAIN' +is_format_valid 'user' 'domain' +is_system_enabled "$DNS_SYSTEM" 'DNS_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_valid 'dns' 'DOMAIN' "$domain" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +suspended=$(grep "DOMAIN='$domain'" $USER_DATA/dns.conf | grep "SUSPENDED='yes'") + +dnssec=$(grep "DOMAIN='$domain'" $USER_DATA/dns.conf | grep "DNSSEC='yes'") + +records=$(wc -l $USER_DATA/dns/$domain.conf | cut -f 1 -d ' ') + +# Deleting system configs +if [[ "$DNS_SYSTEM" =~ named|bind ]]; then + if [ -e '/etc/named.conf' ]; then + dns_conf='/etc/named.conf' + else + dns_conf='/etc/bind/named.conf' + fi + + sed -i "/\/$user\/conf\/dns\/$domain.db\"/d" $dns_conf + rm -f $HOMEDIR/$user/conf/dns/$domain.db +fi + +if [ -n "$dnssec" ]; then + # Delete existing keys + rm -fr $HOMEDIR/$user/conf/dns/$domain.db.* + rm -fr /var/cache/bind/K$domain_idn.* + rm -fr $USER_DATA/keys/K$domain_idn.* +fi + +# Updating dns-cluster queue +if [ "$DNS_CLUSTER" = "yes" ]; then + cmd="$BIN/v-delete-remote-dns-domain $user $domain" + echo "$cmd" >> $HESTIA/data/queue/dns-cluster.pipe +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Deleting domain +sed -i "/DOMAIN='$domain'/ d" $USER_DATA/dns.conf +rm -f $USER_DATA/dns/$domain.conf + +# Decreasing domain value +decrease_user_value "$user" '$U_DNS_DOMAINS' +decrease_user_value "$user" '$U_DNS_RECORDS' "$records" + +# Restarting named +$BIN/v-restart-dns "$restart" +check_result $? "Bind restart failed" > /dev/null + +# Check if is suspended to decrease the suspended value +if [ -n "$suspended" ]; then + decrease_user_value "$user" '$SUSPENDED_DNS' +fi + +# Logging +$BIN/v-log-action "$user" "Info" "DNS" "Deleted DNS zone (Name: $domain)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-delete-dns-domains b/bin/v-delete-dns-domains new file mode 100755 index 0000000..57e2f62 --- /dev/null +++ b/bin/v-delete-dns-domains @@ -0,0 +1,57 @@ +#!/bin/bash +# info: delete dns domains +# options: USER [RESTART] +# +# example: v-delete-dns-domains bob +# +# This function for deleting all users DNS domains. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +restart=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'USER [RESTART]' +is_format_valid 'user' +is_system_enabled "$DNS_SYSTEM" 'DNS_SYSTEM' +is_object_valid 'user' 'USER' "$user" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Starting delete loop +for domain in $(search_objects 'dns' 'SUSPENDED' "no" 'DOMAIN'); do + $BIN/v-delete-dns-domain "$user" "$domain" 'no' +done + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Restarting named +$BIN/v-restart-dns "$restart" +check_result $? "Bind restart failed" > /dev/null + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-delete-dns-domains-src b/bin/v-delete-dns-domains-src new file mode 100755 index 0000000..30e067b --- /dev/null +++ b/bin/v-delete-dns-domains-src @@ -0,0 +1,58 @@ +#!/bin/bash +# info: delete dns domains based on SRC field +# options: USER SRC [RESTART] +# +# example: v-delete-dns-domains-src admin '' yes +# +# This function for deleting DNS domains related to a certain host. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +src=$2 +restart=$3 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER SRC [RESTART]' +is_format_valid 'user' 'src' +is_system_enabled "$DNS_SYSTEM" 'DNS_SYSTEM' +is_object_valid 'user' 'USER' "$user" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Starting delete loop +for domain in $(search_objects 'dns' 'SRC' "$src" 'DOMAIN'); do + $BIN/v-delete-dns-domain "$user" "$domain" 'no' +done + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Restart named +$BIN/v-restart-dns "$restart" +check_result $? "Bind restart failed" > /dev/null + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-delete-dns-on-web-alias b/bin/v-delete-dns-on-web-alias new file mode 100755 index 0000000..db2fb3b --- /dev/null +++ b/bin/v-delete-dns-on-web-alias @@ -0,0 +1,92 @@ +#!/bin/bash +# info: delete dns domain or dns record based on web domain alias +# options: USER DOMAIN ALIAS [RESTART] +# +# example: v-delete-dns-on-web-alias admin example.com www.example.com +# +# This function deletes dns domain or dns record based on web domain alias. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +alias=$3 +domain_idn=$2 +dom_alias=$(idn2 --quiet -d "$3") +dom_alias=$(echo $dom_alias | sed -e 's/\.*$//g' -e 's/^\.*//g') +dom_alias=$(echo $dom_alias | tr '[:upper:]' '[:lower:]') +dom_alias_idn=$(idn2 --quiet "$dom_alias") +restart="$4" + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn +# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ? + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '3' "$#" 'USER DOMAIN ALIAS [RESTART]' +is_format_valid 'user' 'domain' 'alias' 'restart' +is_system_enabled "$WEB_SYSTEM" 'WEB_SYSTEM' +is_system_enabled "$DNS_SYSTEM" 'DNS_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_valid 'web' 'DOMAIN' "$domain" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Parsing domain values +get_domain_values 'web' + +# Check if it a simple domain +if [ $(echo -e "${dom_alias//\./\n}" | wc -l) -le 2 ]; then + if [ -e "$USER_DATA/dns/$dom_alias.conf" ]; then + $BIN/v-delete-dns-domain $user $dom_alias $IP $restart + fi +else + # Check subdomain + sub=$(echo "$dom_alias" | cut -f1 -d . -s) + root=$(echo "$dom_alias" | sed "s/^$sub.//") + if [ -e "$USER_DATA/dns/$root.conf" ]; then + if [ "$sub" == '*' ]; then + rec=$(grep -w "RECORD='\*'" $USER_DATA/dns/$root.conf) + else + rec=$(grep -w "RECORD='$sub'" $USER_DATA/dns/$root.conf) + fi + if [ -n "$rec" ]; then + parse_object_kv_list "$rec" + $BIN/v-delete-dns-record "$user" "$root" "$ID" "$restart" + fi + fi +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-delete-dns-record b/bin/v-delete-dns-record new file mode 100755 index 0000000..0c495d6 --- /dev/null +++ b/bin/v-delete-dns-record @@ -0,0 +1,95 @@ +#!/bin/bash +# info: delete dns record +# options: USER DOMAIN ID [RESTART] +# +# example: v-delete-dns-record bob acme.com 42 yes +# +# This function for deleting a certain record of DNS zone. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 +id=$3 +restart=$4 +quiet=$5 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# shellcheck source=/usr/local/hestia/func/rebuild.sh +source $HESTIA/func/rebuild.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn +# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ? + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '3' "$#" 'USER DOMAIN ID [RESTART]' +is_format_valid 'user' 'domain' 'id' +is_object_valid 'user' 'USER' "$user" +is_object_valid 'dns' 'DOMAIN' "$domain" +is_object_valid "dns/$domain" 'ID' "$id" +is_dns_record_critical + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Deleting record +sed -i "/^ID='$id'/d" $USER_DATA/dns/$domain.conf + +# Update serial +update_domain_serial +# Updating zone +if [[ "$DNS_SYSTEM" =~ named|bind ]]; then + rebuild_dns_domain_conf +fi + +# Updating dns-cluster queue +if [ "$DNS_CLUSTER" = "yes" ]; then + # Check for first sync + dlock=$(grep "domain $user $domain" $HESTIA/data/queue/dns-cluster.pipe) + if [ -z "$dlock" ]; then + cmd="$BIN/v-delete-remote-dns-record $user $domain $id" + echo "$cmd" >> $HESTIA/data/queue/dns-cluster.pipe + fi +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Upddate counters +records="$(wc -l $USER_DATA/dns/$domain.conf | cut -f1 -d ' ')" +update_object_value 'dns' 'DOMAIN' "$domain" '$RECORDS' "$records" +decrease_user_value "$user" '$U_DNS_RECORDS' + +# Restarting named +$BIN/v-restart-dns "$restart" +check_result $? "Bind restart failed" > /dev/null + +# Logging +if [ "$quiet" != "yes" ]; then + $BIN/v-log-action "$user" "Info" "DNS" "Deleted DNS record (ID: $id, Domain: $domain)." +fi +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-delete-domain b/bin/v-delete-domain new file mode 100755 index 0000000..3a4f247 --- /dev/null +++ b/bin/v-delete-domain @@ -0,0 +1,90 @@ +#!/bin/bash +# info: delete web/dns/mail domain +# options: USER DOMAIN +# +# example: v-delete-domain admin domain.tld +# +# This function deletes web/dns/mail domain. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +restart="${3-yes}" + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DOMAIN' +is_format_valid 'user' 'domain' +is_object_valid 'user' 'USER' "$user" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Working on Web domain +if [ -n "$WEB_SYSTEM" ]; then + str=$(grep "DOMAIN='$domain'" $USER_DATA/web.conf) + if [ -n "$str" ]; then + domain_found='yes' + $BIN/v-delete-web-domain "$user" "$domain" 'no' + check_result $? "can't suspend web" > /dev/null + fi +fi + +# Working on DNS domain +if [ -n "$DNS_SYSTEM" ]; then + str=$(grep "DOMAIN='$domain'" $USER_DATA/dns.conf) + if [ -n "$str" ]; then + domain_found='yes' + $BIN/v-delete-dns-domain "$user" "$domain" 'no' + check_result $? "can't suspend dns" > /dev/null + fi +fi + +# Working on Mail domain +if [ -n "$MAIL_SYSTEM" ]; then + str=$(grep "DOMAIN='$domain'" $USER_DATA/mail.conf) + if [ -n "$str" ]; then + domain_found='yes' + $BIN/v-delete-mail-domain "$user" "$domain" + check_result $? "can't suspend mail" > /dev/null + fi +fi + +# Checking domain search result +if [ -z "$domain_found" ]; then + check_result "$E_NOTEXIST" "domain $domain doesn't exist" +fi + +# Restarting services +$BIN/v-restart-web "$restart" +check_result $? "can't restart web" > /dev/null + +$BIN/v-restart-proxy "$restart" +check_result $? "can't restart proxy" > /dev/null + +$BIN/v-restart-dns "$restart" +check_result $? "can't restart dns" > /dev/null + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-delete-fastcgi-cache b/bin/v-delete-fastcgi-cache new file mode 100755 index 0000000..e89b74c --- /dev/null +++ b/bin/v-delete-fastcgi-cache @@ -0,0 +1,90 @@ +#!/bin/bash +# info: Disable FastCGI cache for nginx +# options: USER DOMAIN [RESTART] +# +# example: v-delete-fastcgi-cache user domain.tld +# +# This function disables FastCGI cache for nginx + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +restart=$3 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf + +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DOMAIN' +is_format_valid 'user' 'domain' +is_object_valid 'user' 'USER' "$user" +is_object_valid 'web' 'DOMAIN' "$domain" +is_object_valid 'web' 'DOMAIN' "$domain" "$FASTCGI_CACHE" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Load domain data +parse_object_kv_list $(grep "DOMAIN='$domain'" $USER_DATA/web.conf) + +# Remove FastCGI cache configuration +if [ -f "$HOMEDIR/$user/conf/web/$domain/$WEB_SYSTEM.fastcgi_cache.conf" ]; then + rm -rf $HOMEDIR/$user/conf/web/$domain/$WEB_SYSTEM.fastcgi_cache.conf +fi + +conf='/etc/nginx/conf.d/fastcgi_cache_pool.conf' +if [ -f "$conf" ]; then + sed -i "/ keys_zone=$domain/d" $conf + if [ ! -s "$conf" ]; then + rm -rf $conf + fi +fi + +# Delete FastCGI cache folder +if [ -d "/var/cache/nginx/micro/$domain" ]; then + rm -rf /var/cache/nginx/micro/$domain +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +if [ -z "$FASTCGI_CACHE" ]; then + add_object_key "web" 'DOMAIN' "$domain" 'FASTCGI_CACHE' 'ALIAS' +fi +if [ -z "$FASTCGI_DURATION" ]; then + add_object_key "web" 'DOMAIN' "$domain" 'FASTCGI_DURATION' 'ALIAS' +fi + +# Set FastCGI cache flag to disabled +update_object_value 'web' 'DOMAIN' "$domain" '$FASTCGI_CACHE' 'no' +update_object_value 'web' 'DOMAIN' "$domain" '$FASTCGI_DURATION' '0s' + +# Restart web server +if [ -n "$restart" ]; then + $BIN/v-restart-web "$restart" + check_result $? "Web server restart failed" > /dev/null +fi + +# Logging +$BIN/v-log-action "$user" "Info" "Web" "FastCGI cache disabled (Domain: $domain)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-delete-firewall-ban b/bin/v-delete-firewall-ban new file mode 100755 index 0000000..6972247 --- /dev/null +++ b/bin/v-delete-firewall-ban @@ -0,0 +1,88 @@ +#!/bin/bash +# info: delete firewall blocking rule +# options: IP CHAIN +# +# example: v-delete-firewall-ban 198.11.130.250 MAIL +# +# This function deletes blocking rule from system firewall + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +ip=$1 +chain=$(echo $2 | tr '[:lower:]' '[:upper:]') + +# Defining absolute path for iptables and modprobe +iptables="/sbin/iptables" + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/firewall.sh +source $HESTIA/func/firewall.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'IP CHAIN' +is_format_valid 'ip' 'chain' +is_system_enabled "$FIREWALL_SYSTEM" 'FIREWALL_SYSTEM' + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Self heal iptables links +heal_iptables_links + +conf="$HESTIA/data/firewall/banlist.conf" +if [ "$chain" == "ALL" ]; then + check_ip=$(grep "IP='$ip' CHAIN='*'" $conf) + if [ -z "$check_ip" ]; then + exit + fi + grep "IP='$ip' CHAIN='*'" $conf | while read -r line; do + parse_object_kv_list $line + + # Deleting ip from banlist + sip=$(echo "$IP" | sed "s|/|\\\/|g") + sed -i "/IP='$sip' CHAIN='$CHAIN'/d" $conf + b=$($iptables -L fail2ban-$CHAIN --line-number -n | grep -w $ip | awk '{print $1}') + $iptables -D fail2ban-$CHAIN $b 2> /dev/null + done +else + # Checking ip in banlist + check_ip=$(grep "IP='$ip' CHAIN='$chain'" $conf 2> /dev/null) + if [ -z "$check_ip" ]; then + exit + fi + + # Deleting ip from banlist + sip=$(echo "$ip" | sed "s|/|\\\/|g") + sed -i "/IP='$sip' CHAIN='$chain'/d" $conf + b=$($iptables -L fail2ban-$chain --line-number -n | grep -w $ip | awk '{print $1}') + $iptables -D fail2ban-$chain $b 2> /dev/null +fi + +# Changing permissions +chmod 660 $conf + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +$BIN/v-log-action "system" "Info" "Firewall" "Removed IP from ban list (IP: $ip, Service: $chain)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-delete-firewall-chain b/bin/v-delete-firewall-chain new file mode 100755 index 0000000..363cbe8 --- /dev/null +++ b/bin/v-delete-firewall-chain @@ -0,0 +1,71 @@ +#!/bin/bash +# info: delete firewall chain +# options: CHAIN +# +# example: v-delete-firewall-chain WEB +# +# This function adds new rule to system firewall + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +chain=$(echo $1 | tr '[:lower:]' '[:upper:]') + +iptables='/sbin/iptables' +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/firewall.sh +source $HESTIA/func/firewall.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'CHAIN' +is_format_valid 'chain' +is_system_enabled "$FIREWALL_SYSTEM" 'FIREWALL_SYSTEM' + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Self heal iptables links +heal_iptables_links + +# Deleting chain +chains=$HESTIA/data/firewall/chains.conf +banlist=$HESTIA/data/firewall/banlist.conf +chain_param=$(grep "CHAIN='$chain'" $chains 2> /dev/null) +if [ -n "$chain_param" ]; then + parse_object_kv_list "$chain_param" + sed -i "/CHAIN='$chain'/d" $chains + sed -i "/CHAIN='$chain'/d" $banlist + $iptables -D INPUT -p $PROTOCOL \ + --dport $PORT -j fail2ban-$CHAIN 2> /dev/null +fi + +# Deleting iptables chain +$iptables -F fail2ban-$CHAIN 2> /dev/null +$iptables -X fail2ban-$CHAIN 2> /dev/null + +# Changing permissions +chmod 660 $chains + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-delete-firewall-ipset b/bin/v-delete-firewall-ipset new file mode 100755 index 0000000..293f11f --- /dev/null +++ b/bin/v-delete-firewall-ipset @@ -0,0 +1,80 @@ +#!/bin/bash +# info: delete firewall ipset +# options: NAME +# +# example: v-delete-firewall-ipset country-nl +# +# This function removes ipset from system and from hestia + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +ip_name=${1} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'NAME' +is_format_valid 'ip_name' +is_system_enabled "$FIREWALL_SYSTEM" 'FIREWALL_SYSTEM' + +# Define variables for ipset configuration +ipset_hstobject='../../data/firewall/ipset' +is_object_valid "$ipset_hstobject" 'LISTNAME' "$ip_name" +ip_version="$(get_object_value "$ipset_hstobject" 'LISTNAME' "$ip_name" '$IP_VERSION')" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +IPSET_BIN="$(command -v ipset)" +IPSET_PATH="$HESTIA/data/firewall/ipset" +IPSET_FILE="${ip_name}.${ip_version}" + +# Install ipset package if missing +if [ -z "$IPSET_BIN" ]; then + if [ -f '/etc/redhat-release' ]; then + dnf install -q -y ipset > /dev/null + else + apt-get --quiet --yes install ipset > /dev/null + fi + check_result $? "Installing IPset package" + + IPSET_BIN="$(which ipset)" + check_result $? "IPset binary not found" +fi + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +if $IPSET_BIN -quiet list "${ip_name}-tmp" > /dev/null; then + $IPSET_BIN -quiet destroy "${ip_name}-tmp" +fi + +if $IPSET_BIN -quiet list "${ip_name}" > /dev/null; then + $IPSET_BIN -quiet destroy "${ip_name}" + check_result $? "ipset ${ip_name} still used by iptables. Cannot remove" +fi + +sed -i "/LISTNAME='$ip_name'/d" "${IPSET_PATH}.conf" +rm -f "${IPSET_PATH}/${IPSET_FILE}.iplist" + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +$BIN/v-log-action "system" "Info" "Firewall" "IPset IP list deleted (Name: $ip_name)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-delete-firewall-rule b/bin/v-delete-firewall-rule new file mode 100755 index 0000000..4544021 --- /dev/null +++ b/bin/v-delete-firewall-rule @@ -0,0 +1,54 @@ +#!/bin/bash +# info: delete firewall rule +# options: RULE +# +# example: v-delete-firewall-rule SSH_BLOCK +# +# This function deletes firewall rule. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +rule=$1 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'RULE' +is_format_valid 'rule' +is_system_enabled "$FIREWALL_SYSTEM" 'FIREWALL_SYSTEM' +is_object_valid '../../data/firewall/rules' 'RULE' "$rule" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Deleting rule +sed -i "/RULE='$rule' /d" $HESTIA/data/firewall/rules.conf + +# Updating system firewall +$BIN/v-update-firewall + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +$BIN/v-log-action "system" "Info" "Firewall" "Removed firewall rule (ID: $rule)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-delete-fs-directory b/bin/v-delete-fs-directory new file mode 100755 index 0000000..7f30d41 --- /dev/null +++ b/bin/v-delete-fs-directory @@ -0,0 +1,57 @@ +#!/bin/bash +# info: delete directory +# options: USER DIRECTORY +# +# example: v-delete-fs-directory admin report1 +# +# This function deletes directory on the file system + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +user=$1 +dst_dir=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DIRECTORY' +is_format_valid 'user' +is_object_valid 'user' 'USER' "$user" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +# Checking user homedir +homedir=$(grep "^$user:" /etc/passwd | cut -f 6 -d :) +if [ -z "$homedir" ]; then + echo "Error: user home directory doesn't exist" + exit 12 +fi + +# Checking destination path +rpath=$(readlink -f "$dst_dir") +if [ -z "$(echo $rpath | egrep "^/tmp|^$homedir")" ]; then + echo "Error: invalid destination path $dst_dir" + exit 1 +fi + +# Deleting directory +user_exec rm -rf "$dst_dir" # >/dev/null 2>&1 +if [ $? -ne 0 ]; then + echo "Error: directory $dst_dir was not deleted" + exit 3 +fi + +# Exiting +exit diff --git a/bin/v-delete-fs-file b/bin/v-delete-fs-file new file mode 100755 index 0000000..dacd9d3 --- /dev/null +++ b/bin/v-delete-fs-file @@ -0,0 +1,55 @@ +#!/bin/bash +# info: delete file +# options: USER FILE +# +# example: v-delete-fs-file admin readme.txt +# +# This function deletes file on the file system + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +user=$1 +dst_file=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER FILE' +is_format_valid 'user' +is_object_valid 'user' 'USER' "$user" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +# Checking user homedir +homedir=$(grep "^$user:" /etc/passwd | cut -f 6 -d :) +if [ -z $homedir ]; then + echo "Error: user home directory doesn't exist" + exit 12 +fi + +# Checking destination path +rpath=$(readlink -f "$dst_file") +if [ -z "$(echo $rpath | egrep "^/tmp|^$homedir")" ]; then + echo "Error: invalid destination path $dst_file" + exit 2 +fi + +# Deleting file +user_exec rm -f "$dst_file" > /dev/null 2>&1 +if [ $? -ne 0 ]; then + echo "Error: file $dst_file was not deleted" + exit 3 +fi + +# Exiting +exit diff --git a/bin/v-delete-letsencrypt-domain b/bin/v-delete-letsencrypt-domain new file mode 100755 index 0000000..6ccf3ea --- /dev/null +++ b/bin/v-delete-letsencrypt-domain @@ -0,0 +1,117 @@ +#!/bin/bash +# info: deleting letsencrypt ssl cetificate for domain +# options: USER DOMAIN [RESTART] [MAIL] +# +# example: v-delete-letsencrypt-domain admin acme.com yes +# +# This function turns off letsencrypt SSL support for a domain. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +restart=$3 +mail=$4 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DOMAIN [RESTART] [MAIL]' +is_format_valid 'user' 'domain' +is_system_enabled "$WEB_SYSTEM" 'WEB_SYSTEM' +is_system_enabled "$WEB_SSL" 'SSL_SUPPORT' +is_object_valid 'user' 'USER' "$user" +if [ -z "$mail" ]; then + is_object_valid 'web' 'DOMAIN' "$domain" + is_object_unsuspended 'web' 'DOMAIN' "$domain" + is_object_value_exist 'web' 'DOMAIN' "$domain" '$LETSENCRYPT' +else + is_object_valid 'mail' 'DOMAIN' "$domain" + is_object_unsuspended 'mail' 'DOMAIN' "$domain" + is_object_value_exist 'mail' 'DOMAIN' "$domain" '$LETSENCRYPT' +fi + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Delete DNS CAA record +if [ -n "$DNS_SYSTEM" ]; then + dns_domain=$($BIN/v-list-dns-domains "$user" | grep "$domain" | cut -d' ' -f1) + caa_record=$($BIN/v-list-dns-records "$user" "$domain" | grep -i "letsencrypt" | cut -d' ' -f1) + + if [ "$dns_domain" = "$domain" ]; then + if [ -n "$caa_record" ]; then + if [ -z "$mail" ]; then + mail_exists=$(is_object_value_exist 'mail' 'DOMAIN' "$domain" '$LETSENCRYPT') + if [ "$mail_exists" != '' ]; then + $BIN/v-delete-dns-record "$user" "$domain" "$caa_record" + fi + else + web_exists=$(is_object_value_exist 'web' 'DOMAIN' "$domain" '$LETSENCRYPT') + if [ "$web_exists" != '' ]; then + $BIN/v-delete-dns-record "$user" "$domain" "$caa_record" + fi + fi + fi + fi +fi + +# Delete SSL +if [ -z "$mail" ]; then + $BIN/v-delete-web-domain-ssl "$user" "$domain" "$restart" > /dev/null 2>&1 +else + $BIN/v-delete-mail-domain-ssl "$user" "$domain" "$restart" > /dev/null 2>&1 +fi + +if [ $? -ne "$E_NOTEXIST" ]; then + check_result $? "SSL delete" > /dev/null +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Updating letsencrypt flag +if [ -z "$mail" ]; then + update_object_value 'web' 'DOMAIN' "$domain" '$LETSENCRYPT' 'no' +else + update_object_value 'mail' 'DOMAIN' "$domain" '$LETSENCRYPT' 'no' +fi + +# Restarting web +$BIN/v-restart-web "$restart" +check_result $? "Web restart failed" > /dev/null + +if [ -n "$PROXY_SYSTEM" ]; then + $BIN/v-restart-web "$restart" > /dev/null + check_result $? "Proxy restart failed" > /dev/null +fi + +if [ -n "$mail" ]; then + # Restarting mail + $BIN/v-restart-mail "$restart" + check_result $? "Mail restart failed" > /dev/null +fi + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-delete-mail-account b/bin/v-delete-mail-account new file mode 100755 index 0000000..a635635 --- /dev/null +++ b/bin/v-delete-mail-account @@ -0,0 +1,82 @@ +#!/bin/bash +# info: delete mail account +# options: USER DOMAIN ACCOUNT +# +# example: v-delete-mail-account admin acme.com alice +# +# This function deletes email account. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 +account=$3 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '3' "$#" 'USER DOMAIN ACCOUNT' +is_format_valid 'user' 'domain' 'account' +is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_valid 'mail' 'DOMAIN' "$domain" +is_object_valid "mail/$domain" 'ACCOUNT' "$account" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +if [[ "$MAIL_SYSTEM" =~ exim ]]; then + aliases=$(get_object_value "mail/$domain" 'ACCOUNT' "$account" '$ALIAS') + for al in ${aliases//,/ }; do + sed -i "/^$al@$domain_idn:$account/d" \ + $HOMEDIR/$user/conf/mail/$domain/aliases + done + + sed -i "/^$account@$domain_idn:/d" $HOMEDIR/$user/conf/mail/$domain/aliases + sed -i "/^$account:/d" $HOMEDIR/$user/conf/mail/$domain/passwd + sed -i "/^$account:/d" $HOMEDIR/$user/conf/mail/$domain/accounts + sed -i "/^$account$/d" $HOMEDIR/$user/conf/mail/$domain/fwd_only + sed -i "/^$account@$domain_idn:/d" $HOMEDIR/$user/conf/mail/$domain/limits + rm -rf $HOMEDIR/$user/mail/$domain_idn/$account +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Update config +sed -i "/ACCOUNT='$account'/d" $USER_DATA/mail/$domain.conf + +# Decrease mail accounts counter +accounts=$(wc -l $USER_DATA/mail/$domain.conf | cut -f 1 -d ' ') +decrease_user_value "$user" '$U_MAIL_ACCOUNTS' +update_object_value 'mail' 'DOMAIN' "$domain" '$ACCOUNTS' "$accounts" + +# Logging +$BIN/v-log-action "$user" "Info" "Mail" "Mail account removed (User: $account@$domain)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-delete-mail-account-alias b/bin/v-delete-mail-account-alias new file mode 100755 index 0000000..89f3758 --- /dev/null +++ b/bin/v-delete-mail-account-alias @@ -0,0 +1,80 @@ +#!/bin/bash +# info: delete mail account alias aka nickname +# options: USER DOMAIN ACCOUNT ALIAS +# +# example: v-delete-mail-account-alias admin example.com alice alicia +# +# This function deletes email account alias. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 +account=$3 +malias=$4 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '4' "$#" 'USER DOMAIN ACCOUNT ALIAS' +is_format_valid 'user' 'domain' 'account' 'malias' +is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_valid 'mail' 'DOMAIN' "$domain" +is_object_valid "mail/$domain" 'ACCOUNT' "$account" +aliases=$(get_object_value "mail/$domain" 'ACCOUNT' "$account" '$ALIAS') +if [ -z "$(echo $aliases | grep -w $malias)" ]; then + echo "Error: alias $malias doesn't exist" + log_event "$E_NOTEXIST $ARGUMENTS" + exit "$E_NOTEXIST" +fi + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +if [[ "$MAIL_SYSTEM" =~ exim ]]; then + sed -i "/^$malias@$domain_idn:$account/d" \ + $HOMEDIR/$user/conf/mail/$domain/aliases +fi + +aliases=$(echo "$aliases" \ + | sed "s/,/\n/g" \ + | sed "s/^$malias$//g" \ + | sed "/^$/d" \ + | sed ':a;N;$!ba;s/\n/,/g') + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Update config +update_object_value "mail/$domain" 'ACCOUNT' "$account" '$ALIAS' "$aliases" + +# Logging +$BIN/v-log-action "$user" "Info" "Mail" "Mail account alias removed (Alias: $malias, User: $account@$domain)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-delete-mail-account-autoreply b/bin/v-delete-mail-account-autoreply new file mode 100755 index 0000000..1d1557e --- /dev/null +++ b/bin/v-delete-mail-account-autoreply @@ -0,0 +1,73 @@ +#!/bin/bash +# info: delete mail account autoreply message +# options: USER DOMAIN ACCOUNT ALIAS +# +# example: v-delete-mail-account-autoreply admin mydomain.tld bob +# +# This function deletes an email accounts autoreply. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 +account=$3 +malias=$4 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn +# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ? + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '3' "$#" 'USER DOMAIN ACCOUNT' +is_format_valid 'user' 'domain' 'account' +is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_valid 'mail' 'DOMAIN' "$domain" +is_object_valid "mail/$domain" 'ACCOUNT' "$account" +is_object_value_exist "mail/$domain" 'ACCOUNT' "$account" '$AUTOREPLY' + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Deleting exim autoreply message +if [[ "$MAIL_SYSTEM" =~ exim ]]; then + rm -f $HOMEDIR/$user/conf/mail/$domain/autoreply.$account.msg +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Deleting autoreply message +rm -f $USER_DATA/mail/$domain/$account@$domain.msg + +# Update config +update_object_value "mail/$domain" 'ACCOUNT' "$account" '$AUTOREPLY' 'no' + +# Logging +$BIN/v-log-action "$user" "Info" "Mail" "Mail account auto-reply removed (User: $account@$domain)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-delete-mail-account-forward b/bin/v-delete-mail-account-forward new file mode 100755 index 0000000..cc6efb1 --- /dev/null +++ b/bin/v-delete-mail-account-forward @@ -0,0 +1,83 @@ +#!/bin/bash +# info: delete mail account forward +# options: USER DOMAIN ACCOUNT EMAIL +# +# example: v-delete-mail-account-forward admin acme.com tony bob@acme.com +# +# This function deletes an email accounts forwarding address. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 +account=$3 +forward=$4 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '4' "$#" 'USER DOMAIN ACCOUNT FORWARD' +is_format_valid 'user' 'domain' 'account' +if [ "$forward" != ':blackhole:' ]; then + is_format_valid 'forward' +fi +is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_valid 'mail' 'DOMAIN' "$domain" +is_object_valid "mail/$domain" 'ACCOUNT' "$account" +fwd=$(get_object_value "mail/$domain" 'ACCOUNT' "$account" '$FWD') +if [ -z "$(echo $fwd | grep -w $forward)" ]; then + check_result "$E_NOTEXIST" "forward $forward doesn't exist" +fi + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Define new fwd string +fwd=$(echo "$fwd" \ + | sed "s/,/\n/g" \ + | sed "s/^$forward$//g" \ + | sed "/^$/d" \ + | sed ':a;N;$!ba;s/\n/,/g') + +# Deleting exim forward +if [[ "$MAIL_SYSTEM" =~ exim ]]; then + sed -i "/^$account@$domain_idn:/ d" $HOMEDIR/$user/conf/mail/$domain/aliases + echo "$account@$domain_idn:$fwd" >> $HOMEDIR/$user/conf/mail/$domain/aliases +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Updating config +update_object_value "mail/$domain" 'ACCOUNT' "$account" '$FWD' "$fwd" + +# Logging +$BIN/v-log-action "$user" "Info" "Mail" "Mail account forwarding address removed (User: $account@$domain, Send To: $forward)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-delete-mail-account-fwd-only b/bin/v-delete-mail-account-fwd-only new file mode 100755 index 0000000..b27791d --- /dev/null +++ b/bin/v-delete-mail-account-fwd-only @@ -0,0 +1,68 @@ +#!/bin/bash +# info: delete mail account forward-only flag +# options: USER DOMAIN ACCOUNT +# +# example: v-delete-mail-account-fwd-only admin example.com jack +# +# This function deletes fwd-only flag + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 +account=$3 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn +# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ? + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '3' "$#" 'USER DOMAIN ACCOUNT' +is_format_valid 'user' 'domain' 'account' +is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_valid 'mail' 'DOMAIN' "$domain" +is_object_valid "mail/$domain" 'ACCOUNT' "$account" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Deleting account from fwd_only +if [[ "$MAIL_SYSTEM" =~ exim ]]; then + sed -i "/^$account$/d" $HOMEDIR/$user/conf/mail/$domain/fwd_only +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Updating config +update_object_value "mail/$domain" 'ACCOUNT' "$account" '$FWD_ONLY' '' + +# Logging +$BIN/v-log-action "$user" "Info" "Mail" "Mail account forwarding disabled (User: $account@$domain)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-delete-mail-domain b/bin/v-delete-mail-domain new file mode 100755 index 0000000..039fe5b --- /dev/null +++ b/bin/v-delete-mail-domain @@ -0,0 +1,111 @@ +#!/bin/bash +# info: delete mail domain +# options: USER DOMAIN +# +# example: v-delete-mail-domain admin mydomain.tld +# +# This function for deleting MAIL domain. By deleting it all accounts will +# also be deleted. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DOMAIN' +is_format_valid 'user' 'domain' +is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_valid 'mail' 'DOMAIN' "$domain" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Get domain values +get_domain_values 'mail' +accounts=$(wc -l "$USER_DATA/mail/$domain.conf" | cut -f 1 -d ' ') + +# Deleting exim configuration files +if [[ "$MAIL_SYSTEM" =~ exim ]]; then + rm -f /etc/$MAIL_SYSTEM/domains/$domain_idn + rm -rf $HOMEDIR/$user/conf/mail/$domain + rm -rf $HOMEDIR/$user/mail/$domain_idn +fi + +# Deleting dkim dns record +if [ "$DKIM" = 'yes' ] && [ -e "$USER_DATA/dns/$domain.conf" ]; then + dkim_records=$($BIN/v-list-dns-records "$user" "$domain" | grep -E "\s(mail\._domainkey|_domainkey)\s" | cut -f 1 -d ' ') + for id in $dkim_records; do + $BIN/v-delete-dns-record "$user" "$domain" "$id" '' 'yes' + done +fi + +# Delete SSL certificates and configuration +if [ "$SSL" = 'yes' ] || [ -e "$HOMEDIR/$user/conf/mail/$domain/ssl/$domain.crt" ]; then + $BIN/v-delete-mail-domain-ssl "$user" "$domain" +fi + +# Delete webmail configuration if it exists +if [ -n "$WEB_SYSTEM" ] || [ -n "$PROXY_SYSTEM" ]; then + if [ -n "$IMAP_SYSTEM" ]; then + $BIN/v-delete-mail-domain-webmail "$user" "$domain" 'yes' + fi +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Delete domain config +sed -i "/DOMAIN='$domain'/ d" $USER_DATA/mail.conf +rm -f $USER_DATA/mail/$domain.conf +rm -f $USER_DATA/mail/$domain.pem +rm -f $USER_DATA/mail/$domain.pub +rm -f $USER_DATA/mail/*@$domain.msg + +# Decreasing domain value +decrease_user_value "$user" '$U_MAIL_DOMAINS' +if [ "$DKIM" = 'yes' ]; then + decrease_user_value "$user" '$U_MAIL_DKIM' +fi + +decrease_user_value "$user" '$U_MAIL_ACCOUNTS' "$accounts" + +# Check if is suspended to decrease the suspended value +if [ -n "$SUSPENDED" ]; then + if [ "$SUSPENDED" == "yes" ]; then + decrease_user_value "$user" '$SUSPENDED_MAIL' + fi +fi + +# Logging +$BIN/v-log-action "$user" "Info" "Mail" "Mail domain deleted (Domain: $domain)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-delete-mail-domain-antispam b/bin/v-delete-mail-domain-antispam new file mode 100755 index 0000000..f1d9f2a --- /dev/null +++ b/bin/v-delete-mail-domain-antispam @@ -0,0 +1,68 @@ +#!/bin/bash +# info: delete mail domain antispam support +# options: USER DOMAIN +# +# example: v-delete-mail-domain-antispam admin mydomain.tld +# +# This function disable spamassasin for incoming emails. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" +# Additional argument formatting +format_domain +format_domain_idn +# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ? + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DOMAIN' +is_format_valid 'user' 'domain' +is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'mail' 'DOMAIN' "$domain" +is_object_unsuspended 'mail' 'DOMAIN' "$domain" +is_object_value_exist 'mail' 'DOMAIN' "$domain" '$ANTISPAM' + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Delete antispam flag +if [[ "$MAIL_SYSTEM" =~ exim ]]; then + rm -f $HOMEDIR/$user/conf/mail/$domain/antispam +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Delete antispam in config +update_object_value 'mail' 'DOMAIN' "$domain" '$ANTISPAM' 'no' + +# Logging +$BIN/v-log-action "$user" "Info" "Mail" "Anti-spam protection disabled (Domain: $domain)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-delete-mail-domain-antivirus b/bin/v-delete-mail-domain-antivirus new file mode 100755 index 0000000..33f71ad --- /dev/null +++ b/bin/v-delete-mail-domain-antivirus @@ -0,0 +1,69 @@ +#!/bin/bash +# info: delete mail domain antivirus support +# options: USER DOMAIN +# +# example: v-delete-mail-domain-antivirus admin mydomain.tld +# +# This function disables clamav scan for incoming emails. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn +# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ? + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DOMAIN' +is_format_valid 'user' 'domain' +is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'mail' 'DOMAIN' "$domain" +is_object_unsuspended 'mail' 'DOMAIN' "$domain" +is_object_value_exist 'mail' 'DOMAIN' "$domain" '$ANTIVIRUS' + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Delete antivirus flag +if [[ "$MAIL_SYSTEM" =~ exim ]]; then + rm -f $HOMEDIR/$user/conf/mail/$domain/antivirus +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Delete antivirus in config +update_object_value 'mail' 'DOMAIN' "$domain" '$ANTIVIRUS' 'no' + +# Logging +$BIN/v-log-action "$user" "Info" "Mail" "Anti-virus scanning disabled (Domain: $domain)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-delete-mail-domain-catchall b/bin/v-delete-mail-domain-catchall new file mode 100755 index 0000000..0eeee20 --- /dev/null +++ b/bin/v-delete-mail-domain-catchall @@ -0,0 +1,66 @@ +#!/bin/bash +# info: delete mail domain catchall email +# options: USER DOMAIN +# +# example: v-delete-mail-domain-catchall admin mydomain.tld +# +# This function disables mail domain cathcall. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DOMAIN' +is_format_valid 'user' 'domain' +is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_valid 'mail' 'DOMAIN' "$domain" +is_object_value_exist 'mail' 'DOMAIN' "$domain" '$CATCHALL' + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Delete cathcall alias +if [[ "$MAIL_SYSTEM" =~ exim ]]; then + sed -i "/*@$domain_idn:/d" $HOMEDIR/$user/conf/mail/$domain/aliases +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Delete catchall in config +update_object_value 'mail' 'DOMAIN' "$domain" '$CATCHALL' '' + +# Logging +$BIN/v-log-action "$user" "Info" "Mail" "Catch-all forwarding disabled (Domain: $domain)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-delete-mail-domain-dkim b/bin/v-delete-mail-domain-dkim new file mode 100755 index 0000000..70cde00 --- /dev/null +++ b/bin/v-delete-mail-domain-dkim @@ -0,0 +1,74 @@ +#!/bin/bash +# info: delete mail domain dkim support +# options: USER DOMAIN +# +# example: v-delete-mail-domain-dkim admin mydomain.tld +# +# This function delete DKIM domain pem. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain=$(echo $domain | tr '[:upper:]' '[:lower:]') + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DOMAIN' +is_format_valid 'user' 'domain' +is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_valid 'mail' 'DOMAIN' "$domain" +is_object_value_exist 'mail' 'DOMAIN' "$domain" '$DKIM' + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Deleting dkim +if [[ "$MAIL_SYSTEM" =~ exim ]]; then + rm -f $USER_DATA/mail/$domain.pem + rm -f $USER_DATA/mail/$domain.pub + rm -f $HOMEDIR/$user/conf/mail/$domain/dkim.pem +fi + +# Deleting dns record +if [ -n "$DNS_SYSTEM" ] && [ -e "$USER_DATA/dns/$domain.conf" ]; then + records=$($BIN/v-list-dns-records "$user" "$domain") + dkim_records=$(echo "$records" | grep -E "\s(mail\._domainkey|_domainkey)\s" | cut -f 1 -d ' ') + for id in $dkim_records; do + $BIN/v-delete-dns-record "$user" "$domain" "$id" 'yes' + done +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Updating config +update_object_value 'mail' 'DOMAIN' "$domain" '$DKIM' 'no' +decrease_user_value "$user" '$U_MAIL_DKIM' + +# Logging +$BIN/v-log-action "$user" "Info" "Mail" "DKIM message signing disabled (Domain: $domain)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-delete-mail-domain-reject b/bin/v-delete-mail-domain-reject new file mode 100755 index 0000000..1b8a4ed --- /dev/null +++ b/bin/v-delete-mail-domain-reject @@ -0,0 +1,70 @@ +#!/bin/bash +# info: delete mail domain reject spam support +# options: USER DOMAIN +# labels: mail +# +# example: v-delete-mail-domain-reject admin mydomain.tld +# +# The function disables spam rejection for incoming emails. + +#----------------------------------------------------------# +# Variable&Function # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" +# Additional argument formatting +format_domain +format_domain_idn +# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ? + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DOMAIN' +is_format_valid 'user' 'domain' +is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'mail' 'DOMAIN' "$domain" +is_object_unsuspended 'mail' 'DOMAIN' "$domain" +is_object_value_exist 'mail' 'DOMAIN' "$domain" '$REJECT' + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Delete antispam flag +if [[ "$MAIL_SYSTEM" =~ exim ]]; then + # Reject spam > 10 when enabled + rm -f $HOMEDIR/$user/conf/mail/$domain/reject_spam +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Delete antispam in config +update_object_value 'mail' 'DOMAIN' "$domain" '$REJECT' 'no' + +# Logging +$BIN/v-log-action "$user" "Info" "Mail" "Anti-spam protection disabled (Domain: $domain)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-delete-mail-domain-smtp-relay b/bin/v-delete-mail-domain-smtp-relay new file mode 100755 index 0000000..2af82aa --- /dev/null +++ b/bin/v-delete-mail-domain-smtp-relay @@ -0,0 +1,65 @@ +#!/bin/bash +# info: Remove mail domain smtp relay support +# options: USER DOMAIN +# +# example: v-delete-mail-domain-smtp-relay user domain.tld +# +# This function removes mail domain smtp relay support. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DOMAIN' +is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'mail' 'DOMAIN' "$domain" +is_object_unsuspended 'mail' 'DOMAIN' "$domain" + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +rm -f /etc/exim4/domains/${domain}/smtp_relay.conf + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Adding smtp relay values in config +if [ -z "$U_SMTP_RELAY" ]; then + add_object_key 'mail' 'DOMAIN' "$domain" 'U_SMTP_RELAY' 'ACCOUNTS' + add_object_key 'mail' 'DOMAIN' "$domain" 'U_SMTP_RELAY_HOST' 'ACCOUNTS' + add_object_key 'mail' 'DOMAIN' "$domain" 'U_SMTP_RELAY_PORT' 'ACCOUNTS' + add_object_key 'mail' 'DOMAIN' "$domain" 'U_SMTP_RELAY_USERNAME' 'ACCOUNTS' + add_object_key 'mail' 'DOMAIN' "$domain" 'U_SMTP_RELAY_PASSWORD' 'ACCOUNTS' +fi + +update_object_value 'mail' 'DOMAIN' "$domain" '$U_SMTP_RELAY' 'false' +update_object_value 'mail' 'DOMAIN' "$domain" '$U_SMTP_RELAY_HOST' '' +update_object_value 'mail' 'DOMAIN' "$domain" '$U_SMTP_RELAY_PORT' '' +update_object_value 'mail' 'DOMAIN' "$domain" '$U_SMTP_RELAY_USERNAME' '' +update_object_value 'mail' 'DOMAIN' "$domain" '$U_SMTP_RELAY_PASSWORD' '' + +# Logging +$BIN/v-log-action "$user" "Info" "Mail" "SMTP Relay disabled (Domain: $domain)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-delete-mail-domain-ssl b/bin/v-delete-mail-domain-ssl new file mode 100755 index 0000000..3bed1af --- /dev/null +++ b/bin/v-delete-mail-domain-ssl @@ -0,0 +1,72 @@ +#!/bin/bash +# info: delete mail domain ssl support +# options: USER DOMAIN +# +# example: v-delete-mail-domain-ssl user demo.com +# +# This function delete ssl certificates. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +restart=$3 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DOMAIN' +is_format_valid 'user' 'domain' +is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_valid 'mail' 'DOMAIN' "$domain" +is_object_value_exist 'mail' 'DOMAIN' "$domain" '$SSL' + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Delete mail domain SSL configuration +del_mail_ssl_config +del_mail_ssl_certificates +del_webmail_ssl_config + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Updating config +update_object_value 'mail' 'DOMAIN' "$domain" '$SSL' 'no' +update_object_value 'mail' 'DOMAIN' "$domain" '$LETSENCRYPT' 'no' +decrease_user_value "$user" '$U_MAIL_SSL' + +# Restarting mail server +$BIN/v-restart-mail "$restart" +check_result $? "Mail restart failed" > /dev/null + +# Logging +$BIN/v-log-action "$user" "Warning" "Mail" "SSL disabled (Domain: $domain)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-delete-mail-domain-webmail b/bin/v-delete-mail-domain-webmail new file mode 100755 index 0000000..483996c --- /dev/null +++ b/bin/v-delete-mail-domain-webmail @@ -0,0 +1,101 @@ +#!/bin/bash +# info: delete webmail support for a domain +# options: USER DOMAIN [RESTART] [QUIET] +# +# example: v-delete-mail-domain-webmail user demo.com +# +# This function removes support for webmail from +# a specified mail domain. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +restart="$3" +quiet=$4 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DOMAIN [RESTART]' +is_format_valid 'user' 'domain' +is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM' +is_system_enabled "$WEB_SYSTEM" 'WEB_SYSTEM' +is_system_enabled "$IMAP_SYSTEM" 'IMAP_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_valid 'mail' 'DOMAIN' "$domain" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +if [ -n "$WEBMAIL_ALIAS" ]; then + # Delete webmail configuration + del_webmail_config + del_webmail_ssl_config + + # Ensure that corresponding DNS records are removed + if [ -n "$DNS_SYSTEM" ]; then + dns_domain=$($BIN/v-list-dns-domains "$user" | grep "$domain" | cut -d' ' -f1) + if [ "WEBMAIL_ALIAS" != "mail" ]; then + #Prevent mail.domain.com being removed + webmail_record=$($BIN/v-list-dns-records $user $domain | grep -i " $WEBMAIL_ALIAS " | cut -d' ' -f1) + if [ "$dns_domain" = "$domain" ]; then + if [ -n "$webmail_record" ]; then + if [ "$quiet" = "yes" ]; then + $BIN/v-delete-dns-record "$user" "$domain" "$webmail_record" "$restart" 'yes' + else + $BIN/v-delete-dns-record "$user" "$domain" "$webmail_record" "$restart" + fi + fi + fi + fi + fi +else + echo "Error: WEBMAIL_ALIAS is not defined in hestia.conf." +fi + +# Set SSL as enabled in configuration +update_object_value 'mail' 'DOMAIN' "$domain" '$WEBMAIL' "" + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +if [ -n "$restart" ]; then + # Restarting web server + $BIN/v-restart-web "$restart" + check_result $? "Web restart failed" > /dev/null + + $BIN/v-restart-proxy "$restart" + check_result $? "Proxy restart failed" > /dev/null +fi + +# Logging +if [ "$quiet" != 'yes' ]; then + $BIN/v-log-action "$user" "Info" "Mail" "Webmail access disabled (Domain: $domain)." +fi +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-delete-mail-domains b/bin/v-delete-mail-domains new file mode 100755 index 0000000..80a61f7 --- /dev/null +++ b/bin/v-delete-mail-domains @@ -0,0 +1,52 @@ +#!/bin/bash +# info: delete mail domains +# options: USER +# +# example: v-delete-mail-domains admin +# +# This function for deleting all users mail domains. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'USER' +is_format_valid 'user' +is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM' +is_object_valid 'user' 'USER' "$user" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Starting delete loop +for domain in $(search_objects 'mail' 'SUSPENDED' "no" 'DOMAIN'); do + $BIN/v-delete-mail-domain "$user" "$domain" +done + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-delete-remote-dns-domain b/bin/v-delete-remote-dns-domain new file mode 100755 index 0000000..458c527 --- /dev/null +++ b/bin/v-delete-remote-dns-domain @@ -0,0 +1,74 @@ +#!/bin/bash +# info: delete remote dns domain +# options: USER DOMAIN +# +# example: v-delete-remote-dns-domain admin example.tld +# +# This function synchronise dns with the remote server. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/remote.sh +source $HESTIA/func/remote.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DOMAIN' +is_format_valid 'user' 'domain' +is_system_enabled "$DNS_CLUSTER" 'DNS_CLUSTER' +is_procces_running +remote_dns_health_check + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Starting cluster loop +IFS=$'\n' +for cluster in $(grep "SUSPENDED='no'" $HESTIA/conf/dns-cluster.conf); do + + # Reset user, password and hash vars + clear_dns_cluster_settings + + # Parsing remote host parameters + parse_object_kv_list "$cluster" + + # Syncing domain + cluster_cmd v-delete-dns-domain "$DNS_USER" "$domain" 'yes' + rc=$? + if [ "$rc" -ne 0 ] && [ $rc -ne 3 ]; then + check_result $rc "$HOST connection failed (sync)" "$E_CONNECT" + fi + +done + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Updating pipe +pipe="$HESTIA/data/queue/dns-cluster.pipe" +str=$(grep -n "$SCRIPT $1 $2$" "$pipe" | cut -f1 -d: | head -n1) +if [ -n "$str" ]; then + sed -i "$str d" "$pipe" +fi + +exit diff --git a/bin/v-delete-remote-dns-domains b/bin/v-delete-remote-dns-domains new file mode 100755 index 0000000..6d8602b --- /dev/null +++ b/bin/v-delete-remote-dns-domains @@ -0,0 +1,78 @@ +#!/bin/bash +# info: delete remote dns domains +# options: [HOST] +# +# This function deletes remote dns domains. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +host=$1 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/remote.sh +source $HESTIA/func/remote.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +is_format_valid 'host' +is_system_enabled "$DNS_CLUSTER" 'DNS_CLUSTER' +is_procces_running +remote_dns_health_check + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +IFS=$'\n' + +if [ -z $host ]; then + hosts=$(cat "$HESTIA/conf/dns-cluster.conf") +else + hosts=$(grep "HOST='$host'" "$HESTIA/conf/dns-cluster.conf") +fi + +# Starting cluster loop +for cluster in $hosts; do + + # Reset user, password and hash vars + clear_dns_cluster_settings + + # Parsing remote host parameters + parse_object_kv_list "$cluster" + + # Deleting source records + cluster_cmd v-delete-dns-domains-src $DNS_USER $HOSTNAME 'no' + check_result $? "$HOST connection failed (cleanup)" "$E_CONNECT" + + # Rebuilding dns zones + cluster_cmd v-rebuild-dns-domains $DNS_USER 'yes' + check_result $? "$HOST connection failed (rebuild)" "$E_CONNECT" + +done + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Updating pipe +pipe="$HESTIA/data/queue/dns-cluster.pipe" +str=$(grep -n "$SCRIPT $1 $2$" $pipe | cut -f1 -d: | head -n1) +if [ -n "$str" ]; then + sed -i "$str d" $pipe +fi + +exit diff --git a/bin/v-delete-remote-dns-host b/bin/v-delete-remote-dns-host new file mode 100755 index 0000000..27966ce --- /dev/null +++ b/bin/v-delete-remote-dns-host @@ -0,0 +1,71 @@ +#!/bin/bash +# info: delete remote dns host +# options: HOST +# +# example: v-delete-remote-dns-host example.org +# +# This function for deleting the remote dns host from hestia configuration. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +host=$1 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/remote.sh +source $HESTIA/func/remote.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'HOST' +is_format_valid 'host' +is_system_enabled "$DNS_CLUSTER" 'DNS_CLUSTER' +is_object_valid "../../conf/dns-cluster" 'HOST' "$host" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Deleting remote domains +$BIN/v-delete-remote-dns-domains "$host" >> /dev/null 2>&1 + +# Deleting server +sed -i "/HOST='$host' /d" "$HESTIA/conf/dns-cluster.conf" + +# Deleting DNS_CLUSTER key +check_cluster=$(grep HOST $HESTIA/conf/dns-cluster.conf | wc -l) +if [ "$check_cluster" -eq '0' ]; then + rm -f "$HESTIA/conf/dns-cluster.conf" + sed -i "/DNS_CLUSTER=/d" "$HESTIA/conf/hestia.conf" + + # Delete cron job + cmd="sudo $BIN/v-update-sys-queue dns-cluster" + check_cron=$(grep "$cmd" $HESTIA/data/users/admin/cron.conf 2> /dev/null) + if [ -n "$check_cron" ]; then + parse_object_kv_list "$check_cron" + $BIN/v-delete-cron-job admin "$JOB" + fi +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +$BIN/v-log-action "system" "Info" "System" "Removed remote DNS host (Host: $host)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-delete-remote-dns-record b/bin/v-delete-remote-dns-record new file mode 100755 index 0000000..a41c4b3 --- /dev/null +++ b/bin/v-delete-remote-dns-record @@ -0,0 +1,83 @@ +#!/bin/bash +# info: delete remote dns domain record +# options: USER DOMAIN ID +# +# example: v-delete-remote-dns-record user07 acme.com 44 +# +# This function synchronise dns with the remote server. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +id=$3 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/remote.sh +source $HESTIA/func/remote.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '3' "$#" 'USER DOMAIN ID' +is_format_valid 'user' 'domain' 'id' +is_system_enabled "$DNS_CLUSTER" 'DNS_CLUSTER' +is_procces_running +remote_dns_health_check + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +if [ "$DNS_CLUSTER_SYSTEM" != "hestia-zone" ]; then + # Starting cluster loop + IFS=$'\n' + for cluster in $(cat $HESTIA/conf/dns-cluster.conf); do + + # Reset user, password and hash vars + clear_dns_cluster_settings + + # Parsing remote host parameters + parse_object_kv_list "$cluster" + + # Syncing serial + str=$(grep "DOMAIN='$domain'" $USER_DATA/dns.conf) + cluster_cmd v-insert-dns-domain "$DNS_USER" "$str" "$HOSTNAME" 'domain' 'no' + check_result $? "$HOST connection failed (soa sync)" "$E_CONNECT" + + # Sync domain + cluster_cmd v-delete-dns-record "$DNS_USER" "$domain" "$id" 'no' + #check_result $? "$HOST connection failed (delete)" $E_CONNECT + + # Rebuilding dns zone + cluster_cmd v-rebuild-dns-domain "$DNS_USER" "$domain" 'yes' 'no' + check_result $? "$HOST connection failed (rebuild)" "$E_CONNECT" + + done +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Updating pipe +pipe="$HESTIA/data/queue/dns-cluster.pipe" +str=$(grep -n "$SCRIPT $1 $2 $3$" "$pipe" | cut -f1 -d: | head -n1) +if [ -n "$str" ]; then + sed -i "$str d" "$pipe" +fi + +exit diff --git a/bin/v-delete-sys-api-ip b/bin/v-delete-sys-api-ip new file mode 100755 index 0000000..c3068ca --- /dev/null +++ b/bin/v-delete-sys-api-ip @@ -0,0 +1,54 @@ +#!/bin/bash +# info: delete ip adresss from allowed ip list api +# options: IP +# +# example: v-delete-sys-api-ip 1.1.1.1 + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +ip46=${1// /} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/ip.sh +source $HESTIA/func/ip.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'IP' +is_format_valid 'ip46' + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +new_list='' +set -f # avoid globbing (expansion of *). +array=("${API_ALLOWED_IP//,/ }") +for i in "${!array[@]}"; do + if [ "${array[i]}" != "$ip46" ]; then + if [ "$new_list" = '' ]; then + new_list="${array[i]}" + else + new_list="$new_list,${array[i]}" + fi + fi +done + +$BIN/v-change-sys-config-value 'API_ALLOWED_IP' "$new_list" + +# Logging +$BIN/v-log-action "system" "Warning" "System" "Removed IP address added from Allowed IP API (IP: $ip46)" +log_event "$OK" "$ARGUMENTS" diff --git a/bin/v-delete-sys-filemanager b/bin/v-delete-sys-filemanager new file mode 100755 index 0000000..d4756be --- /dev/null +++ b/bin/v-delete-sys-filemanager @@ -0,0 +1,76 @@ +#!/bin/bash +# info: remove file manager functionality from Hestia Control Panel +# options: [MODE] +# +# example: v-delete-sys-filemanager +# +# This function removes the File Manager and its entry points + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +MODE=$1 +FORCE=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +FM_INSTALL_DIR="$HESTIA/web/fm" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +# Checking root permissions +if [ "x$(id -u)" != 'x0' ]; then + echo "Error: Script can be run executed only by root" + exit 10 +fi + +# Ensure that $HESTIA (/usr/local/hestia/) and other variables are valid. +if [ -z "$HESTIA" ]; then + HESTIA="/usr/local/hestia" +fi + +if [ -z "$HOMEDIR" ] || [ -z "$HESTIA_INSTALL_DIR" ]; then + echo "Error: Hestia environment vars not present" + exit 2 +fi + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +# Check if File Manager components are installed +if [ "$FORCE" != "yes" ] && [ ! -e "$FM_INSTALL_DIR" ]; then + echo "ERROR: File Manager components are not installed." + exit 1 +fi + +if [ "$FORCE" != "yes" ] && [ "$FILE_MANAGER" = "false" ]; then + echo "ERROR: File Manager is not enabled." + exit 1 +fi + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +rm --recursive --force "$FM_INSTALL_DIR" +$BIN/v-change-sys-config-value 'FILE_MANAGER' 'false' + +if [ "$MODE" != "quiet" ]; then + echo "File Manager has been removed from the system." +fi + +#----------------------------------------------------------# +# Logging # +#----------------------------------------------------------# + +$BIN/v-log-action "system" "Info" "Plugins" "File Manager disabled." +log_event "$OK" "$ARGUMENTS" diff --git a/bin/v-delete-sys-firewall b/bin/v-delete-sys-firewall new file mode 100755 index 0000000..7cc7460 --- /dev/null +++ b/bin/v-delete-sys-firewall @@ -0,0 +1,50 @@ +#!/bin/bash +# info: delete system firewall +# options: NONE +# +# example: v-delete-sys-firewall +# +# This function disables firewall support + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +if [ -z "$FIREWALL_SYSTEM" ]; then + exit +fi + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Updating FIREWALL_SYSTEM value +$BIN/v-change-sys-config-value "FIREWALL_SYSTEM" "" + +# Stopping firewall +$BIN/v-stop-firewall + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +$BIN/v-log-action "system" "Warning" "Firewall" "System firewall disabled." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-delete-sys-ip b/bin/v-delete-sys-ip new file mode 100755 index 0000000..76e602f --- /dev/null +++ b/bin/v-delete-sys-ip @@ -0,0 +1,171 @@ +#!/bin/bash +# info: delete system IP +# options: IP +# +# example: v-delete-sys-ip 203.0.113.1 +# +# This function for deleting a system IP. It does not allow to delete first IP +# on interface and do not allow to delete IP which is used by a web domain. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +ip="$1" + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/ip.sh +source $HESTIA/func/ip.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'IP' +is_format_valid 'ip' +is_ip_valid "$ip" +is_ip_key_empty '$U_WEB_DOMAINS' +is_ip_key_empty '$U_SYS_USERS' + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Import IP variables +source "$HESTIA/data/ips/$ip" +cidr="$(convert_netmask "$NETMASK")" + +# Get primary IP +default_nic="$(ip -d -j route show | jq -r '.[] | if .dst == "default" then .dev else empty end')" +primary_ipv4="$(ip -4 -d -j addr show "$default_nic" | jq -r '.[].addr_info[] | if .scope == "global" then .local else empty end' | head -n1)" + +# Checking primary IP on the interface +interface="$(ip -d -j addr show | jq --arg IP "$ip" -r '.[] | if .addr_info[].local == $IP then .ifname else empty end')" +if [ -n "$interface" ] && [ "$ip" = "$primary_ipv4" ]; then + echo "Error: can't delete primary IP address" + log_event "$E_FORBIDEN" "$ARGUMENTS" + exit "$E_FORBIDEN" +fi + +# Deleting system IP +if [ -n "$interface" ]; then + ip addr del "$ip/$cidr" dev "$interface" 2> /dev/null + if [ "$?" -ne "0" ]; then + echo "Error: can't delete system IP address" + log_event "$E_FORBIDEN" "$ARGUMENTS" + exit "$E_FORBIDEN" + fi +fi + +# Deleting startup conf on RHEL/CentOS/Fedora +# Need RHEL experts to fix me +if [ -e "/etc/sysconfig/network-scripts/ifcfg-$interface" ]; then + rm -f /etc/sysconfig/network-scripts/ifcfg-$interface +fi + +# Deleting startup conf on Debian/Ubuntu +if [ -f "/etc/netplan/60-hestia.yaml" ]; then + sed -i "/$ip/d" /etc/netplan/60-hestia.yaml + if ! grep -q '-' /etc/netplan/60-hestia.yaml; then + rm /etc/netplan/60-hestia.yaml + fi +elif [ -e "/etc/network/interfaces" ]; then + ip_str="$(grep -n "$ip$" /etc/network/interfaces | cut -f1 -d:)" + if [ -n "$ip_str" ]; then + first_str="$((ip_str - 3))" + last_str="$((ip_str + 1))" + sed -i "$first_str,$last_str d" /etc/network/interfaces + fi +fi + +# Deleting Hestia IP +rm -f $HESTIA/data/ips/$ip + +# Deleting web config +if [ -n "$WEB_SYSTEM" ]; then + rm -f /etc/$WEB_SYSTEM/conf.d/$ip.conf +fi + +# Deleting proxy config +if [ -n "$PROXY_SYSTEM" ]; then + rm -f /etc/$PROXY_SYSTEM/conf.d/$ip.conf + + # mod_extract_forwarded + fw_conf="/etc/$WEB_SYSTEM/conf.d/mod_extract_forwarded.conf" + if [ -e "$fw_conf" ]; then + ips="$(grep 'MEFaccept 127.0.0.1' "$fw_conf")" + new_ips="$(echo "$ips" | sed "s/$ip//")" + sed -i "s/$ips/$new_ips/g" "$fw_conf" + fi + + # mod_rpaf + rpaf_conf="/etc/$WEB_SYSTEM/mods-enabled/rpaf.conf" + if [ -e "$rpaf_conf" ]; then + ips="$(grep RPAFproxy_ips "$rpaf_conf")" + new_ips="$(echo "$ips" | sed "s/ $ip//")" + sed -i "s/$ips/$new_ips/g" "$rpaf_conf" + + # Remove RPAFproxy_ips line when ip list is empty + [ "$(grep RPAFproxy_ips "$rpaf_conf" | sed 's/^[[:space:]]*//g')" = "RPAFproxy_ips" ] && sed -i "/RPAFproxy_ips/d" "$rpaf_conf" + fi + + # mod_remoteip + remoteip_conf="/etc/$WEB_SYSTEM/mods-enabled/remoteip.conf" + if [ -e "$remoteip_conf" ]; then + sed -i "/RemoteIPInternalProxy $ip\$/d" "$remoteip_conf" + fi +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Updating user conf +if [ -n "$OWNER" ]; then + decrease_user_value "$OWNER" '$IP_OWNED' +fi + +if [ "$OWNER" = 'admin' ]; then + if [ "$STATUS" = 'shared' ]; then + for hestia_user in $($BIN/v-list-sys-users plain); do + decrease_user_value "$hestia_user" '$IP_AVAIL' + done + else + decrease_user_value "$OWNER" '$IP_AVAIL' + fi +else + decrease_user_value "$OWNER" '$IP_AVAIL' +fi + +# Restarting web server +$BIN/v-restart-web +check_result $? "Web restart failed" > /dev/null + +# Restarting proxy server +if [ -n "$PROXY_SYSTEM" ]; then + $BIN/v-restart-proxy + check_result $? "Proxy restart failed" > /dev/null +fi + +# Restarting firewall +if [ -n "$FIREWALL_SYSTEM" ]; then + $BIN/v-update-firewall +fi + +# Logging +$BIN/v-log-action "system" "Info" "System" "IP address deleted (IP: $ip)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-delete-sys-mail-queue b/bin/v-delete-sys-mail-queue new file mode 100755 index 0000000..01cf11b --- /dev/null +++ b/bin/v-delete-sys-mail-queue @@ -0,0 +1,45 @@ +#!/bin/bash +# info: delete exim mail queue +# options: none +# +# example: v-delete-sys-mail-queue +# +# This function checks for messages stuck in the exim mail queue +# and prompts the user to clear the queue if desired. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +message_count=$(exim -bpc) + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +if [ "$message_count" -gt 0 ]; then + read -p "Are you sure you want to delete $message_count messages from the exim queue? [y/N] " answer + + if [ "$answer" = "y" ] || [ "$answer" = "Y" ]; then + exiqgrep -i | xargs exim -Mrm + fi +fi +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +$BIN/v-log-action "system" "Info" "System" "Mail queue ($message_count) has been deleted" +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-delete-sys-pma-sso b/bin/v-delete-sys-pma-sso new file mode 100755 index 0000000..8a906dc --- /dev/null +++ b/bin/v-delete-sys-pma-sso @@ -0,0 +1,78 @@ +#!/bin/bash +# info: disables support for single sign on PHPMYADMIN +# options: [mode] +# +# example: v-delete-sys-pma-sso +# +# Disables support for SSO to phpMyAdmin + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +MODE=$1 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +PMA_INSTALL="/usr/share/phpmyadmin" +PMA_CONFIG="/etc/phpmyadmin" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +if [ "x$(id -u)" != 'x0' ]; then + echo "Error: Script can be run executed only by root" + exit 10 +fi + +if [ ! -e "$PMA_INSTALL/hestia-sso.php" ]; then + echo 'Error: PMA Single Sign On already disabled' + exit 1 +fi + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +apikey=$(grep -Po "'API_KEY', '(.*)'" /usr/share/phpmyadmin/hestia-sso.php | cut "-d'" -f4) + +if [ -z $(echo $apikey | grep ":") ]; then + $BIN/v-revoke-api-key "$apikey" +else + apikey=$(grep -Po "'API_KEY', '(.*)'" /usr/share/phpmyadmin/hestia-sso.php | cut "-d'" -f4 | cut -d ":" -f1) + $BIN/v-delete-access-key "$apikey" +fi + +#remove new files +rm /usr/share/phpmyadmin/hestia-sso.php +rm /etc/phpmyadmin/hestia-sso.inc.php + +#revert config +sed -i "/hestia-sso.inc.php/d" $PMA_CONFIG/config.inc.php + +# disable key +$BIN/v-change-sys-config-value 'PHPMYADMIN_KEY' "" + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +if [ "$MODE" != "quiet" ]; then + echo "PMA Hestia-SSO plugin has been successfully removed/disabled" +fi + +# Logging +$BIN/v-log-action "system" "Info" "Plugins" "phpMyAdmin Single Sign-On (SSO) disabled." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-delete-sys-quota b/bin/v-delete-sys-quota new file mode 100755 index 0000000..0f35a7c --- /dev/null +++ b/bin/v-delete-sys-quota @@ -0,0 +1,74 @@ +#!/bin/bash +# info: delete system quota +# options: NONE +# +# example: v-delete-sys-quota +# +# This function disables filesystem quota on /home partition + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Deleting group and user quota on /home partition +mnt=$(df -P /home | awk '{print $6}' | tail -n1) +lnr=$(cat -n /etc/fstab | awk '{print $1,$3}' | grep "$mnt$" | cut -f 1 -d ' ') +opt=$(sed -n ${lnr}p /etc/fstab | awk '{print $4}') +fnd='usrquota\|grpquota\|usrjquota=\|grpjquota=\|jqfmt=' +if [ -n "$(echo $opt | grep $fnd)" ]; then + rep=$(echo $(echo $opt | tr ',' '\n' | grep -v $fnd) | tr ' ' ',') + sed -i "$lnr s/$opt/$rep/" /etc/fstab + mount -o remount "$mnt" +fi + +# Disabling group and user quota +quotaoff=$(which --skip-alias --skip-functions quotaoff 2> /dev/null) +if [ $? -eq 0 ]; then + if [ -n "$(quotaon -pa | grep " $mnt " | grep 'user\|group' | grep 'is on')" ]; then + $quotaoff $mnt + fi +fi + +# Deleting v1 + v2 group and user quota index +for idx in $(echo 'quota.user quota.group aquota.user aquota.group'); do + [ -e "$mnt/$idx" ] && rm -f "$mnt/$idx" +done + +# Deleting cron job +rm -f /etc/cron.daily/quotacheck + +# Updating hestia.conf value +if [ -z "$(grep DISK_QUOTA $HESTIA/conf/hestia.conf)" ]; then + echo "DISK_QUOTA='no'" >> $HESTIA/conf/hestia.conf +else + sed -i "s/DISK_QUOTA=.*/DISK_QUOTA='no'/g" $HESTIA/conf/hestia.conf +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +$BIN/v-log-action "system" "Info" "Plugins" "System Quota Enforcement disabled." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-delete-sys-sftp-jail b/bin/v-delete-sys-sftp-jail new file mode 100755 index 0000000..67daf27 --- /dev/null +++ b/bin/v-delete-sys-sftp-jail @@ -0,0 +1,88 @@ +#!/bin/bash +# info: delete system sftp jail +# options: NONE +# +# example: v-delete-sys-sftp-jail +# +# This function disables sftp jailed environment + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Checking sshd directives +config='/etc/ssh/sshd_config' +sftp_n=$(grep -n "Subsystem.*sftp" $config | grep -v internal | grep ":#") +sftp_i=$(grep -n "^# Hestia SFTP Chroot" $config) + +date=$("date +%s") +# Backing up config +cp $config $config.bak-$(date +%s) + +# Enabling normal sftp +if [ -n "$sftp_n" ]; then + fline=$(echo "$sftp_n" | cut -f 1 -d :) + sed -i "${fline}s/#Subsystem/Subsystem sftp/" $config + restart='yes' +fi + +# Disabling jailed sftp +if [ -n "$sftp_i" ]; then + fline=$(echo "$sftp_i" | cut -f 1 -d :) + lline=$((fline + 5)) + sed -i "${fline},${lline}d" $config + restart='yes' +fi + +# Validating opensshd config +if [ "$restart" = 'yes' ]; then + subj="OpenSSH restart failed" + email=$(grep CONTACT $HESTIA/data/users/admin/user.conf | cut -f 2 -d \') + /usr/sbin/sshd -t > /dev/null 2>&1 + if [ "$?" -ne 0 ]; then + mail_text="OpenSSH can not be restarted. Please check config: + \n\n$(/usr/sbin/sshd -t)" + echo -e "$mail_text" | $SENDMAIL -s "$subj" "$email" + else + service ssh restart > /dev/null 2>&1 + service sshd restart > /dev/null 2>&1 + fi +fi + +# Remove v-add-sys-sftp-jail to startup +if [ ! -e "/etc/cron.d/hestia-sftp" ]; then + rm -f /etc/cron.d/hestia-sftp +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Restart ssh service +service ssh restart > /dev/null 2>&1 +service sshd restart > /dev/null 2>&1 + +# Logging +$BIN/v-log-action "system" "Warning" "Plugins" "SFTP Chroot Jail disabled." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-delete-sys-smtp b/bin/v-delete-sys-smtp new file mode 100755 index 0000000..66f97bc --- /dev/null +++ b/bin/v-delete-sys-smtp @@ -0,0 +1,49 @@ +#!/bin/bash +# info: Remove SMTP Account for logging, notification and internal mail +# options: NONE +# +# example: v-delete-sys-smtp +# +# This function allows configuring a SMTP account for the server to use +# for logging, notification and warn emails etc. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +change_sys_value "USE_SERVER_SMTP" "false" +change_sys_value "SERVER_SMTP_HOST" "" +change_sys_value "SERVER_SMTP_PORT" "" +change_sys_value "SERVER_SMTP_SECURITY" "" +change_sys_value "SERVER_SMTP_USER" "" +change_sys_value "SERVER_SMTP_PASSWD" "" +change_sys_value "SERVER_SMTP_ADDR" "" + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +$BIN/v-log-action "system" "Info" "Mail" "Server SMTP disabled." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-delete-sys-smtp-relay b/bin/v-delete-sys-smtp-relay new file mode 100755 index 0000000..f44edd7 --- /dev/null +++ b/bin/v-delete-sys-smtp-relay @@ -0,0 +1,47 @@ +#!/bin/bash +# info: disable system wide smtp relay support +# options: +# +# example: v-delete-sys-smtp-relay +# +# This function disables system wide smtp relay support. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +change_sys_value "SMTP_RELAY" "false" +change_sys_value "SMTP_RELAY_HOST" "" +change_sys_value "SMTP_RELAY_PORT" "" +change_sys_value "SMTP_RELAY_USER" "" + +rm -f /etc/exim4/smtp_relay.conf + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +$BIN/v-log-action "system" "Info" "Mail" "Global SMTP Relay disabled." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-delete-user b/bin/v-delete-user new file mode 100755 index 0000000..15db58f --- /dev/null +++ b/bin/v-delete-user @@ -0,0 +1,125 @@ +#!/bin/bash +# info: delete user +# options: USER [RESTART] +# +# example: v-delete-user whistler +# +# This function deletes a certain user and all his resources such as domains, +# databases, cron jobs, etc. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +restart=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# shellcheck source=/usr/local/hestia/func/db.sh +source $HESTIA/func/db.sh +# shellcheck source=/usr/local/hestia/func/ip.sh +source $HESTIA/func/ip.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'USER [RESTART]' +is_format_valid 'user' +is_object_valid 'user' 'USER' "$user" +if [ "$user" = 'admin' ]; then + exit +fi + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Deleting web domains +if [ -n "$WEB_SYSTEM" ] && [ "$WEB_SYSTEM" != 'no' ]; then + $BIN/v-unsuspend-web-domains "$user" "$restart" + $BIN/v-delete-web-domains "$user" "$restart" + check_result "$?" "web domain deletion failed" +fi + +# Deleting dns domains +if [ -n "$DNS_SYSTEM" ] && [ "$DNS_SYSTEM" != 'no' ]; then + $BIN/v-unsuspend-dns-domains "$user" "$restart" + $BIN/v-delete-dns-domains "$user" "$restart" + check_result "$?" "dns domain deletion failed" +fi + +# Deleting mail domains +if [ -n "$MAIL_SYSTEM" ] && [ "$MAIL_SYSTEM" != 'no' ]; then + $BIN/v-unsuspend-mail-domains "$user" + $BIN/v-delete-mail-domains "$user" + check_result "$?" "mail domain deletion failed" +fi + +# Deleting databases +if [ -n "$DB_SYSTEM" ] && [ "$DB_SYSTEM" != 'no' ]; then + $BIN/v-unsuspend-databases "$user" + $BIN/v-delete-databases "$user" + check_result "$?" "database deletion failed" +fi + +# Unsuspend user just in case +$BIN/v-unsuspend-user "$user" + +# Releasing user ips +$BIN/v-delete-user-ips "$user" +check_result "$?" "user ip release failed" + +# Deleteing user pipes +sed -i "/ $user$/d" "$HESTIA/data/queue/disk.pipe" +sed -i "/ $user$/d" "$HESTIA/data/queue/traffic.pipe" + +# Deleting sftp jail +$BIN/v-delete-user-sftp-jail "$user" + +# Deleting system user +/usr/sbin/userdel -f "$user" >> /dev/null 2>&1 +if [ $? -ne 0 ]; then + sed -i "/^$user:/d" /etc/passwd + sed -i "/^$user:/d" /etc/shadow +fi + +/usr/sbin/groupdel "$user" >> /dev/null 2>&1 +if [ $? -ne 0 ]; then + sed -i "/^$user:/d" /etc/group +fi + +# Deleting user directories +chattr -i $HOMEDIR/$user/conf > /dev/null 2>&1 +rm -rf $HOMEDIR/$user +rm -f /var/spool/mail/$user +rm -f /var/spool/cron/$user +rm -f /var/spool/cron/crontabs/$user +rm -rf $USER_DATA + +# Updating admin counter +if [ "$user" != 'admin' ]; then + decrease_user_value 'admin' '$U_USERS' +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +$BIN/v-log-action "system" "Info" "Users" "User deleted (User: $user)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-delete-user-2fa b/bin/v-delete-user-2fa new file mode 100755 index 0000000..e1bf2a0 --- /dev/null +++ b/bin/v-delete-user-2fa @@ -0,0 +1,61 @@ +#!/bin/bash +# info: delete 2fa of existing user +# options: USER +# +# example: v-delete-user-2fa admin +# +# This function deletes 2fa token of a user. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'USER' +is_format_valid 'user' 'system' +is_object_valid 'user' 'USER' "$user" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Reading user values +source $USER_DATA/user.conf + +# Check if 2FA is enabled +if [ -z "$TWOFA" ]; then + echo "Error: two-factor authentication is not enabled" + exit "$E_NOTEXIST" +fi + +# Remove 2FA from user config +update_user_value "$user" '$TWOFA' "" +update_user_value "$user" '$QRCODE' "" + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +$BIN/v-log-action "system" "Warning" "System" "Two-factor authentication disabled (User: $user)." +$BIN/v-log-action "$user" "Warning" "System" "Two-factor authentication disabled." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-delete-user-auth-log b/bin/v-delete-user-auth-log new file mode 100755 index 0000000..b753195 --- /dev/null +++ b/bin/v-delete-user-auth-log @@ -0,0 +1,44 @@ +#!/bin/bash +# info: Delete auth log file for user +# +# This function for deleting a users auth log file + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'USER' +is_format_valid 'user' +is_object_valid 'user' 'USER' "$user" + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Remove log file and log event +if [ -f "$USER_DATA/auth.log" ]; then + rm -f $USER_DATA/auth.log + $BIN/v-log-action "system" "Warning" "Security" "User authentication log deleted (User: $user)." + $BIN/v-log-action "$user" "Warning" "Security" "Login history cleared." + log_event "$OK" "$ARGUMENTS" +fi + +exit diff --git a/bin/v-delete-user-backup b/bin/v-delete-user-backup new file mode 100755 index 0000000..dcd32fb --- /dev/null +++ b/bin/v-delete-user-backup @@ -0,0 +1,82 @@ +#!/bin/bash +# info: delete user backup +# options: USER BACKUP +# +# example: v-delete-user-backup admin admin.2012-12-21_00-10-00.tar +# +# This function deletes user backup. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +backup=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/backup.sh +source $HESTIA/func/backup.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER BACKUP' +is_format_valid 'user' 'backup' +is_system_enabled "$BACKUP_SYSTEM" 'BACKUP_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_valid 'backup' 'BACKUP' "$2" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +backup_folder="$BACKUP" + +line=$(grep "BACKUP='$backup'" $USER_DATA/backup.conf) +parse_object_kv_list "$line" + +deleted=0 +if [[ "$TYPE" =~ "sftp" ]]; then + sftp_delete "$backup" + deleted=1 +fi +if [[ "$TYPE" =~ "ftp" ]] && [ "$deleted" == "0" ]; then + ftp_delete "$backup" +fi +if [[ "$TYPE" =~ "b2" ]]; then + b2_delete "$user" "$backup" +fi +if [[ "$TYPE" =~ "rclone" ]]; then + rclone_delete "$backup" +fi +if [[ "$TYPE" =~ "local" ]]; then + rm -f "$backup_folder/$2" +fi + +# Deleting backup +sed -i "/BACKUP='$2' /d" "$USER_DATA/backup.conf" + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Update counter +U_BACKUPS=$(grep BACKUP $USER_DATA/backup.conf | wc -l) +update_user_value "$user" '$U_BACKUPS' "$U_BACKUPS" + +# Logging +$BIN/v-log-action "$user" "Info" "Backup" "Deleted backup (Archive: $backup)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-delete-user-backup-exclusions b/bin/v-delete-user-backup-exclusions new file mode 100755 index 0000000..1da753b --- /dev/null +++ b/bin/v-delete-user-backup-exclusions @@ -0,0 +1,82 @@ +#!/bin/bash +# info: delete backup exclusion +# options: USER [SYSTEM] +# +# example: v-delete-user-backup-exclusions admin +# +# This function for deleting backup exclusion + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +system=$(echo "$2" | tr '[:lower:]' '[:upper:]') + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'USER [SYSTEM]' +is_format_valid 'user' +is_object_valid 'user' 'USER' "$user" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Delete system exclusion +if [ -z "$system" ]; then + WEB='' + DNS='' + MAIL='' + DB='' + CRON='' + USER='' +else + touch "$USER_DATA/backup-excludes.conf" + source_conf "$USER_DATA/backup-excludes.conf" + case $system in + WEB) WEB='' ;; + DNS) DNS='' ;; + MAIL) MAIL='' ;; + DB) DB='' ;; + CRON) CRON='' ;; + USER) USER='' ;; + esac +fi + +# Updating exlusion list +echo "WEB='$WEB'" > $USER_DATA/backup-excludes.conf +echo "DNS='$DNS'" >> $USER_DATA/backup-excludes.conf +echo "MAIL='$MAIL'" >> $USER_DATA/backup-excludes.conf +echo "DB='$DB'" >> $USER_DATA/backup-excludes.conf +echo "CRON='$DB'" >> $USER_DATA/backup-excludes.conf +echo "USER='$USER'" >> $USER_DATA/backup-excludes.conf +chmod 660 $USER_DATA/backup-excludes.conf + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +if [ -z "$system" ]; then + $BIN/v-log-action "$user" "Info" "Backup" "Deleted all backup exclusions." +else + $BIN/v-log-action "$user" "Info" "Backup" "Deleted backup exclusions (Service: $system)" +fi +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-delete-user-ips b/bin/v-delete-user-ips new file mode 100755 index 0000000..9153fd2 --- /dev/null +++ b/bin/v-delete-user-ips @@ -0,0 +1,69 @@ +#!/bin/bash +# info: delete user ips +# options: USER +# +# example: v-delete-user-ips admin +# +# This function deletes all user's ip addresses. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/ip.sh +source $HESTIA/func/ip.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'USER' +is_format_valid 'user' +is_object_valid 'user' 'USER' "$user" +if [ "$user" = 'admin' ]; then + exit +fi + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Parsing user ips +ip_list=$(grep -H "OWNER='$user'" $HESTIA/data/ips/* | cut -f 1 -d:) + +for ip in $ip_list; do + ip=$(basename "$ip") + + # Checking webdomains and users + is_ip_key_empty '$U_WEB_DOMAINS' + is_ip_key_empty '$U_SYS_USERS' + + # Assig ip to main account + update_ip_value '$OWNER' 'admin' + update_ip_value '$STATUS' 'dedicated' + increase_user_value 'admin' '$IP_OWNED' + increase_user_value 'admin' '$IP_AVAIL' + $BIN/v-log-action "system" "Info" "System" "Removed IP address from user (IP: $ip, User: $user)." +done + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-delete-user-log b/bin/v-delete-user-log new file mode 100755 index 0000000..6ffcae2 --- /dev/null +++ b/bin/v-delete-user-log @@ -0,0 +1,61 @@ +#!/bin/bash +# info: Delete log file for user +# options: USER +# +# example: v-delete-user-log user +# +# This function for deleting a users log file + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'USER' +is_format_valid 'user' +if [ "$user" != "system" ]; then + is_object_valid 'user' 'USER' "$user" +fi + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Set correct path for log file (system or user) +if [ "$user" = "system" ]; then + log_file="$HESTIA/data/users/admin/system.log" +else + log_file="$HESTIA/data/users/$user/history.log" +fi + +# Verify log file exists before deleting to prevent errors +if [ -f "$log_file" ]; then + rm -f "$log_file" + # Add event to user and system logs specifying that the log history was cleared + if [ "$user" = "system" ]; then + $BIN/v-log-action "system" "Warning" "Security" "System log history deleted." + else + $BIN/v-log-action "system" "Warning" "Security" "User action log deleted (User: $user)." + $BIN/v-log-action "$user" "Info" "Security" "Log entries deleted." + fi + log_event "$OK" "$ARGUMENTS" +fi + +exit diff --git a/bin/v-delete-user-notification b/bin/v-delete-user-notification new file mode 100755 index 0000000..11a5cd4 --- /dev/null +++ b/bin/v-delete-user-notification @@ -0,0 +1,79 @@ +#!/bin/bash +# info: delete user notification +# options: USER NOTIFICATION +# +# example: v-delete-user-notification admin 1 +# +# This function deletes user notification. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +id=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER NOTIFICATION' +if [ "$id" = "all" ]; then + is_format_valid 'user' +else + is_format_valid 'user' 'id' +fi +is_object_valid 'user' 'USER' "$user" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +if [ "$id" = "all" ]; then + notice='no' + rm $USER_DATA/notifications.conf + touch $USER_DATA/notifications.conf +else + # Deleting notification + sed -i "/NID='$id' /d" $USER_DATA/notifications.conf 2> /dev/null + # Checking last notification + if [ -e "$USER_DATA/notifications.conf" ]; then + if [ -z "$(grep NID= $USER_DATA/notifications.conf)" ]; then + notice='no' + fi + if [ -z "$(grep "ACK='no'" $USER_DATA/notifications.conf)" ]; then + notice='no' + fi + else + notice='no' + fi +fi +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Updating notification counter +if [ "$notice" = 'no' ]; then + if [ -z "$(grep NOTIFICATIONS $USER_DATA/user.conf)" ]; then + sed -i "s/^TIME/NOTIFICATIONS='no'\nTIME/g" $USER_DATA/user.conf + else + update_user_value "$user" '$NOTIFICATIONS' "no" + fi +fi + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-delete-user-package b/bin/v-delete-user-package new file mode 100755 index 0000000..d31bf18 --- /dev/null +++ b/bin/v-delete-user-package @@ -0,0 +1,63 @@ +#!/bin/bash +# info: delete user package +# options: PACKAGE +# +# example: v-delete-user-package admin palegreen +# +# This function for deleting user package. +# +# If the package is in use, users will be updated to +# use the default package. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +package=$1 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Functions +is_package_in_use() { + check_package=$(grep "PACKAGE='$package" $HESTIA/data/users/*/user.conf | cut -d'/' -f7) + if [ -n "$check_package" ]; then + for user in $check_package; do + $BIN/v-change-user-package "$user" 'default' + done + fi +} + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'PACKAGE' +is_format_valid 'package' +is_package_valid +is_package_in_use + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Deleting user package +rm -f "$HESTIA/data/packages/$package.pkg" + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +$BIN/v-log-action "system" "Info" "System" "Deleted package (Name: $package)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-delete-user-sftp-jail b/bin/v-delete-user-sftp-jail new file mode 100755 index 0000000..fd8c068 --- /dev/null +++ b/bin/v-delete-user-sftp-jail @@ -0,0 +1,82 @@ +#!/bin/bash +# info: delete user sftp jail +# options: USER +# +# example: v-delete-user-sftp-jail whistler +# +# This function disables sftp jailed environment for USER + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'USER' +is_format_valid 'user' +user_str=$(grep "^$user:" /etc/passwd) +if [ -z "$user_str" ]; then + exit +fi + +# Get current users and split into array +ssh_users=$(grep -A1 "^# Hestia SFTP Chroot" /etc/ssh/sshd_config | sed -n 2p | sed 's/Match User //') +IFS=',' read -r -a users <<< "$ssh_users" + +match_string="$ssh_users," +# Check if jail exist +if [[ ! "$match_string" =~ ,$user, ]]; then + exit 2 +fi + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Remove user from array +for sftp_user in "${users[@]}"; do + if [ "$sftp_user" != "$user" ]; then + new_users+=($sftp_user) + fi +done + +# Write new user list to config +users=$( + IFS=',' + echo "${new_users[*]// /|}" + IFS=$' \t\n' +) +sed -i "s/$ssh_users/$users/g" /etc/ssh/sshd_config + +# chown permissions back to user:user +if [ -d "/home/$user" ]; then + chown $user:$user /home/$user +fi +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Restart ssh service +service ssh restart > /dev/null 2>&1 +service sshd restart > /dev/null 2>&1 + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-delete-user-ssh-key b/bin/v-delete-user-ssh-key new file mode 100755 index 0000000..71a4e86 --- /dev/null +++ b/bin/v-delete-user-ssh-key @@ -0,0 +1,61 @@ +#!/bin/bash +# info: add ssh key +# options: USER KEY +# +# example: v-delete-user-ssh-key user unique_id +# +# Delete user ssh key from authorized_keys + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +keyid=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" +# Additional argument formatting + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER KEYID' +is_format_valid 'user' +is_no_new_line_format "$key_id" +is_object_valid 'user' 'USER' "$user" + +source "$USER_DATA/user.conf" + +AUTHKEY_FILE="$HOMEDIR/$user/.ssh/authorized_keys" +[ -z "$(readlink -f "$AUTHKEY_FILE" | egrep "^$HOMEDIR/$user/.ssh/")" ] && check_result "$E_FORBIDEN" "Invalid authorized keys path" + +if [ ! -f "$AUTHKEY_FILE" ]; then + exit +fi + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +sed -i "/${keyid}/d" "$AUTHKEY_FILE" + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +$BIN/v-log-action "$user" "Info" "SSH" "SSH key deleted (Key ID: $keyid)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-delete-user-stats b/bin/v-delete-user-stats new file mode 100755 index 0000000..67aa75f --- /dev/null +++ b/bin/v-delete-user-stats @@ -0,0 +1,60 @@ +#!/bin/bash +# info: delete user usage statistics +# options: USER DOMAIN +# +# example: v-delete-user-stats user +# example: v-delete-user-stats admin overall +# +# This function deletes user statistics data. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +mode=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'USER' +is_format_valid 'user' +is_object_valid 'user' 'USER' "$user" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Actions # +#----------------------------------------------------------# + +if [ "$user" = 'admin' ] && [ "$mode" = "overall" ]; then + log_file="$USER_DATA/overall_stats.log" +else + log_file="$USER_DATA/stats.log" +fi + +if [ -f "$USER_DATA/stats.log" ]; then + rm -f "$log_file" + touch "$log_file" +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +if [ "$mode" = "overall" ]; then + $BIN/v-log-action "system" "Info" "System" "Overall usage statistics deleted." +else + $BIN/v-log-action "system" "Info" "System" "Usage statistics deleted (User: $user)." +fi diff --git a/bin/v-delete-web-domain b/bin/v-delete-web-domain new file mode 100755 index 0000000..90deaeb --- /dev/null +++ b/bin/v-delete-web-domain @@ -0,0 +1,163 @@ +#!/bin/bash +# info: delete web domain +# options: USER DOMAIN [RESTART] +# +# example: v-delete-web-domain admin wonderland.com +# +# The call of function leads to the removal of domain and all its components +# (statistics, folders contents, ssl certificates, etc.). This operation is +# not fully supported by "undo" function, so the data recovery is possible +# only with a help of reserve copy. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 +restart=$3 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# shellcheck source=/usr/local/hestia/func/ip.sh +source $HESTIA/func/ip.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn +# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ? + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DOMAIN [RESTART]' +is_format_valid 'user' 'domain' +is_system_enabled "$WEB_SYSTEM" 'WEB_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_valid 'web' 'DOMAIN' "$domain" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Parsing domain values +get_domain_values 'web' +local_ip=$(get_real_ip "$IP") + +# Deleting ftp users +if [ -n "$FTP_USER" ]; then + for ftp_user in ${FTP_USER//:/ }; do + $BIN/v-delete-web-domain-ftp "$user" "$domain" "$ftp_user" + done +fi + +# Deleting web backend +if [ -n "$WEB_BACKEND" ]; then + $BIN/v-delete-web-domain-backend "$user" "$domain" 'no' +fi + +# Deleting vhost configuration +del_web_config "$WEB_SYSTEM" "$TPL.tpl" + +# Deleting SSL configuration and certificates +if [ "$SSL" = 'yes' ]; then + del_web_config "$WEB_SYSTEM" "$TPL.stpl" + $BIN/v-delete-web-domain-ssl-force "$user" "$domain" 'no' 'yes' + rm -f $HOMEDIR/$user/conf/web/$domain/ssl/$domain.* + rm -f $USER_DATA/ssl/$domain.* +fi + +if [ "$FASTCGI_CACHE" = "yes" ]; then + # make sure no trails left behind + $BIN/v-delete-fastcgi-cache "$user" "$domain" +fi + +# Deleting domain from web.conf +sed -i "/DOMAIN='$domain'/ d" "$USER_DATA/web.conf" + +# Deleting proxy +if [ -n "$PROXY_SYSTEM" ]; then + del_web_config "$PROXY_SYSTEM" "$PROXY.tpl" + if [ "$SSL" = 'yes' ]; then + del_web_config "$PROXY_SYSTEM" "$PROXY.stpl" + fi + if [ -e "/etc/$PROXY_SYSTEM/conf.d/01_caching_pool.conf" ]; then + sed -i "/=$domain:/d" "/etc/$PROXY_SYSTEM/conf.d/01_caching_pool.conf" + fi +fi + +# Deleting web stats +if [ -n "$STATS" ] && [ "$STATS" != 'no' ]; then + sed -i "/ $domain$/d" $HESTIA/data/queue/webstats.pipe + rm -f $HOMEDIR/$user/conf/web/$domain/$STATS.conf + rm -f /etc/awstats/$STATS.$domain.conf +fi + +# Deleting logs +rm -f /var/log/$WEB_SYSTEM/domains/$domain.log* +rm -f /var/log/$WEB_SYSTEM/domains/$domain.bytes +rm -f /var/log/$WEB_SYSTEM/domains/$domain.error* + +# Deleting directory +rm -rf $HOMEDIR/$user/web/$domain +rm -rf $HOMEDIR/$user/conf/web/$domain + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Decreasing user counters +decrease_ip_value "$local_ip" +decrease_user_value "$user" '$U_WEB_DOMAINS' +if [ "$SSL" = 'yes' ]; then + decrease_user_value "$user" '$U_WEB_SSL' +fi +if [ -n "$ALIAS" ]; then + aliases=$(echo "$ALIAS" | tr ',' '\n' | wc -l) + decrease_user_value "$user" '$U_WEB_ALIASES' "$aliases" +fi + +# Check if is suspended to decrease the suspended value +if [ -n "$SUSPENDED" ]; then + if [ "$SUSPENDED" == "yes" ]; then + decrease_user_value "$user" '$SUSPENDED_WEB' + fi +fi + +# Detect php version + +if [[ $BACKEND =~ ^.*PHP-([0-9])\_([0-9])$ ]]; then + version="${BASH_REMATCH[1]}.${BASH_REMATCH[2]}" +else + version=$(multiphp_default_version) +fi +# Restarting web server +$BIN/v-restart-web "$restart" +check_result $? "Web restart failed" > /dev/null + +# Restarting proxy server +$BIN/v-restart-proxy "$restart" +check_result $? "Proxy restart failed" > /dev/null + +# Restarting php interpreter +$BIN/v-restart-web-backend "$restart" "$version" +check_result $? "PHP restart failed" > /dev/null + +# Logging +$BIN/v-log-action "$user" "Info" "Web" "Deleted web domain (Name: $domain)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-delete-web-domain-alias b/bin/v-delete-web-domain-alias new file mode 100755 index 0000000..d9766fb --- /dev/null +++ b/bin/v-delete-web-domain-alias @@ -0,0 +1,99 @@ +#!/bin/bash +# info: delete web domain alias +# options: USER DOMAIN ALIAS [RESTART] +# +# example: v-delete-web-domain-alias admin example.com www.example.com +# +# This function of deleting the alias domain (parked domain). By this call +# default www aliase can be removed as well. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +dom_alias=$3 +restart=$4 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# shellcheck source=/usr/local/hestia/func/ip.sh +source $HESTIA/func/ip.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '3' "$#" 'USER DOMAIN DOM_ALIAS [RESTART]' +is_format_valid 'user' 'domain' 'dom_alias' +is_system_enabled "$WEB_SYSTEM" 'WEB_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_valid 'web' 'DOMAIN' "$domain" +get_domain_values 'web' +if [ -z "$(echo $ALIAS | tr ',' '\n' | grep ^$dom_alias$)" ]; then + check_result "$E_NOTEXIST" "alias $dom_alias doesn't exist" +fi + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Preparing domain values for the template substitution +local_ip=$(get_real_ip $IP) +ALIAS=$(echo "$ALIAS" \ + | sed -e "s/,/\n/g" \ + | sed -e "s/^$dom_alias$//g" \ + | sed -e "/^$/d" \ + | sed -e ':a;N;$!ba;s/\n/,/g') +prepare_web_domain_values + +# Rebuilding vhost +del_web_config "$WEB_SYSTEM" "$TPL.tpl" +add_web_config "$WEB_SYSTEM" "$TPL.tpl" +if [ "$SSL" = 'yes' ]; then + del_web_config "$WEB_SYSTEM" "$TPL.stpl" + add_web_config "$WEB_SYSTEM" "$TPL.stpl" +fi + +# Rebuilding proxy configuration +if [ -n "$PROXY_SYSTEM" ] && [ -n "$PROXY" ]; then + del_web_config "$PROXY_SYSTEM" "$PROXY.tpl" + add_web_config "$PROXY_SYSTEM" "$PROXY.tpl" + if [ "$SSL" = 'yes' ]; then + del_web_config "$PROXY_SYSTEM" "$PROXY.stpl" + add_web_config "$PROXY_SYSTEM" "$PROXY.stpl" + fi +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Update config +update_object_value 'web' 'DOMAIN' "$domain" '$ALIAS' "$ALIAS" +decrease_user_value "$user" '$U_WEB_ALIASES' + +# Restarting web server +$BIN/v-restart-web "$restart" +check_result $? "Web restart failed" > /dev/null + +$BIN/v-restart-proxy "$restart" +check_result $? "Proxy restart failed" > /dev/null + +# Logging +$BIN/v-log-action "$user" "Info" "Web" "Deleted web domain alias (Alias: $dom_alias, Domain: $domain)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-delete-web-domain-allow-users b/bin/v-delete-web-domain-allow-users new file mode 100755 index 0000000..1067091 --- /dev/null +++ b/bin/v-delete-web-domain-allow-users @@ -0,0 +1,69 @@ +#!/bin/bash +# info: disables other users create subdomains +# options: USER DOMAIN +# +# example: v-delete-web-domain-allow-users admin admin.com +# +# Enable the rule check for Enforce subdomain ownership for a specific domain. +# Enforce subdomain ownership setting in /edit/server/ set to no will always overwrite this behaviour +# eg: admin adds admin.com +# user can create user.admin.com + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DOMAIN' +is_format_valid 'user' 'domain' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'web' 'DOMAIN' "$domain" +is_object_unsuspended 'web' 'DOMAIN' "$domain" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Load domain data +parse_object_kv_list $(grep "DOMAIN='$domain'" $USER_DATA/web.conf) + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +if [ -z "$ALLOW_USERS" ]; then + add_object_key "web" 'DOMAIN' "$domain" 'ALLOW_USERS' 'TIME' +fi + +# Adding new alias +update_object_value 'web' 'DOMAIN' "$domain" '$ALLOW_USERS' "no" + +$BIN/v-log-action "system" "Info" "Web" "Subdomain ownership enforcement enabled (Domain: $domain)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-delete-web-domain-backend b/bin/v-delete-web-domain-backend new file mode 100755 index 0000000..464b55d --- /dev/null +++ b/bin/v-delete-web-domain-backend @@ -0,0 +1,99 @@ +#!/bin/bash +# info: deleting web domain backend configuration +# options: USER DOMAIN [RESTART] +# +# example: v-delete-web-domain-backend admin acme.com +# +# This function of deleting the virtualhost backend configuration. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 +restart=$3 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn +# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ? + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DOMAIN [RESTART]' +is_format_valid 'user' 'domain' +is_system_enabled "$WEB_SYSTEM" 'WEB_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_valid 'web' 'DOMAIN' "$domain" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +get_domain_values 'web' +BACKEND="$template" + +# Defining pool directory +if [ -f "/etc/redhat-release" ]; then + pool=$(find -L /etc/opt/remi/php80/ -name "$domain.conf" -exec dirname {} \;) +else + pool=$(find -L /etc/php/ -name "$domain.conf" -exec dirname {} \;) +fi +if [ ! -e "$pool" ]; then + check_result "$E_NOTEXIST" "php-fpm pool doesn't exist" +fi + +# Defining backend type +backend_type="$domain" +if [ "$WEB_BACKEND_POOL" = 'user' ]; then + backend_type="$user" +fi + +# Checking last webdomain +if [ "$WEB_BACKEND_POOL" = 'user' ]; then + domains=$(search_objects 'web' 'SUSPENDED' "no" 'DOMAIN' | wc -l) + if [ "$backend_type" = "$user" ] && [ "$domains" -gt 1 ]; then + exit + fi +fi + +# Deleting backend +delete_web_backend + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Detect prev version +if [[ $BACKEND =~ ^.*PHP-([0-9])\_([0-9])$ ]]; then + version="${BASH_REMATCH[1]}.${BASH_REMATCH[2]}" +else + version=$(multiphp_default_version) +fi +# Restarting php interpreter +$BIN/v-restart-web-backend "$restart" "$version" +check_result $? "PHP restart failed" > /dev/null + +# Logging +$BIN/v-log-action "$user" "Info" "Web" "Web domain configuration deleted (Domain: $domain)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-delete-web-domain-ftp b/bin/v-delete-web-domain-ftp new file mode 100755 index 0000000..4cc5d98 --- /dev/null +++ b/bin/v-delete-web-domain-ftp @@ -0,0 +1,89 @@ +#!/bin/bash +# info: delete webdomain ftp account +# options: USER DOMAIN FTP_USER +# +# example: v-delete-web-domain-ftp admin wonderland.com bob_ftp +# +# This function deletes additional ftp account. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 +ftp_user=$3 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn +# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ? + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '3' "$#" 'USER DOMAIN FTP_USER' +is_format_valid 'user' 'domain' 'ftp_user' +is_system_enabled "$WEB_SYSTEM" 'WEB_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_valid 'web' 'DOMAIN' "$domain" +get_domain_values 'web' +if [ -z "$(echo $FTP_USER | tr ':' '\n' | grep ^$ftp_user$)" ]; then + echo "Error: account $ftp_user doesn't exist" + log_event "$E_NOTEXIST" "$ARGUMENTS" + exit "$E_NOTEXIST" +fi + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# +# Deleting sftp jail +$BIN/v-delete-user-sftp-jail "$ftp_user" + +# Deleting ftp user +/usr/sbin/userdel $ftp_user >> /dev/null 2>&1 +if [ "$?" != 0 ]; then + sed -i "/^$ftp_user:/d" /etc/passwd + sed -i "/^$ftp_user:/d" /etc/shadow +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Rebuilding FTP variables +position=$(echo $FTP_USER | tr ':' '\n' | grep -n '' | grep ":$ftp_user$" \ + | cut -f 1 -d:) +ftp_user=$(echo $FTP_USER | tr ':' '\n' | grep -n '' | grep -v "^$position:" \ + | cut -f 2 -d : | sed -e "/^$/d" | sed -e ':a;N;$!ba;s/\n/:/g') +ftp_md5=$(echo $FTP_MD5 | tr ':' '\n' | grep -n '' | grep -v "^$position:" \ + | cut -f 2 -d : | sed -e ':a;N;$!ba;s/\n/:/g') +ftp_path=$(echo $FTP_PATH | tr ':' '\n' | grep -n '' | grep -v "^$position:" \ + | cut -f 2 -d : | sed -e ':a;N;$!ba;s/\n/:/g') + +# Update config +update_object_value 'web' 'DOMAIN' "$domain" '$FTP_USER' "$ftp_user" +update_object_value 'web' 'DOMAIN' "$domain" '$FTP_MD5' "$ftp_md5" +update_object_value 'web' 'DOMAIN' "$domain" '$FTP_PATH' "$ftp_path" + +# Logging +$BIN/v-log-action "$user" "Info" "Web" "Deleted FTP account (User: ${3}, Domain: $domain)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-delete-web-domain-httpauth b/bin/v-delete-web-domain-httpauth new file mode 100755 index 0000000..2e7854b --- /dev/null +++ b/bin/v-delete-web-domain-httpauth @@ -0,0 +1,98 @@ +#!/bin/bash +# info: delete http auth user +# options: USER DOMAIN AUTH_USER [RESTART] +# +# example: v-delete-web-domain-httpauth admin example.com alice +# +# This function is used for deleting http auth user + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +auth_user=$3 +restart=${4-yes} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '3' "$#" 'USER DOMAIN AUTH_USER [RESTART]' +is_format_valid 'user' 'domain' +is_system_enabled "$WEB_SYSTEM" 'WEB_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_valid 'web' 'DOMAIN' "$domain" +is_password_valid +get_domain_values 'web' +if [ -z "$(echo "$AUTH_USER" | tr : '\n' | grep ^$auth_user$)" ]; then + echo "Error: auth user $auth_user doesn't exist" + log_event "$E_NOTEXIST" "$ARGUMENTS" + exit "$E_NOTEXIST" +fi + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +htpasswd="$HOMEDIR/$user/conf/web/$domain/htpasswd" +# Deleting auth user +sed -i "/^$auth_user:/d" $htpasswd + +# Deleting password protection +if [ "$(echo "$AUTH_USER" | tr : '\n' | wc -l)" -le 1 ]; then + if [ "$WEB_SYSTEM" = "nginx" ] || [ "$PROXY_SYSTEM" = "nginx" ]; then + htaccess="$HOMEDIR/$user/conf/web/$domain/nginx.conf_htaccess" + shtaccess="$HOMEDIR/$user/conf/web/$domain/nginx.ssl.conf_htaccess" + else + htaccess="$HOMEDIR/$user/conf/web/$domain/apache2.conf_htaccess" + shtaccess="$HOMEDIR/$user/conf/web/$domain/apache2.ssl.conf_htaccess" + fi + rm -f $htaccess $htpasswd $shtaccess + restart_required='yes' +fi + +# Restarting web server +if [ "$restart" != 'no' ] && [ "$restart_required" = 'yes' ]; then + $BIN/v-restart-web + if [ -n "$PROXY_SYSTEM" ]; then + $BIN/v-restart-proxy + fi +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Rebuilding FTP variables +position=$(echo $AUTH_USER | tr ':' '\n' | grep -n '' | grep ":$auth_user$" \ + | cut -f 1 -d:) +auth_user=$(echo $AUTH_USER | tr ':' '\n' | grep -n '' | grep -v "^$position:" \ + | cut -f 2 -d : | sed -e "/^$/d" | sed -e ':a;N;$!ba;s/\n/:/g') +auth_hash=$(echo $AUTH_HASH | tr ':' '\n' | grep -n '' | grep -v "^$position:" \ + | cut -f 2 -d : | sed -e ':a;N;$!ba;s/\n/:/g') + +# Update config +update_object_value 'web' 'DOMAIN' "$domain" '$AUTH_USER' "$auth_user" +update_object_value 'web' 'DOMAIN' "$domain" '$AUTH_HASH' "$auth_hash" + +# Logging +$BIN/v-log-action "$user" "Info" "Web" "Web domain password disabled (Domain: $domain)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-delete-web-domain-proxy b/bin/v-delete-web-domain-proxy new file mode 100755 index 0000000..1bd4a2d --- /dev/null +++ b/bin/v-delete-web-domain-proxy @@ -0,0 +1,77 @@ +#!/bin/bash +# info: deleting web domain proxy configuration +# options: USER DOMAIN [RESTART] +# +# example: v-delete-web-domain-proxy alice lookinglass.com +# +# This function of deleting the virtualhost proxy configuration. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 +restart=$3 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn +# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ? + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DOMAIN [RESTART]' +is_format_valid 'user' 'domain' +is_system_enabled "$PROXY_SYSTEM" 'WEB_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_valid 'web' 'DOMAIN' "$domain" +is_object_value_exist 'web' 'DOMAIN' "$domain" '$PROXY' + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Defining domain parameters +get_domain_values 'web' +del_web_config "$PROXY_SYSTEM" "$PROXY.tpl" + +# Checking SSL +if [ "$SSL" = 'yes' ]; then + del_web_config "$PROXY_SYSTEM" "$PROXY.stpl" +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Update config +update_object_value 'web' 'DOMAIN' "$domain" '$PROXY' '' +update_object_value 'web' 'DOMAIN' "$domain" '$PROXY_EXT' '' + +# Restart proxy server +$BIN/v-restart-proxy "$restart" +check_result $? "Proxy restart failed" > /dev/null + +# Logging +$BIN/v-log-action "$user" "Info" "Web" "Proxy disabled (Domain: $domain)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-delete-web-domain-redirect b/bin/v-delete-web-domain-redirect new file mode 100755 index 0000000..1e9f33d --- /dev/null +++ b/bin/v-delete-web-domain-redirect @@ -0,0 +1,72 @@ +#!/bin/bash +# info: Delete force redirect to domain +# options: USER DOMAIN [RESTART] +# +# example: v-add-web-domain-redirect user domain.tld +# +# Function delete a forced redirect to a domain + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +restart=${3-no} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DOMAIN [RESTART]' +is_format_valid 'user' 'domain' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'web' 'DOMAIN' "$domain" +is_object_unsuspended 'web' 'DOMAIN' "$domain" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Check if proxy is active +if [ "$WEB_SYSTEM" = 'nginx' ] || [ "$PROXY_SYSTEM" = 'nginx' ]; then + rm "$HOMEDIR/$user/conf/web/$domain/nginx.conf_redirect" + rm "$HOMEDIR/$user/conf/web/$domain/nginx.ssl.conf_redirect" +else + echo "Non supported please use .htaccess instead" + exit 2 +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +update_object_value 'web' 'DOMAIN' "$domain" '$REDIRECT' "" +update_object_value 'web' 'DOMAIN' "$domain" '$REDIRECT_CODE' "" + +$BIN/v-restart-web "$restart" +check_result $? "Web restart failed" > /dev/null + +$BIN/v-restart-proxy "$restart" +check_result $? "Proxy restart failed" > /dev/null + +# Logging +$BIN/v-log-action "$user" "Info" "Web" "Domain redirection disabled (Domain: $domain)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-delete-web-domain-ssl b/bin/v-delete-web-domain-ssl new file mode 100755 index 0000000..5430959 --- /dev/null +++ b/bin/v-delete-web-domain-ssl @@ -0,0 +1,97 @@ +#!/bin/bash +# info: delete web domain SSL support +# options: USER DOMAIN [RESTART] +# +# example: v-delete-web-domain-ssl admin acme.com +# +# This function disable https support and deletes SSL certificates. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 +restart=$3 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn +# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ? + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DOMAIN [RESTART]' +is_format_valid 'user' 'domain' +is_system_enabled "$WEB_SYSTEM" 'WEB_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_valid 'web' 'DOMAIN' "$domain" +is_object_value_exist 'web' 'DOMAIN' "$domain" '$SSL' + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Parsing domain values +get_domain_values 'web' + +# Deleting domain +del_web_config "$WEB_SYSTEM" "$TPL.stpl" + +# Checking proxy +if [ -n "$PROXY_SYSTEM" ] && [ -n "$PROXY" ]; then + del_web_config "$PROXY_SYSTEM" "$PROXY.stpl" +fi + +# Deleting old certificate +rm -f $HOMEDIR/$user/conf/web/$domain/ssl/$domain.* +rm -f $USER_DATA/ssl/$domain.ca +rm -f $USER_DATA/ssl/$domain.crt +rm -f $USER_DATA/ssl/$domain.key +rm -f $USER_DATA/ssl/$domain.pem + +# Deleting force ssl +$BIN/v-delete-web-domain-ssl-force "$user" "$domain" 'no' 'yes' + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Update config +if [ -n "$LETSENCRYPT" ]; then + update_object_value 'web' 'DOMAIN' "$domain" '$LETSENCRYPT' 'no' +fi +update_object_value 'web' 'DOMAIN' "$domain" '$SSL' 'no' + +# Decreasing domain value +decrease_user_value "$user" '$U_WEB_SSL' + +# Restarting web server +$BIN/v-restart-web "$restart" +check_result $? "Web restart failed" > /dev/null + +$BIN/v-restart-proxy "$restart" +check_result $? "Proxy restart failed" > /dev/null + +# Logging +$BIN/v-log-action "$user" "Warning" "Web" "SSL disabled (Domain: $domain)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-delete-web-domain-ssl-force b/bin/v-delete-web-domain-ssl-force new file mode 100755 index 0000000..40919b8 --- /dev/null +++ b/bin/v-delete-web-domain-ssl-force @@ -0,0 +1,80 @@ +#!/bin/bash +# info: remove ssl force from domain +# options: USER DOMAIN [RESTART] [QUIET] +# +# example: v-delete-web-domain-ssl-force admin domain.tld +# +# This function removes force SSL configurations. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +restart="$3" +quiet="$4" + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DOMAIN' +is_format_valid 'user' 'domain' +is_object_valid 'user' 'USER' "$user" +is_object_valid 'web' 'DOMAIN' "$domain" +is_object_valid 'web' 'DOMAIN' "$domain" "$SSL_FORCE" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Load domain data +parse_object_kv_list $(grep "DOMAIN='$domain'" $USER_DATA/web.conf) + +# Remove forcessl configs +if [ -f "$HOMEDIR/$user/conf/web/$domain/$WEB_SYSTEM.forcessl.conf" ]; then + rm -f $HOMEDIR/$user/conf/web/$domain/$WEB_SYSTEM.forcessl.conf +fi +if [ -f "$HOMEDIR/$user/conf/web/$domain/$PROXY_SYSTEM.forcessl.conf" ]; then + rm -f $HOMEDIR/$user/conf/web/$domain/$PROXY_SYSTEM.forcessl.conf +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +if [ -z "$SSL_FORCE" ]; then + add_object_key "web" 'DOMAIN' "$domain" 'SSL_FORCE' 'SSL_HOME' +fi + +update_object_value 'web' 'DOMAIN' "$domain" '$SSL_FORCE' 'no' + +# Restart services if requested +$BIN/v-restart-web "$restart" +check_result $? "Web restart failed" > /dev/null + +$BIN/v-restart-proxy "$restart" +check_result $? "Proxy restart failed" > /dev/null + +# Logging +if [ "$quiet" != "yes" ]; then + $BIN/v-log-action "$user" "Info" "Web" "Automatic HTTPS redirection disabled (Domain: $domain)." +fi +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-delete-web-domain-ssl-hsts b/bin/v-delete-web-domain-ssl-hsts new file mode 100755 index 0000000..3553023 --- /dev/null +++ b/bin/v-delete-web-domain-ssl-hsts @@ -0,0 +1,78 @@ +#!/bin/bash +# info: remove ssl force from domain +# options: USER DOMAIN [RESTART] [QUIET] +# +# example: v-delete-web-domain-ssl-hsts user domain.tld +# +# This function removes force SSL configurations. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +restart=$3 +quiet=$4 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DOMAIN' +is_format_valid 'user' 'domain' +is_object_valid 'user' 'USER' "$user" +is_object_valid 'web' 'DOMAIN' "$domain" +is_object_valid 'web' 'DOMAIN' "$domain" "$SSL_FORCE" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Load domain data +parse_object_kv_list $(grep "DOMAIN='$domain'" $USER_DATA/web.conf) + +# Check for Apache/Nginx or Nginx/PHP-FPM configuration +if [ -z $PROXY_SYSTEM ]; then + hstsconf="$HOMEDIR/$user/conf/web/$domain/$WEB_SYSTEM.hsts.conf" +else + hstsconf="$HOMEDIR/$user/conf/web/$domain/$PROXY_SYSTEM.hsts.conf" +fi + +rm -f $hstsconf + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Set forcessl flag to enabled +update_object_value 'web' 'DOMAIN' "$domain" '$SSL_HSTS' 'no' + +# Restart services if requested +$BIN/v-restart-web "$restart" +check_result $? "Web restart failed" > /dev/null + +$BIN/v-restart-proxy "$restart" +check_result $? "Proxy restart failed" > /dev/null + +# Logging +if [ "$quiet" != "yes" ]; then + $BIN/v-log-action "$user" "Info" "Web" "HTTP Strict Transport Security disabled (Domain: $domain)." +fi +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-delete-web-domain-stats b/bin/v-delete-web-domain-stats new file mode 100755 index 0000000..e2d0f9a --- /dev/null +++ b/bin/v-delete-web-domain-stats @@ -0,0 +1,75 @@ +#!/bin/bash +# info: delete web domain statistics +# options: USER DOMAIN +# +# example: v-delete-web-domain-stats user02 h1.example.com +# +# This function of deleting site's system of statistics. Its type is +# automatically chooses from client's configuration file. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DOMAIN' +is_format_valid 'user' 'domain' +is_system_enabled "$WEB_SYSTEM" 'WEB_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_valid 'web' 'DOMAIN' "$domain" +is_object_value_exist 'web' 'DOMAIN' "$domain" '$STATS' + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Defining statistic type +get_domain_values 'web' + +# Deleting dir content +rm -rf "$HOMEDIR/$user/web/$domain/stats" + +# Deleting config +rm -f "/etc/awstats/$STATS.$domain_idn.conf" +rm -f "$HOMEDIR/$user/conf/web/$domain/$STATS.conf" + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Deleting pipe command +sed -i "/ $domain$/d" $HESTIA/data/queue/webstats.pipe + +# Update config +update_object_value 'web' 'DOMAIN' "$domain" '$STATS' '' + +# Logging +$BIN/v-log-action "$user" "Info" "Web" "Web traffic analyzer disabled (Domain: $domain)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-delete-web-domain-stats-user b/bin/v-delete-web-domain-stats-user new file mode 100755 index 0000000..9f6491f --- /dev/null +++ b/bin/v-delete-web-domain-stats-user @@ -0,0 +1,73 @@ +#!/bin/bash +# info: disable web domain stats authentication support +# options: USER DOMAIN [RESTART] +# +# example: v-delete-web-domain-stats-user admin acme.com +# +# This function removes authentication of statistics system. If the script is +# called without naming a certain user, all users will be removed. After +# deleting all of them statistics will be accessible for view without an +# authentication. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +restart=$3 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DOMAIN [RESTART]' +is_format_valid 'user' 'domain' +is_system_enabled "$WEB_SYSTEM" 'WEB_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_valid 'web' 'DOMAIN' "$domain" +is_object_value_exist 'web' 'DOMAIN' "$domain" '$STATS_USER' + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Deleting statistic dir +stats_dir="$HOMEDIR/$user/web/$domain/stats" +rm -f "$stats_dir/.htpasswd" +rm -f "$stats_dir/.htaccess" + +# Deleting nginx auth config +if [ "$WEB_SYSTEM" = 'nginx' ]; then + rm -f $stats_dir/auth.conf 2> /dev/null + $BIN/v-restart-web "$restart" + check_result $? "Web restart failed" > /dev/null +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Update config +update_object_value 'web' 'DOMAIN' "$domain" '$STATS_USER' '' +update_object_value 'web' 'DOMAIN' "$domain" '$STATS_CRYPT' '' + +# Logging +$BIN/v-log-action "$user" "Info" "Web" "Web traffic analyzer password enabled (Domain: $domain)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-delete-web-domains b/bin/v-delete-web-domains new file mode 100755 index 0000000..116e83e --- /dev/null +++ b/bin/v-delete-web-domains @@ -0,0 +1,62 @@ +#!/bin/bash +# info: delete web domains +# options: USER [RESTART] +# +# example: v-delete-web-domains admin +# +# This function deletes all user's webdomains. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +restart=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'USER [RESTART]' +is_format_valid 'user' +is_system_enabled "$WEB_SYSTEM" 'WEB_SYSTEM' +is_object_valid 'user' 'USER' "$user" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Starting delete loop +for domain in $(search_objects 'web' 'SUSPENDED' "no" 'DOMAIN'); do + $BIN/v-delete-web-domain "$user" "$domain" 'no' +done + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Restarting web server +$BIN/v-restart-web "$restart" +check_result $? "Web restart failed" > /dev/null + +$BIN/v-restart-proxy "$restart" +check_result $? "Proxy restart failed" > /dev/null + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-delete-web-php b/bin/v-delete-web-php new file mode 100755 index 0000000..9680df1 --- /dev/null +++ b/bin/v-delete-web-php @@ -0,0 +1,125 @@ +#!/bin/bash +# info: delete php fpm version +# options: VERSION +# +# example: v-delete-web-php 7.3 +# +# This function checks and delete a fpm php version if not used by any domain. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +version=$1 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'VERSION' + +if [ -z "$WEB_BACKEND" ]; then + echo "Multiple php versions are not supported for modphp" +fi + +# Set file locations +php_fpm="/etc/init.d/php$version-fpm" + +# Verify php version format +if [[ ! $version =~ ^[0-9]\.[0-9]+ ]]; then + echo "The PHP version format is invalid, it should look like [0-9].[0-9]." + echo "Example: 7.0, 7.4" + exit +fi + +# Remove backend template +[ -f $HESTIA/data/templates/web/php-fpm/PHP-${version/\./_}.tpl ] && rm -f $HESTIA/data/templates/web/php-fpm/PHP-${version/\./_}.tpl + +# Check if php version exists +version_check=$($BIN/v-list-sys-php plain | grep "$version") +if [ -z "$version_check" ]; then + echo "ERROR: Specified PHP version is not installed." + exit "$E_INVALID" +fi + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +mph="php$version-common php$version-mbstring php$version-bcmath php$version-cli php$version-curl + php$version-fpm php$version-gd php$version-intl php$version-mysql + php$version-soap php$version-xml php$version-zip php$version-mbstring + php$version-json php$version-bz2 php$version-pspell php$version-imagick php$version-pgsql + php$version-imap php$version-ldap" + +# Check is version is 7.1 or below to add mcrypt +if [[ $(echo "$version 7.2" | awk '{print ($1 < $2)}') == 1 ]]; then + mph="$mph php$version-mcrypt" +fi + +# Purge php packages +if [ -f '/etc/redhat-release' ]; then + dnf remove -y $mph > /dev/null 2>&1 & +else + apt-get -y purge $mph > /dev/null 2>&1 & +fi +BACK_PID=$! + +# Check if package removal is done, print a spinner +echo "Removing PHP-$version, please wait..." +spinner="/-\|" +spin_i=1 +while kill -0 $BACK_PID > /dev/null 2>&1; do + printf "\b${spinner:spin_i++%${#spinner}:1}" + sleep 0.5 +done + +# Do a blank echo to get the \n back +echo + +# Check if installation was successfully +if [ -f "$php_fpm" ]; then + echo "ERROR: Uninstallation failed, please run the following command manually for debugging:" + if [ -f '/etc/redhat-release' ]; then + echo "dnf remove $mph" + else + echo "apt-get purge $mph" + fi + exit 1 +fi + +# Cleanup php folder +[[ -d /etc/php/$version ]] && rm -rf "/etc/php/$version" + +if [ "$WEB_BACKEND" = "php-fpm" ]; then + conf=$(find /etc/php* -name www.conf) + # Check if www.conf exists + if [ -z "$conf" ]; then + # If not grab the "last php version + last=$($BIN/v-list-sys-php "shell" | tail -n1) + cp -f $HESTIA/install/deb/php-fpm/www.conf /etc/php/$last/fpm/pool.d/www.conf + $BIN/v-restart-web-backend + fi +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +$BIN/v-log-action "system" "Info" "System" "Uninstalled PHP $version." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-download-backup b/bin/v-download-backup new file mode 100755 index 0000000..9a8f20d --- /dev/null +++ b/bin/v-download-backup @@ -0,0 +1,119 @@ +#!/bin/bash +# info: Download backup +# options: USER BACKUP +# +# example: v-download-backup admin admin.2020-11-05_05-10-21.tar +# +# This function download back-up from remote server + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +backup=$2 + +# Define backup dir +if [ -z "$BACKUP" ]; then + BACKUP=/backup +fi + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# shellcheck source=/usr/local/hestia/func/ip.sh +source $HESTIA/func/ip.sh +# shellcheck source=/usr/local/hestia/func/db.sh +source $HESTIA/func/db.sh +# shellcheck source=/usr/local/hestia/func/rebuild.sh +source $HESTIA/func/rebuild.sh +# shellcheck source=/usr/local/hestia/func/backup.sh +source $HESTIA/func/backup.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER BACKUP' +is_format_valid 'user' 'backup' + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Checking available disk space +disk_usage=$(df $BACKUP | tail -n1 | tr ' ' '\n' | grep % | cut -f 1 -d %) +if [ "$disk_usage" -ge "$BACKUP_DISK_LIMIT" ]; then + echo "Error: Not enough disk space" | $SENDMAIL -s "$subj" $email $notify + sed -i "/ $user /d" $HESTIA/data/queue/backup.pipe + check_result $E_DISK "Not enough disk space" +fi + +# Checking local backup +if [ ! -e "$BACKUP/$backup" ]; then + if [[ "$BACKUP_SYSTEM" =~ "google" ]]; then + google_download "$backup" + downloaded='yes' + fi + if [[ "$BACKUP_SYSTEM" =~ "sftp" ]] && [ -z "$downloaded" ]; then + sftp_download "$backup" + downloaded='yes' + fi + if [[ "$BACKUP_SYSTEM" =~ "ftp" ]] && [ -z "$downloaded" ]; then + ftp_download "$backup" + downloaded='yes' + fi + if [[ "$BACKUP_SYSTEM" =~ "rclone" ]] && [ -z "$downloaded" ]; then + rclone_download "$backup" + downloaded='yes' + fi + if [[ "$BACKUP_SYSTEM" =~ "b2" ]] && [ -z "$downloaded" ]; then + b2_download "$backup" + downloaded='yes' + fi + if [ -z "$downloaded" ]; then + subj="Download of $backup failed for $user" + $BIN/v-add-user-notification $user "$subj" "

Unable to retrieve backup file from remote server.

Error: $backup file doesn't exist in '${BACKUP}' directory.

" + sed -i "/v-download-backup $user /d" $HESTIA/data/queue/backup.pipe + check_result "$E_NOTEXIST" "backup file $backup doesn't exist in '${BACKUP}' folder" + else + if [ -e "$BACKUP/$backup" ]; then + chmod 0640 $BACKUP/$backup + chown admin:admin $BACKUP/$backup + echo "rm $BACKUP/$backup" | at now + 1 day + fi + fi +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Send notification +if [ -e "$BACKUP/$backup" ]; then + cd $BACKUP + subj="Download of $backup completed for $user" + email=$(get_user_value '$CONTACT') + echo "Backup file $backup was retrieved from the remote server and will be available to download for 12 hours." | $SENDMAIL -s "$subj" "$email" "$notify" + $BIN/v-add-user-notification "$user" "$subj" "

Backup file $backup was retrieved from the remote server and will be available to download for 12 hours.

" +fi + +# Cleaning restore queue +sed -i "/v-download-backup $user /d" $HESTIA/data/queue/backup.pipe + +# Logging +$BIN/v-log-action "system" "Info" "Backup" "Backup download requested (User: $user, Archive: $backup)." +$BIN/v-log-action "$user" "Info" "Backup" "Backup download requested (Archive: $backup)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-dump-database b/bin/v-dump-database new file mode 100755 index 0000000..714cb3d --- /dev/null +++ b/bin/v-dump-database @@ -0,0 +1,90 @@ +#!/bin/bash +# info: Dumps database contents in STDIN / file +# options: USER DATABASE [FILE] +# +# example: v-dump-database user user_databse > test.sql +# example: v-dump-database user user_databse file +# +# Dumps database in STDIN or /backup/user.database.type.sql + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +database=$2 +output=$3 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/db.sh +source $HESTIA/func/db.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +check_args '2' "$#" 'USER DATABASE' +is_format_valid 'user' 'database' +is_system_enabled "$DB_SYSTEM" 'DB_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Create timestamp in Y-M-D_h-m-s format +timestamp=$(date +'%G-%m-%d_%H-%M-%S') + +# Check db existence +db_data=$(grep "DB='$database'" $HESTIA/data/users/$user/db.conf) +if [ -z "$db_data" ]; then + echo "Error: database $database doesn't exist" + log_event "$E_NOTEXIST" "$ARGUMENTS" + exit "$E_NOTEXIST" +fi + +parse_object_kv_list "$db_data" + +# Creating temporary directory +tmpdir=$(mktemp -p $BACKUP -d "tmp.$database.XXXXXXXXXX") + +# Dump database +dump="$tmpdir/$database.$TYPE.sql" +grants="$tmpdir/$database.$TYPE.$DBUSER" +case $TYPE in + mysql) dump_mysql_database ;; + pgsql) dump_pgsql_database ;; +esac + +if [ "$output" = "file" ]; then + # echo filename for use in the php + echo "${user}_${database}_${TYPE}_${timestamp}.sql" + + cp $dump $BACKUP/${user}_${database}_${TYPE}_${timestamp}.sql + + # echo file location for use in the php + echo "$BACKUP/${user}_${database}_${TYPE}_${timestamp}.sql" + + # cleanup + echo "rm $BACKUP/${user}_${database}_${TYPE}_${timestamp}.sql" | at now + 1 hour +else + cat $dump +fi + +rm -fr $tmpdir + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-dump-site b/bin/v-dump-site new file mode 100755 index 0000000..b8af1a7 --- /dev/null +++ b/bin/v-dump-site @@ -0,0 +1,70 @@ +#!/bin/bash +# info: Dumps the files of a site into a zip archive +# options: USER DOMAIN [TYPE] +# +# example: v-dump-site user domain +# example: v-dump-site user domain full +# +# Dumps site files in /backup/user.domain.timestamp.zip + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +type=$3 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +check_args '2' "$#" 'USER DOMAIN' +is_format_valid 'user' 'domain' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'web' 'DOMAIN' "$domain" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Create timestamp in Y-M-D_h-m-s format +timestamp=$(date +'%G-%m-%d_%H-%M-%S') + +if [ "$type" = "full" ]; then + cd /home/$user/web/$domain/ +else + cd /home/$user/web/$domain/public_html/ +fi + +zip -rq $BACKUP/${user}_${domain}_${timestamp}.zip . + +if [[ -f "$BACKUP/${user}_${domain}_${timestamp}.zip" ]]; then + # echo filename for use in the php + echo "${user}_${domain}_${timestamp}.zip" + + # echo file location for use in the php + echo "$BACKUP/${user}_${domain}_${timestamp}.zip" + + # cleanup + echo "rm $BACKUP/${user}_${domain}_${timestamp}.zip" | at now + 1 hour +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit + diff --git a/bin/v-export-rrd b/bin/v-export-rrd new file mode 100755 index 0000000..09e5083 --- /dev/null +++ b/bin/v-export-rrd @@ -0,0 +1,201 @@ +#!/bin/bash +# info: export rrd charts as json +# options: [CHART] [TIMESPAN] +# +# example: v-export-rrd chart format + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +chart=$1 +timespan=${2-daily} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'chart' + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +function generate_load_table() { + rrdtool xport --json -s $start -e $end --step $step \ + DEF:la=$RRD/la/la.rrd:LA:AVERAGE \ + DEF:pr=$RRD/la/la.rrd:PR:AVERAGE \ + XPORT:la:Load \ + XPORT:pr:Processes +} + +function generate_mem_table() { + rrdtool xport --json -s $start -e $end --step $step \ + DEF:used=$RRD/mem/mem.rrd:RAM:AVERAGE \ + DEF:swap=$RRD/mem/mem.rrd:SWAP:AVERAGE \ + DEF:free=$RRD/mem/mem.rrd:FREE:AVERAGE \ + XPORT:used:Used \ + XPORT:swap:Swap \ + XPORT:free:Free +} + +function generate_apache2_table() { + rrdtool xport --json -s $start -e $end --step $step \ + DEF:a=$RRD/web/apache2.rrd:A:AVERAGE \ + XPORT:a:Connections +} + +function generate_httpd_table() { + rrdtool xport --json -s $start -e $end --step $step \ + DEF:a=$RRD/web/httpd.rrd:A:AVERAGE \ + XPORT:a:Connections +} + +function generate_nginx_table() { + rrdtool xport --json -s $start -e $end --step $step \ + DEF:a=$RRD/web/nginx.rrd:A:AVERAGE \ + XPORT:a:Connections +} + +function generate_ftp_table() { + rrdtool xport --json -s $start -e $end --step $step \ + DEF:a=$RRD/ftp/ftp.rrd:A:AVERAGE \ + XPORT:a:Connections +} + +function generate_ssh_table() { + rrdtool xport --json -s $start -e $end --step $step \ + DEF:a=$RRD/ssh/ssh.rrd:A:AVERAGE \ + XPORT:a:Connections +} + +function generate_mysql_table() { + if [ -f "$RRD/db/mysql_$host.rrd" ]; then + rrdtool xport --json -s $start -e $end --step $step \ + DEF:a=$RRD/db/mysql_$host.rrd:A:AVERAGE \ + DEF:s=$RRD/db/mysql_$host.rrd:S:AVERAGE \ + XPORT:a:Queries \ + XPORT:s:Slow + else + echo "Does not exists" + exit 1 + fi +} + +function generate_pgsql_table() { + if [ -f "$RRD/db/pgsql_$host.rrd" ]; then + rrdtool xport --json -s $start -e $end --step $step \ + DEF:a=$RRD/db/pgsql_$host.rrd:A:AVERAGE \ + DEF:t=$RRD/db/pgsql_$host.rrd:T:AVERAGE \ + XPORT:a:Queries \ + XPORT:t:Transactions + else + echo "Does not exists" + exit 1 + fi +} + +function generate_mail_table() { + rrdtool xport --json -s $start -e $end --step $step \ + DEF:a=$RRD/mail/mail.rrd:A:AVERAGE \ + XPORT:a:Emails +} + +function generate_net_table() { + if [ -f "$RRD/net/$host.rrd" ]; then + rrdtool xport --json -s $start -e $end --step $step \ + DEF:inoctets=$RRD/net/$host.rrd:RX:AVERAGE \ + DEF:outoctets=$RRD/net/$host.rrd:TX:AVERAGE \ + XPORT:inoctets:"Input (rx)" \ + XPORT:outoctets:"Output (tx)" + else + echo "Does not exists" + exit 1 + fi +} + +if [ "$timespan" = "weekly" ]; then + start=$(date -d "7 days ago" +%s) + # every 30 min + step=3600 +elif [ "$timespan" = "monthly" ]; then + start=$(date -d "1 month ago" +%s) + step=21600 +elif [ "$timespan" = "yearly" ]; then + start=$(date -d "1 year ago" +%s) + step=172800 +elif [ "$timespan" = "biennially" ]; then + start=$(date -d "2 year ago" +%s) + step=345600 +elif [ "$timespan" = "triennially" ]; then + start=$(date -d "3 year ago" +%s) + step=518400 +else + start=$(date -d "1 day ago" +%s) + # every 5min + step=300 +fi +end=$(date +%s) + +host=$(echo $chart | cut -d'_' -f2) +chart=$(echo $chart | cut -d'_' -f1) + +case $chart in + "la") + generate_load_table + ;; + + "mem") + generate_mem_table + ;; + + "apache2") + generate_apache2_table + ;; + + "httpd") + generate_httpd_table + ;; + + "nginx") + generate_nginx_table + ;; + + "ftp") + generate_ftp_table + ;; + + "ssh") + generate_ssh_table + ;; + + "mysql") + generate_mysql_table + ;; + + "pgsql") + generate_pgsql_table + ;; + + "mail") + generate_mail_table + ;; + + "net") + generate_net_table + ;; + + \ + *) + echo "Does not exists" + exit 1 + ;; +esac diff --git a/bin/v-extract-fs-archive b/bin/v-extract-fs-archive new file mode 100755 index 0000000..b3c62a2 --- /dev/null +++ b/bin/v-extract-fs-archive @@ -0,0 +1,171 @@ +#!/bin/bash +# info: archive to directory +# options: USER ARCHIVE DIRECTORY [SELECTED_DIR] [STRIP] [TEST] +# +# example: v-extract-fs-archive admin latest.tar.gz /home/admin +# +# This function extracts archive into directory on the file system + +user=$1 +src_file=$2 +dst_dir=$3 +selected_dir=$4 +strip=$5 +test=$6 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '3' "$#" 'USER ARCHIVE DIRECTORY [SELECTED_DIR] [STRIP] [TEST]' +is_format_valid 'user' +is_object_valid 'user' 'USER' "$user" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +# Checking user homedir +homedir=$(grep "^$user:" /etc/passwd | cut -f 6 -d :) +if [ -z "$homedir" ]; then + echo "Error: user home directory doesn't exist" + exit 12 +fi + +# Checking source dir +if [ ! -e "$src_file" ]; then + echo "Error: source file $src_file doesn't exist" + exit 3 +fi + +# Checking source path +rpath=$(readlink -f "$src_file") +if [ -z "$(echo $rpath | egrep "^/tmp|^$homedir|^$BACKUP/$user\.|^$BACKUP/tmp\.")" ]; then + echo "Error: invalid source path $src_file" + exit 2 +fi + +# Checking destination path +rpath=$(readlink -f "$dst_dir") +if [ -z "$(echo $rpath | egrep "^/tmp|^$homedir")" ]; then + echo "Error: invalid destination path $dst_dir" + exit 2 +fi + +if [ -n "$strip" ]; then + is_int_format_valid "$strip" 'strip-components' + tar_strip_level="--strip-components $strip" +fi +# Extracting gziped archive +if [ -n "$(echo $src_file | egrep -i '.tgz|.tar.gz')" ]; then + x='yes' + if [ -z "$test" ] || [ "$test" = "no" ]; then + user_exec mkdir -p "$dst_dir" > /dev/null 2>&1 + user_exec tar -xzf "$src_file" -C "$dst_dir" --no-wildcards "$selected_dir" $tar_strip_level > /dev/null 2>&1 + rc=$? + else + user_exec tar -tf "$src_file" --no-wildcards "$selected_dir" > /dev/null 2>&1 + rc=$? + fi +fi + +# Extracting bziped archive +if [ -n "$(echo $src_file | egrep -i '.tbz|.tar.bz')" ]; then + x='yes' + if [ -z "$test" ] || [ "$test" = "no" ]; then + user_exec mkdir -p "$dst_dir" > /dev/null 2>&1 + user_exec tar -xjf "$src_file" -C "$dst_dir" --no-wildcards "$selected_dir" $tar_strip_level > /dev/null 2>&1 + rc=$? + else + user_exec tar -tf "$src_file" --no-wildcards "$selected_dir" > /dev/null 2>&1 + rc=$? + fi +fi + +# Extracting ZSTD archive +if [ -n "$(echo $src_file | egrep -i '.tar.zst')" ]; then + x='yes' + if [ -z "$test" ] || [ "$test" = "no" ]; then + user_exec mkdir -p "$dst_dir" > /dev/null 2>&1 + user_exec tar -I pzstd -xf "$src_file" -C "$dst_dir" --no-wildcards "$selected_dir" $tar_strip_level > /dev/null 2>&1 + rc=$? + else + user_exec tar -I pzstd -tf "$src_file" --no-wildcards "$selected_dir" > /dev/null 2>&1 + rc=$? + fi +fi + +# Extracting gziped file +if [ -n "$(echo $src_file | grep -i '.zst')" ] && [ -z "$x" ]; then + user_exec mkdir -p "$dst_dir" > /dev/null 2>&1 + user_exec mv "$src_file" "$dst_dir" > /dev/null 2>&1 + user_exec pzstd -d "$dst_dir/$(basename $src_file)" > /dev/null 2>&1 + rc=$? +fi + +# Extracting gziped file +if [ -n "$(echo $src_file | grep -i '.gz')" ] && [ -z "$x" ]; then + user_exec mkdir -p "$dst_dir" > /dev/null 2>&1 + user_exec mv "$src_file" "$dst_dir" > /dev/null 2>&1 + user_exec gzip -d "$dst_dir/$(basename $src_file)" > /dev/null 2>&1 + rc=$? +fi + +# Extracting bziped file +if [ -n "$(echo $src_file | grep -i '.bz')" ] && [ -z "$x" ]; then + user_exec mkdir -p "$dst_dir" > /dev/null 2>&1 + user_exec mv "$src_file" "$dst_dir" # >/dev/null 2>&1 + user_exec bzip2 -d "$dst_dir/$(basename $src_file)" > /dev/null 2>&1 + rc=$? +fi + +# Extracting ziped archive +if [ -n "$(echo $src_file | grep -i '.zip')" ]; then + user_exec mkdir -p "$dst_dir" > /dev/null 2>&1 + user_exec unzip "$src_file" -d "$dst_dir" > /dev/null 2>&1 + rc=$? +fi + +# Extracting ziped archive +if [ -n "$(echo $src_file | grep -i '.7z')" ]; then + user_exec mkdir -p "$dst_dir" > /dev/null 2>&1 + user_exec mv "$src_file" "$dst_dir" > /dev/null 2>&1 + user_exec p7zip -d "$src_file" > /dev/null 2>&1 + rc=$? +fi + +# Extracting tared archive +if [ -n "$(echo $src_file | grep -i '.tar')" ] && [ -z "$x" ]; then + x='yes' + if [ -z "$test" ] || [ "$test" = "no" ]; then + user_exec mkdir -p "$dst_dir" > /dev/null 2>&1 + user_exec tar -xf "$src_file" -C "$dst_dir" --no-wildcards "$selected_dir" $tar_strip_level > /dev/null 2>&1 + rc=$? + else + user_exec tar -tf "$src_file" --no-wildcards "$selected_dir" > /dev/null 2>&1 + rc=$? + fi +fi + +# Extracting rared archive +if [ -n "$(echo $src_file | grep -i '.rar')" ]; then + user_exec mkdir -p "$dst_dir" > /dev/null 2>&1 + user_exec unrar "$src_file" "$dst_dir" > /dev/null 2>&1 + rc=$? +fi + +# Checking result +if [ $rc -ne 0 ]; then + echo "Error: $src_file was not extracted" + exit 3 +fi + +# Exiting +exit diff --git a/bin/v-generate-api-key b/bin/v-generate-api-key new file mode 100755 index 0000000..caee3e2 --- /dev/null +++ b/bin/v-generate-api-key @@ -0,0 +1,56 @@ +#!/bin/bash +# info: generate api key +# options: NONE +# +# example: v-generate-api-key +# +# This function creates a key file in $HESTIA/data/keys/ + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +keygen() { + tr < /dev/urandom -dc _A-Z-a-z-0-9 | head -c 32 + echo +} +HASH=$(keygen) + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +if [ ! -d "$HESTIA/data/keys/" ]; then + mkdir -p $HESTIA/data/keys/ + chown admin:root $HESTIA/data/keys/ + chmod 750 $HESTIA/data/keys/ +fi + +if [[ -e "$HESTIA/data/keys/$HASH" ]]; then + while [[ -e "$HESTIA/data/keys/$HASH" ]]; do + HASH=$(keygen) + done +fi + +touch $HESTIA/data/keys/$HASH +echo "$HASH" + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +$BIN/v-log-action "system" "Warning" "System" "New system API key generated (Key: ${HASH})." + +exit diff --git a/bin/v-generate-debug-report b/bin/v-generate-debug-report new file mode 100755 index 0000000..906ec51 --- /dev/null +++ b/bin/v-generate-debug-report @@ -0,0 +1,74 @@ +#!/bin/bash + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Variables and arguments +HESTIA="/usr/local/hestia" +script=$1 +log=$2 +mode=${3-$2} + +if [ "$DEBUG_MODE" = "no" ] || [ -z "$DEBUG_MODE" ]; then + echo "ERROR: Developer mode is disabled." + echo "Enable with v-change-sys-config-value DEBUG_MODE yes" + exit 1 +fi + +if [ -z "$script" ]; then + echo "ERROR: No script specified." + echo "Usage: v-generate-debug-report v-script-name LOG_OUTPUT" + echo "" + echo "Example: v-generate-debug-report v-add-user yes" + echo " Log output to file located in ~/hst-debug/" + echo "" + echo "Example: v-generate-debug-report v-list-web-domains" + echo " Show output in console." + echo "" + exit 1 +fi + +# Install shellcheck +package_check=$(dpkg -l | grep shellcheck) +if [ -z "$package_check" ]; then + echo "[ * ] Updating APT package cache..." + apt-get -qq update > /dev/null 2>&1 + echo "[ * ] Installing shellcheck code linter..." + apt-get -qq install -y shellcheck > /dev/null 2>&1 +fi + +# Set debug path and ensure it exists +DEBUG_PATH="$HOME/hst-debug/" +if [ ! -d "$DEBUG_PATH" ]; then + mkdir "$DEBUG_PATH" +fi + +# Generate timestamp +time_n_date=$(date +'%F %T') +time_n_date=$(echo "$time_n_date" | sed "s|:||g" | sed "s| |_|g") + +# If logging specified, export shellcheck output to log +if [ "$log" = "yes" ]; then + if [ "$mode" = "all" ]; then + shellcheck -x "$BIN/$script" > "$DEBUG_PATH/${script}_$time_n_date.log" + fi + if [ "$mode" = "warn" ]; then + shellcheck -x -e "SC2086,SC1090,SC2154,SC2153" "$BIN/$script" > "$DEBUG_PATH/${script}_$time_n_date.log" + else + shellcheck -x -e "SC2086,SC2016,SC2153,SC2154,SC1090,SC2034,SC2119" "$BIN/$script" > "$DEBUG_PATH/${script}_$time_n_date.log" + fi +else + # Prompt user to scroll output from shellcheck + clear + if [ "$mode" = "all" ]; then + shellcheck -x "$BIN/$script" + fi + if [ "$mode" = "warn" ]; then + shellcheck -x -e "SC2086,SC1090,SC2154,SC2153" "$BIN/$script" + else + shellcheck -x -e "SC2086,SC2016,SC2153,SC2154,SC1090,SC2034,SC2119" "$BIN/$script" + fi +fi diff --git a/bin/v-generate-password-hash b/bin/v-generate-password-hash new file mode 100755 index 0000000..895fde6 --- /dev/null +++ b/bin/v-generate-password-hash @@ -0,0 +1,49 @@ +#!/usr/local/hestia/php/bin/php + "$domain.key" 2> /dev/null + +subj="" +# Generate the CSR +if [ -n "$email" ]; then + subj="/emailAddress=$email" +fi + +subj="$subj/C=$country/ST=$state/L=$city/O=$org" +subj="$subj/OU=$org_unit/CN=$domain_idn" + +if [ -z "$aliases" ]; then + openssl req -sha256 -new \ + -batch \ + -subj "$subj" \ + -key $domain.key \ + -out $domain.csr > /dev/null 2>&1 +else + for alias in $(echo $domain,$aliases | tr ',' '\n' | sort -u); do + if [[ "$alias" = *[![:ascii:]]* ]]; then + alias=$(idn2 --quiet $alias) + fi + dns_aliases="${dns_aliases}DNS:$alias," + done + dns_aliases=$(echo $dns_aliases | sed "s/,$//") + if [ -e "/etc/ssl/openssl.cnf" ]; then + ssl_conf='/etc/ssl/openssl.cnf' + else + ssl_conf="/etc/pki/tls/openssl.cnf" + fi + + openssl req -sha256 -new \ + -batch \ + -subj "$subj" \ + -key $domain.key \ + -reqexts SAN \ + -config <(cat $ssl_conf \ + <(printf "[SAN]\nsubjectAltName=$dns_aliases")) \ + -out $domain.csr > /dev/null 2>&1 +fi + +# Generate the cert 1 year +openssl x509 -req -sha256 \ + -days $DAYS \ + -in $domain.csr \ + -signkey $domain.key \ + -out $domain.crt > /dev/null 2>&1 + +# Listing certificates +if [ -e "$domain.crt" ]; then + crt=$(cat $domain.crt | sed ':a;N;$!ba;s/\n/\\n/g') +fi + +if [ -e "$domain.key" ]; then + key=$(cat $domain.key | sed ':a;N;$!ba;s/\n/\\n/g') +fi + +if [ -e "$domain.csr" ]; then + csr=$(cat $domain.csr | sed ':a;N;$!ba;s/\n/\\n/g') +fi + +case $format in + json) json_list_ssl ;; + plain) + nohead=1 + shell_list_ssl + ;; + shell) shell_list_ssl ;; + *) check_args '1' '0' '[FORMAT]' ;; +esac + +# Don't allow non root users view folder +chmod 660 $workdir +# Clean up the mess +echo "rm -rf $workdir" | at -M "now +15 minute" > /dev/null 2>&1 +# Delete tmp dir +#rm -rf $workdir + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-get-dns-domain-value b/bin/v-get-dns-domain-value new file mode 100755 index 0000000..111d51a --- /dev/null +++ b/bin/v-get-dns-domain-value @@ -0,0 +1,57 @@ +#!/bin/bash +# info: get dns domain value +# options: USER DOMAIN KEY +# +# example: v-get-dns-domain-value admin example.com SOA +# +# This function for getting a certain DNS domain parameter. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 +key=$3 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn +# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ? + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '3' "$#" 'USER DOMAIN KEY' +is_format_valid 'user' 'domain' 'key' +is_object_valid 'user' 'USER' "$user" +is_object_valid 'dns' 'DOMAIN' "$domain" + +key=$(echo "$key" | tr '[:lower:]' '[:upper:]' | sed "s/^/$/") + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Print +get_object_value 'dns' 'DOMAIN' "$domain" "$key" + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-get-fs-file-type b/bin/v-get-fs-file-type new file mode 100755 index 0000000..c8d548f --- /dev/null +++ b/bin/v-get-fs-file-type @@ -0,0 +1,46 @@ +#!/bin/bash +# info: get file type +# options: USER FILE +# +# example: v-get-fs-file-type admin index.html +# +# This function shows file type + +user=$1 +path=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER FILE' +is_format_valid 'user' +is_object_valid 'user' 'USER' "$user" + +# Checking user homedir +homedir=$(grep "^$user:" /etc/passwd | cut -f 6 -d :) +if [ -z "$homedir" ]; then + echo "Error: user home directory doesn't exist" + exit 12 +fi + +# Checking path +rpath=$(readlink -f "$path") +if [ -z "$(echo $rpath | grep $homedir)" ]; then + echo "Error: invalid path $path" + exit 2 +fi + +# Listing file type +user_exec file -i -b "$path" 2> /dev/null + +# Exiting +exit $? diff --git a/bin/v-get-mail-account-value b/bin/v-get-mail-account-value new file mode 100755 index 0000000..f3e6a69 --- /dev/null +++ b/bin/v-get-mail-account-value @@ -0,0 +1,59 @@ +#!/bin/bash +# info: get mail account value +# options: USER DOMAIN ACCOUNT KEY +# +# example: v-get-mail-account-value admin example.tld tester QUOTA +# +# This function for getting a certain mail account parameter. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 +account=$3 +key=$4 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn +# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ? + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '3' "$#" 'USER DOMAIN KEY' +is_format_valid 'user' 'domain' 'key' +is_object_valid 'user' 'USER' "$user" +is_object_valid 'mail' 'DOMAIN' "$domain" +is_object_valid "mail/$domain" 'ACCOUNT' "$account" + +key=$(echo "$key" | tr '[:lower:]' '[:upper:]' | sed "s/^/$/") + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Print +get_object_value "mail/$domain" 'ACCOUNT' "$account" "$key" + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-get-mail-domain-value b/bin/v-get-mail-domain-value new file mode 100755 index 0000000..7b32fb2 --- /dev/null +++ b/bin/v-get-mail-domain-value @@ -0,0 +1,57 @@ +#!/bin/bash +# info: get mail domain value +# options: USER DOMAIN KEY +# +# example: v-get-mail-domain-value admin example.com DKIM +# +# This function for getting a certain mail domain parameter. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 +key=$3 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn +# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ? + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '3' "$#" 'USER DOMAIN KEY' +is_format_valid 'user' 'domain' 'key' +is_object_valid 'user' 'USER' "$user" +is_object_valid 'mail' 'DOMAIN' "$domain" + +key=$(echo "$key" | tr '[:lower:]' '[:upper:]' | sed "s/^/$/") + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Print +get_object_value 'mail' 'DOMAIN' "$domain" "$key" + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-get-sys-timezone b/bin/v-get-sys-timezone new file mode 100755 index 0000000..6207ca0 --- /dev/null +++ b/bin/v-get-sys-timezone @@ -0,0 +1,51 @@ +#!/bin/bash +# info: get system timezone +# options: [FORMAT] +# +# This function to get system timezone + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +format=${1-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Checking timesonze on RHEL/CentOS +if [ -f "/etc/sysconfig/clock" ]; then + source /etc/sysconfig/clock + +# Checking timezone on Debian/Ubuntu +elif [ -f "/etc/timezone" ]; then + ZONE=$(cat /etc/timezone) + +# Checking symlynks +elif [ -h /etc/localtime ]; then + ZONE=$(readlink /etc/localtime | sed "s%.*share/zoneinfo/%%") + +# Parsing zoneinfo (very slow) +else + checksum=$(md5sum /etc/localtime | cut -d' ' -f1) + ZONE=$(find /usr/share/zoneinfo/ -type f -exec md5sum {} \; \ + | grep "^$checksum" | sed "s/.*\/usr\/share\/zoneinfo\///" | head -n 1) +fi + +echo $ZONE + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-get-sys-timezones b/bin/v-get-sys-timezones new file mode 100755 index 0000000..e375075 --- /dev/null +++ b/bin/v-get-sys-timezones @@ -0,0 +1,61 @@ +#!/bin/bash +# info: list system timezone +# options: [FORMAT] +# +# example: v-get-sys-timezones json +# +# This function checks system timezone settings + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +format=${1-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +json_list() { + jq -ncR '[inputs]' <<< "$zones" +} + +shell_list() { + IFS=$'\n' + echo "Timezone" + echo "--------" + for zone in $zones; do + echo $zone + done +} + +plain_list() { + IFS=$'\n' + for zone in $zones; do + echo $zone + done +} + +zones=$(cd /usr/share/zoneinfo/posix && find -L * -type f -or -type l | sort) + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + shell) shell_list | column -t ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-get-user-salt b/bin/v-get-user-salt new file mode 100755 index 0000000..d248755 --- /dev/null +++ b/bin/v-get-user-salt @@ -0,0 +1,124 @@ +#!/bin/bash +# info: get user salt +# options: USER [IP] [FORMAT] +# +# example: v-get-user-salt admin +# +# This function provides users salt + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +ip46=${2-127.0.0.1} +format=${3-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/conf/hestia.conf +source $HESTIA/conf/hestia.conf +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +time_n_date=$(date +'%T %F') +time=$(echo "$time_n_date" | cut -f 1 -d \ ) +date=$(echo "$time_n_date" | cut -f 2 -d \ ) + +# JSON list function +json_list() { + echo '{' + echo ' "'$user'": { + "METHOD": "'$method'", + "SALT": "'$salt'", + "TIME": "'$time'", + "DATE": "'$date'" + }' + echo '}' +} + +# SHELL list function +shell_list() { + echo "METHOD: $method" + echo "SALT: $salt" +} + +# PLAIN list function +plain_list() { + echo -e "$method\t$salt" +} + +# CSV list function +csv_list() { + echo "METHOD,SALT" + echo "$method, $salt" +} + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'USER [IP] [FORMAT]' +is_format_valid 'user' 'ip46' + +# Checking user +if [ ! -d "$HESTIA/data/users/$user" ]; then + echo "Error: password missmatch" + echo "$date $time $user $ip46 failed to login" >> $HESTIA/log/auth.log + exit 9 +fi + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Parsing user's salt +shadow=$(grep "^$user:" /etc/shadow | cut -f 2 -d :) + +if echo "$shadow" | grep -qE '^\$[0-9a-z]+\$[^\$]+\$'; then + salt=$(echo "$shadow" | cut -f 3 -d \$) + method=$(echo "$shadow" | cut -f 2 -d \$) + if [ "$method" = "y" ]; then + method='yescrypt' + salt=$(echo "$shadow" | cut -f 4 -d \$) + elif [ "$method" -eq '1' ]; then + method='md5' + elif [ "$method" -eq '6' ]; then + method='sha-512' + else + echo "Error: password missmatch" + echo "$date $time $user $ip46 failed to login" >> $HESTIA/log/auth.log + exit 9 + fi +elif [[ "$shadow" =~ ! ]]; then + echo "Error: Account has been suspended" + echo "$date $time $user $ip46 has been suspended" >> $HESTIA/log/auth.log + exit 5 +else + salt=${shadow:0:2} + method='des' +fi + +if [ -z "$salt" ]; then + echo "Error: password missmatch" + echo "$date $time $user $ip46 failed to login" >> $HESTIA/log/auth.log + exit 9 +fi + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-get-user-value b/bin/v-get-user-value new file mode 100755 index 0000000..0f34872 --- /dev/null +++ b/bin/v-get-user-value @@ -0,0 +1,47 @@ +#!/bin/bash +# info: get user value +# options: USER KEY +# +# example: v-get-user-value admin FNAME +# +# This function for obtaining certain user's parameters. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +key=$(echo "$2" | tr '[:lower:]' '[:upper:]') + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER KEY' +is_format_valid 'user' 'key' +is_object_valid 'user' 'USER' "$user" + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Checking key +value=$(get_user_value "$key") + +# Printing value +echo "$value" + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-import-cpanel b/bin/v-import-cpanel new file mode 100755 index 0000000..ce3c2d2 --- /dev/null +++ b/bin/v-import-cpanel @@ -0,0 +1,304 @@ +#!/bin/bash +# info: Import Cpanel backup to a new user +# options: BACKUP [MX] +# +# example: v-import-cpanel /backup/backup.tar.gz yes +# +# Based on sk-import-cpanel-backup-to-vestacp +# Credits: Maks Usmanov (skamasle) and contributors: +# Thanks to + +# Known issue +# - Importing certificates fails at the moment. Due to format changes of CPanel side +# - It doesn't update DKIM + +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +if [ $# -lt 1 ]; then + echo "usage: bash $0 cpanel-backup.tar.gz" + echo "or" + echo "usage: bash $0 cpanel-backup.tar.gz MX" + exit 1 +fi + +if [ ! -e /usr/bin/rsync ] || [ ! -e /usr/bin/file ]; then + echo "#######################################" + echo "rsync not installed, try install it" + echo "This script need: rsync, file" + echo "#######################################" + if [ -e /etc/redhat-release ]; then + echo "Run: yum install rsync file" + else + echo "Run: apt-get install rsync file" + fi + exit 3 +fi +# Default settings +# Put this to 0 if you want use bash -x to debug it +debug=1 +# Pacakge to be used by default "default" +hestia_package=default + +if [ -f "$1" ]; then + cpanel_backup="$1" +fi +if [ -n "$2" ]; then + mx="$2" +fi +if [ -z "$BACKUP_TEMP" ]; then + BACKUP_TEMP=$BACKUP +else + echo "File does not exists" + exit 1 +fi + +# Creating temporary directory +tmpdir=$(mktemp -p "$BACKUP_TEMP" -d) + +tput setaf 2 +echo "Checking provided file..." +tput sgr0 +if ! file "$cpanel_backup" | grep -q -c "gzip compressed data,"; then + echo "Error 3 not-gzip - no stantard cpanel backup provided of file not installed ( Try yum install file, or apt-get install file )" + rm -rf "$tmpdir" + exit 3 +fi + +tput setaf 2 +echo "OK - Gziped File" +tput sgr0 +echo "Extracting backup..." +if tar xzf "$cpanel_backup" -C "$tmpdir"; then + tput setaf 2 + echo "Backup extracted without errors..." + tput sgr0 +else + echo "Error on backup extraction, check your file, try extract it manually" + echo "Remove tmp" + rm -rf "$tmpdir" + exit 1 +fi + +cd $tmpdir/* + +echo "Get prefix..." +user_prefix=$(cat meta/dbprefix) + +main_dir=$(pwd) +echo "Access tmp directory $main_dir" +dbprefix=$(cat meta/dbprefix) +if [ $dbprefix = 1 ]; then + echo "Error 255 - I dont like your prefix, I dont want do this job" + exit 255 +fi +main_domain1=$(grep main_domain userdata/main | cut -d " " -f2) +new_user=$(grep "user:" userdata/${main_domain1} | cut -d " " -f2) +echo "Get User: $new_user" +check_sysuser=$(cut -f 1 -d : /etc/passwd | grep "^$new_user$") +if [ -n "$check_sysuser" ] || [ -e "$HESTIA/data/users/$new_user" ]; then + check_result "$E_EXISTS" "user $user exists" + echo "User allready exists" + exit 2 +fi + +# Create a new user +tmp_passwd=$(generate_password) +email=$(cat ./cp/$new_user | grep CONTACTEMAIL= | cut -f2 -d'=') +if [ -z "$email" ]; then + # Hestia does not like email to be set to an empty string + email="info@"$(hostname) +fi +$BIN/v-add-user "$new_user" "$tmp_passwd" "$email" "$hestia_package" +if [ "$?" -ne 0 ]; then + echo "Unable to create user" + exit 1 +fi +# Restore user password +update_user_value "$new_user" 'MD5' "$(cat shadow)" +$BIN/v-rebuild-user "$new_user" + +# Restore databases +mysql -e "SET GLOBAL max_allowed_packet=1073741824;" +tput setaf 2 +echo "Start with Databases" +tput sgr0 +sed -i 's/\\//g' mysql.sql +sed -i "s/\`/'/g" mysql.sql + +grep "GRANT USAGE ON" mysql.sql | awk -F "'" '{ print $2, $6 }' | uniq > user_password_db +# User and database +grep "GRANT" mysql.sql | grep -v "USAGE ON" > u_db +cat u_db | awk -F "'" '{ print $2, $4 }' | sort | uniq > uni_u_db + +## User / Password +grep "GRANT USAGE ON" mysql.sql | awk -F "'" '{ print $2, $6 }' | uniq > user_password_db +# User and database +grep "GRANT" mysql.sql | grep -v "USAGE ON" > u_db +cat u_db | awk -F "'" '{ print $2, $4 }' | sort | uniq > uni_u_db +sed -i "s/$user_prefix //g" user_password_db +# Get database list +db_list=$(grep -m 1 Database: mysql/*.create | awk '{ print $5 }') +mysql -e "SHOW DATABASES" > server_dbs +for db in $db_list; do + grep -w db server_dbs + if [ $? == "1" ]; then + echo " Create and restore ${db} " + mysql < mysql/${db}.create + sed -i "s/utf8mb4_0900_ai_ci/utf8mb4_unicode_ci/g" mysql/${db}.sql + mysql ${db} < mysql/${db}.sql + else + echo "Error: Cant restore database $db alredy exists in mysql server" + fi +done + +time=$(echo "$time_n_date" | cut -f 1 -d \ ) +date=$(echo "$time_n_date" | cut -f 2 -d \ ) + +cat uni_u_db | while read db userdb; do + grep -w $userdb user_password_db | while read user end_user_pass; do + # default cpanel user has all database privileges + # if you use default user in your config files to connect with database + # you will need remove && [ "$userdb" != "$sk_cp_user" ] to restore main user, but + # this will cause database duplication in db.conf and will interfer with hestiacp backups + if [ "$userdb" == "$user" ] && [ "$userdb" != "$new_user" ] && [ "$userdb" != "$sk_real_cp_user" ]; then + echo "DB='$db' DBUSER='$userdb' MD5='$end_user_pass' HOST='localhost' TYPE='mysql' CHARSET='UTF8' U_DISK='0' SUSPENDED='no' TIME='$time' DATE='$data'" >> /usr/local/hestia/data/users/$new_user/db.conf + fi + done +done + +# Leave hestia restore passwords and create users +tput setaf 2 +echo "Rebuild databases files for $new_user" +tput sgr0 +$BIN/v-rebuild-databases $new_user +## end mysql + +addon_domains=$(cat addons | cut -d "=" -f1) +sed -i 's/_/./g; s/=/ /g' addons +echo "Converting addons domains, subdomains and some other fun" +cp sds hst_sds +cp sds2 hst_sds2 +sed -i 's/_/./g' hst_sds +cat addons | while read ddon_domain addon_sub; do + echo "Converting default subdomain: $addon_sub in domain: $addon_domain" + sed -i -e "s/$addon_sub/$addon_domain/g" hst_sds + sed -i -e "s/$addon_sub/$addon_domain/g" hst_sds2 + mv userdata/$addon_sub userdata/${addon_domain} +done +sed -i 's/public_html/public@html/g; s/_/./g; s/public@html/public_html/g; s/=/ /g' hst_sds2 + +tput setaf 2 +echo "Start restoring domains" +tput sgr0 +function get_domain_path() { + while read cp_domain path; do + echo "Import $cp_domain" + if [ -e userdata/$cp_domain ]; then + echo $cp_domain + $BIN/v-add-domain "$new_user" "$cp_domain" + if [ $? -ne 0 ]; then + check_result "1" "Unable to create domain it allready exists" + fi + rm -f /home/$new_user/web/$cp_domain/public_html/index.html + rm -f /home/$new_user/web/$cp_domain/public_html/robots.txt + sync_count=0 + rsync -av homedir/$path/ /home/$new_user/web/$cp_domain/public_html 2>&1 \ + | while read file_dm; do + sync_count=$(($sync_count + 1)) + echo -en "-- $sync_count restored files\r" + done + chown $new_user:$new_user -R /home/$new_user/web/$cp_domain/public_html + chmod 751 /home/$new_user/web/$cp_domain/public_html + fi + done +} +get_domain_path < hst_sds2 + +echo $main_domain1 +$BIN/v-add-domain $new_user $main_domain1 + +if [ $? -ne 0 ]; then + check_result "1" "Unable to create domain it allready exists" +fi + +# need it for restore main domain +if [ ! -e exclude_path ]; then + touch exclude_path +fi +echo "Restore main domain: $main_domain1" +rm -f /home/$new_user/web/$main_domain1/public_html/index.html +rm -f /home/$new_user/web/$main_domain1/public_html/robots.txt + +rsync -av --exclude-from='exclude_path' homedir/public_html/ /home/$new_user/web/$main_domain1/public_html 2>&1 \ + | while read file_dm; do + sync_count=$(($sync_count + 1)) + echo -en "-- $sync_count restored files\r" + done + +chown $new_user:$new_user -R /home/$new_user/web/$main_domain1/public_html +chmod 751 /home/$new_user/web/$main_domain1/public_html + +################## +# mail +tput setaf 2 +echo "" +echo "Start Restoring Mails" +tput sgr0 +cd homedir/mail + +for folder in *; do + if [ -d "$folder" ]; then + if [[ "$folder" != "cur" && "$folder" != "new" && "$folder" != "tmp" ]]; then + echo "Domain: $folder" + cd $folder + for mail_account in *; do + echo "Import mail account: $mail_account@$folder" + # Doesn't really matter but we don't know the unhashed one + tmp_pass=$(generate_password) + $BIN/v-add-mail-account $new_user $folder $mail_account $tmp_pass + mv $mail_account /home/$new_user/mail/$folder/ + chown -R $new_user:mail /home/$new_user/mail/$folder/ + find /home/$new_user/mail/$folder -type f -name 'dovecot*' -delete + pass=$(grep "^$mail_account:" ../../etc/${folder}/shadow | awk -F ":" '{print $2}') + USER_DATA=$HESTIA/data/users/$new_user/ + update_object_value "mail/$folder" 'ACCOUNT' "$mail_account" '$MD5' "$pass" + done + cd .. + $BIN/v-rebuild-mail-domain $new_user $folder + fi + fi +done +echo "All mail accounts restored" + +if [ "$mx" = 'yes' ]; then + cd $main_dir/dnszones + for domain in $($BIN/v-list-mail-domains $new_user plain | awk '{ print $1 }'); do + echo "Replace MX record for $domain" + mx_id=$(grep MX $HESTIA/data/users/${new_user}/dns/${domain}.conf | tr "'" " " | cut -d " " -f 2) + $BIN/v-delete-dns-record $new_user $domain $mx_id + grep MX ${domain}.db | awk '{for(sk=NF;sk>=1;sk--) printf "%s ", $sk;print ""}' | while read value pri ns rest; do + if [ "$ns" = "MX" ]; then + if [ "$value" == "$sk_mx" ] || [ "$value" == "$sk_mx." ]; then + value=mail.$value + fi + $BIN/v-add-dns-record $new_user $domain @ MX $value $pri + if [[ "$?" -ge "1" ]]; then + $BIN/v-add-dns-record $new_user $domain @ MX mail.${domain} 0 + fi + echo "MX fixed in $sk_mx" + fi + done + done +fi + +rm -rf "$tmpdir" + +echo "##############################" +echo "cPanel Backup restored" +echo "Review your content and report any fail" +exit diff --git a/bin/v-insert-dns-domain b/bin/v-insert-dns-domain new file mode 100755 index 0000000..3829057 --- /dev/null +++ b/bin/v-insert-dns-domain @@ -0,0 +1,92 @@ +#!/bin/bash +# info: insert dns domain +# options: USER DATA [SRC] [FLUSH] # +# This function inserts raw record to the dns.conf + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +data=$2 +src=$3 +flush=$4 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh + +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DATA [SRC] [FLUSH] [RESTART]' +is_format_valid 'user' 'data' +is_system_enabled "$DNS_SYSTEM" 'DNS_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +parse_object_kv_list "$data" + +domain="$DOMAIN" +if [ -z "$domain" ]; then + check_result $E_ARGS "Domain name missing from DATA" +fi +is_format_valid 'domain' + +if [ "$flush" = 'no' ]; then + is_domain_new 'dns' $domain +fi + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Flush records +if [ "$flush" = 'records' ]; then + rm -f $USER_DATA/dns/$DOMAIN.conf + touch $USER_DATA/dns/$DOMAIN.conf + chmod 660 $USER_DATA/dns/$DOMAIN.conf +fi + +# Flush domain +if [ "$flush" != 'no' ]; then + sed -i "/DOMAIN='$DOMAIN'/d" $USER_DATA/dns.conf 2> /dev/null +fi + +# Generating timestamp +time_n_date=$(date +'%T %F') +time=$(echo "$time_n_date" | cut -f 1 -d \ ) +date=$(echo "$time_n_date" | cut -f 2 -d \ ) + +# Prepare values for the insert +dns_rec="DOMAIN='$DOMAIN' IP='$IP' TPL='$TPL' TTL='$TTL' EXP='$EXP'" +dns_rec="$dns_rec SOA='$SOA' SERIAL='$SERIAL' SRC='$src' RECORDS='$RECORDS'" +dns_rec="$dns_rec DNSSEC='$DNSSEC' KEY='$KEY' SLAVE='$SLAVE' MASTER='$MASTER'" +dns_rec="$dns_rec SUSPENDED='$SUSPENDED' TIME='$time' DATE='$date'" +echo "$dns_rec" >> $USER_DATA/dns.conf + +if [ "$SLAVE" = "yes" ]; then + touch $USER_DATA/dns/$domain.conf +fi +# Set permission +chmod 660 $USER_DATA/dns.conf + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-insert-dns-record b/bin/v-insert-dns-record new file mode 100755 index 0000000..c6d4404 --- /dev/null +++ b/bin/v-insert-dns-record @@ -0,0 +1,53 @@ +#!/bin/bash +# info: insert dns record +# options: USER DOMAIN DATA +# +# This function inserts raw dns record to the domain conf + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +data=$3 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '3' "$#" 'USER DOMAIN DATA [RESTART]' +is_format_valid 'user' 'domain' 'data' +is_system_enabled "$DNS_SYSTEM" 'DNS_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'dns' 'DOMAIN' "$domain" +parse_object_kv_list "$data" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Insert values +echo "$data" >> $USER_DATA/dns/$domain.conf + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-insert-dns-records b/bin/v-insert-dns-records new file mode 100755 index 0000000..ea26e0e --- /dev/null +++ b/bin/v-insert-dns-records @@ -0,0 +1,55 @@ +#!/bin/bash +# info: inserts dns records +# options: USER DOMAIN DATA_FILE +# +# This function copy dns record to the domain conf + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +data_file=$3 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '3' "$#" 'USER DOMAIN DATAFILE [RESTART]' +is_format_valid 'user' 'domain' 'data_file' +is_system_enabled "$DNS_SYSTEM" 'DNS_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'dns' 'DOMAIN' "$domain" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Insert values +if [ -e "$data_file" ]; then + mv -f $data_file $USER_DATA/dns/$domain.conf + chmod 660 $USER_DATA/dns/$domain.conf +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-list-access-key b/bin/v-list-access-key new file mode 100755 index 0000000..2ad6226 --- /dev/null +++ b/bin/v-list-access-key @@ -0,0 +1,88 @@ +#!/bin/bash +# info: list all API access keys +# options: ACCESS_KEY_ID [FORMAT] +# +# example: v-list-access-key 1234567890ABCDefghij json + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +access_key_id="$1" +format="${2:-shell}" + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# JSON list function +json_list() { + local PERMISSIONS_ARR='[]' + if [[ -n "$PERMISSIONS" ]]; then + PERMISSIONS_ARR="[\"$(echo "$PERMISSIONS" | sed -E 's|,|", "|g')\"]" + fi + + echo '{ + "ACCESS_KEY_ID": "'$access_key_id'", + "SECRET_ACCESS_KEY": "'$SECRET_ACCESS_KEY'", + "USER": "'$USER'", + "PERMISSIONS": '$PERMISSIONS_ARR', + "COMMENT": "'$COMMENT'", + "TIME": "'$TIME'", + "DATE": "'$DATE'" +}' +} + +# SHELL list function +shell_list() { + echo "ACCESS_KEY_ID: $access_key_id" + echo "SECRET_ACCESS_KEY: $SECRET_ACCESS_KEY" + echo "USER: $USER" + echo "PERMISSIONS: $PERMISSIONS" + echo "COMMENT: $COMMENT" + echo "TIME: $TIME" + echo "DATE: $DATE" +} + +plain_list() { + echo $access_key_id:$SECRET_ACCESS_KEY +} + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'ACCESS_KEY_ID [FORMAT]' +is_format_valid 'access_key_id' +is_object_valid 'key' 'KEY' "$access_key_id" + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Avoid "USER" receive "root" in old keys +USER="admin" +PERMISSIONS="" +COMMENT="" +DATE="" +TIME="" + +source_conf "${HESTIA}/data/access-keys/${access_key_id}" + +# Listing data +case $format in + json) json_list ;; + shell) shell_list ;; + plain) plain_list ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-access-keys b/bin/v-list-access-keys new file mode 100755 index 0000000..c91cd7c --- /dev/null +++ b/bin/v-list-access-keys @@ -0,0 +1,93 @@ +#!/bin/bash +# info: list all API access keys +# options: [FORMAT] +# +# example: v-list-access-keys json + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user="$1" +format="${2:-shell}" + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# JSON list function +json_list() { + echo -n '{' + local quote='' + local PERMISSIONS_ARR ACCESS_KEY_ID + for key_file in $HESTIA/data/access-keys/*; do + key_file="$(basename -- "$key_file")" + if [[ "$key_file" =~ ^[[:alnum:]]{20}$ ]]; then + USER="admin" SECRET_ACCESS_KEY="" PERMISSIONS="" DATE="" TIME="" COMMENT="" + source_conf "$HESTIA/data/access-keys/$key_file" + if [ "$user" = "$USER" ] || [ -z "$user" ]; then + PERMISSIONS_ARR='[]' + if [[ -n "$PERMISSIONS" ]]; then + PERMISSIONS_ARR="[\"$(echo "$PERMISSIONS" | sed -E 's|,|", "|g')\"]" + fi + + ACCESS_KEY_ID="$(basename "$key_file")" + + echo -en "${quote:-\n}" + echo -n ' "'$ACCESS_KEY_ID'": {' + echo -n '"ACCESS_KEY_ID": "'${ACCESS_KEY_ID}'", ' + echo -n '"USER": "'${USER}'", ' + echo -n '"PERMISSIONS": '${PERMISSIONS_ARR}', ' + echo -n '"COMMENT": "'${COMMENT}'", ' + echo -n '"TIME": "'${TIME}'", ' + echo -n '"DATE": "'${DATE}'"' + echo -n '}' + quote=",\n" + fi + fi + done + + [[ -n "$quote" ]] && echo + echo -e '}' +} + +# SHELL list function +shell_list() { + list="ID\tUSER\tPERMISSIONS\tCOMMENT\tTIME\tDATE\n" + list+="--\t------\t----\t-----------\t-------\t----\t----\n" + + for key_file in $HESTIA/data/access-keys/*; do + key_file="$(basename -- "$key_file")" + if [[ "$key_file" =~ ^[[:alnum:]]{20}$ ]]; then + USER="admin" SECRET_ACCESS_KEY="" PERMISSIONS="" DATE="" TIME="" COMMENT="" + source_conf "$HESTIA/data/access-keys/$key_file" + if [ "$user" = "$USER" ] || [ -z "$user" ]; then + ACCESS_KEY_ID="$(basename "$key_file")" + list+="${ACCESS_KEY_ID}\t${USER}\t${PERMISSIONS:--}\t${COMMENT:--}\t${TIME}\t${DATE}\n" + fi + fi + done + + echo -e "$list" | column -t -s " " +} + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Listing data +case $format in + json) json_list ;; + shell) shell_list ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-api b/bin/v-list-api new file mode 100755 index 0000000..76cfe5a --- /dev/null +++ b/bin/v-list-api @@ -0,0 +1,70 @@ +#!/bin/bash +# info: list api +# options: API [FORMAT] +# +# example: v-list-api mail-accounts json + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +api="$1" +format="${2:-shell}" + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# JSON list function +json_list() { + local COMMANDS_ARR='[]' + if [[ -n "$COMMANDS" ]]; then + COMMANDS_ARR="[\"$(echo "$COMMANDS" | sed -E 's|,|", "|g')\"]" + fi + + echo '{ + "API": "'$api'", + "ROLE": "'$ROLE'", + "COMMANDS": '$COMMANDS_ARR' +}' +} + +# SHELL list function +shell_list() { + echo "API: $api" + echo "ROLE: $ROLE" + echo "COMMANDS: $COMMANDS" +} + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'API [FORMAT]' + +if [[ -z "$api" || ! -f "$HESTIA/data/api/${api}" ]]; then + check_result "$E_INVALID" "API $api doesn't exist" +fi + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +source_conf "${HESTIA}/data/api/${api}" + +# Listing data +case $format in + json) json_list ;; + shell) shell_list ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-apis b/bin/v-list-apis new file mode 100755 index 0000000..339bfb2 --- /dev/null +++ b/bin/v-list-apis @@ -0,0 +1,65 @@ +#!/bin/bash +# info: list available APIs +# options: [FORMAT] +# +# example: v-list-apis json + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +format="${1:-shell}" + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# JSON list function +json_list() { + echo '{' + local quote COMMANDS_ARR + for api in $HESTIA/data/api/*; do + api="$(basename -- "$api")" + source_conf $HESTIA/data/api/$api + + COMMANDS_ARR='[]' + if [[ -n "$COMMANDS" ]]; then + COMMANDS_ARR="[\"$(echo "$COMMANDS" | sed -E 's|,|", "|g')\"]" + fi + + echo -en "$quote" + echo -n ' "'$api'": {"COMMANDS": '${COMMANDS_ARR}', "ROLE": "'${ROLE}'"}' + quote=",\n" + done + echo -e '\n}' +} + +# SHELL list function +shell_list() { + list="API\tROLE\tCOMMANDS\n" + list+="---\t----\t--------\n" + + for api in $HESTIA/data/api/*; do + api="$(basename -- "$api")" + source_conf $HESTIA/data/api/$api + list+="${api}\t${ROLE}\t${COMMANDS}\n" + done + echo -e "$list" | column -t -s " " +} + +# Listing data +case $format in + json) json_list ;; + shell) shell_list ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-backup-host b/bin/v-list-backup-host new file mode 100755 index 0000000..7529209 --- /dev/null +++ b/bin/v-list-backup-host @@ -0,0 +1,142 @@ +#!/bin/bash +# info: list backup host +# options: TYPE [FORMAT] +# +# example: v-list-backup-host local +# +# This function for obtaining the list of backup host parameters. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +type=$1 +format=${2-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# JSON list function +json_list() { + case $type in + 'sftp' | 'ftp' | 'rclone') + echo '{' + echo ' "'$type'": { + "HOST": "'$HOST'", + "USERNAME": "'$USERNAME'", + "PORT": "'$PORT'", + "TYPE": "'$type'", + "BPATH": "'$BPATH'", + "TIME": "'$TIME'", + "DATE": "'$DATE'" + }' + echo '}' + ;; + 'b2') + echo '{' + echo ' "'$type'": { + "BUCKET": "'$BUCKET'", + "TYPE": "'$type'", + "B2_KEY_ID": "'$B2_KEYID'", + "TIME": "'$TIME'", + "DATE": "'$DATE'" + }' + echo '}' + ;; + esac +} + +# SHELL list function +shell_list() { + case $type in + 'sftp' | 'ftp' | 'rclone') + echo "HOST: $HOST" + echo "USERNAME: $USERNAME" + echo "PORT: $PORT" + echo "TYPE: $type" + echo "PATH: $BPATH" + echo "TIME: $TIME" + echo "DATE: $DATE" + ;; + 'b2') + echo "BUCKET $BUCKET" + echo "TYPE $type" + echo "B2_KEY_ID $B2_KEYID" + echo "TIME: $TIME" + echo "DATE: $DATE" + ;; + esac +} + +# PLAIN list function +plain_list() { + case $type in + 'sftp' | 'ftp' | 'rclone') + echo -e "$HOST\t$USERNAME\t$PORT\t$type\t$BPATH\t$TIME\t$DATE" + ;; + 'b2') + echo -e "$BUCKET\t$type\t$B2_KEYID\t$TIME\t$DATE" + ;; + esac +} + +# CSV list function +csv_list() { + case $type in + 'sftp' | 'ftp' | 'rclone') + echo "HOST,USERNAME,PORT,TYPE,PATH,TIME,DATE" + echo "$HOST,$USERNAME,$PORT,$type,$BPATH,$TIME,$DATE" + ;; + 'b2') + echo "BUCKET,TYPE,B2_KEYID,TIME,DATE" + echo "$BUCKET,$type,$B2_KEYID,$TIME,$DATE" + ;; + esac +} + +# Type format validator +is_type_format_valid() { + exclude="[!|#|$|^|&|(|)|+|=|{|}|:|@|<|>|?|/|\|\"|'|;|%|\`| ]|\." + if [[ "$1" =~ $exclude ]]; then + check_result "$E_INVALID" "invalid type extention format :: $1" + fi +} + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'TYPE [FORMAT]' +is_common_format_valid $type "type" + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Checking backup config +if [ ! -e "$HESTIA/conf/$type.backup.conf" ]; then + exit +fi + +# Parsing backup config +source_conf "$HESTIA/conf/$type.backup.conf" + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list | column -t ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-cron-job b/bin/v-list-cron-job new file mode 100755 index 0000000..2df5b49 --- /dev/null +++ b/bin/v-list-cron-job @@ -0,0 +1,108 @@ +#!/bin/bash +# info: list cron job +# options: USER JOB [FORMAT] +# +# example: v-list-cron-job admin 7 +# +# This function of obtaining cron job parameters. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +job=$2 +format=${3-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# JSON list function +json_list() { + echo "{" + echo -n ' "'$job'": { + "MIN": "'$MIN'", + "HOUR": "'$HOUR'", + "DAY": "'$DAY'", + "MONTH": "'$MONTH'", + "WDAY": "'$WDAY'", + "CMD": "'$CMD'", + "JOB": "'$JOB'", + "SUSPENDED": "'$SUSPENDED'", + "TIME": "'$TIME'", + "DATE": "'$DATE'" + }' + echo + echo '}' +} + +# SHELL list function +shell_list() { + echo "MINUTE: $MIN" + echo "HOUR: $HOUR" + echo "DAY: $DAY" + echo "DAY OF WEEK: $WDAY" + echo "COMMAND: $CMD" + echo "SUSPENDED: $SUSPENDED" + echo "TIME: $TIME" + echo "DATE: $DATE" +} + +# PLAIN list function +plain_list() { + echo -e "$MIN\t$HOUR\t$DAY\t$WDAY\t$CMD\t$SUSPENDED\t$TIME\t$DATE" +} + +# CSV list function +csv_list() { + echo "MIN,HOUR,DAY,WDAY,CMD,SUSPENDED,TIME,DATE" + echo "$MIN,$HOUR,$DAY,$WDAY,\"$CMD\",$SUSPENDED,$TIME,$DATE'" +} + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER JOB [FORMAT]' +is_format_valid 'user' +is_number_format_valid "$job" "job_id" +is_object_valid 'user' 'USER' "$user" + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Defining config +conf=$USER_DATA/cron.conf + +# Checking job id +cron_line=$(grep "JOB='$job'" $conf) +if [ -z "$cron_line" ]; then + check_result "$E_NOTEXIST" "cron job $job doesn't exist" +fi + +# Parsing cron job +parse_object_kv_list "$cron_line" + +# Replacing quoted and backslahed text +CMD=$(echo "$CMD" | sed -e 's/"/\\"/g' -e "s/%quote%/'/g") + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-cron-jobs b/bin/v-list-cron-jobs new file mode 100755 index 0000000..4f8b16c --- /dev/null +++ b/bin/v-list-cron-jobs @@ -0,0 +1,115 @@ +#!/bin/bash +# info: list user cron jobs +# options: USER [FORMAT] +# +# example: v-list-cron-jobs admin +# +# This function for obtaining the list of all users cron jobs. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +format=${2-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# JSON list function +json_list() { + IFS=$'\n' + i=1 + objects=$(grep JOB $USER_DATA/cron.conf | wc -l) + echo "{" + while read str; do + parse_object_kv_list "$str" + CMD=$(echo "$CMD" | sed -e 's/"/\\"/g' -e "s/%quote%/'/g") + echo -n ' "'$JOB'": { + "MIN": "'$MIN'", + "HOUR": "'$HOUR'", + "DAY": "'$DAY'", + "MONTH": "'$MONTH'", + "WDAY": "'$WDAY'", + "CMD": "'$CMD'", + "JOB": "'$JOB'", + "SUSPENDED": "'$SUSPENDED'", + "TIME": "'$TIME'", + "DATE": "'$DATE'" + }' + if [ "$i" -lt "$objects" ]; then + echo ',' + else + echo + fi + ((i++)) + done < <(cat $USER_DATA/cron.conf) + echo '}' +} + +# SHELL list function +shell_list() { + IFS=$'\n' + echo "JOB^MIN^HOUR^MONTH^WDAY^COMMAND" + echo "---^---^----^-----^----^-------" + while read str; do + parse_object_kv_list "$str" + CMD=$(echo "$CMD" | sed -e 's/"/\\"/g' -e "s/%quote%/'/g") + echo "$JOB^$MIN^$HOUR^$MONTH^$WDAY^$CMD" + done < <(cat $USER_DATA/cron.conf) +} + +# PLAIN list function +plain_list() { + IFS=$'\n' + while read str; do + parse_object_kv_list "$str" + CMD=$(echo "$CMD" | sed -e 's/"/\\"/g' -e "s/%quote%/'/g") + echo -ne "$JOB\t$MIN\t$HOUR\t$MONTH\t$WDAY\t$CMD\t" + echo -e "$SUSPENDED\t$TIME\t$DATE" + done < <(cat $USER_DATA/cron.conf) +} + +# CSV list function +csv_list() { + IFS=$'\n' + echo "MIN,HOUR,DAY,WDAY,CMD,SUSPENDED,TIME,DATE" + while read str; do + parse_object_kv_list "$str" + CMD=$(echo "$CMD" | sed -e 's/"/\\"/g' -e "s/%quote%/'/g") + echo -n "$JOB,$MIN,$HOUR,$MONTH,$WDAY,\"$CMD\"," + echo "$SUSPENDED,$TIME,$DATE" + done < <(cat $USER_DATA/cron.conf) +} + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'USER [FORMAT]' +is_format_valid 'user' +is_object_valid 'user' 'USER' "$user" + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list | column -t -s '^' ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-database b/bin/v-list-database new file mode 100755 index 0000000..4d7d055 --- /dev/null +++ b/bin/v-list-database @@ -0,0 +1,96 @@ +#!/bin/bash +# info: list database +# options: USER DATABASE [FORMAT] +# +# example: v-list-database wp_db +# +# This function for obtaining of all database's parameters. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +database=$2 +format=${3-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# JSON list function +json_list() { + echo '{' + echo ' "'$database'": { + "DATABASE": "'$DB'", + "DBUSER": "'$DBUSER'", + "HOST": "'$HOST'", + "TYPE": "'$TYPE'", + "CHARSET": "'$CHARSET'", + "U_DISK": "'$U_DISK'", + "SUSPENDED": "'$SUSPENDED'", + "TIME": "'$TIME'", + "DATE": "'$DATE'" + }' + echo '}' +} + +# SHELL list function +shell_list() { + echo "DATABASE: $DB" + echo "DB USER: $DBUSER" + echo "HOST: $HOST" + echo "TYPE: $TYPE" + echo "CHARSET: $CHARSET" + echo "DISK: $U_DISK" + echo "SUSPENDED: $SUSPENDED" + echo "TIME: $TIME" + echo "DATE: $DATE" +} + +# PLAIN list function +plain_list() { + echo -ne "$DB\t$DBUSER\t$HOST\t$TYPE\t$CHARSET\t$U_DISK\t" + echo -e "$SUSPENDED\t$TIME\t$DATE" +} + +# CSV list function +csv_list() { + echo "DATABASE,DBUSER,HOST,TYPE,CHARSET,U_DISK,SUSPENDED,TIME,DATE" + echo "$DB,$DBUSER,$HOST,$TYPE,$CHARSET,$U_DISK,$SUSPENDED,$TIME,$DATE" +} + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DATABASE [FORMAT]' +is_format_valid 'user' 'database' +is_object_valid 'user' 'USER' "$user" +is_object_valid 'db' 'DB' "$database" + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Parsing database +parse_object_kv_list $(grep "DB='$database'" $USER_DATA/db.conf) + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-database-host b/bin/v-list-database-host new file mode 100755 index 0000000..1cb685b --- /dev/null +++ b/bin/v-list-database-host @@ -0,0 +1,115 @@ +#!/bin/bash +# info: list database host +# options: TYPE HOST [FORMAT] +# +# example: v-list-database-host mysql localhost +# +# This function for obtaining database host parameters. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +type=$1 +host=$2 +format=${3-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/db.sh +source $HESTIA/func/db.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# JSON list function +json_list() { + echo '{' + echo ' "'$HOST'": { + "HOST": "'$HOST'", + "PORT": "'$PORT'", + "TYPE": "'$type'", + "CHARSETS": "'$CHARSETS'", + "MAX_DB": "'$MAX_DB'", + "U_SYS_USERS": "'$U_SYS_USERS'", + "U_DB_BASES": "'$U_DB_BASES'", + "TPL": "'$TPL'", + "SUSPENDED": "'$SUSPENDED'", + "TIME": "'$TIME'", + "DATE": "'$DATE'" + }' + echo '}' +} + +# SHELL list function +shell_list() { + echo "HOST: $HOST" + echo "PORT: $PORT" + echo "TYPE: $type" + echo "CHARSETS: $CHARSETS" + echo "MAX_DB: $MAX_DB" + echo "U_DB_BASES: $U_DB_BASES" + echo "U_SYS_USERS: $U_SYS_USERS" + echo "TPL: $TPL" + echo "SUSPENDED: $SUSPENDED" + echo "TIME: $TIME" + echo "DATE: $DATE" +} + +# PLAIN list function +plain_list() { + echo -ne "$HOST\t$PORT\t$type\t$CHARSETS\t$MAX_DB\t$U_SYS_USERS\t" + echo -e "$U_DB_BASES\t$TPL\t$SUSPENDED\t$TIME\t$DATE" +} + +# CSV list function +csv_list() { + echo -n "HOST,PORT,TYPE,CHARSETS,MAX_DB,U_SYS_USERS," + echo "U_DB_BASES,TPL,SUSPENDED,TIME,DATE'" + echo -n "$HOST,$PORT,$type,\"$CHARSETS\",$MAX_DB,\"$U_SYS_USERS\"," + echo "$U_DB_BASES,$TPL,$SUSPENDED,$TIME,$DATE" +} + +# Type format validator +is_type_format_valid() { + exclude="[!|#|$|^|&|(|)|+|=|{|}|:|@|<|>|?|/|\|\"|'|;|%|\`| ]|\." + if [[ "$1" =~ $exclude ]]; then + check_result "$E_INVALID" "invalid type extention format :: $1" + fi +} + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'TYPE HOST [FORMAT]' +is_format_valid 'host' +is_type_format_valid "$type" +is_object_valid "../../conf/$type" 'HOST' "$host" + +# Set default port values if they don't exist in host configuration file +database_set_default_ports + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Parsing hosts +parse_object_kv_list $(grep "HOST='$host'" $HESTIA/conf/$type.conf) + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list | column -t ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-database-hosts b/bin/v-list-database-hosts new file mode 100755 index 0000000..c8210cf --- /dev/null +++ b/bin/v-list-database-hosts @@ -0,0 +1,145 @@ +#!/bin/bash +# info: list database hosts +# options: [FORMAT] +# +# example: v-list-database-hosts json +# +# This function for obtaining the list of all configured database hosts. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +format=${1-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/db.sh +source $HESTIA/func/db.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# JSON list function +json_list() { + IFS=$'\n' + i=1 + objects=0 + for type in $(echo $DB_SYSTEM | sed -e 's/,/\n/'); do + if [ -e "$HESTIA/conf/$type.conf" ]; then + # Set default port values if they don't exist in database configuration file. + database_set_default_ports + db_hosts=$(grep HOST $HESTIA/conf/$type.conf | wc -l) + objects=$((objects + db_hosts)) + fi + done + + echo "[" + for type in $(echo $DB_SYSTEM | sed -e 's/,/\n/'); do + if [ -e "$HESTIA/conf/$type.conf" ]; then + for str in $(cat $HESTIA/conf/$type.conf); do + parse_object_kv_list "$str" + echo -n ' { + "HOST": "'$HOST'", + "PORT": "'$PORT'", + "TYPE": "'$type'", + "CHARSETS": "'$CHARSETS'", + "MAX_DB": "'$MAX_DB'", + "U_SYS_USERS": "'$U_SYS_USERS'", + "U_DB_BASES": "'$U_DB_BASES'", + "TPL": "'$TPL'", + "SUSPENDED": "'$SUSPENDED'", + "TIME": "'$TIME'", + "DATE": "'$DATE'" + }' + if [ "$i" -lt "$objects" ]; then + echo ',' + else + echo + fi + ((i++)) + done + fi + done + echo ']' +} + +# SHELL list function +shell_list() { + IFS=$'\n' + echo "HOST PORT TYPE MAX_DB DB_USED SPND TIME DATE" + echo "---- ---- ---- ------ ------- ---- ---- ----" + for type in $(echo $DB_SYSTEM | sed -e 's/,/\n/'); do + if [ -e "$HESTIA/conf/$type.conf" ]; then + # Set default port values if they don't exist in database configuration file. + database_set_default_ports + for str in $(cat $HESTIA/conf/$type.conf); do + parse_object_kv_list "$str" + echo "$HOST $PORT $type $MAX_DB $U_DB_BASES $SUSPENDED $TIME $DATE" + done + fi + done +} + +# PLAIN list function +plain_list() { + IFS=$'\n' + for type in $(echo $DB_SYSTEM | sed -e 's/,/\n/'); do + if [ -e "$HESTIA/conf/$type.conf" ]; then + # Set default port values if they don't exist in database configuration file. + database_set_default_ports + for str in $(cat $HESTIA/conf/$type.conf); do + parse_object_kv_list "$str" + echo -ne "$HOST\t$PORT\t$type\t$CHARSETS\t$MAX_DB\t$U_SYS_USERS\t" + echo -e "$U_DB_BASES\t$TPL\t$SUSPENDED\t$TIME\t$DATE" + done + fi + done +} + +# CSV list function +csv_list() { + IFS=$'\n' + echo -n "HOST,PORT,TYPE,CHARSETS,MAX_DB,U_SYS_USERS," + echo "U_DB_BASES,TPL,SUSPENDED,TIME,DATE" + for type in $(echo $DB_SYSTEM | sed -e 's/,/\n/'); do + if [ -e "$HESTIA/conf/$type.conf" ]; then + # Set default port values if they don't exist in database configuration file. + database_set_default_ports + for str in $(cat $HESTIA/conf/$type.conf); do + parse_object_kv_list "$str" + echo -n "$HOST,$PORT,$type,\"$CHARSETS\",$MAX_DB,\"$U_SYS_USERS\"," + echo "$U_DB_BASES,$TPL,$SUSPENDED,$TIME,$DATE" + done + fi + done +} + +# Type format validator +is_type_format_valid() { + exclude="[!|#|$|^|&|(|)|+|=|{|}|:|@|<|>|?|/|\|\"|'|;|%|\`| ]|\." + if [[ "$1" =~ $exclude ]]; then + check_result $E_INVALID "invalid type extention format :: $1" + fi +} + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list | column -t ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-database-types b/bin/v-list-database-types new file mode 100755 index 0000000..d97c8bf --- /dev/null +++ b/bin/v-list-database-types @@ -0,0 +1,78 @@ +#!/bin/bash +# info: list supported database types +# options: [FORMAT] +# +# example: v-list-database-types json +# +# This function for obtaining the list of database types. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +format=${1-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# JSON list function +json_list() { + objects=$(echo "${DB_SYSTEM//,/ }" | wc -w) + i=1 + echo '[' + for type in ${DB_SYSTEM//,/ }; do + echo -n ' "'$type'"' + if [ "$i" -lt "$objects" ]; then + echo ',' + else + echo + fi + ((i++)) + done + echo "]" +} + +# SHELL list function +shell_list() { + echo -e "TYPE\n----" + echo "$DB_SYSTEM" | sed -e "s/,/\n/" +} + +# PLAIN list function +plain_list() { + for type in ${DB_SYSTEM//,/ }; do + echo "$type" + done +} + +# CSV list function +csv_list() { + echo "TYPE" + for type in ${DB_SYSTEM//,/ }; do + echo "$type" + done +} + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-databases b/bin/v-list-databases new file mode 100755 index 0000000..a779986 --- /dev/null +++ b/bin/v-list-databases @@ -0,0 +1,109 @@ +#!/bin/bash +# info: listing databases +# options: USER [FORMAT] +# +# example: v-list-databases user json +# +# This function for obtaining the list of all user's databases. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +format=${2-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# JSON list function +json_list() { + IFS=$'\n' + i=1 + objects=$(grep "DB=" $USER_DATA/db.conf | wc -l) + echo "{" + while read str; do + parse_object_kv_list "$str" + echo -n ' "'$DB'": { + "DATABASE": "'$DB'", + "DBUSER": "'$DBUSER'", + "HOST": "'$HOST'", + "TYPE": "'$TYPE'", + "CHARSET": "'$CHARSET'", + "U_DISK": "'$U_DISK'", + "SUSPENDED": "'$SUSPENDED'", + "TIME": "'$TIME'", + "DATE": "'$DATE'" + }' + if [ "$i" -lt "$objects" ]; then + echo ',' + else + echo + fi + ((i++)) + done < <(cat $USER_DATA/db.conf) + echo '}' +} + +# SHELL list function +shell_list() { + IFS=$'\n' + echo "DATABASE USER HOST TYPE DISK SPND DATE" + echo "-------- ---- ---- ---- ---- ---- ----" + while read str; do + parse_object_kv_list "$str" + echo "$DB $DBUSER $HOST $TYPE $U_DISK $SUSPENDED $DATE" + done < <(cat $USER_DATA/db.conf) +} + +# PLAIN list function +plain_list() { + IFS=$'\n' + while read str; do + parse_object_kv_list "$str" + echo -ne "$DB\t$DBUSER\t$HOST\t$TYPE\t$CHARSET\t$U_DISK\t" + echo -e "$SUSPENDED\t$TIME\t$DATE" + done < <(cat $USER_DATA/db.conf) +} + +# CSV list function +csv_list() { + IFS=$'\n' + echo "DATABASE,DBUSER,HOST,TYPE,CHARSET,U_DISK,SUSPENDED,TIME,DATE" + while read str; do + parse_object_kv_list "$str" + echo "$DB,$DBUSER,$HOST,$TYPE,$CHARSET,$U_DISK,$SUSPENDED,$TIME,$DATE" + done < <(cat $USER_DATA/db.conf) +} + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'USER [FORMAT]' +is_format_valid 'user' +is_object_valid 'user' 'USER' "$user" + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list | column -t ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-default-php b/bin/v-list-default-php new file mode 100755 index 0000000..ef4b945 --- /dev/null +++ b/bin/v-list-default-php @@ -0,0 +1,87 @@ +#!/bin/bash +# info: list default PHP version used by default.tpl +# options: [FORMAT] +# +# example: v-list-default-php +# +# List the default version used by de the default template + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +format=${1-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# JSON list function +json_list() { + i=1 + objects=$(echo "${versions[@]}" | wc -w) + echo '[' + for version in "${versions[@]}"; do + if [ "$i" -lt "$objects" ]; then + echo -e "\t\"$version\"," + else + echo -e "\t\"$version\"" + fi + ((++i)) + done + echo "]" +} + +# SHELL list function +shell_list() { + echo "VERSION" + echo "--------" + for version in "${versions[@]}"; do + echo "$version" + done +} + +# PLAIN list function +plain_list() { + for version in "${versions[@]}"; do + echo "$version" + done +} + +# CSV list function +csv_list() { + echo "VERSION" + for version in "${versions[@]}"; do + echo "$version" + done +} + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +declare -a versions +# List through /etc/php +for version in /etc/php/*/fpm/pool.d/www.conf; do + ver=$(echo "$version" | awk -F"/" '{ print $4 }') + versions+=("$ver") +done + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-dns-domain b/bin/v-list-dns-domain new file mode 100755 index 0000000..a8e1b11 --- /dev/null +++ b/bin/v-list-dns-domain @@ -0,0 +1,103 @@ +#!/bin/bash +# info: list dns domain +# options: USER DOMAIN [FORMAT] +# +# example: v-list-dns-domain alice wonderland.com +# +# This function of obtaining the list of dns domain parameters. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +format=${3-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# JSON list function +json_list() { + echo '{' + echo ' "'$DOMAIN'": { + "IP": "'$IP'", + "TPL": "'$TPL'", + "TTL": "'$TTL'", + "EXP": "'$EXP'", + "SOA": "'$SOA'", + "SERIAL": "'$SERIAL'", + "DNSSEC": "'$DNSSEC'", + "SRC": "'$SRC'", + "RECORDS": "'$RECORDS'", + "SUSPENDED": "'$SUSPENDED'", + "TIME": "'$TIME'", + "DATE": "'$DATE'" + }' + echo '}' +} + +# SHELL list function +shell_list() { + echo "DOMAIN: $DOMAIN" + echo "IP: $IP" + echo "TEMPLATE: $TPL" + echo "TTL: $TTL" + echo "EXP: $EXP" + echo "SOA: $SOA" + echo "SERIAL: $SERIAL" + echo "DNSSEC: $DNSSEC" + echo "RECORDS: $RECORDS" + echo "SUSPENDED: $SUSPENDED" + echo "TIME: $TIME" + echo "DATE: $DATE" +} + +# PLAIN list function +plain_list() { + echo -ne "$DOMAIN\t$IP\t$TPL\t$TTL\t$EXP\t$SOA\t$SERIAL\t$DNSSEC\t$RECORDS\t" + echo -e "$SUSPENDED\t$TIME\t$DATE" +} + +# CSV list function +csv_list() { + echo "DOMAIN,IP,TPL,TTL,EXP,SOA,SERIAL,DNSSEC,RECORDS,SUSPENDED,TIME,DATE" + echo -n "$DOMAIN,$IP,$TPL,$TTL,$EXP,$SOA,$SERIAL,$DNSSEC,$RECORDS,$SUSPENDED," + echo "$TIME,$DATE" +} + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DOMAIN [FORMAT]' +is_format_valid 'user' 'domain' +is_object_valid 'user' 'USER' "$user" +is_object_valid 'dns' 'DOMAIN' "$domain" + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Parsing domain +parse_object_kv_list $(grep "DOMAIN='$domain'" $USER_DATA/dns.conf) + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-dns-domains b/bin/v-list-dns-domains new file mode 100755 index 0000000..671da2a --- /dev/null +++ b/bin/v-list-dns-domains @@ -0,0 +1,113 @@ +#!/bin/bash +# info: list dns domains +# options: USER [FORMAT] +# +# example: v-list-dns-domains admin +# +# This function for obtaining all DNS domains of a user. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +format=${2-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# JSON list function +json_list() { + IFS=$'\n' + i=1 + objects=$(grep DOMAIN $USER_DATA/dns.conf | wc -l) + echo "{" + while read str; do + parse_object_kv_list "$str" + echo -n ' "'$DOMAIN'": { + "IP": "'$IP'", + "TPL": "'$TPL'", + "TTL": "'$TTL'", + "EXP": "'$EXP'", + "SOA": "'$SOA'", + "SERIAL": "'$SERIAL'", + "DNSSEC": "'$DNSSEC'", + "SRC": "'$SRC'", + "RECORDS": "'$RECORDS'", + "SUSPENDED": "'$SUSPENDED'", + "TIME": "'$TIME'", + "DATE": "'$DATE'" + }' + if [ "$i" -lt "$objects" ]; then + echo ',' + else + echo + fi + ((i++)) + done < <(cat $USER_DATA/dns.conf) + echo '}' +} + +# SHELL list function +shell_list() { + IFS=$'\n' + echo "DOMAIN IP TPL TTL DNSSEC REC SPND DATE" + echo "------ -- --- --- ------ --- ---- ----" + while read str; do + parse_object_kv_list "$str" + echo "$DOMAIN $IP $TPL $TTL $DNSSEC $RECORDS $SUSPENDED $DATE" + done < <(cat $USER_DATA/dns.conf) +} + +# PLAIN list function +plain_list() { + IFS=$'\n' + while read str; do + parse_object_kv_list "$str" + echo -ne "$DOMAIN\t$IP\t$TPL\t$TTL\t$EXP\t$SOA\t$DNSSEC\t$SERIAL\t" + echo -e "$SRC\t$RECORDS\t$SUSPENDED\t$TIME\t$DATE" + done < <(cat $USER_DATA/dns.conf) +} + +# CSV list function +csv_list() { + IFS=$'\n' + echo "DOMAIN,IP,TPL,TTL,EXP,SOA,SERIAL,SRC,DNSSEC,RECORDS,SUSPENDED,TIME,DATE" + while read str; do + parse_object_kv_list "$str" + echo -n "$DOMAIN,$IP,$TPL,$TTL,$EXP,$SOA,$SERIAL," + echo "$SRC,$DNSSEC,$RECORDS,$SUSPENDED,$TIME,$DATE" + done < <(cat $USER_DATA/dns.conf) +} + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'USER [FORMAT]' +is_format_valid 'user' +is_object_valid 'user' 'USER' "$user" + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list | column -t ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-dns-records b/bin/v-list-dns-records new file mode 100755 index 0000000..2b8949f --- /dev/null +++ b/bin/v-list-dns-records @@ -0,0 +1,125 @@ +#!/bin/bash +# info: list dns domain records +# options: USER DOMAIN [FORMAT] +# +# example: v-list-dns-records admin example.com +# +# This function for getting all DNS domain records. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +format=${3-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# JSON list function +json_list() { + IFS=$'\n' + i=1 + objects=$(grep ID $USER_DATA/dns/$domain.conf | wc -l) + echo "{" + while read str; do + unset TTL + parse_object_kv_list "$str" + [ -z "$TTL" ] && TTL="$zone_ttl" + VALUE=$(echo "$VALUE" | sed -e 's/"/\\"/g' -e "s/%quote%/'/g" -e 's/ /\\u0009/g') + echo -n ' "'$ID'": { + "RECORD": "'$RECORD'", + "TYPE": "'$TYPE'", + "PRIORITY": "'$PRIORITY'", + "VALUE": "'$VALUE'", + "ID": "'$ID'", + "SUSPENDED": "'$SUSPENDED'", + "TIME": "'$TIME'", + "DATE": "'$DATE'", + "TTL": "'$TTL'" + }' + if [ "$i" -lt "$objects" ]; then + echo ',' + else + echo + fi + ((i++)) + done < <(cat $USER_DATA/dns/$domain.conf) + echo '}' +} + +# SHELL list function +shell_list() { + IFS=$'\n' + echo "ID^RECORD^TYPE^VALUE^DATE^TTL" + echo "--^------^----^-----^----^----" + while read str; do + unset TTL + parse_object_kv_list "$str" + [ -z "$TTL" ] && TTL="$zone_ttl" + echo "$ID^$RECORD^$TYPE^${VALUE:0:30}^$DATE^$TTL" + done < <(cat $USER_DATA/dns/$domain.conf) +} + +# PLAIN list function +plain_list() { + IFS=$'\n' + while read str; do + unset TTL + parse_object_kv_list "$str" + [ -z "$TTL" ] && TTL="$zone_ttl" + VALUE=$(echo "$VALUE" | sed -e "s/%quote%/\\'/g") + echo -ne "$ID\t$RECORD\t$TYPE\t$PRIORITY\t$VALUE\t" + echo -e "$SUSPENDED\t$TIME\t$DATE\t$TTL" + done < <(cat $USER_DATA/dns/$domain.conf) +} + +# CSV list function +csv_list() { + IFS=$'\n' + echo "ID,RECORD,TYPE,PRIORITY,VALUE,SUSPENDED,TIME,DATE,TTL" + while read str; do + unset TTL + parse_object_kv_list "$str" + [ -z "$TTL" ] && TTL="$zone_ttl" + VALUE=$(echo "$VALUE" | sed -e "s/%quote%/\\'/g") + echo -n "$ID,$RECORD,$TYPE,$PRIORITY,\"$VALUE\"," + echo "$SUSPENDED,$TIME,$DATE,$TTL" + done < <(cat $USER_DATA/dns/$domain.conf) +} + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DOMAIN [FORMAT]' +is_format_valid 'user' 'domain' +is_object_valid 'user' 'USER' "$user" +is_object_valid 'dns' 'DOMAIN' "$domain" + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +zone_ttl="$(get_object_value 'dns' 'DOMAIN' "$domain" '$TTL')" + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list | column -t -s '^' ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-dns-template b/bin/v-list-dns-template new file mode 100755 index 0000000..b8b93e0 --- /dev/null +++ b/bin/v-list-dns-template @@ -0,0 +1,109 @@ +#!/bin/bash +# info: list dns template +# options: TEMPLATE [FORMAT] +# +# example: v-list-dns-template zoho +# +# This function for obtaining the DNS template parameters. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +template=$1 +format=${2-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# JSON list function +json_list() { + IFS=$'\n' + i=1 + objects=$(grep ID $DNSTPL/$template.tpl | wc -l) + echo "{" + while read str; do + parse_object_kv_list "$str" + VALUE=$(echo "$VALUE" | sed -e 's/"/\\"/g' -e "s/%quote%/'/g") + echo -n ' "'$ID'": { + "RECORD": "'$RECORD'", + "TYPE": "'$TYPE'", + "PRIORITY": "'$PRIORITY'", + "VALUE": "'$VALUE'", + "ID": "'$ID'" + }' + if [ "$i" -lt "$objects" ]; then + echo ',' + else + echo + fi + ((i++)) + done < <(cat $DNSTPL/$template.tpl) + echo '}' +} + +# SHELL list function +shell_list() { + IFS=$'\n' + echo "ID^RECORD^TYPE^VALUE" + echo "--^------^----^-----" + while read str; do + parse_object_kv_list "$str" + echo "$ID^$RECORD^$TYPE^$VALUE" + done < <(cat $DNSTPL/$template.tpl) +} + +# PLAIN list function +plain_list() { + IFS=$'\n' + while read str; do + parse_object_kv_list "$str" + VALUE=$(echo "$VALUE" | sed -e "s/%quote%/\\'/g") + echo -e "$ID\t$RECORD\t$TYPE\t$PRIORITY\t$VALUE" + done < <(cat $DNSTPL/$template.tpl) +} + +# CSV list function +csv_list() { + IFS=$'\n' + echo "ID,RECORD,TYPE,PRIORITY,VALUE" + while read str; do + parse_object_kv_list "$str" + VALUE=$(echo "$VALUE" | sed -e "s/%quote%/\\'/g") + echo "$ID,$RECORD,$TYPE,$PRIORITY,\"$VALUE\"" + done < <(cat $DNSTPL/$template.tpl) +} + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'TEMPLATE [FORMAT]' +is_format_valid 'template' +is_dns_template_valid "$template" + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list | column -t -s '^' ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-dns-templates b/bin/v-list-dns-templates new file mode 100755 index 0000000..156ed14 --- /dev/null +++ b/bin/v-list-dns-templates @@ -0,0 +1,83 @@ +#!/bin/bash +# info: list dns templates +# options: [FORMAT] +# +# example: v-list-dns-templates json +# +# This function for obtaining the list of all DNS templates available. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +format=${1-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# JSON list function +json_list() { + objects=$(echo "$templates" | wc -l) + i=1 + echo "[" + for template in $templates; do + echo -n ' "'$template'"' + if [ "$i" -lt "$objects" ]; then + echo ',' + else + echo + fi + ((i++)) + done + echo "]" + +} + +# SHELL list function +shell_list() { + echo "TEMPLATE" + echo "--------" + ls -t $DNSTPL | grep '\.tpl' | cut -f 1 -d '.' +} + +# PLAIN list function +plain_list() { + for template in $templates; do + echo "$template" + done +} + +# CSV list function +csv_list() { + echo "TEMPLATE" + for template in $templates; do + echo "$template" + done +} + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Defining template list +templates=$(ls -t $DNSTPL | grep '\.tpl' | cut -f 1 -d '.') + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-dnssec-public-key b/bin/v-list-dnssec-public-key new file mode 100755 index 0000000..54eb5c2 --- /dev/null +++ b/bin/v-list-dnssec-public-key @@ -0,0 +1,99 @@ +#!/bin/bash +# info: list public dnssec key +# options: USER DOMAIN [FROMAT] +# +# example: v-list-dns-public-key admin acme.com +# +# This function list the public key to be used with DNSSEC and needs to be added to the domain register. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +format=$3 +dnstype=$4 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +format_domain +format_domain_idn + +check_args '2' "$#" 'USER DOMAIN [FORMAT]' +is_format_valid 'user' 'domain' +is_object_valid 'user' 'USER' "$user" +is_object_valid 'dns' 'DOMAIN' "$domain" + +# JSON list function +json_list() { + echo '{' + echo ' "'$DOMAIN'": { + "RECORD": "'$record'", + "KEYTAG": "'$keytag'", + "FLAG": "'$flag'", + "ALGORITHM": "'$algorithm'", + "KEY": "'$key'", + "DS":"'$ds'" + }' + echo '}' +} + +# SHELL list function +shell_list() { + echo "RECORD: $record" + echo "DS: $ds" + echo "KEYTAG: $keytag" + echo "FLAG: $flag" + echo "ALGORITHM: $algorithm" + echo "KEY: $key" +} + +# PLAIN list function +plain_list() { + if [ "$dnstype" != "DS" ]; then + echo -e "$record" + else + echo -e "$ds" + fi +} + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +parse_object_kv_list $(grep "DOMAIN='$domain'" $USER_DATA/dns.conf) + +if [ -n "$KEY" ]; then + record=$(cat "/var/cache/bind/K$domain_idn.+013+$KEY.key" | grep DNSKEY) + ds=$(dnssec-dsfromkey "/var/cache/bind/K$domain_idn.+013+$KEY.key") + keytag=$(echo "$ds" | cut -d' ' -f4) + flag=$(echo "$record" | cut -d' ' -f5) + algorithm=$(echo "$record" | cut -d' ' -f7) + key="$(echo "$record" | cut -d' ' -f8) $(echo "$record" | cut -d' ' -f9)" +fi + +case $format in + json) json_list ;; + plain) plain_list ;; + shell) shell_list ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-firewall b/bin/v-list-firewall new file mode 100755 index 0000000..71d14df --- /dev/null +++ b/bin/v-list-firewall @@ -0,0 +1,104 @@ +#!/bin/bash +# info: list iptables rules +# options: [FORMAT] +# +# example: v-list-firewall json +# +# This function of obtaining the list of all iptables rules. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +format=${1-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# JSON list function +json_list() { + IFS=$'\n' + i=1 + objects=$(grep RULE $HESTIA/data/firewall/rules.conf | wc -l) + echo "{" + while read str; do + [[ -z "$str" ]] && continue + parse_object_kv_list "$str" + echo -n ' "'$RULE'": { + "ACTION": "'$ACTION'", + "PROTOCOL": "'$PROTOCOL'", + "PORT": "'$PORT'", + "IP": "'$IP'", + "COMMENT": "'$COMMENT'", + "SUSPENDED": "'$SUSPENDED'", + "TIME": "'$TIME'", + "DATE": "'$DATE'" + }' + if [ "$i" -lt "$objects" ]; then + echo ',' + else + echo + fi + ((i++)) + done < <(cat $HESTIA/data/firewall/rules.conf) + echo '}' +} + +# SHELL list function +shell_list() { + IFS=$'\n' + echo "RULE^ACTION^PROTO^PORT^IP^SPND^DATE" + echo "----^------^-----^----^--^----^----" + while read str; do + [[ -z "$str" ]] && continue + parse_object_kv_list "$str" + echo "$RULE^$ACTION^$PROTOCOL^$PORT^$IP^$SUSPENDED^$DATE" + done < <(cat $HESTIA/data/firewall/rules.conf) +} + +# PLAIN list function +plain_list() { + IFS=$'\n' + while read str; do + [[ -z "$str" ]] && continue + parse_object_kv_list "$str" + echo -ne "$RULE\t$ACTION\t$PROTOCOL\t$PORT\t$IP\t$COMMENT\t" + echo -e "$SUSPENDED\t$TIME\t$DATE" + done < <(cat $HESTIA/data/firewall/rules.conf) +} + +# CSV list function +csv_list() { + IFS=$'\n' + echo "RULE,ACTION,PROTOCOL,PORT,IP,COMMENT,SUSPENDED,TIME,DATE" + while read str; do + [[ -z "$str" ]] && continue + parse_object_kv_list "$str" + echo -n "$RULE,$ACTION,$PROTOCOL,$PORT,$IP,\"$COMMENT\"," + echo "$SUSPENDED,$TIME,$DATE" + done < <(cat $HESTIA/data/firewall/rules.conf) +} + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list | column -t -s '^' ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-firewall-ban b/bin/v-list-firewall-ban new file mode 100755 index 0000000..0a0d765 --- /dev/null +++ b/bin/v-list-firewall-ban @@ -0,0 +1,94 @@ +#!/bin/bash +# info: list firewall block list +# options: [FORMAT] +# +# example: v-list-firewall-ban json +# +# This function of obtaining the list of currently blocked ips. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +format=${1-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# JSON list function +json_list() { + IFS=$'\n' + i=1 + objects=$(grep IP $HESTIA/data/firewall/banlist.conf | wc -l) + echo "{" + while read str; do + parse_object_kv_list "$str" + echo -n ' "'$IP'": { + "IP": "'$IP'", + "CHAIN": "'$CHAIN'", + "TIME": "'$TIME'", + "DATE": "'$DATE'" + }' + if [ "$i" -lt "$objects" ]; then + echo ',' + else + echo + fi + ((i++)) + done < <(cat $HESTIA/data/firewall/banlist.conf) + echo '}' +} + +# SHELL list function +shell_list() { + IFS=$'\n' + echo "IP CHAIN TIME DATE" + echo "-- ----- ---- ----" + while read str; do + parse_object_kv_list "$str" + echo "$IP $CHAIN $TIME $DATE" + done < <(cat $HESTIA/data/firewall/banlist.conf) +} + +# PLAIN list function +plain_list() { + IFS=$'\n' + while read str; do + parse_object_kv_list "$str" + echo -e "$IP\t$CHAIN\t$TIME\t$DATE" + done < <(cat $HESTIA/data/firewall/banlist.conf) +} + +# CSV list function +csv_list() { + IFS=$'\n' + echo "IP,CHAIN,TIME,DATE" + while read str; do + parse_object_kv_list "$str" + echo "$IP,$CHAIN,$TIME,$DATE" + done < <(cat $HESTIA/data/firewall/banlist.conf) +} + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list | column -t ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-firewall-ipset b/bin/v-list-firewall-ipset new file mode 100755 index 0000000..c4df73f --- /dev/null +++ b/bin/v-list-firewall-ipset @@ -0,0 +1,108 @@ +#!/bin/bash +# info: List firewall ipset +# options: [FORMAT] +# +# example: v-list-firewall-ipset json +# +# This function prints defined ipset lists + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +format=${1-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/conf/hestia.conf +source $HESTIA/conf/hestia.conf +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +is_system_enabled "$FIREWALL_SYSTEM" 'FIREWALL_SYSTEM' + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# JSON list function +json_list() { + IFS=$'\n' + i=1 + objects=$(grep LISTNAME $HESTIA/data/firewall/ipset.conf | wc -l) + echo "{" + while read str; do + [[ -z "$str" ]] && continue + parse_object_kv_list "$str" + echo -n ' "'$LISTNAME'": { + "IP_VERSION": "'$IP_VERSION'", + "AUTOUPDATE": "'$AUTOUPDATE'", + "SUSPENDED": "'$SUSPENDED'", + "SOURCE": "'$SOURCE'", + "TIME": "'$TIME'", + "DATE": "'$DATE'" + }' + [[ "$i" -lt "$objects" ]] && echo ',' || echo + ((i++)) + done < <(cat $HESTIA/data/firewall/ipset.conf) + echo '}' +} + +# SHELL list function +shell_list() { + IFS=$'\n' + echo "LISTNAME^IP_VERSION^AUTOUPDATE^SUSPENDED^SOURCE^TIME^DATE" + echo "----^------^-----^----^--^----^----" + while read str; do + [[ -z "$str" ]] && continue + parse_object_kv_list "$str" + echo "$LISTNAME^$IP_VERSION^$AUTOUPDATE^$SUSPENDED^$SOURCE^$TIME^$DATE" + done < <(cat $HESTIA/data/firewall/ipset.conf) +} + +# PLAIN list function +plain_list() { + IFS=$'\n' + while read str; do + [[ -z "$str" ]] && continue + parse_object_kv_list "$str" + echo -ne "$LISTNAME\t$IP_VERSION\t$AUTOUPDATE\t$SUSPENDED\t$SOURCE\t" + echo -e "$TIME\t$DATE" + done < <(cat $HESTIA/data/firewall/ipset.conf) +} + +# CSV list function +csv_list() { + IFS=$'\n' + echo "LISTNAME,IP_VERSION,AUTOUPDATE,SUSPENDED,SOURCE,SUSPENDED,TIME,DATE" + while read str; do + [[ -z "$str" ]] && continue + parse_object_kv_list "$str" + echo -n "$LISTNAME,$IP_VERSION,$AUTOUPDATE,$SUSPENDED,\"$SOURCE\"," + echo "$TIME,$DATE" + done < <(cat $HESTIA/data/firewall/ipset.conf) +} + +[ ! -f "$HESTIA/data/firewall/ipset.conf" ] && touch "$HESTIA/data/firewall/ipset.conf" + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list | column -t -s '^' ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-firewall-rule b/bin/v-list-firewall-rule new file mode 100755 index 0000000..4404900 --- /dev/null +++ b/bin/v-list-firewall-rule @@ -0,0 +1,91 @@ +#!/bin/bash +# info: list firewall rule +# options: RULE [FORMAT] +# +# example: v-list-firewall-rule 2 +# +# This function of obtaining firewall rule parameters. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +rule=$1 +format=${2-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +json_list() { + echo '{' + echo ' "'$RULE'": { + "ACTION": "'$ACTION'", + "PROTOCOL": "'$PROTOCOL'", + "PORT": "'$PORT'", + "IP": "'$IP'", + "COMMENT": "'$COMMENT'", + "SUSPENDED": "'$SUSPENDED'", + "TIME": "'$TIME'", + "DATE": "'$DATE'" + }' + echo '}' +} + +# SHELL list function +shell_list() { + echo "ACTION: $ACTION" + echo "PROTOCOL: $PROTOCOL" + echo "PORT: $PORT" + echo "IP: $IP" + echo "COMMENT: $COMMENT" + echo "SUSPENDED: $SUSPENDED" + echo "TIME: $TIME" + echo "DATE: $DATE" +} + +# PLAIN list function +plain_list() { + echo -ne "$RULE\t$ACTION\t$PROTOCOL\t$PORT\t$IP\t$COMMENT\t" + echo -e "$SUSPENDED\t$TIME\t$DATE" +} + +# CSV list function +csv_list() { + echo "RULE,ACTION,PROTOCOL,PORT,IP,COMMENT,SUSPENDED,TIME,DATE" + echo "$RULE,$ACTION,$PROTOCOL,$PORT,$IP,$COMMENT,$SUSPENDED,$TIME,$DATE" +} + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'RULE [FORMAT]' +is_number_format_valid "$rule" "rule id" +is_object_valid '../../data/firewall/rules' 'RULE' "$rule" + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Parsing rules +parse_object_kv_list $(grep "RULE='$rule'" $HESTIA/data/firewall/rules.conf) + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-fs-directory b/bin/v-list-fs-directory new file mode 100755 index 0000000..85a4da2 --- /dev/null +++ b/bin/v-list-fs-directory @@ -0,0 +1,51 @@ +#!/bin/bash +# info: list directory +# options: USER DIRECTORY +# +# example: v-list-fs-directory /home/admin/web +# +# This function lists directory on the file system + +user=$1 +path=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'USER [DIRECTORY]' +is_format_valid 'user' +is_object_valid 'user' 'USER' "$user" + +# Checking user homedir +homedir=$(grep "^$user:" /etc/passwd | cut -f 6 -d :) +if [ -z $homedir ]; then + echo "Error: user home directory doesn't exist" + exit 12 +fi + +# Checking path +if [ ! -z "$path" ]; then + rpath=$(readlink -f "$path") + if [ -z "$(echo $rpath | grep $homedir)" ]; then + echo "Error: invalid path $path" + exit 2 + fi +else + path=$homedir +fi + +# Listing directory +user_exec find "$path" -maxdepth 1 \ + -printf "%y|%m|%TY-%Tm-%Td|%TH:%TM|%u|%g|%s|%P\n" 2> /dev/null + +# Exiting +exit $? diff --git a/bin/v-list-letsencrypt-user b/bin/v-list-letsencrypt-user new file mode 100755 index 0000000..7345552 --- /dev/null +++ b/bin/v-list-letsencrypt-user @@ -0,0 +1,89 @@ +#!/bin/bash +# info: list letsencrypt key +# options: USER [FORMAT] +# +# example: v-list-letsencrypt-user admin +# +# This function for obtaining the letsencrypt key thumbprint + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +format=${2-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# JSON list function +json_list() { + echo '{' + echo ' "'$user'": { + "EMAIL": "'$EMAIL'", + "EXPONENT": "'$EXPONENT'", + "MODULUS": "'$MODULUS'", + "THUMB": "'$THUMB'", + "KID": "'$KID'" + }' + echo '}' +} + +# SHELL list function +shell_list() { + echo "USER: $user" + echo "EMAIL: $EMAIL" + echo "THUMB: $THUMB" + echo "EXPONENT: $EXPONENT" + echo "MODULUS: $MODULUS" + echo "KID: $KID" +} + +# PLAIN list function +plain_list() { + echo -e "$user\t$EMAIL\t$EXPONENT\t$MODULUS\t$THUMB\t$KID" +} + +# CSV list function +csv_list() { + echo "USER,EMAIL,EXPONENT,MODULUS,THUMB,KID" + echo "$user,$EMAIL,$EXPONENT,$MODULUS,$THUMB,$KID" +} + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'USER [FORMAT]' +is_format_valid 'user' +is_object_valid 'user' 'USER' "$user" +if [ ! -e "$USER_DATA/ssl/le.conf" ]; then + check_result "$E_NOTEXIST" "LetsEncrypt user account doesn't exist" +fi + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# load config file +source_conf "$USER_DATA/ssl/le.conf" + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-mail-account b/bin/v-list-mail-account new file mode 100755 index 0000000..f3474b5 --- /dev/null +++ b/bin/v-list-mail-account @@ -0,0 +1,104 @@ +#!/bin/bash +# info: list mail domain account +# options: USER DOMAIN ACCOUNT [FORMAT] +# +# example: v-list-mail-account admin domain.tld tester +# +# This function of obtaining the list of account parameters. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +account=$3 +format=${4-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# JSON list function +json_list() { + echo '{' + echo ' "'$account'": { + "ALIAS": "'$ALIAS'", + "FWD": "'$FWD'", + "FWD_ONLY": "'$FWD_ONLY'", + "AUTOREPLY": "'$AUTOREPLY'", + "QUOTA": "'$QUOTA'", + "RATE_LIMIT": "'$RATE_LIMIT'", + "U_DISK": "'$U_DISK'", + "SUSPENDED": "'$SUSPENDED'", + "TIME": "'$TIME'", + "DATE": "'$DATE'", + "WEBMAIL_ALIAS": "'$WEBMAIL_ALIAS.$domain'" + }' + echo '}' +} + +# SHELL list function +shell_list() { + echo "ACCOUNT: $account" + echo "ALIAS: $ALIAS" + echo "FORWARD: $FWD" + echo "FORWARD_ONLY: $FWD_ONLY" + echo "AUTOREPLY: $AUTOREPLY" + echo "QUOTA: $QUOTA" + echo "DISK: $U_DISK" + echo "SUSPENDED: $SUSPENDED" + echo "TIME: $TIME" + echo "DATE: $DATE" + echo "WEBMAIL_ALIAS: $WEBMAIL_ALIAS.$domain" +} + +# PLAIN list function +plain_list() { + echo -ne "$account\t$ALIAS\t$FWD\t$FWD_ONLY\t$AUTOREPLY\t$QUOTA\t" + echo -e "$U_DISK\t$SUSPENDED\t$TIME\t$DATE\t$WEBMAIL_ALIAS.$domain" +} + +# CSV list function +csv_list() { + echo -n "ACCOUNT,ALIAS,FWD,FWD_ONLY,AUTOREPLY,QUOTA,U_DISK" + echo "SUSPENDED,TIME,DATE" + echo -n "$ACCOUNT,\"$ALIAS\",\"$FWD\",$FWD_ONLY,$AUTOREPLY,$QUOTA," + echo "$U_DISK,$SUSPENDED,$TIME,$DATE\t$WEBMAIL_ALIAS.$domain" +} + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '3' "$#" 'USER DOMAIN ACCOUNT [FORMAT]' +is_format_valid 'user' 'domain' 'account' +is_object_valid 'user' 'USER' "$user" +is_object_valid 'mail' 'DOMAIN' "$domain" +is_object_valid "mail/$domain" 'ACCOUNT' "$account" + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Parsing mail account +parse_object_kv_list $(grep "ACCOUNT='$account'" $USER_DATA/mail/$domain.conf) + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-mail-account-autoreply b/bin/v-list-mail-account-autoreply new file mode 100755 index 0000000..0ee0cdd --- /dev/null +++ b/bin/v-list-mail-account-autoreply @@ -0,0 +1,86 @@ +#!/bin/bash +# info: list mail account autoreply +# options: USER DOMAIN ACCOUNT [FORMAT] +# +# example: v-list-mail-account-autoreply admin example.com testing +# +# This function of obtaining mail account autoreply message. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +account=$3 +format=${4-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# JSON list function +json_list() { + TO_ESCAPE='\\' + msg=$(echo "$msg" | sed -e "s|${TO_ESCAPE}|${TO_ESCAPE}${TO_ESCAPE}|g" -e 's/"/\\"/g' -e "s/%quote%/'/g") + echo '{' + echo -e "\t\"$account\": {" + echo " \"MSG\": \"$msg\"" + echo -e "\t}\n}" +} + +# SHELL list function +shell_list() { + echo "$msg" +} + +# PLAIN list function +plain_list() { + echo "$msg" +} + +# CSV list function +csv_list() { + echo "MSG" + echo "$msg" +} + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '3' "$#" 'USER DOMAIN ACCOUNT [FORMAT]' +is_format_valid 'user' 'domain' 'account' +is_object_valid 'user' 'USER' "$user" +is_object_valid 'mail' 'DOMAIN' "$domain" +is_object_unsuspended 'mail' 'DOMAIN' "$domain" +is_object_valid "mail/$domain" 'ACCOUNT' "$account" +is_object_unsuspended "mail/$domain" 'ACCOUNT' "$account" + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +if [ -e "$USER_DATA/mail/$account@$domain.msg" ]; then + msg=$(cat $USER_DATA/mail/$account@$domain.msg \ + | sed ':a;N;$!ba;s/\n/\\n/g') +fi + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-mail-accounts b/bin/v-list-mail-accounts new file mode 100755 index 0000000..62db32b --- /dev/null +++ b/bin/v-list-mail-accounts @@ -0,0 +1,127 @@ +#!/bin/bash +# info: list mail domain accounts +# options: USER DOMAIN [FORMAT] +# +# example: v-list-mail-accounts admin acme.com +# +# This function of obtaining the list of all user domains. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +format=${3-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# JSON list function +json_list() { + IFS=$'\n' + i=1 + objects=$(grep ACCOUNT $USER_DATA/mail/$domain.conf | wc -l) + echo "{" + while read str; do + parse_object_kv_list "$str" + echo -n ' "'$ACCOUNT'": { + "ALIAS": "'$ALIAS'", + "FWD": "'$FWD'", + "FWD_ONLY": "'$FWD_ONLY'", + "AUTOREPLY": "'$AUTOREPLY'", + "QUOTA": "'$QUOTA'", + "U_DISK": "'$U_DISK'", + "SUSPENDED": "'$SUSPENDED'", + "TIME": "'$TIME'", + "DATE": "'$DATE'" + }' + if [ "$i" -lt "$objects" ]; then + echo ',' + else + echo + fi + ((i++)) + done < <(cat $USER_DATA/mail/$domain.conf) + echo '}' +} + +# SHELL list function +shell_list() { + IFS=$'\n' + echo "ACCOUNT ALIAS FWD DISK DATE" + echo "------- ----- --- ---- ----" + while read str; do + parse_object_kv_list "$str" + if [ -z "$ALIAS" ]; then + ALIAS='no' + else + if [ "${#ALIAS}" -gt 12 ]; then + ALIAS="${ALIAS:0:12}..." + fi + fi + if [ -z "$FWD" ]; then + FWD='no' + else + if [ "${#FWD}" -gt 20 ]; then + FWD="${FWD:0:20}..." + fi + fi + echo "$ACCOUNT $ALIAS $FWD $U_DISK $DATE" + done < <(cat $USER_DATA/mail/$domain.conf) +} + +# PLAIN list function +plain_list() { + IFS=$'\n' + while read str; do + parse_object_kv_list "$str" + echo -ne "$ACCOUNT\t$ALIAS\t$FWD\t$FWD_ONLY\t$AUTOREPLY\t" + echo -e "$QUOTA\t$U_DISK\t$SUSPENDED\t$TIME\t$DATE" + done < <(cat $USER_DATA/mail/$domain.conf) +} + +# CSV list function +csv_list() { + IFS=$'\n' + echo -n "ACCOUNT,ALIAS,FWD,FWD_ONLY,AUTOREPLY,QUOTA,U_DISK," + echo "SUSPENDED,TIME,DATE" + while read str; do + parse_object_kv_list "$str" + echo -n "$ACCOUNT,\"$ALIAS\",\"$FWD\",$FWD_ONLY,$AUTOREPLY," + echo "$QUOTA,$U_DISK,$SUSPENDED,$TIME,$DATE" + done < <(cat $USER_DATA/mail/$domain.conf) +} + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DOMAIN [FORMAT]' +is_format_valid 'user' 'domain' +is_object_valid 'user' 'USER' "$user" +is_object_valid 'mail' 'DOMAIN' "$domain" + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list | column -t ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-mail-domain b/bin/v-list-mail-domain new file mode 100755 index 0000000..a724a5f --- /dev/null +++ b/bin/v-list-mail-domain @@ -0,0 +1,123 @@ +#!/bin/bash +# info: list mail domain +# options: USER DOMAIN [FORMAT] +# +# example: v-list-mail-domain user01 mydomain.com +# +# This function of obtaining the list of domain parameters. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +format=${3-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# JSON list function +json_list() { + parse_object_kv_list $(grep "DOMAIN='$domain'" $USER_DATA/mail.conf) + echo '{' + echo ' "'$DOMAIN'": { + "ANTIVIRUS": "'$ANTIVIRUS'", + "ANTISPAM": "'$ANTISPAM'", + "DKIM": "'$DKIM'", + "CATCHALL": "'$CATCHALL'", + "ACCOUNTS": "'$ACCOUNTS'", + "RATE_LIMIT": "'$RATE_LIMIT'", + "REJECT": "'$REJECT'", + "U_DISK": "'$U_DISK'", + "SSL": "'$SSL'", + "LETSENCRYPT": "'$LETSENCRYPT'", + "SUSPENDED": "'$SUSPENDED'", + "TIME": "'$TIME'", + "DATE": "'$DATE'", + "WEBMAIL_ALIAS": "'$WEBMAIL_ALIAS.$domain'", + "WEBMAIL":"'$WEBMAIL'", + "U_SMTP_RELAY":"'$U_SMTP_RELAY'", + "U_SMTP_RELAY_HOST":"'$U_SMTP_RELAY_HOST'", + "U_SMTP_RELAY_PORT":"'$U_SMTP_RELAY_PORT'", + "U_SMTP_RELAY_USERNAME":"'$U_SMTP_RELAY_USERNAME'" + }' + echo '}' +} + +# SHELL list function +shell_list() { + echo "DOMAIN: $DOMAIN" + echo "ANTIVIRUS: $ANTIVIRUS" + echo "ANTISPAM: $ANTISPAM" + echo "DKIM: $DKIM" + echo "CATCHALL: $CATCHALL" + echo "ACCOUNTS: $ACCOUNTS" + echo "DISK: $U_DISK" + echo "SSL: $SSL" + echo "RATE_LIMIT: $RATE_LIMIT" + echo "REJECT: $REJECT" + echo "LETSENCRYPT: $LETSENCRYPT" + echo "SUSPENDED: $SUSPENDED" + echo "TIME: $TIME" + echo "DATE: $DATE" + echo "WEBMAIL_ALIAS: $WEBMAIL_ALIAS.$domain" + echo "WEBMAIL: $WEBMAIL" + echo "U_SMTP_RELAY: $U_SMTP_RELAY" + echo "U_SMTP_RELAY_HOST $U_SMTP_RELAY_HOST" + echo "U_SMTP_RELAY_PORT $U_SMTP_RELAY_PORT" + echo "U_SMTP_RELAY_USERNAME $U_SMTP_RELAY_USERNAME" +} + +# PLAIN list function +plain_list() { + echo -ne "$DOMAIN\t$ANTIVIRUS\t$ANTISPAM\t$DKIM\t$CATCHALL\t" + echo -e "$ACCOUNTS\t$U_DISK\t$SSL\t$LETSENCRYPT\t$SUSPENDED\t$TIME\t$DATE\t$WEBMAIL_ALIAS.$domain\t$WEBMAIL\t" + echo -e "$U_SMTP_RELAY\t$U_SMTP_RELAY_HOST\t$U_SMTP_RELAY_PORT\t$U_SMTP_RELAY_USERNAME" +} + +# CSV list function +csv_list() { + echo -n "DOMAIN,ANTIVIRUS,ANTISPAM,DKIM,CATCHALL,ACCOUNTS,U_DISK," + echo "SSL,LETSENCRYPT,SUSPENDED,TIME,DATE,WEBMAIL_ALIAS,WEBMAIL," + echo "U_SMTP_RELAY,U_SMTP_RELAY_HOST,U_SMTP_RELAY_PORT,U_SMTP_RELAY_USERNAME" + echo -n "$DOMAIN,$ANTIVIRUS,$ANTISPAM,$DKIM,$CATCHALL,$ACCOUNTS,$U_DISK," + echo "$SSL,$LETSENCRYPT,$SUSPENDED,$TIME,$DATE,$WEBMAIL_ALIAS.$domain,$WEBMAIL," + echo "$U_SMTP_RELAY,$U_SMTP_RELAY_HOST,$U_SMTP_RELAY_PORT,$U_SMTP_RELAY_USERNAME" +} + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DOMAIN [FORMAT]' +is_format_valid 'user' 'domain' +is_object_valid 'user' 'USER' "$user" +is_object_valid 'mail' 'DOMAIN' "$domain" + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Parsing mail domain +parse_object_kv_list $(grep "DOMAIN='$domain'" $USER_DATA/mail.conf) + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-mail-domain-dkim b/bin/v-list-mail-domain-dkim new file mode 100755 index 0000000..cac5636 --- /dev/null +++ b/bin/v-list-mail-domain-dkim @@ -0,0 +1,86 @@ +#!/bin/bash +# info: list mail domain dkim +# options: USER DOMAIN [FORMAT] +# +# example: v-list-mail-domain-dkim admin maildomain.tld +# +# This function of obtaining domain dkim files. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +format=${3-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# JSON list function +json_list() { + echo '{' + echo -e "\t\"$domain\": {" + echo " \"PEM\": \"$pem\"," + echo " \"PUB\": \"$pub\"," + echo -e "\t}\n}" +} + +# SHELL list function +shell_list() { + echo -e "$pem" + echo -e "\n$pub" +} + +# PLAIN list function +plain_list() { + echo "$pem\t$pub" +} + +# CSV list function +csv_list() { + echo "PEM,PUB" + echo "\"$pem\",\"$pub\"" +} + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DOMAIN [FORMAT]' +is_format_valid 'user' 'domain' +is_object_valid 'user' 'USER' "$user" +is_object_valid 'mail' 'DOMAIN' "$domain" + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Parsing domain keys +if [ -e "$USER_DATA/mail/$domain.pem" ]; then + pem=$(cat $USER_DATA/mail/$domain.pem | sed ':a;N;$!ba;s/\n/\\n/g') +fi + +if [ -e "$USER_DATA/mail/$domain.pub" ]; then + pub=$(cat $USER_DATA/mail/$domain.pub | sed ':a;N;$!ba;s/\n/\\n/g') +fi + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-mail-domain-dkim-dns b/bin/v-list-mail-domain-dkim-dns new file mode 100755 index 0000000..779988c --- /dev/null +++ b/bin/v-list-mail-domain-dkim-dns @@ -0,0 +1,93 @@ +#!/bin/bash +# info: list mail domain dkim dns records +# options: USER DOMAIN [FORMAT] +# +# example: v-list-mail-domain-dkim-dns admin example.com +# +# This function of obtaining domain dkim dns records for proper setup. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +format=${3-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# JSON list function +json_list() { + echo '{' + echo -e "\t\"_domainkey\": {" + echo " \"TTL\": \"3600\"," + echo " \"TXT\": \"'t=y; o=~;'\"" + echo -e "\t}," + echo -e "\n\t\"mail._domainkey\": {" + echo " \"TTL\": \"3600\"," + echo " \"TXT\": \"'v=DKIM1; k=rsa; p=$pub'\"" + echo -e "\t}\n}" +} + +# SHELL list function +shell_list() { + echo "RECORD TTL TYPE VALUE" + echo "------ --- ---- -----" + echo "_domainkey 3600 IN TXT \"t=y; o=~;\"" + echo "mail._domainkey 3600 IN TXT \"v=DKIM1; k=rsa; p=$pub\"" +} + +# PLAIN list function +plain_list() { + echo -e "_domainkey\t3600\tIN\tTXT\t\"t=y; o=~;\"" + echo -e "mail._domainkey\t3600\tIN\tTXT\t\"v=DKIM1; k=rsa; p=$pub\"" +} + +# CSV list function +csv_list() { + echo "RECORD,TTL,IN,TYPE,VALUE" + echo "_domainkey,3600,IN,TXT,\"\"t=y; o=~;\"\"" + echo "mail._domainkey,3600,IN,TXT,\"\"v=DKIM1; k=rsa; p=$pub\"\"" +} + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DOMAIN [FORMAT]' +is_format_valid 'user' 'domain' +is_object_valid 'user' 'USER' "$user" +is_object_valid 'mail' 'DOMAIN' "$domain" + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Parsing domain keys +if [ -e "$USER_DATA/mail/$domain.pub" ]; then + pub=$(cat $USER_DATA/mail/$domain.pub | grep -v "KEY-----") + pub=$(echo "$pub" | sed ':a;N;$!ba;s/\n//g') +else + pub="DKIM-SUPPORT-IS-NOT-ACTIVATED" +fi + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list | column -t -s '^' ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-mail-domain-ssl b/bin/v-list-mail-domain-ssl new file mode 100755 index 0000000..a68ae69 --- /dev/null +++ b/bin/v-list-mail-domain-ssl @@ -0,0 +1,154 @@ +#!/bin/bash +# info: list mail domain ssl certificate +# options: USER DOMAIN [FORMAT] +# +# example: v-list-mail-domain-ssl user acme.com json +# +# This function of obtaining domain ssl files. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +format=${3-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn + +# JSON list function +json_list() { + echo '{' + echo -e "\t\"$domain\": {" + echo " \"CRT\": \"$crt\"," + echo " \"KEY\": \"$key\"," + echo " \"CA\": \"$ca\"," + echo " \"SUBJECT\": \"$subj\"," + echo " \"ALIASES\": \"$alt_dns\"," + echo " \"NOT_BEFORE\": \"$before\"," + echo " \"NOT_AFTER\": \"$after\"," + echo " \"SIGNATURE\": \"$signature\"," + echo " \"PUB_KEY\": \"$pub_key\"," + echo " \"ISSUER\": \"$issuer\"" + echo -e "\t}\n}" +} + +# SHELL list function +shell_list() { + if [ -n "$crt" ]; then + echo -e "$crt" + fi + if [ -n "$key" ]; then + echo -e "\n$key" + fi + if [ -n "$ca" ]; then + echo -e "\n$ca" + fi + if [ -n "$crt" ]; then + echo + echo + echo "SUBJECT: $subj" + if [ -n "$alt_dns" ]; then + echo "ALIASES: ${alt_dns//,/ }" + fi + echo "VALID FROM: $before" + echo "VALID TIL: $after" + echo "SIGNATURE: $signature" + echo "PUB_KEY: $pub_key" + echo "ISSUER: $issuer" + fi +} + +# PLAIN list function +plain_list() { + if [ -n "$crt" ]; then + echo -e "$crt" + fi + if [ -n "$key" ]; then + echo -e "\n$key" + fi + if [ -n "$ca" ]; then + echo -e "\n$ca" + fi + if [ -n "$crt" ]; then + echo "$subj" + echo "${alt_dns//,/ }" + echo "$before" + echo "$after" + echo "$signature" + echo "$pub_key" + echo "$issuer" + fi + +} + +# CSV list function +csv_list() { + echo -n "CRT,KEY,CA,SUBJECT,ALIASES,NOT_BEFORE,NOT_AFTER,SIGNATURE," + echo "PUB_KEY,ISSUER" + echo -n "\"$crt\",\"$key\",\"$ca\",\"$subj\",\"${alt_dns//,/ }\"," + echo "\"$before\",\"$after\",\"$signature\",\"$pub_key\",\"$issuer\"" +} + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DOMAIN [FORMAT]' +is_format_valid 'user' 'domain' +is_object_valid 'user' 'USER' "$user" +is_object_valid 'mail' 'DOMAIN' "$domain" + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Parsing domain SSL certificate +if [ -e "$USER_DATA/ssl/mail.$domain.crt" ]; then + crt=$(cat $USER_DATA/ssl/mail.$domain.crt | sed ':a;N;$!ba;s/\n/\\n/g') + + info=$(openssl x509 -text -in $USER_DATA/ssl/mail.$domain.crt) + subj=$(echo "$info" | grep Subject: | sed -e "s/\"//g" -e "s/.*= //") + before=$(echo "$info" | grep Before: | sed -e "s/.*Before: //") + after=$(echo "$info" | grep "After :" | sed -e "s/.*After : //") + signature=$(echo "$info" | grep "Algorithm:" | head -n1) + signature=$(echo "$signature" | sed -e "s/.*Algorithm: //") + pub_key=$(echo "$info" | grep Public-Key: | cut -f2 -d \( | tr -d \)) + issuer=$(echo "$info" | grep Issuer: | sed -e "s/.*Issuer: //") + alt_dns=$(echo "$info" | grep DNS | sed -e 's/DNS:/\n/g' | tr -d ',') + alt_dns=$(echo "$alt_dns" | tr -d ' ' | sed -e "/^$/d") + alt_dns=$(echo "$alt_dns" | sed -e ':a;N;$!ba;s/\n/,/g') +fi + +if [ -e "$USER_DATA/ssl/mail.$domain.key" ]; then + key=$(cat $USER_DATA/ssl/mail.$domain.key | sed ':a;N;$!ba;s/\n/\\n/g') +fi + +if [ -e "$USER_DATA/ssl/mail.$domain.ca" ]; then + ca=$(cat $USER_DATA/ssl/mail.$domain.ca | sed ':a;N;$!ba;s/\n/\\n/g') +fi + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-mail-domains b/bin/v-list-mail-domains new file mode 100755 index 0000000..21aab08 --- /dev/null +++ b/bin/v-list-mail-domains @@ -0,0 +1,118 @@ +#!/bin/bash +# info: list mail domains +# options: USER [FORMAT] +# +# example: v-list-mail-domains admin +# +# This function of obtaining the list of all user domains. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +format=${2-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# JSON list function +json_list() { + IFS=$'\n' + i=1 + objects=$(grep DOMAIN $USER_DATA/mail.conf | wc -l) + echo "{" + while read str; do + parse_object_kv_list "$str" + echo -n ' "'$DOMAIN'": { + "ANTIVIRUS": "'$ANTIVIRUS'", + "ANTISPAM": "'$ANTISPAM'", + "REJECT": "'$REJECT'", + "RATE_LIMIT": "'$RATE_LIMIT'", + "DKIM": "'$DKIM'", + "CATCHALL": "'$CATCHALL'", + "ACCOUNTS": "'$ACCOUNTS'", + "U_DISK": "'$U_DISK'", + "SSL": "'$SSL'", + "SUSPENDED": "'$SUSPENDED'", + "TIME": "'$TIME'", + "DATE": "'$DATE'", + "WEBMAIL_ALIAS": "'$WEBMAIL_ALIAS'", + "WEBMAIL": "'$WEBMAIL'" + }' + if [ "$i" -lt "$objects" ]; then + echo ',' + else + echo + fi + ((i++)) + done < <(cat $USER_DATA/mail.conf) + echo '}' +} + +# SHELL list function +shell_list() { + IFS=$'\n' + echo "DOMAIN ANTIVIRUS ANTISPAM DKIM SSL ACC DISK SPND DATE" + echo "------ --------- -------- ---- --- --- ---- --- ----" + while read str; do + parse_object_kv_list "$str" + echo -n "$DOMAIN $ANTIVIRUS $ANTISPAM $DKIM $SSL $ACCOUNTS $U_DISK " + echo "$SUSPENDED $DATE" + done < <(cat $USER_DATA/mail.conf) +} + +# PLAIN list function +plain_list() { + IFS=$'\n' + while read str; do + parse_object_kv_list "$str" + echo -ne "$DOMAIN\t$ANTIVIRUS\t$ANTISPAM\t$DKIM\t$SSL\$CATCHALL\t" + echo -e "$ACCOUNTS\t$U_DISK\t$SUSPENDED\t$TIME\t$DATE\t$WEBMAIL_ALIAS\t$WEBMAIL" + done < <(cat $USER_DATA/mail.conf) +} + +# CSV list function +csv_list() { + IFS=$'\n' + echo -n "DOMAIN,ANTIVIRUS,ANTISPAM,DKIM,SSL,CATCHALL,ACCOUNTS,U_DISK," + echo "SUSPENDED,TIME,DATE,WEBMAIL_ALIAS,WEBMAIL" + while read str; do + parse_object_kv_list "$str" + echo -n "$DOMAIN,$ANTIVIRUS,$ANTISPAM,$DKIM,$SSL,$CATCHALL,$ACCOUNTS," + echo "'$U_DISK,$SUSPENDED,$TIME,$DATE,$WEBMAIL_ALIAS,$WEBMAIL" + echo + done < <(cat $USER_DATA/mail.conf) +} + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'USER [FORMAT]' +is_format_valid 'user' +is_object_valid 'user' 'USER' "$user" + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list | column -t ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-remote-dns-hosts b/bin/v-list-remote-dns-hosts new file mode 100755 index 0000000..7e39779 --- /dev/null +++ b/bin/v-list-remote-dns-hosts @@ -0,0 +1,106 @@ +#!/bin/bash +# info: list remote dns host +# options: [FORMAT] +# +# example: v-list-remote-dns-hosts json +# +# This function for obtaining the list of remote dns host. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +format=${1-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# JSON list function +json_list() { + IFS=$'\n' + i=1 + objects=$(grep HOST $HESTIA/conf/dns-cluster.conf | wc -l) + echo "{" + while read str; do + parse_object_kv_list "$str" + echo -n ' "'$HOST'": { + "PORT": "'$PORT'", + "TYPE": "'$TYPE'", + "USER": "'$USER'", + "DNS_USER": "'$DNS_USER'", + "SUSPENDED": "'$SUSPENDED'", + "TIME": "'$TIME'", + "DATE": "'$DATE'" + }' + if [ "$i" -lt "$objects" ]; then + echo ',' + else + echo + fi + ((i++)) + done < <(cat $HESTIA/conf/dns-cluster.conf) + echo '}' +} + +# SHELL list function +shell_list() { + IFS=$'\n' + echo "HOST PORT TYPE USER DNS_USER SPND DATE" + echo "---- ---- ---- ---- -------- ---- ----" + while read str; do + parse_object_kv_list "$str" + echo "$HOST $PORT $TYPE $USER $DNS_USER $SUSPENDED $DATE" + done < <(cat $HESTIA/conf/dns-cluster.conf) +} + +# PLAIN list function +plain_list() { + IFS=$'\n' + while read str; do + parse_object_kv_list "$str" + echo -ne "$HOST\t$PORT\t$TYPE\t$USER\t$DNS_USER\t" + echo -e "$SUSPENDED\t$TIME\t$DATE" + done < <(cat $HESTIA/conf/dns-cluster.conf) +} + +# CSV list function +csv_list() { + IFS=$'\n' + echo "HOST,PORT,TYPE,USER,DNS_USER,SUSPENDED,TIME,DATE" + while read str; do + parse_object_kv_list "$str" + echo "$HOST,$PORT,$TYPE,$USER,$DNS_USER,$SUSPENDED,$TIME,$DATE" + done < <(cat $HESTIA/conf/dns-cluster.conf) +} + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +if [ ! -e "$HESTIA/conf/dns-cluster.conf" ]; then + exit +fi + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list | column -t ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-sys-clamd-config b/bin/v-list-sys-clamd-config new file mode 100755 index 0000000..4683e43 --- /dev/null +++ b/bin/v-list-sys-clamd-config @@ -0,0 +1,77 @@ +#!/bin/bash +# info: list clamd config parameters +# options: [FORMAT] +# +# example: v-list-sys-clamd-config +# +# This function for obtaining the list of clamd config parameters. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +format=${1-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# JSON list function +json_list() { + echo '{ + "CONFIG": { + "config_path": "'$config_path'" + } +}' +} + +# SHELL list function +shell_list() { + echo "config_path: $config_path" +} + +# PLAIN list function +plain_list() { + echo "$config_path" +} + +# CSV list function +csv_list() { + echo "config_path" + echo "$config_path" +} + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Defining config path +if [ -e '/etc/clamav/clamd.conf' ]; then + config_path='/etc/clamav/clamd.conf' +else + if [ -e '/etc/clamd.conf' ]; then + config_path='/etc/clamd.conf' + fi + if [ -e '/etc/clamd.d/clamd.conf' ]; then + config_path='/etc/clamav/clamd.conf' + fi +fi + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-sys-config b/bin/v-list-sys-config new file mode 100755 index 0000000..97bc512 --- /dev/null +++ b/bin/v-list-sys-config @@ -0,0 +1,301 @@ +#!/bin/bash +# info: list system configuration +# options: [FORMAT] +# +# example: v-list-sys-config json +# +# This function for obtaining the list of system parameters. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +format=${1-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/conf/hestia.conf +source $HESTIA/conf/hestia.conf +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# JSON list function +json_list() { + echo '{ + "config": { + "WEB_SYSTEM": "'$WEB_SYSTEM'", + "WEB_RGROUPS": "'$WEB_RGROUPS'", + "WEB_PORT": "'$WEB_PORT'", + "WEB_SSL": "'$WEB_SSL'", + "WEB_SSL_PORT": "'$WEB_SSL_PORT'", + "WEB_BACKEND": "'$WEB_BACKEND'", + "PROXY_SYSTEM": "'$PROXY_SYSTEM'", + "PROXY_PORT": "'$PROXY_PORT'", + "PROXY_SSL_PORT": "'$PROXY_SSL_PORT'", + "FTP_SYSTEM": "'$FTP_SYSTEM'", + "MAIL_SYSTEM": "'$MAIL_SYSTEM'", + "IMAP_SYSTEM": "'$IMAP_SYSTEM'", + "ANTIVIRUS_SYSTEM": "'$ANTIVIRUS_SYSTEM'", + "ANTISPAM_SYSTEM": "'$ANTISPAM_SYSTEM'", + "DB_SYSTEM": "'$DB_SYSTEM'", + "DNS_SYSTEM": "'$DNS_SYSTEM'", + "DNS_CLUSTER": "'$DNS_CLUSTER'", + "DNS_CLUSTER_SYSTEM": "'$DNS_CLUSTER_SYSTEM'", + "SUPPORT_DNSSEC": "'$SUPPORT_DNSSEC'", + "STATS_SYSTEM": "'$STATS_SYSTEM'", + "BACKUP_SYSTEM": "'$BACKUP_SYSTEM'", + "CRON_SYSTEM": "'$CRON_SYSTEM'", + "DISK_QUOTA": "'$DISK_QUOTA'", + "FIREWALL_SYSTEM": "'$FIREWALL_SYSTEM'", + "FIREWALL_EXTENSION": "'$FIREWALL_EXTENSION'", + "FILE_MANAGER": "'$FILE_MANAGER'", + "REPOSITORY": "'$REPOSITORY'", + "VERSION": "'$VERSION'", + "RELEASE_BRANCH": "'$RELEASE_BRANCH'", + "UPGRADE_SEND_EMAIL": "'$UPGRADE_SEND_EMAIL'", + "UPGRADE_SEND_EMAIL_LOG": "'$UPGRADE_SEND_EMAIL_LOG'", + "SMTP_RELAY": "'$SMTP_RELAY'", + "SMTP_RELAY_HOST": "'$SMTP_RELAY_HOST'", + "SMTP_RELAY_PORT": "'$SMTP_RELAY_PORT'", + "SMTP_RELAY_USER": "'$SMTP_RELAY_USER'", + "DEMO_MODE": "'$DEMO_MODE'", + "THEME": "'$THEME'", + "LANGUAGE": "'$LANGUAGE'", + "BACKUP_GZIP": "'$BACKUP_GZIP'", + "BACKUP": "'$BACKUP'", + "BACKUP_MODE": "'$BACKUP_MODE'", + "WEBMAIL_ALIAS": "'$WEBMAIL_ALIAS'", + "WEBMAIL_SYSTEM": "'$WEBMAIL_SYSTEM'", + "DB_PMA_ALIAS": "'$DB_PMA_ALIAS'", + "DB_PGA_ALIAS": "'$DB_PGA_ALIAS'", + "LOGIN_STYLE": "'$LOGIN_STYLE'", + "INACTIVE_SESSION_TIMEOUT": "'$INACTIVE_SESSION_TIMEOUT'", + "PHPMYADMIN_KEY": "'$PHPMYADMIN_KEY'", + "ENFORCE_SUBDOMAIN_OWNERSHIP": "'$ENFORCE_SUBDOMAIN_OWNERSHIP'", + "DEBUG_MODE": "'$DEBUG_MODE'", + "API": "'$API'", + "API_SYSTEM": "'$API_SYSTEM'", + "API_ALLOWED_IP": "'$API_ALLOWED_IP'", + "UPDATE_AVAILABLE": "'$UPDATE_AVAILABLE'", + "PLUGIN_APP_INSTALLER": "'$PLUGIN_APP_INSTALLER'", + "PLUGIN_FILE_MANAGER": "'$PLUGIN_FILE_MANAGER'", + "POLICY_SYSTEM_ENABLE_BACON": "'$POLICY_SYSTEM_ENABLE_BACON'", + "POLICY_SYSTEM_PROTECTED_ADMIN": "'$POLICY_SYSTEM_PROTECTED_ADMIN'", + "POLICY_SYSTEM_HIDE_ADMIN": "'$POLICY_SYSTEM_HIDE_ADMIN'", + "POLICY_SYSTEM_HIDE_SERVICES": "'$POLICY_SYSTEM_HIDE_SERVICES'", + "POLICY_SYSTEM_PASSWORD_RESET": "'$POLICY_SYSTEM_PASSWORD_RESET'", + "POLICY_USER_VIEW_SUSPENDED": "'$POLICY_USER_VIEW_SUSPENDED'", + "POLICY_BACKUP_SUSPENDED_USERS": "'$POLICY_BACKUP_SUSPENDED_USERS'", + "POLICY_USER_EDIT_DETAILS": "'$POLICY_USER_EDIT_DETAILS'", + "POLICY_USER_EDIT_WEB_TEMPLATES": "'$POLICY_USER_EDIT_WEB_TEMPLATES'", + "POLICY_USER_EDIT_DNS_TEMPLATES": "'$POLICY_USER_EDIT_DNS_TEMPLATES'", + "POLICY_USER_DELETE_LOGS": "'$POLICY_USER_DELETE_LOGS'", + "POLICY_USER_VIEW_LOGS": "'$POLICY_USER_VIEW_LOGS'", + "POLICY_USER_CHANGE_THEME": "'$POLICY_USER_CHANGE_THEME'", + "POLICY_CSRF_STRICTNESS": "'$POLICY_CSRF_STRICTNESS'", + "POLICY_SYNC_SKELETON": "'$POLICY_SYNC_SKELETON'", + "POLICY_SYNC_ERROR_DOCUMENTS": "'$POLICY_SYNC_ERROR_DOCUMENTS'", + "USE_SERVER_SMTP": "'$USE_SERVER_SMTP'", + "SERVER_SMTP_HOST": "'$SERVER_SMTP_HOST'", + "SERVER_SMTP_PORT": "'$SERVER_SMTP_PORT'", + "SERVER_SMTP_SECURITY": "'$SERVER_SMTP_SECURITY'", + "SERVER_SMTP_USER": "'$SERVER_SMTP_USER'", + "SERVER_SMTP_PASSWD": "'$SERVER_SMTP_PASSWD'", + "SERVER_SMTP_ADDR": "'$SERVER_SMTP_ADDR'", + "DISABLE_IP_CHECK": "'$DISABLE_IP_CHECK'", + "FROM_NAME": "'$FROM_NAME'", + "FROM_EMAIL": "'$FROM_EMAIL'", + "APP_NAME": "'$APP_NAME'", + "TITLE": "'$TITLE'", + "SUBJECT_EMAIL": "'$SUBJECT_EMAIL'", + "HIDE_DOCS": "'$HIDE_DOCS'" + } + }' +} + +# Shell list +shell_list() { + if [ -n "$WEB_SYSTEM" ]; then + echo "Web Server: $WEB_SYSTEM:$WEB_PORT ($WEB_RGROUPS)" + echo "SSL Support: $WEB_SSL:$WEB_SSL_PORT" + fi + if [ -n "$WEB_BACKEND" ]; then + echo "PHP Intepreter: $WEB_BACKEND" + fi + if [ -n "$PROXY_SYSTEM" ]; then + echo "Proxy Server: $PROXY_SYSTEM:$PROXY_PORT" + echo "Proxy SSL: $PROXY_SYSTEM:$PROXY_SSL_PORT" + fi + if [ -n "$STATS_SYSTEM" ]; then + echo "Statistics Engine: ${STATS_SYSTEM//,/, }" + fi + if [ -n "$FTP_SYSTEM" ]; then + echo "FTP Server: $FTP_SYSTEM" + fi + if [ -n "$MAIL_SYSTEM" ]; then + echo -n "Mail Server: $MAIL_SYSTEM" + if [ -n "$IMAP_SYSTEM" ]; then + echo -n " + $IMAP_SYSTEM" + fi + if [ -n "$ANTIVIRUS_SYSTEM" ]; then + echo -n " + $ANTIVIRUS_SYSTEM" + fi + if [ -n "$ANTISPAM_SYSTEM" ]; then + echo -n " + $ANTISPAM_SYSTEM" + fi + echo + if [ -n "$WEBMAIL_ALIAS" ]; then + echo "Webmail alias: $WEBMAIL_ALIAS" + fi + fi + if [ -n "$DB_SYSTEM" ]; then + echo "Database: ${DB_SYSTEM//,/, }" + if [ -n "$DB_PMA_ALIAS" ]; then + echo "phpMyAdmin Alias: $DB_PMA_ALIAS" + fi + if [ -n "$DB_PGA_ALIAS" ]; then + echo "phpPgAdmin Alias: $DB_PGA_ALIAS" + fi + fi + if [ -n "$DNS_SYSTEM" ]; then + echo -n "DNS Server: $DNS_SYSTEM" + if [ -n "$DNS_CLUSTER" ]; then + echo -n " (cluster)" + fi + echo + fi + if [ -n "$CRON_SYSTEM" ]; then + echo "CRON daemon: $CRON_SYSTEM" + fi + if [ -n "$FIREWALL_SYSTEM" ]; then + echo -n "Firewall: $FIREWALL_SYSTEM" + if [ -n "$FIREWALL_EXTENSION" ]; then + echo -n "+ $FIREWALL_EXTENSION" + fi + echo + fi + if [ -n "$BACKUP_SYSTEM" ]; then + echo "Backups: ${BACKUP_SYSTEM//,/, }" + echo "Backup Directory: $BACKUP" + fi + if [ -n "$DISK_QUOTA" ]; then + echo "Disk Quota enabled: $DISK_QUOTA" + fi + if [ -n "$LANGUAGE" ] && [ "$LANGUAGE" != 'en' ]; then + echo "System Language: $LANGUAGE" + fi + echo "Version: $VERSION" + if [ -n "$DEMO_MODE" ]; then + echo "Demo Mode: $DEMO_MODE" + fi + if [ -n "$FILE_MANAGER" ]; then + echo "File Manager enabled: $FILE_MANAGER" + fi + if [ -n "$API" ]; then + echo "API enabled: $API" + echo "API allowed IP's: $API_ALLOWED_IP" + + fi + + if [ -n "$SMTP_RELAY" ] && [ "$SMTP_RELAY" != 'false' ]; then + echo "SMTP Relay enabled: $SMTP_RELAY" + echo "SMTP Relay Server: $SMTP_RELAY_HOST" + echo "SMTP Relay Port: $SMTP_RELAY_PORT" + echo "SMTP Relay User: $SMTP_RELAY_USER" + fi + + echo "SMTP Server Account enabled: $USE_SERVER_SMTP" + + if [ -n "$USE_SERVER_SMTP" ] && [ "$USE_SERVER_SMTP" != 'false' ]; then + echo "SMTP Server Account Host: $SERVER_SMTP_HOST" + echo "SMTP Server Account Port: $SERVER_SMTP_PORT" + echo "SMTP Server Account Security: $SERVER_SMTP_SECURITY" + echo "SMTP Server Account Username: $SERVER_SMTP_USER" + echo "SMTP Server Account Password: $SERVER_SMTP_PASSWD" + echo "SMTP Server Account Address: $SERVER_SMTP_ADDR" + fi + + echo "Release Branch: $RELEASE_BRANCH" + echo "Debug Mode: $DEBUG_MODE" + echo "Theme: $THEME" + echo "Restricted Admin Access: $POLICY_SYSTEM_PROTECTED_ADMIN" + echo "Hide System Administator: $POLICY_SYSTEM_HIDE_ADMIN" + echo "Updates: Notify by email: $UPGRADE_SEND_EMAIL" + echo "Updates: Email install log: $UPGRADE_SEND_EMAIL_LOG" +} + +# PLAIN list function +plain_list() { + echo -ne "$WEB_SYSTEM\t$WEB_RGROUPS\t$WEB_PORT\t$WEB_SSL\t" + echo -ne "$WEB_SSL_PORT\t$WEB_BACKEND\t$PROXY_SYSTEM\t$PROXY_PORT\t" + echo -ne "$PROXY_SSL_PORT\t$FTP_SYSTEM\t$MAIL_SYSTEM\t$IMAP_SYSTEM\t" + echo -ne "$ANTIVIRUS_SYSTEM\t$ANTISPAM_SYSTEM\t$DB_SYSTEM\t" + echo -ne "$DNS_SYSTEM\t$DNS_CLUSTER\t$STATS_SYSTEM\t$BACKUP_SYSTEM\t" + echo -ne "$CRON_SYSTEM\t$DISK_QUOTA\t$FIREWALL_SYSTEM\t$FIREWALL_EXTENSION\t" + echo -ne "$FILE_MANAGER\t$REPOSITORY\t$VERSION\t$DEMO_MODE\t$RELEASE_BRANCH\t" + echo -ne "$SMTP_RELAY_HOST\t$SMTP_RELAY_PORT\t$SMTP_RELAY_USER\t" + echo -ne "$UPGRADE_SEND_EMAIL\t$UPGRADE_SEND_EMAIL_LOG\t$THEME\t$LANGUAGE\t$BACKUP_GZIP\t" + echo -ne "$BACKUP\t$WEBMAIL_ALIAS\t$DB_PMA_URL\t$DB_PGA_URL\t\t$DEBUG_MODE\t$API\t$API_ALLOWED_IP" + echo -e "$POLICY_SYSTEM_PROTECTED_ADMIN\t$POLICY_SYSTEM_HIDE_ADMIN" +} + +# CSV list +csv_list() { + echo -n "'WEB_SYSTEM','WEB_RGROUPS','WEB_PORT','WEB_SSL'," + echo -n "'WEB_SSL_PORT','WEB_BACKEND','PROXY_SYSTEM','PROXY_PORT'," + echo -n "'PROXY_SSL_PORT','FTP_SYSTEM','MAIL_SYSTEM','IMAP_SYSTEM'," + echo -n "'ANTIVIRUS_SYSTEM','ANTISPAM_SYSTEM','DB_SYSTEM'," + echo -n "'DNS_SYSTEM','DNS_CLUSTER','STATS_SYSTEM','BACKUP_SYSTEM'," + echo -n "'CRON_SYSTEM','DISK_QUOTA','FIREWALL_SYSTEM'," + echo -n "'FIREWALL_EXTENSION','FILE_MANAGER','REPOSITORY'," + echo -n "'VERSION','DEMO_MODE','RELEASE_BRANCH'," + echo -n "'SMTP_RELAY','SMTP_RELAY_HOST','SMTP_RELAY_PORT','SMTP_RELAY_USER'," + echo -n "'UPGRADE_SEND_EMAIL','UPGRADE_SEND_EMAIL_LOG'," + echo -n "'THEME', 'LANGUAGE','BACKUP_GZIP','BACKUP','WEBMAIL_ALIAS'," + echo -n "'DB_PMA_ALIAS','DB_PGA_ALIAS','DEBUG_MODE','API','API_ALLOWED_IP'," + echo -n "'POLICY_SYSTEM_PROTECTED_ADMIN',POLICY_SYSTEM_HIDE_ADMIN'" + echo + echo -n "'$WEB_SYSTEM','$WEB_RGROUPS','$WEB_PORT','$WEB_SSL'," + echo -n "'$WEB_SSL_PORT','$WEB_BACKEND','$PROXY_SYSTEM','$PROXY_PORT'," + echo -n "'$PROXY_SSL_PORT','$FTP_SYSTEM','$MAIL_SYSTEM','$IMAP_SYSTEM'," + echo -n "'$ANTIVIRUS_SYSTEM','$ANTISPAM_SYSTEM','$DB_SYSTEM','$DNS_SYSTEM'," + echo -n "'$DNS_CLUSTER','$STATS_SYSTEM','$BACKUP_SYSTEM','$CRON_SYSTEM'," + echo -n "'$DISK_QUOTA','$FIREWALL_SYSTEM','$FIREWALL_EXTENSION','$FILE_MANAGER'," + echo -n "'$REPOSITORY', '$VERSION','$DEMO_MODE','$RELEASE_BRANCH'," + echo -n "'$SMTP_RELAY','$SMTP_RELAY_HOST','$SMTP_RELAY_PORT','$SMTP_RELAY_USER'," + echo -n "'$UPGRADE_SEND_EMAIL','$UPGRADE_SEND_EMAIL_LOG','$THEME','$LANGUAGE'," + echo -n "'$BACKUP_GZIP','$BACKUP','$WEBMAIL_ALIAS','$DB_PMA_URL','$DB_PGA_URL'" + echo -n "'$DEBUG_MODE','$API','$API_ALLOWED_IP','$POLICY_SYSTEM_PROTECTED_ADMIN,$POLICY_SYSTEM_HIDE_ADMIN" + echo +} + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +if [ -n "$DNS_SYSTEM" ]; then + version=$(named -v | awk 'NR==1{print $2}') + if version_ge '9.16.18' $version; then + SUPPORT_DNSSEC="no" + else + SUPPORT_DNSSEC="yes" + fi +fi + +# Listing data +case $format in + json) json_list ;; + plain) shell_list ;; + csv) csv_list ;; + shell) shell_list ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-sys-cpu-status b/bin/v-list-sys-cpu-status new file mode 100755 index 0000000..bf3ab3c --- /dev/null +++ b/bin/v-list-sys-cpu-status @@ -0,0 +1,32 @@ +#!/bin/bash +# info: list system cpu info +# options: +# +# example: v-list-sys-cpu-status +# +# This function lists cpu information + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Displaying top 30 +top -b -n1 | head -n 37 +echo -en "\n---------------------------------------------" +echo -en "---------------------------------------------\n\n" + +# Displaying process tree +pstree -s +echo -en "\n---------------------------------------------" +echo -en "---------------------------------------------\n\n" + +# Displaying CPU information +grep 'model name' /proc/cpuinfo | cut -f 2 -d : | sed "s/ //" +echo +lscpu 2> /dev/null + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-sys-db-status b/bin/v-list-sys-db-status new file mode 100755 index 0000000..72cb81d --- /dev/null +++ b/bin/v-list-sys-db-status @@ -0,0 +1,87 @@ +#!/bin/bash +# info: list db status +# options: +# +# v-list-sys-db-status +# +# This function lists db server status + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +#format=${1-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Checking db system +if [ -z "$DB_SYSTEM" ]; then + exit +fi + +# Checking supported database systems +for db in $(echo $DB_SYSTEM | tr ',' '\n'); do + OLD_IFS="$IFS" + IFS=$'\n' + + # Checking database config + if [ -e "$HESTIA/conf/$db.conf" ]; then + + # Checking server status + for host_str in $(cat $HESTIA/conf/$db.conf); do + parse_object_kv_list "$host_str" + + # Checking MySQL + if [ "$db" = 'mysql' ]; then + mycnf="$HESTIA/conf/.mysql.$HOST" + if [ ! -e "$mycnf" ]; then + echo "[client]" > $mycnf + echo "host='$HOST'" >> $mycnf + echo "user='$USER'" >> $mycnf + echo "password='$PASSWORD'" >> $mycnf + chmod 600 $mycnf + else + mypw=$(grep password $mycnf | cut -f 2 -d \') + if [ "$mypw" != "$PASSWORD" ]; then + echo "[client]" > $mycnf + echo "host='$HOST'" >> $mycnf + echo "user='$USER'" >> $mycnf + echo "password='$PASSWORD'" >> $mycnf + chmod 660 $mycnf + fi + fi + echo "MySQL $HOST status" + mysqladmin --defaults-file=$mycnf status | sed -e "s/ /\n/g" + echo + mysqladmin --defaults-file=$mycnf processlist + echo -en "\n---------------------------------------------" + echo -en "---------------------------------------------\n\n" + fi + + # Checking PostgreSQL + if [ "$db" = 'pgsql' ] && [ ! -z "$(which psql)" ]; then + echo "PostgreSQL $HOST status" + export PGPASSWORD="$PASSWORD" + psql -h $HOST -U $USER -c "SELECT * FROM pg_stat_activity" + fi + done + fi + IFS="$OLD_IFS" +done + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-sys-disk-status b/bin/v-list-sys-disk-status new file mode 100755 index 0000000..b5080bf --- /dev/null +++ b/bin/v-list-sys-disk-status @@ -0,0 +1,35 @@ +#!/bin/bash +# info: list disk information +# options: +# +# example: v-list-sys-disk-status +# +# This function lists disk information + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Displaying disk usage +df -h +echo -en "\n---------------------------------------------" +echo -en "---------------------------------------------\n\n" + +# Displaying inodes usage +df -ih +echo -en "\n---------------------------------------------" +echo -en "---------------------------------------------\n\n" + +# Displaying I/O usage +iostat -m +echo -en "\n---------------------------------------------" +echo -en "---------------------------------------------\n\n" + +# Displaying disk information +fdisk -l + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-sys-dns-status b/bin/v-list-sys-dns-status new file mode 100755 index 0000000..3966d9d --- /dev/null +++ b/bin/v-list-sys-dns-status @@ -0,0 +1,80 @@ +#!/bin/bash +# info: list dns status +# options: +# +# example: v-list-sys-dns-status +# +# This function lists dns server status + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +#format=${1-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Checking dns system +if [ -z "$DNS_SYSTEM" ]; then + exit +fi + +# Checking statistics-file on RHEL/CentOS +if [ -e "/etc/named/named.conf" ]; then + conf="/etc/named/named.conf" + dump_file='/var/named/data/named_stats.txt' + dump_option=" dump-file \"$dump_file\";" + opt_check=$(grep $dump_file $conf | grep -v //) + if [ -z "$opt_check" ]; then + sed -i "s|options {|options {\n$dump_option|" $conf + service named restart > /dev/null 2>&1 + fi +fi +if [ -e "/etc/named.conf" ]; then + conf="/etc/named.conf" + dump_file='/var/named/data/named_stats.txt' + dump_option=" dump-file \"$dump_file\";" + opt_check=$(grep $dump_file $conf | grep -v //) + if [ -z "$opt_check" ]; then + sed -i "s|options {|options {\n$dump_option|" $conf + service named restart > /dev/null 2>&1 + fi +fi + +# Checking statistics-file on Debian/Ubuntu +if [ -e "/etc/bind/named.conf" ]; then + conf="/etc/bind/named.conf.options" + dump_file='/var/cache/bind/named.stats' + #dump_option=" dump-file \"$dump_file\";" + #opt_check=$(grep $dump_file $conf |grep -v //) + #if [ -z "$opt_check" ]; then + # sed -i "s|options {|options {\n$dump_option|" $conf + # service named restart >/dev/null 2>&1 + #fi +fi + +# Generating dns stats +rm -f $dump_file 2> /dev/null +/usr/sbin/rndc stats 2> /dev/null + +# Displaying dns status +if [ -e "$dump_file" ]; then + cat $dump_file +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-sys-dovecot-config b/bin/v-list-sys-dovecot-config new file mode 100755 index 0000000..f2ab259 --- /dev/null +++ b/bin/v-list-sys-dovecot-config @@ -0,0 +1,107 @@ +#!/bin/bash +# info: list dovecot config parameters +# options: [FORMAT] +# +# example: v-list-sys-dovecot-config +# +# This function for obtaining the list of dovecot config parameters. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +format=${1-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# JSON list function +json_list() { + echo '{ + "CONFIG": { + "config_path": "'$config_path'", + "config_path1": "'$config_path1'", + "config_path2": "'$config_path2'", + "config_path3": "'$config_path3'", + "config_path4": "'$config_path4'", + "config_path5": "'$config_path5'", + "config_path6": "'$config_path6'", + "config_path7": "'$config_path7'", + "config_path8": "'$config_path8'" + } +}' +} + +# SHELL list function +shell_list() { + echo "config_path: $config_path" + echo "config_path1: $config_path1" + echo "config_path2: $config_path2" + echo "config_path3: $config_path3" + echo "config_path4: $config_path4" + echo "config_path5: $config_path5" + echo "config_path6: $config_path6" + echo "config_path7: $config_path7" + echo "config_path8: $config_path8" +} + +# PLAIN list function +plain_list() { + echo -en "$config_path\t" + echo -en "$config_path1\t" + echo -en "$config_path2\t" + echo -en "$config_path3\t" + echo -en "$config_path4\t" + echo -en "$config_path5\t" + echo -en "$config_path6\t" + echo -en "$config_path7\t" + echo -e "$config_path8\t" +} + +# CSV list function +csv_list() { + echo -n "config_path,config_path1,config_path2,config_path3," + echo "config_path4,config_path5,config_path6,config_path7,config_path8" + echo -n "$config_path,$config_path1,$config_path2,$config_path3," + echo -n "$config_path4,$config_path5,$config_path6,$config_path7," + echo "$config_path8" +} + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Defining config path +if [ -e '/etc/dovecot.conf' ]; then + config_path='/etc/dovecot.conf' +else + config_path='/etc/dovecot/dovecot.conf' + config_path1='/etc/dovecot/conf.d/10-auth.conf' + config_path2='/etc/dovecot/conf.d/10-logging.conf' + config_path3='/etc/dovecot/conf.d/10-mail.conf' + config_path4='/etc/dovecot/conf.d/10-master.conf' + config_path5='/etc/dovecot/conf.d/10-ssl.conf' + config_path6='/etc/dovecot/conf.d/20-imap.conf' + config_path7='/etc/dovecot/conf.d/20-pop3.conf' + config_path8='/etc/dovecot/conf.d/auth-passwdfile.conf.ext' +fi + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-sys-hestia-autoupdate b/bin/v-list-sys-hestia-autoupdate new file mode 100755 index 0000000..c48efb2 --- /dev/null +++ b/bin/v-list-sys-hestia-autoupdate @@ -0,0 +1,84 @@ +#!/bin/bash +# info: list hestia autoupdate settings +# options: [FORMAT] +# +# example: v-list-sys-hestia-autoupdate +# +# This function for obtaining autoupdate settings. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user='admin' +format=${1-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# JSON list function +json_list() { + echo '[' + if [ -z "$check_cron" ]; then + echo -e "\t\"Disabled\"," + else + echo -e "\t\"Enabled\"" + fi + echo "]" +} + +# SHELL list function +shell_list() { + echo -n "AUTOUPDATE: " + if [ -z "$check_cron" ]; then + echo "Disabled" + else + echo "Enabled" + fi +} + +# PLAIN list function +plain_list() { + if [ -z "$check_cron" ]; then + echo "Disabled" + else + echo "Enabled" + fi +} + +# CSV list function +csv_list() { + echo "AUTOUPDATE" + if [ -z "$check_cron" ]; then + echo "Disabled" + else + echo "Enabled" + fi +} + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Check cron tab +check_cron=$(grep 'v-update-sys-hestia-all' $USER_DATA/cron.conf) + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-sys-hestia-ssl b/bin/v-list-sys-hestia-ssl new file mode 100755 index 0000000..236a961 --- /dev/null +++ b/bin/v-list-sys-hestia-ssl @@ -0,0 +1,128 @@ +#!/bin/bash +# info: list hestia ssl certificate +# options: [FORMAT] +# +# example: v-list-sys-hestia-ssl +# +# This function of obtaining hestia ssl files. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +format=${1-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# JSON list function +json_list() { + echo '{' + echo -e "\t\"HESTIA\": {" + echo " \"CRT\": \"$crt\"," + echo " \"KEY\": \"$key\"," + echo " \"CA\": \"$ca\"," + echo " \"SUBJECT\": \"$subj\"," + echo " \"ALIASES\": \"$alt_dns\"," + echo " \"NOT_BEFORE\": \"$before\"," + echo " \"NOT_AFTER\": \"$after\"," + echo " \"SIGNATURE\": \"$signature\"," + echo " \"PUB_KEY\": \"$pub_key\"," + echo " \"ISSUER\": \"$issuer\"" + echo -e "\t}\n}" +} + +# SHELL list function +shell_list() { + if [ -n "$crt" ]; then + echo -e "$crt" + fi + if [ -n "$key" ]; then + echo -e "\n$key" + fi + if [ -n "$crt" ]; then + echo + echo + echo "SUBJECT: $subj" + if [ -n "$alt_dns" ]; then + echo "ALIASES: ${alt_dns//,/ }" + fi + echo "VALID FROM: $before" + echo "VALID TIL: $after" + echo "SIGNATURE: $signature" + echo "PUB_KEY: $pub_key" + echo "ISSUER: $issuer" + fi +} + +# PLAIN list function +plain_list() { + if [ -n "$crt" ]; then + echo -e "$crt" + fi + if [ -n "$key" ]; then + echo -e "\n$key" + fi + if [ -n "$ca" ]; then + echo -e "\n$ca" + fi + if [ -n "$crt" ]; then + echo "$subj" + echo "${alt_dns//,/ }" + echo "$before" + echo "$after" + echo "$signature" + echo "$pub_key" + echo "$issuer" + fi + +} + +# CSV list function +csv_list() { + echo -n "CRT,KEY,CA,SUBJECT,ALIASES,NOT_BEFORE,NOT_AFTER,SIGNATURE," + echo "PUB_KEY,ISSUER" + echo -n "\"$crt\",\"$key\",\"$ca\",\"$subj\",\"${alt_dns//,/ }\"," + echo "\"$before\",\"$after\",\"$signature\",\"$pub_key\",\"$issuer\"" +} + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Parsing SSL certificate +crt=$(cat $HESTIA/ssl/certificate.crt | sed ':a;N;$!ba;s/\n/\\n/g') +key=$(cat $HESTIA/ssl/certificate.key | sed ':a;N;$!ba;s/\n/\\n/g') + +# Parsing SSL certificate details without CA +info=$(openssl x509 -text -in $HESTIA/ssl/certificate.crt) +subj=$(echo "$info" | grep Subject: | cut -f 2 -d =) +before=$(echo "$info" | grep Before: | sed -e "s/.*Before: //") +after=$(echo "$info" | grep "After :" | sed -e "s/.*After : //") +signature=$(echo "$info" | grep "Algorithm:" | head -n1) +signature=$(echo "$signature" | sed -e "s/.*Algorithm: //") +pub_key=$(echo "$info" | grep Public-Key: | cut -f2 -d \( | tr -d \)) +issuer=$(echo "$info" | grep Issuer: | sed -e "s/.*Issuer: //") +alt_dns=$(echo "$info" | grep DNS | sed -e 's/DNS:/\n/g' | tr -d ',') +alt_dns=$(echo "$alt_dns" | tr -d ' ' | sed -e "/^$/d") +alt_dns=$(echo "$alt_dns" | sed -e ':a;N;$!ba;s/\n/,/g') + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-sys-hestia-updates b/bin/v-list-sys-hestia-updates new file mode 100755 index 0000000..a138299 --- /dev/null +++ b/bin/v-list-sys-hestia-updates @@ -0,0 +1,156 @@ +#!/bin/bash +# info: list system updates +# options: [FORMAT] +# +# example: v-list-sys-hestia-updates +# +# This function checks available updates for hestia packages. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +format=${1-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +fields="\$NAME \$VERSION \$ARCH \$UPDATED \$DESCR \$TIME \$DATE" + +# Check details of installed .deb package function +check_installed_deb() { + dpkg_data=$(dpkg-query -s $1) + pkg_date=$(stat -c "%Y" /var/lib/dpkg/info/$1.list) + ARCH=$(echo "$dpkg_data" | grep Architecture | cut -f 2 -d ' ') + VERSION=$(echo "$dpkg_data" | grep ^Version | cut -f 2 -d ' ') + DATE=$(date -d @$pkg_date +"%F") + TIME=$(date -d @$pkg_date +"%T") +} + +# Check details of installed .rpm package function +check_installed_rpm() { + rpm_data=$(rpm -qi $1) + ARCH=$(echo "$rpm_data" | grep Architecture | cut -f 2 -d ' ') + VERSION=$(echo "$rpm_data" | grep Version | cut -f 2 -d ':' | xargs) + DATE=$(echo "$rpm_data" | grep "Build Date" | awk '{print $5 " " $6 " " $7}') + TIME=$(echo "$rpm_data" | grep "Build Date" | awk '{print $8 " " $9 " " $10}') +} + +# JSON list function +json_list() { + IFS=$'\n' + i=1 + objects=$(echo -e "$data" | grep NAME | wc -l) + echo "{" + for str in $(echo -e "$data"); do + parse_object_kv_list "$str" + echo -n ' "'$NAME'": { + "VERSION": "'$VERSION'", + "ARCH": "'$ARCH'", + "UPDATED": "'$UPDATED'", + "DESCR": "'$DESCR'", + "TIME": "'$TIME'", + "DATE": "'$DATE'" + }' + if [ "$i" -lt "$objects" ]; then + echo ',' + else + echo + fi + ((i++)) + done + echo '}' +} + +# SHELL list function +shell_list() { + IFS=$'\n' + echo "PKG VER ARCH UPDT DATE" + echo "--- --- ---- ---- ----" + for str in $(echo -e "$data"); do + parse_object_kv_list "$str" + echo "$NAME $VERSION $ARCH $UPDATED $DATE" + done +} + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Checking official latest version +if [ -f '/etc/redhat-release' ]; then + hestia_v=$(dnf list hestia | grep hestia | awk '{print $2}' | cut -f 1 -d '-') + nginx_v=$(dnf list hestia-nginx | grep hestia-nginx | awk '{print $2}' | cut -f 1 -d '-') + php_v=$(dnf list hestia-php | grep hestia-php | awk '{print $2}' | cut -f 1 -d '-') +else + hestia_v=$(apt-cache policy hestia | grep Candidate | cut -d ':' -f 2 | xargs) + nginx_v=$(apt-cache policy hestia-nginx | grep Candidate | cut -d ':' -f 2 | xargs) + php_v=$(apt-cache policy hestia-php | grep Candidate | cut -d ':' -f 2 | xargs) +fi + +# Checking installed hestia version +if [ -f '/etc/redhat-release' ]; then + check_installed_rpm hestia +else + check_installed_deb hestia +fi + +UPDATED='yes' +if [ -n "$hesta_v" ] && [ "$hestia_v" \> "$VERSION" ]; then + UPDATED='no' +fi + +data="NAME='hestia' VERSION='$VERSION' ARCH='$ARCH'" +data="$data UPDATED='$UPDATED' DESCR='Hestia core package' TIME='$TIME' DATE='$DATE'" + +# Checking installed hestia-php version +if [ -f '/etc/redhat-release' ]; then + check_installed_rpm hestia-php +else + check_installed_deb hestia-php +fi + +UPDATED='yes' +if [ -n "$php_v" ] && [ "$php_v" \> "$VERSION" ]; then + UPDATED='no' +fi + +data="$data\nNAME='hestia-php' VERSION='$VERSION'" +data="$data ARCH='$ARCH' UPDATED='$UPDATED' DESCR='Hestia internal php interpreter'" +data="$data TIME='$TIME' DATE='$DATE'" + +# Checking installed hestia-nginx version +if [ -f '/etc/redhat-release' ]; then + check_installed_rpm hestia-nginx +else + check_installed_deb hestia-nginx +fi + +UPDATED='yes' +if [ -n "$nginx_v" ] && [ "$nginx_v" \> "$VERSION" ]; then + UPDATED='no' +fi + +data="$data\nNAME='hestia-nginx' VERSION='$VERSION'" +data="$data ARCH='$ARCH' UPDATED='$UPDATED' DESCR='Hestia internal web server'" +data="$data TIME='$TIME' DATE='$DATE'" + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list | column -t ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-sys-info b/bin/v-list-sys-info new file mode 100755 index 0000000..66b462e --- /dev/null +++ b/bin/v-list-sys-info @@ -0,0 +1,116 @@ +#!/bin/bash +# info: list system os +# options: [FORMAT] +# +# example: v-list-sys-info +# +# This function checks available updates for hestia packages. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +format=${1-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Retrieve Hestia Control Panel version number +HESTIA_VERSION=$(grep VERSION $HESTIA/conf/hestia.conf | cut -d '=' -f2 | sed "s|'||g") +HESTIA_RELEASE=$(grep RELEASE_BRANCH $HESTIA/conf/hestia.conf | cut -d '=' -f2 | sed "s|'||g") + +# JSON list function +json_list() { + echo '{' + echo ' "sysinfo": { + "HOSTNAME": "'$HOSTNAME'", + "OS": "'$OS'", + "VERSION": "'$VERSION'", + "ARCH": "'$ARCH'", + "HESTIA": "'$HESTIA_VERSION'", + "RELEASE": "'$HESTIA_RELEASE'", + "UPTIME": "'$UPTIME'", + "LOADAVERAGE": "'$LOADAVERAGE'" + }' + echo '}' +} + +# SHELL list function +shell_list() { + echo "HOSTNAME OS VER ARCH HESTIA RELEASE UPTIME LA" + echo "-------- -- --- ---- ------ ------- ------ --" + echo "$HOSTNAME $OS $VERSION $ARCH $HESTIA_VERSION $HESTIA_RELEASE $UPTIME $LOADAVERAGE" +} + +# PLAIN list function +plain_list() { + echo -e "$HOSTNAME\t$OS\t$VERSION\t$ARCH\t$HESTIA_VERSION\t$HESTIA_RELEASE\t$UPTIME\t$LOADAVERAGE" +} + +# CSV list function +csv_list() { + echo "HOSTNAME,OS,VERSION,ARCH,HESTIA,RELEASE,UPTIME,LOADAVERAGE" + echo "$HOSTNAME,$OS,$VERSION,$ARCH,$HESTIA_VERSION,$HESTIA_RELEASE,$UPTIME,$LOADAVERAGE" +} + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Check hostname +HOSTNAME=$(hostname) + +# Check OS/Release +if [ -d '/etc/sysconfig' ]; then + if [ -e '/etc/redhat-release' ]; then + OS='CentOS' + VERSION=$(cat /etc/redhat-release | tr ' ' '\n' | grep [0-9]) + else + OS="Amazon" + VERSION=$(cat /etc/issue | tr ' ' '\n' | grep [0-9]) + fi +else + if [ "$(lsb_release -si)" == "Ubuntu" ] && [ -e '/etc/debian_version' ]; then + OS="Ubuntu" + VERSION=$(grep DISTRIB_RELEASE /etc/lsb-release | cut -f 2 -d '=') + else + distro=$(head -n1 /etc/issue | cut -f 1 -d ' ') + if [ "$distro" = 'Debian' ]; then + OS="Debian" + VERSION=$(cat /etc/debian_version) + else + OS='UNKNOWN' + VERSION='UNKNOWN' + fi + fi +fi + +# Check architecture +ARCH=$(arch) + +# Check uptime +UPTIME=$(cat /proc/uptime | cut -f 1 -d ' ' | cut -f 1 -d .) +UPTIME="$(echo $UPTIME / 60 | bc)" + +# Check LoadAverage +LOADAVERAGE=$(cat /proc/loadavg | cut -f 1-3 -d ' ' | sed 's/ / \/ /g') + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list | column -t ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-sys-interfaces b/bin/v-list-sys-interfaces new file mode 100755 index 0000000..3ca5bde --- /dev/null +++ b/bin/v-list-sys-interfaces @@ -0,0 +1,88 @@ +#!/bin/bash +# info: list system interfaces +# options: [FORMAT] +# +# example: v-list-sys-interfaces +# +# This function for obtaining the list of network interfaces. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +format="${1-shell}" + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# JSON list function +json_list() { + objects=$(echo "$physical_nics" | wc -l) + i=1 + echo '[' + for interface in $physical_nics; do + echo -n ' "'$interface'"' + if [ "$i" -lt "$objects" ]; then + echo ',' + else + echo + fi + ((i++)) + done + echo ']' +} + +# SHELL list function +shell_list() { + echo "INTERFACE" + echo "---------" + for interface in $physical_nics; do + echo "$interface" + done +} + +# PLAIN list function +plain_list() { + for interface in $physical_nics; do + echo "$interface" + done +} + +# CSV list function +csv_list() { + echo "INTERFACE" + for interface in $physical_nics; do + echo "$interface" + done +} + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Defining interface list +# Detect "physical" NICs only (virtual NICs created by Docker, WireGuard etc. are excluded) +physical_nics="$(ip -d -j link show | jq -r '.[] | if .link_type == "loopback" // .linkinfo.info_kind then empty else .ifname end')" +if [ -z "$physical_nics" ]; then + physical_nics="$(ip -d -j link show | jq -r '.[] | if .link_type == "loopback" then empty else .ifname end')" +fi + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-sys-ip b/bin/v-list-sys-ip new file mode 100755 index 0000000..2ca8c3c --- /dev/null +++ b/bin/v-list-sys-ip @@ -0,0 +1,103 @@ +#!/bin/bash +# info: list system IP +# options: IP [FORMAT] +# +# example: v-list-sys-ip 203.0.113.1 +# +# This function for getting the list of system IP parameters. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +ip="$1" +format="${2-shell}" + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/ip.sh +source $HESTIA/func/ip.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# JSON list function +json_list() { + echo '{' + echo ' "'$ip'": { + "OWNER": "'$OWNER'", + "STATUS": "'$STATUS'", + "NAME": "'$NAME'", + "U_SYS_USERS": "'$U_SYS_USERS'", + "U_WEB_DOMAINS": "'$U_WEB_DOMAINS'", + "INTERFACE": "'$INTERFACE'", + "NETMASK": "'$NETMASK'", + "NAT": "'$NAT'", + "TIME": "'$TIME'", + "DATE": "'$DATE'" + }' + echo '}' +} + +# SHELL list function +shell_list() { + echo "IP: $ip" + echo "NETMASK: $NETMASK" + echo "INTERFACE: $INTERFACE" + echo "NAT: $NAT" + echo "OWNER: $OWNER" + echo "STATUS: $STATUS" + echo "NAME: $NAME" + echo "USERS: $U_SYS_USERS" + echo "DOMAINS: $U_WEB_DOMAINS" + echo "TIME: $TIME" + echo "DATE: $DATE" +} + +# PLAIN list function +plain_list() { + echo -ne "$ip\t$OWNER\t$STATUS\t$NAME\t$U_SYS_USERS\t$U_WEB_DOMAINS\t" + echo -e "$INTERFACE\t$NETMASK\t$NAT\t$TIME\t$DATE" +} + +# CSV list function +csv_list() { + echo -n "IP,OWNER,STATUS,NAME,U_SYS_USERS,U_WEB_DOMAINS,INTERFACE" + echo "NETMASK,NAT,TIME,DATE" + echo -n "$ip,$OWNER,$STATUS,$NAME,\"$U_SYS_USERS\",$U_WEB_DOMAINS," + echo "$INTERFACE, $NETMASK,$NAT,$TIME,$DATE" +} + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'IP [FORMAT]' +is_format_valid 'ip' +if [ ! -e "$HESTIA/data/ips/$ip" ]; then + check_result $E_NOTEXIST "IP $ip doesn't exist" +fi + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Parsing IP +source_conf "$HESTIA/data/ips/$ip" + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-sys-ips b/bin/v-list-sys-ips new file mode 100755 index 0000000..a024907 --- /dev/null +++ b/bin/v-list-sys-ips @@ -0,0 +1,104 @@ +#!/bin/bash +# info: list system IPs +# options: [FORMAT] +# +# example: v-list-sys-ips +# +# This function for obtaining the list of system IP addresses. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +format="${1-shell}" + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/ip.sh +source $HESTIA/func/ip.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# JSON list function +json_list() { + echo '{' + ip_count="$(ls $HESTIA/data/ips/ | wc -l)" + i=1 + while read IP; do + source_conf "$HESTIA/data/ips/$IP" + echo -n ' "'$IP'": { + "OWNER": "'$OWNER'", + "STATUS": "'$STATUS'", + "NAME": "'$NAME'", + "U_SYS_USERS": "'$U_SYS_USERS'", + "U_WEB_DOMAINS": "'$U_WEB_DOMAINS'", + "INTERFACE": "'$INTERFACE'", + "NETMASK": "'$NETMASK'", + "NAT": "'$NAT'", + "TIME": "'$TIME'", + "DATE": "'$DATE'" + }' + if [ "$i" -lt "$ip_count" ]; then + echo ',' + else + echo + fi + ((i++)) + done < <(ls $HESTIA/data/ips/) + echo '}' +} + +# SHELL list function +shell_list() { + echo "IP MASK NAT STATUS WEB DATE" + echo "-- ---- --- ------ --- ----" + while read IP; do + source_conf "$HESTIA/data/ips/$IP" + if [ -z "$NAT" ]; then + NAT='no' + fi + echo "$IP $NETMASK $NAT $STATUS $U_WEB_DOMAINS $DATE" + done < <(ls $HESTIA/data/ips/) +} + +# PLAIN list function +plain_list() { + while read IP; do + source_conf "$HESTIA/data/ips/$IP" + echo -ne "$IP\t$OWNER\t$STATUS\t$NAME\t$U_SYS_USERS\t$U_WEB_DOMAINS\t" + echo -e "$INTERFACE\t$NETMASK\t$NAT\t$TIME\t$DATE" + done < <(ls $HESTIA/data/ips/) +} + +# CSV list function +csv_list() { + echo -n "IP,OWNER,STATUS,NAME,U_SYS_USERS,U_WEB_DOMAINS,INTERFACE" + echo "NETMASK,NAT,TIME,DATE" + while read IP; do + source_conf "$HESTIA/data/ips/$IP" + echo -n "$IP,$OWNER,$STATUS,$NAME,\"$U_SYS_USERS\",$U_WEB_DOMAINS," + echo "$INTERFACE, $NETMASK,$NAT,$TIME,$DATE" + done < <(ls $HESTIA/data/ips/) +} + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list | column -t ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-sys-languages b/bin/v-list-sys-languages new file mode 100755 index 0000000..1921dd1 --- /dev/null +++ b/bin/v-list-sys-languages @@ -0,0 +1,88 @@ +#!/bin/bash +# info: list system languages +# options: [FORMAT] +# +# example: v-list-sys-languages json +# +# This function for obtaining the available languages for HestiaCP +# Output is always in the ISO language code + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +format=${1-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# JSON list function +json_list() { + objects=$(echo "$languages" | wc -l) + i=1 + echo '[' + echo -e "\t\"en\"," + for lang in $languages; do + if [ "$i" -lt "$objects" ]; then + echo -e "\t\"$lang\"," + else + echo -e "\t\"$lang\"" + fi + ((++i)) + done + echo ']' +} + +# SHELL list function +shell_list() { + echo "LANGUAGE" + echo "--------" + echo "en" + for lang in $languages; do + echo "$lang" + done +} + +# PLAIN list function +plain_list() { + echo "en" + for lang in $languages; do + echo "$lang" + done +} + +# CSV list function +csv_list() { + echo "LANGUAGE" + echo "en" + for lang in $languages; do + echo "$lang" + done +} + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Defining language list +languages=$(ls -d $HESTIA/web/locale/*/ | awk -F'/' '{print $(NF-1)}') + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-sys-mail-status b/bin/v-list-sys-mail-status new file mode 100755 index 0000000..c441850 --- /dev/null +++ b/bin/v-list-sys-mail-status @@ -0,0 +1,57 @@ +#!/bin/bash +# info: list mail status +# options: +# +# example: v-list-sys-mail-status +# +# This function lists mail server status + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +#format=${1-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/conf/hestia.conf +source $HESTIA/conf/hestia.conf +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Checking mail system +if [ -z "$MAIL_SYSTEM" ]; then + exit +fi + +# Displaying exim queue status +echo "Exim queue status" +exim -bp +echo -en "\n---------------------------------------------" +echo -en "---------------------------------------------\n\n" + +# Displaying exim stats +if [ -e "/var/log/exim4/mainlog" ]; then + eximstats /var/log/exim4/mainlog 2> /dev/null +else + eximstats /var/log/exim/main.log 2> /dev/null +fi + +if [ $? -ne 0 ]; then + echo "[Exim4] No valid log lines read" + exit 0 +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit 0 diff --git a/bin/v-list-sys-memory-status b/bin/v-list-sys-memory-status new file mode 100755 index 0000000..fd26ead --- /dev/null +++ b/bin/v-list-sys-memory-status @@ -0,0 +1,30 @@ +#!/bin/bash +# info: list virtual memory info +# options: +# +# example: v-list-sys-memory-status +# +# This function lists virtual memory information + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Displaying memory and swap usage +free -t -m +echo -en "\n---------------------------------------------" +echo -en "---------------------------------------------\n\n" + +# Displaying memory stats +vmstat -S m -s +echo -en "\n---------------------------------------------" +echo -en "---------------------------------------------\n\n" + +# Displaying ram information +dmidecode -t 17 2> /dev/null + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-sys-mysql-config b/bin/v-list-sys-mysql-config new file mode 100755 index 0000000..c5a9121 --- /dev/null +++ b/bin/v-list-sys-mysql-config @@ -0,0 +1,86 @@ +#!/bin/bash +# info: list mysql config parameters +# options: [FORMAT] +# +# example: v-list-sys-mysql-config +# +# This function for obtaining the list of mysql config parameters. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +format=${1-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# JSON list function +json_list() { + str=$(echo "$config" | egrep "$keys" \ + | sed -e "s/[ ]*=/=/" -e "s/=[ ]*/=\'/" -e "s/$/'/") + parse_object_kv_list "$str" + echo '{ + "CONFIG": { + "max_user_connections": "'$max_user_connections'", + "max_connections": "'$max_connections'", + "wait_timeout": "'$wait_timeout'", + "interactive_timeout": "'$interactive_timeout'", + "max_allowed_packet": "'$max_allowed_packet'", + "config_path": "'$config_path'" + } +}' +} + +# SHELL list function +shell_list() { + echo "$config" | egrep "$keys" | tr '=' ' ' + echo "config_path $config_path" +} + +# PLAIN list function +plain_list() { + echo "$config" | egrep "$keys" | tr '=' ' ' + echo "config_path $config_path" +} + +# CSV list function +csv_list() { + echo "$keys" | sed "s/|/,/g" + echo "$config" | egrep "$keys" | tr '=' ' ' | awk '{print $2}' | tr '\n' ',' + echo +} + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Defining config path +config_path=$(find /etc/my* -name my.cnf) + +# Defining keys +keys="max_user_connections|max_connections|wait_timeout|interactive_timeout" +keys="${keys}|max_allowed_packet" + +# Reading config +config=$(cat $config_path | grep -v "^;") + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list | column -t ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-sys-network-status b/bin/v-list-sys-network-status new file mode 100755 index 0000000..87f7ca1 --- /dev/null +++ b/bin/v-list-sys-network-status @@ -0,0 +1,30 @@ +#!/bin/bash +# info: list system network status +# options: +# +# example: v-list-sys-network-status +# +# This function lists network status + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Displaying network stats +ss -s +echo -en "\n---------------------------------------------" +echo -en "---------------------------------------------\n\n" + +# Displaying network usage +lsof -iudp -itcp -n -P +echo -en "\n---------------------------------------------" +echo -en "---------------------------------------------\n\n" + +# Displaying network interfaces +ip addr list + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-sys-nginx-config b/bin/v-list-sys-nginx-config new file mode 100755 index 0000000..4560dd8 --- /dev/null +++ b/bin/v-list-sys-nginx-config @@ -0,0 +1,91 @@ +#!/bin/bash +# info: list nginx config parameters +# options: [FORMAT] +# +# example: v-list-sys-nginx-config +# +# This function for obtaining the list of nginx config parameters. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +format=${1-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# JSON list function +json_list() { + parse_object_kv_list $(echo "$config" | egrep "$keys" | tr -d ';' | awk '{print $1"="$2}') + echo '{ + "CONFIG": { + "worker_processes": "'$worker_processes'", + "worker_connections": "'$worker_connections'", + "send_timeout": "'$send_timeout'", + "proxy_connect_timeout": "'$proxy_connect_timeout'", + "proxy_send_timeout": "'$proxy_send_timeout'", + "proxy_read_timeout": "'$proxy_read_timeout'", + "client_max_body_size": "'$client_max_body_size'", + "gzip": "'$gzip'", + "gzip_comp_level": "'$gzip_comp_level'", + "charset": "'$charset'", + "config_path": "'$config_path'" + } +}' +} + +# SHELL list function +shell_list() { + echo "$config" | egrep "$keys" | tr -d ';' + echo "config_path $config_path" +} + +# PLAIN list function +plain_list() { + echo "$config" | egrep "$keys" | tr -d ';' + echo "config_path $config_path" +} + +# CSV list function +csv_list() { + echo "$keys" | sed "s/ |/,/g" + echo "$config" | egrep "$keys" | awk '{print $2}' | tr -d ';' | tr '\n' ',' + echo +} + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Defining config path +config_path='/etc/nginx/nginx.conf' + +# Defining keys +keys="worker_processes |worker_connections |send_timeout" +keys="$keys |proxy_connect_timeout |proxy_send_timeout" +keys="$keys |proxy_read_timeout |client_max_body_size" +keys="$keys |gzip |gzip_comp_level |charset " + +# Reading nginx config +config=$(cat $config_path) + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list | column -t ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-sys-pgsql-config b/bin/v-list-sys-pgsql-config new file mode 100755 index 0000000..3cee3f2 --- /dev/null +++ b/bin/v-list-sys-pgsql-config @@ -0,0 +1,73 @@ +#!/bin/bash +# info: list postgresql config parameters +# options: [FORMAT] +# +# example: v-list-sys-pgsql-config +# +# This function for obtaining the list of postgresql config parameters. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +format=${1-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# JSON list function +json_list() { + echo '{ + "CONFIG": { + "pg_hba_path": "'$pg_hba_path'", + "config_path": "'$config_path'" + } +}' +} + +# SHELL list function +shell_list() { + echo "config_path: $config_path" + echo "pg_hba_path: $pg_hba_path" +} + +# PLAIN list function +plain_list() { + echo -e "$config_path\t$pg_hba_path" +} + +# CSV list function +csv_list() { + echo "config_path,pg_hba_path" + echo "$config_path,$pg_hba_path" +} + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Defining config path +config_path=$(find /etc/postgresql /var/lib/pgsql/data -name \ + postgresql.conf 2> /dev/null) +pg_hba_path=$(find /etc/postgresql /var/lib/pgsql/data -name \ + pg_hba.conf 2> /dev/null) + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-sys-php b/bin/v-list-sys-php new file mode 100755 index 0000000..5f1ecab --- /dev/null +++ b/bin/v-list-sys-php @@ -0,0 +1,94 @@ +#!/bin/bash +# info: listing available PHP versions installed +# options: [FORMAT] +# +# example: v-list-sys-php +# +# List /etc/php/* version check if folder fpm is available + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +format=${1-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# JSON list function +json_list() { + i=1 + objects=$(echo "${versions[@]}" | wc -w) + echo '[' + for version in "${versions[@]}"; do + if [ "$i" -lt "$objects" ]; then + echo -e "\t\"$version\"," + else + echo -e "\t\"$version\"" + fi + ((++i)) + done + echo "]" +} + +# SHELL list function +shell_list() { + echo "VERSION" + echo "--------" + for version in "${versions[@]}"; do + echo "$version" + done +} + +# PLAIN list function +plain_list() { + for version in "${versions[@]}"; do + echo "$version" + done +} + +# CSV list function +csv_list() { + echo "VERSION" + for version in "${versions[@]}"; do + echo "$version" + done +} + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +declare -a versions +# List through /etc/php +if [ -n "$WEB_BACKEND" ]; then + for version in /etc/php/*/fpm; do + ver=$(echo "$version" | awk -F"/" '{ print $4 }') + versions+=("$ver") + done +else + # Fix for modphp + for version in /etc/php/*/cli; do + ver=$(echo "$version" | awk -F"/" '{ print $4 }') + versions+=("$ver") + done +fi +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-sys-php-config b/bin/v-list-sys-php-config new file mode 100755 index 0000000..b78e774 --- /dev/null +++ b/bin/v-list-sys-php-config @@ -0,0 +1,97 @@ +#!/bin/bash +# info: list php config parameters +# options: [FORMAT] +# +# example: v-list-sys-php-config +# +# This function for obtaining the list of php config parameters. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +format=${1-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# JSON list function +json_list() { + parse_object_kv_list $(echo "$config" | egrep "$keys" \ + | sed -e "s/[ ]*=/=/" -e "s/=[ ]*/=\'/" -e "s/$/'/") + echo '{ + "CONFIG": { + "memory_limit": "'$memory_limit'", + "max_execution_time": "'$max_execution_time'", + "max_input_time": "'$max_input_time'", + "upload_max_filesize": "'$upload_max_filesize'", + "post_max_size": "'$post_max_size'", + "display_errors": "'$display_errors'", + "error_reporting": "'$error_reporting'", + "config_path": "'$config_path'" + } +}' +} + +# SHELL list function +shell_list() { + echo "$config" | egrep "$keys" | tr -d '=' + echo "config_path $config_path" +} + +# PLAIN list function +plain_list() { + echo "$config" | egrep "$keys" | tr -d '=' + echo "config_path $config_path" +} + +# CSV list function +csv_list() { + echo "$keys" | sed "s/ |/,/g" + echo "$config" | egrep "$keys" | tr -d '=' | awk '{print $2}' | tr '\n' ',' + echo +} + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Defining config path +config_path=$(find /etc/php* -name php.ini) +config_count=$(echo "$config_path" | wc -l) +if [ "$config_count" -gt 1 ]; then + multiphp_versions=$(ls -d /etc/php/*/fpm/pool.d 2> /dev/null | wc -l) + if [ "$WEB_BACKEND" = 'php-fpm' ] || [ "$multiphp_versions" -gt 0 ]; then + config_path=$(echo "$config_path" | grep fpm) + else + config_path=$(echo "$config_path" | grep apache) + fi +fi + +# Defining keys +keys="memory_limit |max_execution_time |max_input_time" +keys="$keys |upload_max_filesize |post_max_size" +keys="$keys |display_errors |error_reporting " + +# Reading config +config=$(cat $config_path | grep -v "^;") + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list | column -t ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-sys-proftpd-config b/bin/v-list-sys-proftpd-config new file mode 100755 index 0000000..0af3782 --- /dev/null +++ b/bin/v-list-sys-proftpd-config @@ -0,0 +1,68 @@ +#!/bin/bash +# info: list proftpd config parameters +# options: [FORMAT] +# +# example: v-list-sys-proftpd-config +# +# This function for obtaining the list of proftpd config parameters. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +format=${1-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# JSON list function +json_list() { + echo '{ + "CONFIG": { + "config_path": "'$config_path'" + } +}' +} + +# SHELL list function +shell_list() { + echo "config_path: $config_path" +} + +# PLAIN list function +plain_list() { + echo "$config_path" +} + +# CSV list function +csv_list() { + echo "config_path" + echo "$config_path" +} + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Defining config path +config_path=$(find /etc/proftpd* -name proftpd.conf 2> /dev/null) + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-sys-rrd b/bin/v-list-sys-rrd new file mode 100755 index 0000000..874691d --- /dev/null +++ b/bin/v-list-sys-rrd @@ -0,0 +1,163 @@ +#!/bin/bash +# info: list system rrd charts +# options: [FORMAT] +# +# example: v-list-sys-rrd +# +# List available rrd graphics, its titles and paths. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +format=${1-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# JSON list function +json_list() { + i=1 + echo "{" + + # Generating timestamp + new_timestamp + + for type in $rrd_types; do + for rrd in $(ls $RRD/$type | grep rrd$ | sed "s/\.rrd$//g"); do + if [ "$i" -ne 1 ]; then + echo -e "\t}," + fi + if [ "$type" = 'la' ]; then + title="Load Average" + fi + if [ "$type" = 'mem' ]; then + title="Memory Usage" + fi + if [ "$type" = 'net' ]; then + title="Bandwidth Usage $rrd" + fi + if [ "$type" = 'web' ] || [ "$type" = 'ftp' ] \ + || [ "$type" = 'ssh' ]; then + title="$(echo $rrd | tr '[:lower:]' '[:upper:]') Usage" + fi + if [ "$type" = 'mail' ]; then + title="Exim Usage" + fi + if [ "$type" = 'db' ]; then + db_type=$(echo $rrd | cut -f 1 -d _ | sed -e 's/mysql/MySQL/g' \ + -e 's/pgsql/PostgreSQL/g') + db_host=$(echo $rrd | cut -f 2 -d _) + title="$db_type Usage on $db_host" + fi + echo -e "\t\"$i\": {" + echo -e "\t\t\"TYPE\": \"$type\"", + echo -e "\t\t\"RRD\": \"$rrd\"", + echo -e "\t\t\"TITLE\": \"$title\"," + echo -e "\t\t\"TIME\": \"$TIME\"," + echo -e "\t\t\"DATE\": \"$DATE\"" + ((++i)) + done + done + if [ "$i" -gt 1 ]; then + echo -e "\t}" + fi + echo "}" +} + +# SHELL list function +shell_list() { + echo "TYPE VAL_1 VAL_2 VAL_3 TIME DATE" + echo "---- ----- ----- ----- ---- ----" + for type in $rrd_types; do + for rrd in $(ls $RRD/$type | grep rrd$ | sed "s/\.rrd$//g"); do + rrd_type=$(echo "$rrd" | tr '[:lower:]' '[:upper:]') + rrd_data=$(rrdtool fetch "$RRD/$type/$rrd.rrd" AVERAGE -e 0 -s 0) + rrd_data=$(echo "$rrd_data" | tail -n 1) + rrd_timestamp=$(echo "$rrd_data" | cut -f 1 -d :) + rrd_time=$(date -d "@$rrd_timestamp" +%F) + rrd_date=$(date -d "@$rrd_timestamp" +%T) + rrd_val1=$(echo "$rrd_data" | awk '{print $2}' | cut -d. -f1) + rrd_val2=$(echo "$rrd_data" | awk '{print $3}' | cut -d. -f1) + rrd_val3=$(echo "$rrd_data" | awk '{print $4}' | cut -d. -f1) + if [ -z "$rrd_val1" ]; then + rrd_val1="-nan" + fi + if [ -z "$rrd_val2" ]; then + rrd_val2="-nan" + fi + if [ -z "$rrd_val3" ]; then + rrd_val3="-nan" + fi + echo "$rrd_type $rrd_val1 $rrd_val2 $rrd_val3 $rrd_time $rrd_date" + done + done +} + +# PLAIN list function +plain_list() { + for type in $rrd_types; do + for rrd in $(ls $RRD/$type | grep rrd$ | sed "s/\.rrd$//g"); do + echo "$RRD/$type/$rrd.rrd" + done + done +} + +# CSV list function +csv_list() { + for type in $rrd_types; do + echo "RRD" + for rrd in $(ls $RRD/$type | grep rrd$ | sed "s/\.rrd$//g"); do + echo "$RRD/$type/$rrd.rrd" + done + done +} + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Definng rrd charts +rrd_types="la mem net" + +# Checking web system +if [ -n "$WEB_SYSTEM" ]; then + rrd_types="$rrd_types web" +fi + +# Checking mail system +if [ -n "$MAIL_SYSTEM" ]; then + rrd_types="$rrd_types mail" +fi + +# Checking db system +if [ -n "$DB_SYSTEM" ]; then + rrd_types="$rrd_types db" +fi + +# Checking ftp system +if [ -n "$FTP_SYSTEM" ]; then + rrd_types="$rrd_types ftp" +fi + +# Adding ssh +rrd_types="$rrd_types ssh" + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list | column -t ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-sys-services b/bin/v-list-sys-services new file mode 100755 index 0000000..2ee0cdb --- /dev/null +++ b/bin/v-list-sys-services @@ -0,0 +1,343 @@ +#!/bin/bash +# info: list system services +# options: [FORMAT] +# +# example: v-list-sys-services json +# +# This function for obtaining the list of configured system services. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +format=${1-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# JSON list function +json_list() { + IFS=$'\n' + i=1 + objects=$(echo -e "$data" | grep NAME | wc -l) + echo "{" + while read str; do + parse_object_kv_list "$str" + echo -n ' "'$NAME'": { + "SYSTEM": "'$SYSTEM'", + "STATE": "'$STATE'", + "CPU": "'$CPU'", + "MEM": "'$MEM'", + "RTIME": "'$RTIME'" + }' + if [ "$i" -lt "$objects" ]; then + echo ',' + else + echo + fi + ((i++)) + done < <(echo -e "$data" | grep NAME) + echo '}' +} + +# SHELL list function +shell_list() { + IFS=$'\n' + echo "NAME STATE CPU MEM UPTIME" + echo "---- ----- --- --- ------" + while read str; do + parse_object_kv_list "$str" + echo "$NAME $STATE $CPU $MEM $RTIME" + done < <(echo -e "$data" | grep NAME) +} + +# PLAIN list function +plain_list() { + IFS=$'\n' + while read str; do + parse_object_kv_list "$str" + echo -e "$NAME\t$SYSTEM\t$STATE\t$CPU\t$MEM\t$RTIME" + done < <(echo -e "$data" | grep NAME) +} + +# CSV list function +csv_list() { + IFS=$'\n' + echo "NAME,SYSTEM,STATE,CPU,MEM,RTIME" + while read str; do + parse_object_kv_list "$str" + echo "$NAME,\"$SYSTEM\",$STATE,$CPU,$MEM,$RTIME" + done < <(echo -e "$data" | grep NAME) +} + +# Get service state function +get_srv_state() { + srv=$1 + name=${2-$1} + state='running' + mem=0 + cpu=0 + rtime="0" + + # Searching related pids + if [ -z $3 ]; then + pids=$(pidof $name | tr ' ' '|') + else + pids=$(pidof -x $name | tr ' ' '|') + fi + if [ -z "$pids" ] && [ "$name" != 'nginx' ]; then + pids=$(pgrep $name | tr '\n' '|') + fi + + # Prevent from an SSH false positive when there is a TTY or SFTP connection but service is down + if [ "$name" == 'ssh' ] && [ "$(systemctl show sshd.service | grep 'SubState=' | cut -f2 -d=)" != "running" ]; then + pids='' + fi + + # Checking pid + if [ -n "$pids" ]; then + pid=$(echo "$pids" | cut -f 1 -d '|') + pids=${pids%|} + pids=$(egrep "$pids" $tmp_file) + + # Calculating CPU usage + cpu=$(echo "$pids" | awk '{ sum += $2} END {print sum}') + + # Calculating memory usage + mem=$(echo "$pids" | awk '{sum += $3} END {print sum/1024 }') + mem=$(echo "${mem%%.*}") + + # Searching pid file + pid_file='' + if [ -e "/run/$srv.pid" ]; then + pid_file="/run/$srv.pid" + fi + if [ -z "$pid_file" ] && [ -e "/run/$srv/$srv.pid" ]; then + pid_file="/run/$srv/$srv.pid" + fi + if [ -z "$pid_file" ] && [ -e "/run/$name/$name.pid" ]; then + pid_file="/run/$name/$name.pid" + fi + if [ -z "$pid_file" ] && [ -e "/proc/$pid" ]; then + pid_file="/proc/$pid" + fi + + # Calculating uptime + if [ -n "$pid_file" ]; then + mtime=$(stat -c "%Y" $pid_file) + rtime=$((ctime - mtime)) + rtime=$((rtime / 60)) + else + rtime=0 + fi + else + state='stopped' + mem=0 + cpu=0 + rtime="0" + fi +} + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Saving current proccess list +tmp_file=$(mktemp) +ps -eo pid,pcpu,size > $tmp_file + +# Checking current time +ctime=$(date +%s) + +# Checking WEB system +if [ -n "$WEB_SYSTEM" ] && [ "$WEB_SYSTEM" != 'remote' ]; then + get_srv_state $WEB_SYSTEM + data="NAME='$WEB_SYSTEM' SYSTEM='web server' STATE='$state' CPU='$cpu'" + data="$data MEM='$mem' RTIME='$rtime'" +fi + +# Checking PHP intepreter +if [ -n "$WEB_BACKEND" ] && [ "$WEB_BACKEND" != 'remote' ]; then + php_versions=$(ls /usr/sbin/php*fpm* | cut -d'/' -f4 | sed 's|php-fpm||') + for version in $php_versions; do + proc_name="php-fpm${version}" + service_name="php${version}-fpm" + get_srv_state "$proc_name" + data="$data\nNAME='$service_name' SYSTEM='php interpreter' STATE='$state'" + data="$data CPU='$cpu' MEM='$mem' RTIME='$rtime'" + done +fi + +# Checking WEB Proxy +if [ -n "$PROXY_SYSTEM" ] && [ "$PROXY_SYSTEM" != 'remote' ]; then + get_srv_state "$PROXY_SYSTEM" + data="$data\nNAME='$PROXY_SYSTEM' SYSTEM='reverse proxy' STATE='$state'" + data="$data CPU='$cpu' MEM='$mem' RTIME='$rtime'" +fi + +# DNS +service="$DNS_SYSTEM" +if [ -n "$service" ] && [ "$service" != 'remote' ]; then + proc_name='named' + get_srv_state $service $proc_name + data="$data\nNAME='$service' SYSTEM='dns server' STATE='$state'" + data="$data CPU='$cpu' MEM='$mem' RTIME='$rtime'" +fi + +# Checking MAIL system +if [ -n "$MAIL_SYSTEM" ] && [ "$MAIL_SYSTEM" != 'remote' ]; then + get_srv_state "$MAIL_SYSTEM" + data="$data\nNAME='$MAIL_SYSTEM' SYSTEM='mail server' STATE='$state'" + data="$data CPU='$cpu' MEM='$mem' RTIME='$rtime'" +fi + +# Checking MAIL IMAP +if [ -n "$IMAP_SYSTEM" ] && [ "$IMAP_SYSTEM" != 'remote' ]; then + get_srv_state "$IMAP_SYSTEM" + data="$data\nNAME='$IMAP_SYSTEM' SYSTEM='imap/pop3 server' STATE='$state'" + data="$data CPU='$cpu' MEM='$mem' RTIME='$rtime'" +fi + +# Checking MAIL ANTIVIRUS +if [ -n "$ANTIVIRUS_SYSTEM" ] && [ "$ANTIVIRUS_SYSTEM" != 'remote' ]; then + if [ -d "/etc/sysconfig" ]; then + if [ "$ANTIVIRUS_SYSTEM" == 'clamav' ]; then + ANTIVIRUS_SYSTEM='clamd' + fi + get_srv_state "$ANTIVIRUS_SYSTEM" + else + if [ "$ANTIVIRUS_SYSTEM" == 'clamav-daemon' ]; then + proc_name='clamd' + fi + get_srv_state "$ANTIVIRUS_SYSTEM" "$proc_name" + fi + data="$data\nNAME='$ANTIVIRUS_SYSTEM' SYSTEM='email anti-virus'" + data="$data STATE='$state' CPU='$cpu' MEM='$mem' RTIME='$rtime'" + proc_name='' +fi + +# Checking MAIL ANTISPAM +if [ -n "$ANTISPAM_SYSTEM" ] && [ "$ANTISPAM_SYSTEM" != 'remote' ]; then + get_srv_state "$ANTISPAM_SYSTEM" "spamd" + data="$data\nNAME='$ANTISPAM_SYSTEM' SYSTEM='email spam filter'" + data="$data STATE='$state' CPU='$cpu' MEM='$mem' RTIME='$rtime'" +fi + +# Checking DB system +if [ -n "$DB_SYSTEM" ] && [ "$DB_SYSTEM" != 'remote' ]; then + for db in ${DB_SYSTEM//,/ }; do + service="$db" + proc_name='' + mysql="/usr/bin/mysql" + if [ -f '/usr/bin/mariadb' ]; then + mysql="/usr/bin/mariadb" + fi + if [ "$service" = 'mysql' ]; then + mysql_version=$($mysql -V) + mariadb_string="MariaDB" + if [[ ! $mysql_version =~ $mariadb_string ]]; then + # MySQL + service='mysql' + proc_name='mysqld' + else + service='mariadb' + proc_name='mariadbd' + # MariaDB 10.4 and lower + if [ -f $mysql ]; then + mariadb_v=$($mysql -V | awk 'NR==1{print $5}') + if [[ $mariadb_v =~ $mariadb_string ]]; then + mariadb_v=$(echo $mariadb_v | cut -f2 -d'.') + if [ $mariadb_v -le "4" ]; then + service='mariadb' + proc_name='mysqld' + fi + fi + fi + fi + fi + if [ "$service" == 'pgsql' ]; then + service='postgresql' + proc_name='postmaster' + if [ ! -d "/etc/sysconfig" ]; then + proc_name='postgres' + fi + if [ ! -e '/etc/init.d/postgresql' ]; then + proc_name='postgres' + fi + fi + get_srv_state "$service" "$proc_name" + data="$data\nNAME='$service' SYSTEM='database server' STATE='$state'" + data="$data CPU='$cpu' MEM='$mem' RTIME='$rtime'" + proc_name='' + done +fi + +# Checking FTP system +if [ -n "$FTP_SYSTEM" ] && [ "$FTP_SYSTEM" != 'remote' ]; then + get_srv_state "$FTP_SYSTEM" + data="$data\nNAME='$FTP_SYSTEM' SYSTEM='ftp server' STATE='$state'" + data="$data CPU='$cpu' MEM='$mem' RTIME='$rtime'" +fi + +# Checking CRON system +if [ -n "$CRON_SYSTEM" ] && [ "$CRON_SYSTEM" != 'remote' ]; then + get_srv_state "$CRON_SYSTEM" + data="$data\nNAME='$CRON_SYSTEM' SYSTEM='job scheduler' STATE='$state'" + data="$data CPU='$cpu' MEM='$mem' RTIME='$rtime'" +fi + +# Checking SSH daemon +if [ -e "/etc/ssh/sshd_config" ]; then + get_srv_state ssh + data="$data\nNAME='ssh' SYSTEM='ssh server' STATE='$state'" + data="$data CPU='$cpu' MEM='$mem' RTIME='$rtime'" +fi + +# Checking FIREWALL system +if [ -n "$FIREWALL_SYSTEM" ] && [ "$FIREWALL_SYSTEM" != 'remote' ]; then + state="stopped" + if $(iptables -S INPUT | grep -qx '\-P INPUT DROP'); then + state="running" + fi + data="$data\nNAME='$FIREWALL_SYSTEM' SYSTEM='firewall'" + data="$data STATE='$state' CPU='0' MEM='0' RTIME='0'" +fi + +# Checking FIREWALL Fail2ban extention +if [ -n "$FIREWALL_EXTENSION" ]; then + if [ -e '/usr/bin/lsb_release' ]; then + if [ "$(lsb_release -s -r)" = "20.04" ]; then + get_srv_state "$FIREWALL_EXTENSION" f2b/server script + else + get_srv_state "$FIREWALL_EXTENSION" fail2ban-server script + fi + else + get_srv_state "$FIREWALL_EXTENSION" fail2ban-server script + fi + data="$data\nNAME='$FIREWALL_EXTENSION' SYSTEM='brute-force protection'" + data="$data STATE='$state' CPU='$cpu' MEM='$mem' RTIME='$rtime'" +fi + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list | column -t ;; +esac + +if [ -f "$tmp_file" ]; then + rm -f "$tmp_file" +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-sys-shells b/bin/v-list-sys-shells new file mode 100755 index 0000000..f62f190 --- /dev/null +++ b/bin/v-list-sys-shells @@ -0,0 +1,83 @@ +#!/bin/bash +# info: list system shells +# options: [FORMAT] +# +# example: v-list-sys-shells +# +# This function for obtaining the list of system shells. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +format=${1-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# JSON list function +json_list() { + sh_counter=$(echo "$shells" | wc -l) + i=1 + echo '[' + for shell in $shells; do + if [ "$i" -lt "$sh_counter" ]; then + echo -e "\t\"$shell\"," + else + echo -e "\t\"$shell\"" + fi + ((++i)) + done + echo "]" +} + +# SHELL list function +shell_list() { + echo "SHELL" + echo "-----" + for shell in $shells; do + echo "$shell" + done +} + +# PLAIN list function +plain_list() { + for shell in $shells; do + echo "$shell" + done +} + +# CSV list function +csv_list() { + echo "SHELL" + for shell in $shells; do + echo "$shell" + done +} + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Defining system shells +shells=$(grep -v '#' /etc/shells | awk -F '/' '{print $NF}' | sort -u) + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-sys-spamd-config b/bin/v-list-sys-spamd-config new file mode 100755 index 0000000..356db0f --- /dev/null +++ b/bin/v-list-sys-spamd-config @@ -0,0 +1,68 @@ +#!/bin/bash +# info: list spamassassin config parameters +# options: [FORMAT] +# +# example: v-list-sys-spamd-config +# +# This function for obtaining the list of spamassassin config parameters. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +format=${1-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# JSON list function +json_list() { + echo '{ + "CONFIG": { + "config_path": "'$config_path'" + } +}' +} + +# SHELL list function +shell_list() { + echo "config_path: $config_path" +} + +# PLAIN list function +plain_list() { + echo "$config_path" +} + +# CSV list function +csv_list() { + echo "config_path" + echo "$config_path" +} + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Defining config path +config_path=$(find /etc/spamassassin /etc/mail -name local.cf 2> /dev/null) + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-sys-sshd-port b/bin/v-list-sys-sshd-port new file mode 100755 index 0000000..eb00acc --- /dev/null +++ b/bin/v-list-sys-sshd-port @@ -0,0 +1,83 @@ +#!/bin/bash +# info: list sshd port +# options: [FORMAT] +# +# example: v-list-sys-sshd-port +# +# This function for obtainings the port of sshd listens to + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +format=${1-shell} + +# Includes +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh + +json_list() { + sh_counter=$(echo "$ports" | wc -l) + i=1 + echo '[' + for port in $ports; do + if [ "$i" -lt "$sh_counter" ]; then + echo -e "\t\"$port\"," + else + echo -e "\t\"$port\"" + fi + ((++i)) + done + echo "]" +} + +# SHELL list function +shell_list() { + echo "PORT" + echo "-----" + for port in $ports; do + echo "$port" + done +} + +# PLAIN list function +plain_list() { + for port in $ports; do + echo "$port" + done +} + +# CSV list function +csv_list() { + echo "PORT" + for port in $ports; do + echo "$port" + done +} + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +version=$(lsb_release -s -r) + +if [[ "$version" = 9 || "$version" = 10 ]]; then + ports=$(sshd -T -C "user=root" | grep '^port' | cut -d ' ' -f2) +else + ports=$(sshd -T | grep '^port' | cut -d ' ' -f2) +fi + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-sys-themes b/bin/v-list-sys-themes new file mode 100755 index 0000000..491c9cc --- /dev/null +++ b/bin/v-list-sys-themes @@ -0,0 +1,111 @@ +#!/bin/bash +# info: list system themes +# options: [FORMAT] +# +# example: v-list-sys-themes +# +# This function for obtaining the list of themes in the theme +# library and displaying them in the backend or user interface. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +format=${1-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Define array for available themes +available_themes=() + +# Function to process CSS theme files +get_themes() { + # Retrieve list of system themes + if [ -d "$HESTIA_THEMES" ]; then + for file in "$HESTIA_THEMES"/*.min.css; do + filename=$(basename "$file" .min.css) + available_themes+=("${filename%.*}") + done + fi + + # Check for existence of custom themes folder and iterate through items + if [ -d "$HESTIA_THEMES_CUSTOM" ] && [ "$(ls -A "$HESTIA_THEMES_CUSTOM")" ]; then + for file in "$HESTIA_THEMES_CUSTOM"/*.css; do + filename=$(basename "$file" .css) + available_themes+=("${filename%.*}") + done + fi + + # Sort theme list alphabetically + IFS=$'\n' available_themes=($(sort <<< "${available_themes[*]}")) + unset IFS + + # Get count of themes (for proper JSON formatting) + theme_count="${#available_themes[@]}" +} + +# JSON list function +json_list() { + i=1 + echo '[' + for theme in "${available_themes[@]}"; do + if [ "$i" -lt "$theme_count" ]; then + echo -e "\t\"$theme\"," + else + echo -e "\t\"$theme\"" + fi + ((++i)) + done + echo ']' +} + +# SHELL list function +shell_list() { + echo "THEME" + echo "-----" + for theme in "${available_themes[@]}"; do + echo "$theme" + done +} + +# PLAIN list function +plain_list() { + for theme in "${available_themes[@]}"; do + echo "$theme" + done +} + +# CSV list function +csv_list() { + echo "THEME" + for theme in "${available_themes[@]}"; do + echo "$theme" + done +} + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +get_themes + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-sys-users b/bin/v-list-sys-users new file mode 100755 index 0000000..b071ee2 --- /dev/null +++ b/bin/v-list-sys-users @@ -0,0 +1,81 @@ +#!/bin/bash +# info: list system users +# options: [FORMAT] +# +# example: v-list-sys-users +# +# This function for obtaining the list of system users without +# detailed information. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +format=${1-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# JSON list function +json_list() { + objects=$(grep @ /etc/passwd | wc -l) + i=1 + echo '[' + while read user; do + if [ "$i" -lt "$objects" ]; then + echo -e "\t\"$user\"," + else + echo -e "\t\"$user\"" + fi + ((++i)) + done < <(grep @ /etc/passwd | cut -f 1 -d :) + echo "]" +} + +# SHELL list function +shell_list() { + echo "USER" + echo "----" + while read user; do + echo "$user" + done < <(grep @ /etc/passwd | cut -f 1 -d :) +} + +# PLAIN list function +plain_list() { + while read user; do + echo "$user" + done < <(grep @ /etc/passwd | cut -f 1 -d :) +} + +# CSV list function +csv_list() { + echo "USER" + while read user; do + echo "$user" + done < <(grep @ /etc/passwd | cut -f 1 -d :) +} + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-sys-vsftpd-config b/bin/v-list-sys-vsftpd-config new file mode 100755 index 0000000..3f18613 --- /dev/null +++ b/bin/v-list-sys-vsftpd-config @@ -0,0 +1,68 @@ +#!/bin/bash +# info: list vsftpd config parameters +# options: [FORMAT] +# +# example: v-list-sys-vsftpd-config +# +# This function for obtaining the list of vsftpd config parameters. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +format=${1-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# JSON list function +json_list() { + echo '{ + "CONFIG": { + "config_path": "'$config_path'" + } +}' +} + +# SHELL list function +shell_list() { + echo "config_path: $config_path" +} + +# PLAIN list function +plain_list() { + echo "$config_path" +} + +# CSV list function +csv_list() { + echo "config_path" + echo "$config_path" +} + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Defining config path +config_path=$(find /etc/vsftpd* -name vsftpd.conf 2> /dev/null) + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-sys-web-status b/bin/v-list-sys-web-status new file mode 100755 index 0000000..f992e14 --- /dev/null +++ b/bin/v-list-sys-web-status @@ -0,0 +1,53 @@ +#!/bin/bash +# info: list web status +# options: +# +# example: v-list-sys-web-status +# +# This function lists web server status + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +#format=${1-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Checking web system +if [ -z "$WEB_SYSTEM" ]; then + exit +fi + +# Displaying proxy status +if [ "$PROXY_SYSTEM" = 'nginx' ]; then + echo "

$PROXY_SYSTEM STATUS

" | tr '[:lower:]' '[:upper:]' + wget -qO- http://localhost:8084/ + echo "


" +fi + +# Displaying web server status +echo "

$WEB_SYSTEM STATUS

" | tr '[:lower:]' '[:upper:]' +if [ "$WEB_SYSTEM" != 'nginx' ]; then + wget -qO- http://localhost:8081/server-status/ \ + | egrep -v "html|DOCTYPE|h1>|title|head" +else + wget -qO- http://localhost:8084/ +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-sys-webmail b/bin/v-list-sys-webmail new file mode 100755 index 0000000..8935aaa --- /dev/null +++ b/bin/v-list-sys-webmail @@ -0,0 +1,81 @@ +#!/bin/bash +# info: listing available webmail clients +# options: [FORMAT] +# labels: hestia mail +# +# example: v-list-sys-webmail +# +# List available webmail clients + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +format=${1-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# JSON list function +json_list() { + i=1 + objects=$(echo -e "${WEBMAIL_SYSTEM//,/\\n}" | wc -l) + echo '[' + for client in ${WEBMAIL_SYSTEM//,/ }; do + if [ "$i" -ne "$objects" ]; then + echo -e "\t\"$client\"," + else + echo -e "\t\"$client\"" + fi + ((++i)) + done + echo ']' +} + +# SHELL list function +shell_list() { + echo "Webmail Client" + echo "--------" + for client in ${WEBMAIL_SYSTEM//,/ }; do + echo "$client" + done +} + +# PLAIN list function +plain_list() { + for client in ${WEBMAIL_SYSTEM//,/ }; do + echo "$client" + done +} + +# CSV list function +csv_list() { + echo "CLIENT" + for client in ${WEBMAIL_SYSTEM//,/ }; do + echo "$client" + done +} + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-user b/bin/v-list-user new file mode 100755 index 0000000..b5db719 --- /dev/null +++ b/bin/v-list-user @@ -0,0 +1,197 @@ +#!/bin/bash +# info: list user parameters +# options: USER [FORMAT] +# +# example: v-list-user admin +# +# This function to obtain user parameters. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +format=${2-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" +# JSON list function +json_list() { + echo '{ + "'$USER'": { + "NAME": "'$NAME'", + "PACKAGE": "'$PACKAGE'", + "WEB_TEMPLATE": "'$WEB_TEMPLATE'", + "BACKEND_TEMPLATE": "'$BACKEND_TEMPLATE'", + "PROXY_TEMPLATE": "'$PROXY_TEMPLATE'", + "DNS_TEMPLATE": "'$DNS_TEMPLATE'", + "WEB_DOMAINS": "'$WEB_DOMAINS'", + "WEB_ALIASES": "'$WEB_ALIASES'", + "DNS_DOMAINS": "'$DNS_DOMAINS'", + "DNS_RECORDS": "'$DNS_RECORDS'", + "MAIL_DOMAINS": "'$MAIL_DOMAINS'", + "MAIL_ACCOUNTS": "'$MAIL_ACCOUNTS'", + "DATABASES": "'$DATABASES'", + "CRON_JOBS": "'$CRON_JOBS'", + "DISK_QUOTA": "'$DISK_QUOTA'", + "BANDWIDTH": "'$BANDWIDTH'", + "HOME": "'$HOME'", + "NS": "'$NS'", + "SHELL": "'$SHELL'", + "BACKUPS": "'$BACKUPS'", + "CONTACT": "'$CONTACT'", + "CRON_REPORTS": "'$CRON_REPORTS'", + "RKEY": "'$RKEY'", + "TWOFA": "'$TWOFA'", + "QRCODE": "'$QRCODE'", + "ROLE": "'$ROLE'", + "SUSPENDED": "'$SUSPENDED'", + "SUSPENDED_USERS": "'$SUSPENDED_USERS'", + "SUSPENDED_WEB": "'$SUSPENDED_WEB'", + "SUSPENDED_DNS": "'$SUSPENDED_DNS'", + "SUSPENDED_MAIL": "'$SUSPENDED_MAIL'", + "SUSPENDED_DB": "'$SUSPENDED_DB'", + "SUSPENDED_CRON": "'$SUSPENDED_CRON'", + "IP_AVAIL": "'$IP_AVAIL'", + "IP_OWNED": "'$IP_OWNED'", + "U_USERS": "'$U_USERS'", + "U_DISK": "'$U_DISK'", + "U_DISK_DIRS": "'$U_DISK_DIRS'", + "U_DISK_WEB": "'$U_DISK_WEB'", + "U_DISK_MAIL": "'$U_DISK_MAIL'", + "U_DISK_DB": "'$U_DISK_DB'", + "U_BANDWIDTH": "'$U_BANDWIDTH'", + "U_WEB_DOMAINS": "'$U_WEB_DOMAINS'", + "U_WEB_SSL": "'$U_WEB_SSL'", + "U_WEB_ALIASES": "'$U_WEB_ALIASES'", + "U_DNS_DOMAINS": "'$U_DNS_DOMAINS'", + "U_DNS_RECORDS": "'$U_DNS_RECORDS'", + "U_MAIL_DOMAINS": "'$U_MAIL_DOMAINS'", + "U_MAIL_DKIM": "'$U_MAIL_DKIM'", + "U_MAIL_ACCOUNTS": "'$U_MAIL_ACCOUNTS'", + "U_DATABASES": "'$U_DATABASES'", + "U_CRON_JOBS": "'$U_CRON_JOBS'", + "U_BACKUPS": "'$U_BACKUPS'", + "LANGUAGE": "'$LANGUAGE'", + "THEME": "'$THEME'", + "NOTIFICATIONS": "'$NOTIFICATIONS'", + "PREF_UI_SORT": "'$PREF_UI_SORT'", + "LOGIN_DISABLED": "'$LOGIN_DISABLED'", + "LOGIN_USE_IPLIST": "'$LOGIN_USE_IPLIST'", + "LOGIN_ALLOW_IPS": "'$LOGIN_ALLOW_IPS'", + "PHPCLI": "'$PHPCLI'", + "TIME": "'$TIME'", + "DATE": "'$DATE'" + } +}' +} + +# SHELL list function +shell_list() { + echo "USERNAME: $USER" + echo "FULL NAME: $NAME" + echo "EMAIL: $CONTACT" + echo "LANGUAGE: $LANGUAGE" + echo "THEME: $THEME" + echo "SUSPENDED: $SUSPENDED" + echo "PACKAGE: $PACKAGE" + echo "SHELL: $SHELL" + echo "WEB DOMAINS: $U_WEB_DOMAINS/$WEB_DOMAINS" + echo "WEB ALIASES: $U_WEB_ALIASES/$WEB_ALIASES" + echo "DNS DOMAINS: $U_DNS_DOMAINS/$DNS_DOMAINS" + echo "DNS RECORDS: $U_DNS_RECORDS/$DNS_RECORDS" + echo "MAIL DOMAINS: $U_MAIL_DOMAINS/$MAIL_DOMAINS" + echo "MAIL ACCOUNTS: $U_MAIL_ACCOUNTS/$MAIL_ACCOUNTS" + echo "BACKUPS: $U_BACKUPS/$BACKUPS" + echo "DATABASES: $U_DATABASES/$DATABASES" + echo "CRON_JOBS: $U_CRON_JOBS/$CRON_JOBS" + echo "DISK: $U_DISK/$DISK_QUOTA" + echo "BANDWIDTH: $U_BANDWIDTH/$BANDWIDTH" + echo "IP ADDRESSES $IP_AVAIL/$IP_OWNED" + echo "TIME: $TIME" + echo "DATE: $DATE" +} + +# PLAIN list function +plain_list() { + echo -ne "$USER\t$NAME\t$PACKAGE\t$WEB_TEMPLATE\t" + echo -ne "$BACKEND_TEMPLATE\t$PROXY_TEMPLATE\t$DNS_TEMPLATE\t" + echo -ne "$WEB_DOMAINS\t$WEB_ALIASES\t$DNS_DOMAINS\t$DNS_RECORDS\t" + echo -ne "$MAIL_DOMAINS\t$MAIL_ACCOUNTS\t$DATABASES\t$CRON_JOBS\t" + echo -ne "$DISK_QUOTA\t$BANDWIDTH\t$NS\t$HOME\t$SHELL\t$BACKUPS\t" + echo -ne "$CONTACT\t$CRON_REPORTS\t$RKEY\t$SUSPENDED\t" + echo -ne "$SUSPENDED_USERS\t$SUSPENDED_WEB\t$SUSPENDED_DNS\t" + echo -ne "$SUSPENDED_MAIL\t$SUSPENDED_DB\t$SUSPENDED_CRON\t" + echo -ne "$IP_AVAIL\t$IP_OWNED\t$U_USERS\t$U_DISK\t$U_DISK_DIRS\t" + echo -ne "$U_DISK_WEB\t$U_DISK_MAIL\t$U_DISK_DB\t$U_BANDWIDTH\t" + echo -ne "$U_WEB_DOMAINS\t$U_WEB_SSL\t$U_WEB_ALIASES\t" + echo -ne "$U_DNS_DOMAINS\t$U_DNS_RECORDS\t$U_MAIL_DOMAINS\t" + echo -ne "$U_MAIL_DKIM\t$U_MAIL_ACCOUNTS\t$U_DATABASES\t" + echo -e "$U_CRON_JOBS\t$U_BACKUPS\t$LANGUAGE\t$THEME\t$TIME\t$DATE" +} + +# CSV list function +csv_list() { + echo -n "USER,NAME,PACKAGE,WEB_TEMPLATE,BACKEND_TEMPLATE," + echo -n "PROXY_TEMPLATE,DNS_TEMPLATE,WEB_DOMAINS,WEB_ALIASES," + echo -n "DNS_DOMAINS,DNS_RECORDS,MAIL_DOMAINS,MAIL_ACCOUNTS," + echo -n "DATABASES,CRON_JOBS,DISK_QUOTA,BANDWIDTH,NS,HOME,SHELL," + echo -n "BACKUPS,CONTACT,CRON_REPORTS,RKEY,SUSPENDED,SUSPENDED_USERS," + echo -n "SUSPENDED_WEB,SUSPENDED_DNS,SUSPENDED_MAIL,SUSPENDED_DB," + echo -n "SUSPENDED_CRON,IP_AVAIL,IP_OWNED,U_USERS,U_DISK,U_DISK_DIRS," + echo -n "U_DISK_WEB,U_DISK_MAIL,U_DISK_DB,U_BANDWIDTH,U_WEB_DOMAINS," + echo -n "U_WEB_SSL,U_WEB_ALIASES,U_DNS_DOMAINS,U_DNS_RECORDS," + echo -n "U_MAIL_DOMAINS,U_MAIL_DKIM,U_MAIL_ACCOUNTS,U_DATABASES" + echo "U_CRON_JOBS,U_BACKUPS,LANGUAGE,THEME,NOTIFICATIONS,TIME,DATE" + echo -n "$USER,\"$NAME\",$PACKAGE,$WEB_TEMPLATE," + echo -n "$BACKEND_TEMPLATE,$PROXY_TEMPLATE,$DNS_TEMPLATE,$WEB_DOMAINS," + echo -n "$WEB_ALIASES,$DNS_DOMAINS,$DNS_RECORDS,$MAIL_DOMAINS," + echo -n "$MAIL_ACCOUNTS,$DATABASES,$CRON_JOBS,$DISK_QUOTA,$BANDWIDTH," + echo -n "\"$NS\",$HOME,$SHELL,$BACKUPS,$CONTACT,$CRON_REPORTS,\"$RKEY\"," + echo -n "$SUSPENDED,$SUSPENDED_USERS,$SUSPENDED_WEB,$SUSPENDED_DNS," + echo -n "$SUSPENDED_MAIL,$SUSPENDED_DB,$SUSPENDED_CRON,$IP_AVAIL," + echo -n "$IP_OWNED,$U_USERS,$U_DISK,$U_DISK_DIRS,$U_DISK_WEB," + echo -n "$U_DISK_MAIL,$U_DISK_DB,$U_BANDWIDTH,$U_WEB_DOMAINS,$U_WEB_SSL," + echo -n "$U_WEB_ALIASES,$U_DNS_DOMAINS,$U_DNS_RECORDS,$U_MAIL_DOMAINS," + echo -n "$U_MAIL_DKIM,$U_MAIL_ACCOUNTS,$U_DATABASES,$U_CRON_JOBS," + echo "$U_BACKUPS,$LANGUAGE,$THEME,$NOTIFICATIONS,$TIME,$DATE" +} + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'USER [FORMAT]' +is_format_valid 'user' +is_object_valid 'user' 'USER' "$user" + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Defining config +USER=$user +HOME=$HOMEDIR/$user +source_conf "$HESTIA/data/users/$user/user.conf" +U_USERS=$(cat $HESTIA/data/users/admin/user.conf | grep "U_USERS" | cut -d'=' -f2 | sed "s/'//g") +SUSPENDED_USERS=$(cat $HESTIA/data/users/admin/user.conf | grep "SUSPENDED_USERS" | cut -d'=' -f2 | sed "s/'//g") + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-user-auth-log b/bin/v-list-user-auth-log new file mode 100755 index 0000000..3b94814 --- /dev/null +++ b/bin/v-list-user-auth-log @@ -0,0 +1,137 @@ +#!/bin/bash +# info: list user log +# options: USER [FORMAT] +# +# This function of obtaining the list of 10 last users commands. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +format=${2-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# JSON list function +json_list() { + IFS=$'\n' + i=1 + objects=$(echo "$logs" | wc -l) + echo "{" + for str in $logs; do + DATE=$(echo "$str" | cut -f 2 -d \') + TIME=$(echo "$str" | cut -f 4 -d \') + IP=$(echo "$str" | cut -f 6 -d \') + ACTION=$(echo "$str" | cut -f 8 -d \') + STATUS=$(echo "$str" | cut -f 10 -d \') + USER_AGENT=$(echo "$str" | cut -f 12 -d \') + SESSION=$(echo "$str" | cut -f 14 -d \') + ACTIVE=$(echo "$str" | cut -f 16 -d \') + echo -n ' "'$i'": { + "DATE": "'$DATE'", + "TIME": "'$TIME'", + "IP": "'$IP'", + "ACTION": "'$ACTION'", + "STATUS": "'$STATUS'", + "USER_AGENT": "'$USER_AGENT'", + "SESSION": "'$SESSION'", + "ACTIVE": "'$ACTIVE'" + }' + if [ "$i" -lt "$objects" ]; then + echo ',' + else + echo + fi + ((i++)) + done + echo '}' +} + +shell_list() { + IFS=$'\n' + echo "DATE~TIME~IP~SESSION~ACTIVE~STATUS" + echo "----~----~--~-----------~------" + for str in $logs; do + DATE=$(echo "$str" | cut -f 2 -d \') + TIME=$(echo "$str" | cut -f 4 -d \') + IP=$(echo "$str" | cut -f 6 -d \') + ACTION=$(echo "$str" | cut -f 8 -d \') + STATUS=$(echo "$str" | cut -f 10 -d \') + USER_AGENT=$(echo "$str" | cut -f 12 -d \') + SESSION=$(echo "$str" | cut -f 14 -d \') + ACTIVE=$(echo "$str" | cut -f 16 -d \') + echo "$DATE~$TIME~$IP~$ACTION~$STATUS~$USER_AGENT~$SESSION~$ACTIVE" + done +} + +# PLAIN list function +plain_list() { + IFS=$'\n' + for str in $logs; do + DATE=$(echo "$str" | cut -f 2 -d \') + TIME=$(echo "$str" | cut -f 4 -d \') + IP=$(echo "$str" | cut -f 6 -d \') + ACTION=$(echo "$str" | cut -f 8 -d \') + STATUS=$(echo "$str" | cut -f 10 -d \') + USER_AGENT=$(echo "$str" | cut -f 12 -d \') + SESSION=$(echo "$str" | cut -f 14 -d \') + ACTIVE=$(echo "$str" | cut -f 16 -d \') + echo -e "$DATE\t$TIME\t$IP\t$ACTION\t$STATUS\t$USER_AGENT\t$SESSION\t$ACTIVE" + done +} + +# CSV list function +csv_list() { + IFS=$'\n' + echo "DATE,TIME,IP,ACTION,STATUS,USER_AGENT,SESSION,ACTIVE" + for str in $logs; do + DATE=$(echo "$str" | cut -f 2 -d \') + TIME=$(echo "$str" | cut -f 4 -d \') + IP=$(echo "$str" | cut -f 6 -d \') + ACTION=$(echo "$str" | cut -f 8 -d \') + STATUS=$(echo "$str" | cut -f 10 -d \') + USER_AGENT=$(echo "$str" | cut -f 12 -d \') + SESSION=$(echo "$str" | cut -f 14 -d \') + ACTIVE=$(echo "$str" | cut -f 16 -d \') + echo "$DATE,$TIME,$IP,$ACTION,$STATUS,$USER_AGENT,$SESSION,$ACTIVE" + + done +} + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'USER [FORMAT]' +is_format_valid 'user' +is_object_valid 'user' 'USER' "$user" + +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Parsing history log +logs=$(tail -n 10 $USER_DATA/auth.log 2> /dev/null) + +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list | column -t -s '~' ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-user-backup b/bin/v-list-user-backup new file mode 100755 index 0000000..ad4673f --- /dev/null +++ b/bin/v-list-user-backup @@ -0,0 +1,106 @@ +#!/bin/bash +# info: list user backup +# options: USER BACKUP [FORMAT] +# +# example: v-list-user-backup admin admin.2019-05-19_03-31-30.tar +# +# This function of obtaining the list of backup parameters. This call, just as +# all v_list_* calls, supports 3 formats - json, shell and plain. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +backup=$2 +format=${3-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +fields="\$BACKUP \$TYPE \$SIZE \$WEB \$DNS \$DB \$MAIL \$CRON \$UDIR" +fields="$fields \$RUNTIME \$TIME \$DATE" + +# JSON list function +json_list() { + echo '{' + echo ' "'$BACKUP'": { + "TYPE": "'$TYPE'", + "SIZE": "'$SIZE'", + "WEB": "'$WEB'", + "DNS": "'$DNS'", + "MAIL": "'$MAIL'", + "DB": "'$DB'", + "CRON": "'$CRON'", + "UDIR": "'$UDIR'", + "RUNTIME": "'$RUNTIME'", + "TIME": "'$TIME'", + "DATE": "'$DATE'" + }' + echo '}' +} + +# SHELL list function +shell_list() { + echo "BACKUP: $BACKUP" + echo "TYPE: $TYPE" + echo "SIZE: $SIZE mb" + echo "RUNTIME: $RUNTIME min" + echo "WEB: ${WEB//,/ }" + echo "DNS: ${DNS//,/ }" + echo "MAIL: ${MAIL//,/ }" + echo "DB: ${DB//,/ }" + echo "CRON: $CRON" + echo "UDIR: ${UDIR//,/ }" + echo "TIME: $TIME" + echo "DATE: $DATE" +} + +# PLAIN list function +plain_list() { + echo -ne "$BACKUP\t$TYPE\t$SIZE\t$WEB\t$DNS\t$MAIL\t$DB\t$CRON\t" + echo -e "$UDIR\t$RUNTIME\t$TIME\t$DATE" +} + +# CSV list function +csv_list() { + echo "BACKUP,TYPE,SIZE,WEB,DNS,MAIL,DB,CRON,UDIR,RUNTIME,TIME,DATE" + echo -n "$BACKUP,$TYPE,$SIZE,\"$WEB\",\"$DNS\",\"$MAIL\",\"$DB\"," + echo "\"$CRON\",\"$UDIR\",$RUNTIME,$TIME,$DATE" +} + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER BACKUP [FORMAT]' +is_format_valid 'user' 'backup' +is_object_valid 'user' 'USER' "$user" +is_object_valid 'backup' 'BACKUP' "$backup" + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Parsing backup config +parse_object_kv_list $(grep "BACKUP='$backup'" $USER_DATA/backup.conf) + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-user-backup-exclusions b/bin/v-list-user-backup-exclusions new file mode 100755 index 0000000..d7db45f --- /dev/null +++ b/bin/v-list-user-backup-exclusions @@ -0,0 +1,187 @@ +#!/bin/bash +# info: list backup exclusions +# options: USER [FORMAT] +# +# example: v-list-user-backup-exclusions admin +# +# This function for obtaining the backup exclusion list + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +format=${2-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# JSON list function +json_list() { + set -f + i=1 + echo '{' + echo ' "WEB": {' + objects=$(echo "${WEB//,/ }" | wc -w) + for object in $(echo "${WEB//,/ }"); do + j=1 + object_keys=$(echo ${object//:/ } | wc -w) + for key in $(echo "${object/:/ }"); do + if [ "$j" -eq 1 ]; then + echo -n " \"${key}\": " + if [ "$object_keys" -eq 1 ]; then + echo -n '""' + fi + else + echo -n "\"${key//:/,}\"" + fi + ((j++)) + done + if [ "$i" -lt "$objects" ]; then + echo ',' + else + echo + fi + ((i++)) + done + echo ' },' + i=1 + echo ' "MAIL": {' + objects=$(echo "${MAIL//,/ }" | wc -w) + for object in $(echo "${MAIL//,/ }"); do + j=1 + object_keys=$(echo ${object//:/ } | wc -w) + for key in $(echo "${object/:/ }"); do + if [ "$j" -eq 1 ]; then + echo -n " \"$key\": " + if [ "$object_keys" -eq 1 ]; then + echo -n '""' + fi + else + echo -n "\"${key//:/,}\"" + fi + ((j++)) + done + if [ "$i" -lt "$objects" ]; then + echo ',' + else + echo + fi + ((i++)) + done + echo ' },' + i=1 + echo ' "DB": {' + objects=$(echo "${DB//,/ }" | wc -w) + for object in $(echo "${DB//,/ }"); do + j=1 + object_keys=$(echo ${object//:/ } | wc -w) + for key in $(echo "${object/:/ }"); do + if [ "$j" -eq 1 ]; then + echo -n " \"$key\": " + if [ "$object_keys" -eq 1 ]; then + echo -n '""' + fi + else + echo -n "\"${key//:/,}\"" + fi + ((j++)) + done + if [ "$i" -lt "$objects" ]; then + echo ',' + else + echo + fi + ((i++)) + done + echo ' },' + i=1 + echo ' "USER": {' + objects=$(echo "${USER//,/ }" | wc -w) + for object in $(echo "${USER//,/ }"); do + j=1 + object_keys=$(echo ${object//:/ } | wc -w) + for key in $(echo "${object/:/ }"); do + if [ "$j" -eq 1 ]; then + echo -n " \"$key\": " + if [ "$object_keys" -eq 1 ]; then + echo -n '""' + fi + else + echo -n "\"${key//:/,}\"" + fi + ((j++)) + done + if [ "$i" -lt "$objects" ]; then + echo ',' + else + echo + fi + ((i++)) + done + echo ' }' + echo '}' + +} + +# SHELL list function +shell_list() { + echo "WEB: $WEB" + echo "MAIL: $MAIL" + echo "DB: $DB" + echo "USER DIRS: $USER" +} + +# PLAIN list function +plain_list() { + echo "$WEB\t$MAIL\t$DB\t$USER" +} + +# CSV list function +csv_list() { + echo "WEB,MAIL,DB,USER" + echo "\"$WEB\",\"$MAIL\",\"$DB\",\"$USER\"" +} + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'USER [FORMAT]' +is_format_valid 'user' +is_object_valid 'user' 'USER' "$user" + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Flushing variables +WEB='' +MAIL='' +DB='' +USER='' + +# Parsing backup exclusion list +if [ -e "$USER_DATA/backup-excludes.conf" ]; then + source_conf "$USER_DATA/backup-excludes.conf" +fi + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-user-backups b/bin/v-list-user-backups new file mode 100755 index 0000000..0f07f6f --- /dev/null +++ b/bin/v-list-user-backups @@ -0,0 +1,118 @@ +#!/bin/bash +# info: list user backups +# options: USER [FORMAT] +# +# example: v-list-user-backups admin +# +# This function for obtaining the list of available user backups. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +format=${2-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# JSON list function +json_list() { + IFS=$'\n' + i=1 + objects=$(grep BACKUP $USER_DATA/backup.conf | wc -l) + echo "{" + while read -r str; do + parse_object_kv_list "$str" + echo -n ' "'$BACKUP'": { + "TYPE": "'$TYPE'", + "SIZE": "'$SIZE'", + "WEB": "'$WEB'", + "DNS": "'$DNS'", + "MAIL": "'$MAIL'", + "DB": "'$DB'", + "CRON": "'$CRON'", + "UDIR": "'$UDIR'", + "RUNTIME": "'$RUNTIME'", + "TIME": "'$TIME'", + "DATE": "'$DATE'" + }' + if [ "$i" -lt "$objects" ]; then + echo ',' + else + echo + fi + ((i++)) + done < <(cat $USER_DATA/backup.conf) + echo '}' +} + +# SHELL list function +shell_list() { + IFS=$'\n' + echo "BACKUP TYPE SIZE TIME DATE" + echo "------ ---- --- ---- ----" + while read -r str; do + parse_object_kv_list "$str" + echo "$BACKUP $TYPE $SIZE $RUNTIME $DATE" + done < <(cat $USER_DATA/backup.conf) +} + +# PLAIN list function +plain_list() { + IFS=$'\n' + while read -r str; do + parse_object_kv_list "$str" + echo -ne "$BACKUP\t$TYPE\t$SIZE\t$WEB\t$DNS\t$MAIL\t$CRON\t$UDIR\t" + echo -e "$RUNTIME\t$TIME\t$DATE" + done < <(cat $USER_DATA/backup.conf) +} + +# CSV list function +csv_list() { + IFS=$'\n' + echo "BACKUP,TYPE,SIZE,WEB,DNS,MAIL,CRON,UDIR,RUNTIME,TIME,DATE" + while read -r str; do + parse_object_kv_list "$str" + echo -n "$BACKUP,$TYPE,$SIZE,\"$WEB\",\"$DNS\",\"$MAIL\",\"$CRON\"," + echo "\"$UDIR\",$RUNTIME,$TIME,$DATE" + done < <(cat $USER_DATA/backup.conf) +} + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'USER [FORMAT]' +is_format_valid 'user' +is_object_valid 'user' 'USER' "$user" + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Checking config +conf=$USER_DATA/backup.conf +if [ ! -e "$conf" ]; then + touch $conf +fi + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list | column -t ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-user-ips b/bin/v-list-user-ips new file mode 100755 index 0000000..52914a6 --- /dev/null +++ b/bin/v-list-user-ips @@ -0,0 +1,115 @@ +#!/bin/bash +# info: list user IPs +# options: USER [FORMAT] +# +# example: v-list-user-ips admin +# +# This function for obtaining the list of available IP addresses. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user="$1" +format="${2-shell}" + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# JSON list function +json_list() { + echo '{' + ip_count="$(echo "$ips" | wc -l)" + i=1 + for IP in $ips; do + source_conf "$HESTIA/data/ips/$IP" + echo -n ' "'$IP'": { + "OWNER": "'$OWNER'", + "STATUS": "'$STATUS'", + "NAME": "'$NAME'", + "NAT": "'$NAT'" + }' + if [ "$i" -lt "$ip_count" ]; then + echo ',' + else + echo + fi + ((i++)) + done + echo '}' +} + +# SHELL list function +shell_list() { + echo "IP NAT OWNER STATUS NAME" + echo "-- --- ----- ------ ---" + for IP in $ips; do + source_conf "$HESTIA/data/ips/$IP" + if [ -z "$NAT" ]; then + NAT='no' + fi + if [ -z "$NAME" ]; then + NAME='no' + fi + echo "$IP $NAT $OWNER $STATUS $NAME" + done +} + +# PLAIN list function +plain_list() { + for IP in $ips; do + source_conf "$HESTIA/data/ips/$IP" + echo -e "$IP\t$OWNER\t$STATUS\t$NAME\t$NAT" + done +} + +# CSV list function +csv_list() { + echo "IP,OWNER,STATUS,NAME,NAT" + for IP in $ips; do + source_conf "$HESTIA/data/ips/$IP" + echo "$IP,$OWNER,$STATUS,$NAME,$NAT" + done +} + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'USER [FORMAT]' +is_format_valid 'user' +is_object_valid 'user' 'USER' "$user" + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Defining fileds to select +owner='admin' +owner_ips="$(grep -A 1 -H "OWNER='$owner'" $HESTIA/data/ips/*)" +owner_ips="$(echo "$owner_ips" | grep "STATUS='shared'")" +owner_ips="$(echo "$owner_ips" | cut -f 7 -d / | cut -f 1 -d -)" +user_ips="$(grep -H "OWNER='$user'" $HESTIA/data/ips/*)" +user_ips="$(echo "$user_ips" | cut -f 7 -d / | cut -f 1 -d :)" +ips="$(echo -e "$user_ips\n$owner_ips" | sort -u | sed "/^$/d")" +fields='$IP $OWNER $STATUS $NAME $NAT' + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list | column -t ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-user-log b/bin/v-list-user-log new file mode 100755 index 0000000..06cc725 --- /dev/null +++ b/bin/v-list-user-log @@ -0,0 +1,133 @@ +#!/bin/bash +# info: list user log +# options: USER [FORMAT] +# +# example: v-list-user-log +# +# This function of obtaining the list of 100 last users commands. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +format=${2-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# JSON list function +json_list() { + IFS=$'\n' + i=1 + objects=$(echo "$logs" | wc -l) + echo "{" + for str in $logs; do + ID=$(echo "$str" | cut -f 2 -d \') + DATE=$(echo "$str" | cut -f 4 -d \') + TIME=$(echo "$str" | cut -f 6 -d \') + LEVEL=$(echo "$str" | cut -f 8 -d \') + CATEGORY=$(echo "$str" | cut -f 10 -d \') + MESSAGE=$(echo "$str" | cut -f 12 -d \') + MESSAGE=${MESSAGE//\"/\\\"} + echo -n ' "'$ID'": { + "DATE": "'$DATE'", + "TIME": "'$TIME'", + "LEVEL": "'$LEVEL'", + "CATEGORY": "'$CATEGORY'", + "MESSAGE": "'$MESSAGE'" + }' + if [ "$i" -lt "$objects" ]; then + echo ',' + else + echo + fi + ((i++)) + done + echo '}' +} + +shell_list() { + IFS=$'\n' + echo "ID~DATE~TIME~LEVEL~CATEGORY~MESSAGE" + echo "----~----~----~-----~--------~-------" + for str in $logs; do + ID=$(echo "$str" | cut -f 2 -d \') + DATE=$(echo "$str" | cut -f 4 -d \') + TIME=$(echo "$str" | cut -f 6 -d \') + LEVEL=$(echo "$str" | cut -f 8 -d \') + CATEGORY=$(echo "$str" | cut -f 10 -d \') + MESSAGE=$(echo "$str" | cut -f 12 -d \') + echo "$ID~$DATE~$TIME~$LEVEL~$CATEGORY~$MESSAGE" + done +} + +# PLAIN list function +plain_list() { + IFS=$'\n' + for str in $logs; do + ID=$(echo "$str" | cut -f 2 -d \') + DATE=$(echo "$str" | cut -f 4 -d \') + TIME=$(echo "$str" | cut -f 6 -d \') + LEVEL=$(echo "$str" | cut -f 8 -d \') + CATEGORY=$(echo "$str" | cut -f 10 -d \') + MESSAGE=$(echo "$str" | cut -f 12 -d \') + echo -e "$ID\t$DATE\t$TIME\t$LEVEL\t$CATEGORY\t$MESSAGE" + done +} + +# CSV list function +csv_list() { + IFS=$'\n' + echo "ID,MESSAGE,TIME,DATE" + for str in $logs; do + ID=$(echo "$str" | cut -f 2 -d \') + DATE=$(echo "$str" | cut -f 4 -d \') + TIME=$(echo "$str" | cut -f 6 -d \') + LEVEL=$(echo "$str" | cut -f 8 -d \') + CATEGORY=$(echo "$str" | cut -f 10 -d \') + MESSAGE=$(echo "$str" | cut -f 12 -d \') + echo "$ID,\"$DATE\",\"$TIME",\"$LEVEL\",\"$CATEGORY\",\"$MESSAGE"" + done +} + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'USER [FORMAT]' +is_format_valid 'user' +if [ "$user" != "system" ]; then + is_object_valid 'user' 'USER' "$user" +fi + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Parsing history log +if [ "$user" = "system" ]; then + log_file="$HESTIA/data/users/admin/system.log" +else + log_file="$USER_DATA/history.log" +fi +logs=$(tail -n 300 $log_file 2> /dev/null) + +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list | column -t -s '~' ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-user-notifications b/bin/v-list-user-notifications new file mode 100755 index 0000000..02c047d --- /dev/null +++ b/bin/v-list-user-notifications @@ -0,0 +1,115 @@ +#!/bin/bash +# info: list user notifications +# options: USER [FORMAT] +# +# example: v-list-user-notifications admin +# +# This function for getting the list notifications + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +format=${2-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# JSON list function +json_list() { + IFS=$'\n' + i=1 + objects=$(grep NID $USER_DATA/notifications.conf | wc -l) + echo "{" + while read str; do + parse_object_kv_list "$str" + TOPIC=$(echo "$TOPIC" | sed -e "s/%quote%/'/g") + NOTICE=$(echo "$NOTICE" | sed -e "s/%quote%/'/g") + echo -n ' "'$NID'": { + "TOPIC": "'$TOPIC'", + "NOTICE": "'${NOTICE//\"/\'}'", + "TYPE": "'$TYPE'", + "ACK": "'$ACK'", + "TPL": "'$TPL'", + "TIME": "'$TIME'", + "DATE": "'$DATE'" + }' + if [ "$i" -lt "$objects" ]; then + echo ',' + else + echo + fi + ((i++)) + done < <(cat $USER_DATA/notifications.conf) + echo '}' +} + +# SHELL list function +shell_list() { + IFS=$'\n' + while read str; do + parse_object_kv_list "$str" + echo "$TOPIC" | sed -e "s/%quote%/'/g" + echo "$NOTICE" | sed -e "s/%quote%/'/g" + echo "$DATE $TIME" + echo "--" + echo + done < <(cat $USER_DATA/notifications.conf) +} + +# PLAIN list function +plain_list() { + IFS=$'\n' + while read str; do + parse_object_kv_list "$str" + TOPIC=$(echo "$TOPIC" | sed -e "s/%quote%/'/g") + NOTICE=$(echo "$NOTICE" | sed -e "s/%quote%/'/g") + echo -e "$NID\t$TOPIC\t$NOTICE\t$TIME\t$DATE" + done < <(cat $USER_DATA/notifications.conf) +} + +# CSV list function +csv_list() { + IFS=$'\n' + echo "NID,TOPIC,NOTICE,ACK,TIME,DATE" + while read str; do + parse_object_kv_list "$str" + TOPIC=$(echo "$TOPIC" | sed -e "s/%quote%/'/g") + NOTICE=$(echo "$NOTICE" | sed -e "s/%quote%/'/g") + echo "$NID,\"$TOPIC\",\"$NOTICE\",$ACK,$TIME,$DATE" + done < <(cat $USER_DATA/notifications.conf) +} + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +# Checking args +check_args '1' "$#" 'USER [FORMAT]' +is_format_valid 'user' +is_object_valid 'user' 'USER' "$user" + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-user-ns b/bin/v-list-user-ns new file mode 100755 index 0000000..4258bf4 --- /dev/null +++ b/bin/v-list-user-ns @@ -0,0 +1,92 @@ +#!/bin/bash +# info: list user nameservers +# options: USER [FORMAT] +# +# example: v-list-user-ns admin +# +# Function for obtaining the list of user's DNS servers. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +format=${2-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# JSON list function +json_list() { + i=1 + objects=$(echo -e "${ns//,/\\n}" | wc -l) + echo '[' + for nameserver in ${ns//,/ }; do + if [ "$i" -ne "$objects" ]; then + echo -e "\t\"$nameserver\"," + else + echo -e "\t\"$nameserver\"" + fi + ((++i)) + done + echo ']' +} + +# SHELL list function +shell_list() { + echo "NS" + echo "--" + for nameserver in ${ns//,/ }; do + echo "$nameserver" + done +} + +# PLAIN list function +plain_list() { + for nameserver in ${ns//,/ }; do + echo "$nameserver" + done +} + +# CSV list function +csv_list() { + echo "NAMESERVER" + for nameserver in ${ns//,/ }; do + echo "$nameserver" + done +} + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'USER [FORMAT]' +is_format_valid 'user' +is_object_valid 'user' 'USER' "$user" + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Parsing name servers +ns=$(grep "^NS='" "$USER_DATA/user.conf" | cut -f 2 -d \') + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-user-package b/bin/v-list-user-package new file mode 100755 index 0000000..309eaae --- /dev/null +++ b/bin/v-list-user-package @@ -0,0 +1,124 @@ +#!/bin/bash +# info: list user package +# options: PACKAGE [FORMAT] +# +# This function for getting the list of system ip parameters. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +package=$1 +PACKAGE=$package +format=${2-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" +# JSON list function +json_list() { + echo '{' + echo ' "'$PACKAGE'": { + "WEB_TEMPLATE": "'$WEB_TEMPLATE'", + "BACKEND_TEMPLATE": "'$BACKEND_TEMPLATE'", + "PROXY_TEMPLATE": "'$PROXY_TEMPLATE'", + "DNS_TEMPLATE": "'$DNS_TEMPLATE'", + "WEB_DOMAINS": "'$WEB_DOMAINS'", + "WEB_ALIASES": "'$WEB_ALIASES'", + "DNS_DOMAINS": "'$DNS_DOMAINS'", + "DNS_RECORDS": "'$DNS_RECORDS'", + "MAIL_DOMAINS": "'$MAIL_DOMAINS'", + "MAIL_ACCOUNTS": "'$MAIL_ACCOUNTS'", + "RATE_LIMIT": "'$RATE_LIMIT'", + "DATABASES": "'$DATABASES'", + "CRON_JOBS": "'$CRON_JOBS'", + "DISK_QUOTA": "'$DISK_QUOTA'", + "BANDWIDTH": "'$BANDWIDTH'", + "NS": "'$NS'", + "SHELL": "'$SHELL'", + "BACKUPS": "'$BACKUPS'", + "TIME": "'$TIME'", + "DATE": "'$DATE'" + }' + echo '}' +} + +# SHELL list function +shell_list() { + echo "PACKAGE: $PACKAGE" + echo "WEB TEMPLATE: $WEB_TEMPLATE" + echo "BACKEND TEMPLATE: $BACKEND_TEMPLATE" + echo "PROXY TEMPLATE: $PROXY_TEMPLATE" + echo "DNS TEMPLATE: $DNS_TEMPLATE" + echo "WEB DOMAINS: $WEB_DOMAINS" + echo "WEB ALIASES: $WEB_ALIASES" + echo "DNS DOMAINS: $DNS_DOMAINS" + echo "DNS RECORDS: $DNS_RECORDS" + echo "MAIL DOMAINS: $MAIL_DOMAINS" + echo "MAIL ACCOUNTS: $MAIL_ACCOUNTS" + echo "RATE_LIMIT: $RATE_LIMIT" + echo "DATABASES: $DATABASES" + echo "CRON JOBS: $CRON_JOBS" + echo "DISK QUOTA: $DISK_QUOTA" + echo "BANDWIDTH: $BANDWIDTH" + echo "NS: $NS" + echo "SHELL: $SHELL" + echo "BACKUPS: $BACKUPS" + echo "TIME: $TIME" + echo "DATE: $DATE" +} + +# PLAIN list function +plain_list() { + echo -ne "$PACKAGE\t$WEB_TEMPLATE\t$BACKEND_TEMPLATE\t$PROXY_TEMPLATE\t$DNS_TEMPLATE\t" + echo -ne "$WEB_DOMAINS\t$WEB_ALIASES\t$DNS_DOMAINS\t$DNS_RECORDS\t" + echo -ne "$MAIL_DOMAINS\t$MAIL_ACCOUNTS\t$RATE_LIMIT\t$DATABASES\t$CRON_JOBS\t" + echo -e "$DISK_QUOTA\t$BANDWIDTH\t$NS\t$SHELL\t$BACKUPS\t$TIME\t$DATE" +} + +# CSV list function +csv_list() { + echo -n "PACKAGE,WEB_TEMPLATE,BACKEND_TEMPLATE,PROXY_TEMPLATE,DNS_TEMPLATE," + echo -n "WEB_DOMAINS,WEB_ALIASES,DNS_DOMAINS,DNS_RECORDS," + echo -n "MAIL_DOMAINS,MAIL_ACCOUNTS,RATE_LIMIT,DATABASES,CRON_JOBS," + echo "DISK_QUOTA,BANDWIDTH,NS,SHELL,BACKUPS,TIME,DATE" + echo -n "$PACKAGE,$WEB_TEMPLATE,$BACKEND_TEMPLATE,$PROXY_TEMPLATE,$DNS_TEMPLATE," + echo -n "$WEB_DOMAINS,$WEB_ALIASES,$DNS_DOMAINS,$DNS_RECORDS," + echo -n "$MAIL_DOMAINS,$MAIL_ACCOUNTS,$RATE_LIMIT,$DATABASES,$CRON_JOBS," + echo "$DISK_QUOTA,$BANDWIDTH,\"$NS\",$SHELL,$BACKUPS,$TIME,$DATE" +} + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +# Checking args +check_args '1' "$#" 'PACKAGE [FORMAT]' +is_format_valid 'package' +is_package_valid + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Parsing package +source_conf "$HESTIA/data/packages/$PACKAGE.pkg" + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-user-packages b/bin/v-list-user-packages new file mode 100755 index 0000000..4d7324b --- /dev/null +++ b/bin/v-list-user-packages @@ -0,0 +1,122 @@ +#!/bin/bash +# info: list user packages +# options: [FORMAT] +# +# This function for obtaining the list of available hosting packages. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +format=${1-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# JSON list function +json_list() { + IFS=$'\n' + i=1 + objects=$(echo "$packages" | wc -l) + echo "{" + for package in $packages; do + PACKAGE=${package/.pkg/} + source_conf "$HESTIA/data/packages/$PACKAGE.pkg" + echo -n ' "'$PACKAGE'": { + "WEB_TEMPLATE": "'$WEB_TEMPLATE'", + "PROXY_TEMPLATE": "'$PROXY_TEMPLATE'", + "DNS_TEMPLATE": "'$DNS_TEMPLATE'", + "WEB_DOMAINS": "'$WEB_DOMAINS'", + "WEB_ALIASES": "'$WEB_ALIASES'", + "DNS_DOMAINS": "'$DNS_DOMAINS'", + "DNS_RECORDS": "'$DNS_RECORDS'", + "MAIL_DOMAINS": "'$MAIL_DOMAINS'", + "MAIL_ACCOUNTS": "'$MAIL_ACCOUNTS'", + "DATABASES": "'$DATABASES'", + "CRON_JOBS": "'$CRON_JOBS'", + "DISK_QUOTA": "'$DISK_QUOTA'", + "BANDWIDTH": "'$BANDWIDTH'", + "NS": "'$NS'", + "SHELL": "'$SHELL'", + "BACKUPS": "'$BACKUPS'", + "TIME": "'$TIME'", + "DATE": "'$DATE'" + }' + if [ "$i" -lt "$objects" ]; then + echo ',' + else + echo + fi + ((i++)) + done + echo '}' +} + +# SHELL list function +shell_list() { + echo "PKG TPL WEB DNS MAIL DB SHELL DISK BW" + echo "--- --- --- --- ---- -- ----- ---- --" + for package in $packages; do + source $HESTIA/data/packages/$package + PACKAGE=${package/.pkg/} + package_data=$(cat $HESTIA/data/packages/$package) + package_data=$(echo "$package_data" | sed -e 's/unlimited/unlim/g') + parse_object_kv_list "$package_data" + echo -n "$PACKAGE $WEB_TEMPLATE $WEB_DOMAINS $DNS_DOMAINS " + echo "$MAIL_DOMAINS $DATABASES $SHELL $DISK_QUOTA $BANDWIDTH" + done +} + +# PLAIN list function +plain_list() { + for package in $packages; do + source $HESTIA/data/packages/$package + PACKAGE=${package/.pkg/} + echo -ne "$PACKAGE\t$WEB_TEMPLATE\t$PROXY_TEMPLATE\t$DNS_TEMPLATE\t" + echo -ne "$WEB_DOMAINS\t$WEB_ALIASES\t$DNS_DOMAINS\t$DNS_RECORDS\t" + echo -ne "$MAIL_DOMAINS\t$MAIL_ACCOUNTS\t$DATABASES\t$CRON_JOBS\t" + echo -e "$DISK_QUOTA\t$BANDWIDTH\t$NS\t$SHELL\t$BACKUPS\t$TIME\t$DATE" + done +} + +# CSV list function +csv_list() { + echo -n "PACKAGE,WEB_TEMPLATE,PROXY_TEMPLATE,DNS_TEMPLATE," + echo -n "WEB_DOMAINS,WEB_ALIASES,DNS_DOMAINS,DNS_RECORDS," + echo -n "MAIL_DOMAINS,MAIL_ACCOUNTS,DATABASES,CRON_JOBS," + echo "DISK_QUOTA,BANDWIDTH,NS,SHELL,BACKUPS,TIME,DATE" + for package in $packages; do + PACKAGE=${package/.pkg/} + echo -n "$PACKAGE,$WEB_TEMPLATE,$PROXY_TEMPLATE,$DNS_TEMPLATE," + echo -n "$WEB_DOMAINS,$WEB_ALIASES,$DNS_DOMAINS,$DNS_RECORDS," + echo -n "$MAIL_DOMAINS,$MAIL_ACCOUNTS,$DATABASES,$CRON_JOBS," + echo "$DISK_QUOTA,$BANDWIDTH,\"$NS\",$SHELL,$BACKUPS,$TIME,$DATE" + done +} + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Parsing packages +packages=$(ls --sort=time $HESTIA/data/packages | grep .pkg) + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list | column -t ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-user-ssh-key b/bin/v-list-user-ssh-key new file mode 100755 index 0000000..bd1e50d --- /dev/null +++ b/bin/v-list-user-ssh-key @@ -0,0 +1,121 @@ +#!/bin/bash +# info: add ssh key +# options: USER [FORMAT] +# +# Lists $user/.ssh/authorized_keys + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 + +format=${2-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# JSON list function +json_list() { + IFS=$'\n' + i=1 + objects=$(echo "$keys" | wc -l) + echo "{" + for str in $keys; do + KEY=$(echo $str | awk '{print $(NF-2)}') + ID=$(echo $str | awk '{print $(NF-1)}') + echo -n ' "'$ID'": { + "ID": "'$ID'", + "KEY": "'$KEY'" + }' + if [ "$i" -lt "$objects" ]; then + echo ',' + fi + ((i++)) + done + echo "}" +} + +shell_list() { + IFS=$'\n' + echo "ID~KEY" + echo "----~----~---" + for str in $keys; do + KEY=$(echo $str | awk '{print $(NF-2)}') + ID=$(echo $str | awk '{print $(NF-1)}') + echo "$ID~$KEY" + done +} + +# PLAIN list function +plain_list() { + IFS=$'\n' + for str in $keys; do + KEY=$(echo $str | awk '{print $(NF-2)}') + ID=$(echo $str | awk '{print $(NF-1)}') + echo -e "$ID\t$KEY" + done +} + +# CSV list function +csv_list() { + IFS=$'\n' + echo "ID,KEY" + for str in $keys; do + KEY=$(echo $str | awk '{print $(NF-2)}') + ID=$(echo $str | awk '{print $(NF-1)}') + echo "\"$ID\",\"$KEY\"" + done +} + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'USER' +is_format_valid 'user' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +AUTHKEY_FILE="$HOMEDIR/$user/.ssh/authorized_keys" +[ -z "$(readlink -f "$AUTHKEY_FILE" | egrep "^$HOMEDIR/$user/.ssh/")" ] && check_result $E_FORBIDEN "Invalid authorized keys path" + +#check if file exsists +if [ ! -f "$AUTHKEY_FILE" ]; then + exit +fi + +first_loop=1 +while read l; do + sshkey=$([[ -n $l && ${l###} = $l ]] && ssh-keygen -l -f <(echo $l)) + if [ -n "$sshkey" ]; then + (($first_loop)) && keys="$sshkey" || keys="$keys"$'\n'"$sshkey" + unset first_loop + fi +done < "$AUTHKEY_FILE" + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list | column -t ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging + +exit diff --git a/bin/v-list-user-stats b/bin/v-list-user-stats new file mode 100755 index 0000000..3dea3c5 --- /dev/null +++ b/bin/v-list-user-stats @@ -0,0 +1,151 @@ +#!/bin/bash +# info: list user stats +# options: USER [FORMAT] +# +# example: v-list-user-stats admin +# +# This function for listing user statistics + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +format=${2-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# JSON list function +json_list() { + IFS=$'\n' + i=1 + objects=$(grep DATE $USER_DATA/stats.log | wc -l) + echo "{" + while read str; do + parse_object_kv_list "$str" + echo -n ' "'$DATE'": { + "TIME": "'$TIME'", + "PACKAGE": "'$PACKAGE'", + "IP_OWNED": "'$IP_OWNED'", + "DISK_QUOTA": "'$DISK_QUOTA'", + "U_DISK": "'$U_DISK'", + "U_DISK_DIRS": "'$U_DISK_DIRS'", + "U_DISK_WEB": "'$U_DISK_WEB'", + "U_DISK_MAIL": "'$U_DISK_MAIL'", + "U_DISK_DB": "'$U_DISK_DB'", + "BANDWIDTH": "'$BANDWIDTH'", + "U_BANDWIDTH": "'$U_BANDWIDTH'", + "U_WEB_DOMAINS": "'$U_WEB_DOMAINS'", + "U_WEB_SSL": "'$U_WEB_SSL'", + "U_WEB_ALIASES": "'$U_WEB_ALIASES'", + "U_DNS_DOMAINS": "'$U_DNS_DOMAINS'", + "U_DNS_RECORDS": "'$U_DNS_RECORDS'", + "U_MAIL_DOMAINS": "'$U_MAIL_DOMAINS'", + "U_MAIL_DKIM": "'$U_MAIL_DKIM'", + "U_MAIL_ACCOUNTS": "'$U_MAIL_ACCOUNTS'", + "U_DATABASES": "'$U_DATABASES'", + "U_CRON_JOBS": "'$U_CRON_JOBS'", + "U_BACKUPS": "'$U_BACKUPS'" + }' + if [ "$i" -lt "$objects" ]; then + echo ',' + else + echo + fi + ((i++)) + done < <(cat $USER_DATA/stats.log) + echo '}' +} + +# SHELL list function +shell_list() { + IFS=$'\n' + echo "DATE WEB DNS MAIL DB BACKUPS IP DISK BW" + echo "---- --- --- ---- -- ------- -- ---- --" + while read str; do + parse_object_kv_list "$str" + if [ -z "$U_USERS" ]; then + U_USERS=1 + fi + echo -n "$DATE $U_WEB_DOMAINS $U_DNS_DOMAINS " + echo -n "$U_MAIL_DOMAINS $U_DATABASES $U_BACKUPS $IP_OWNED " + echo "$U_DISK $U_BANDWIDTH" + done < <(cat $USER_DATA/stats.log) +} + +# PLAIN list function +plain_list() { + IFS=$'\n' + while read str; do + parse_object_kv_list "$str" + echo -ne "$DATE\t$TIME\t$PACKAGE\t$IP_OWNED\t$DISK_QUOTA\t$U_DISK\t" + echo -ne "$U_DISK_DIRS\t$U_DISK_WEB\t$U_DISK_MAIL\t$U_DISK_DB\t" + echo -ne "$BANDWIDTH\t$U_BANDWIDTH\t$U_WEB_DOMAINS\t$U_WEB_SSL\t" + echo -ne "$U_WEB_ALIASES\t$U_DNS_DOMAINS\t$U_DNS_RECORDS\t" + echo -ne "$U_MAIL_DOMAINS\t$U_MAIL_DKIM\t$U_MAIL_ACCOUNTS\t" + echo -e "$U_DATABASES\t$U_CRON_JOBS\t$U_BACKUPS" + done < <(cat $USER_DATA/stats.log) +} + +# CSV list function +csv_list() { + IFS=$'\n' + echo -n "DATE,TIME,PACKAGE,IP_OWNED,DISK_QUOTA,U_DISK," + echo -n "U_DISK_DIRS,U_DISK_WEB,U_DISK_MAIL,U_DISK_DB," + echo -n "BANDWIDTH,U_BANDWIDTH,U_WEB_DOMAINS,U_WEB_SSL," + echo -n "U_WEB_ALIASES,U_DNS_DOMAINS,U_DNS_RECORDS," + echo -n "U_MAIL_DOMAINS,U_MAIL_DKIM,U_MAIL_ACCOUNTS," + echo "U_DATABASES,U_CRON_JOBS,U_BACKUPS" + + while read str; do + parse_object_kv_list "$str" + echo -n "$DATE,$TIME,$PACKAGE,$IP_OWNED,$DISK_QUOTA,$U_DISK," + echo -n "$U_DISK_DIRS,$U_DISK_WEB,$U_DISK_MAIL,$U_DISK_DB," + echo -n "$BANDWIDTH,$U_BANDWIDTH,$U_WEB_DOMAINS,$U_WEB_SSL," + echo -n "$U_WEB_ALIASES,$U_DNS_DOMAINS,$U_DNS_RECORDS," + echo -n "$U_MAIL_DOMAINS,$U_MAIL_DKIM,$U_MAIL_ACCOUNTS," + echo "$U_DATABASES,$U_CRON_JOBS,$U_BACKUPS" + done < <(cat $USER_DATA/stats.log) +} + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'USER [FORMAT]' +is_format_valid 'user' +is_object_valid 'user' 'USER' "$user" + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Ensure statistics are up to date +$BIN/v-update-user-stats $user + +# Defining config +conf="$USER_DATA/stats.log" +if [ ! -e "$conf" ]; then + touch $conf +fi + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list | column -t ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-users b/bin/v-list-users new file mode 100755 index 0000000..a78b7c1 --- /dev/null +++ b/bin/v-list-users @@ -0,0 +1,194 @@ +#!/bin/bash +# info: list users +# options: [FORMAT] +# +# example: v-list-users +# +# This function to obtain the list of all system users. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Argument definition +format=${1-shell} + +# JSON list function +json_list() { + echo '{' + i=1 + while read USER; do + if [ ! -f "$HESTIA/data/users/$USER/user.conf" ]; then + continue + fi + if [ $i -gt 1 ]; then + echo "," + fi + source_conf "$HESTIA/data/users/$USER/user.conf" + echo -n ' "'$USER'": { + "NAME": "'$NAME'", + "PACKAGE": "'$PACKAGE'", + "WEB_TEMPLATE": "'$WEB_TEMPLATE'", + "BACKEND_TEMPLATE": "'$BACKEND_TEMPLATE'", + "PROXY_TEMPLATE": "'$PROXY_TEMPLATE'", + "DNS_TEMPLATE": "'$DNS_TEMPLATE'", + "WEB_DOMAINS": "'$WEB_DOMAINS'", + "WEB_ALIASES": "'$WEB_ALIASES'", + "DNS_DOMAINS": "'$DNS_DOMAINS'", + "DNS_RECORDS": "'$DNS_RECORDS'", + "MAIL_DOMAINS": "'$MAIL_DOMAINS'", + "MAIL_ACCOUNTS": "'$MAIL_ACCOUNTS'", + "DATABASES": "'$DATABASES'", + "CRON_JOBS": "'$CRON_JOBS'", + "DISK_QUOTA": "'$DISK_QUOTA'", + "BANDWIDTH": "'$BANDWIDTH'", + "NS": "'$NS'", + "SHELL": "'$SHELL'", + "BACKUPS": "'$BACKUPS'", + "CONTACT": "'$CONTACT'", + "CRON_REPORTS": "'$CRON_REPORTS'", + "RKEY": "'$RKEY'", + "SUSPENDED": "'$SUSPENDED'", + "SUSPENDED_USERS": "'$SUSPENDED_USERS'", + "SUSPENDED_WEB": "'$SUSPENDED_WEB'", + "SUSPENDED_DNS": "'$SUSPENDED_DNS'", + "SUSPENDED_MAIL": "'$SUSPENDED_MAIL'", + "SUSPENDED_DB": "'$SUSPENDED_DB'", + "SUSPENDED_CRON": "'$SUSPENDED_CRON'", + "IP_AVAIL": "'$IP_AVAIL'", + "IP_OWNED": "'$IP_OWNED'", + "U_USERS": "'$U_USERS'", + "U_DISK": "'$U_DISK'", + "U_DISK_DIRS": "'$U_DISK_DIRS'", + "U_DISK_WEB": "'$U_DISK_WEB'", + "U_DISK_MAIL": "'$U_DISK_MAIL'", + "U_DISK_DB": "'$U_DISK_DB'", + "U_BANDWIDTH": "'$U_BANDWIDTH'", + "U_WEB_DOMAINS": "'$U_WEB_DOMAINS'", + "U_WEB_SSL": "'$U_WEB_SSL'", + "U_WEB_ALIASES": "'$U_WEB_ALIASES'", + "U_DNS_DOMAINS": "'$U_DNS_DOMAINS'", + "U_DNS_RECORDS": "'$U_DNS_RECORDS'", + "U_MAIL_DOMAINS": "'$U_MAIL_DOMAINS'", + "U_MAIL_DKIM": "'$U_MAIL_DKIM'", + "U_MAIL_ACCOUNTS": "'$U_MAIL_ACCOUNTS'", + "U_DATABASES": "'$U_DATABASES'", + "U_CRON_JOBS": "'$U_CRON_JOBS'", + "U_BACKUPS": "'$U_BACKUPS'", + "LANGUAGE": "'$LANGUAGE'", + "TIME": "'$TIME'", + "DATE": "'$DATE'" + }' + ((i++)) + done < <(grep '@' /etc/passwd | cut -f1 -d:) + echo '}' +} + +# SHELL list function +shell_list() { + echo "USER PKG WEB DNS MAIL DB DISK BW SPND DATE" + echo "---- --- --- --- --- -- ---- -- ---- ----" + while read USER; do + if [ ! -f "$HESTIA/data/users/$USER/user.conf" ]; then + continue + fi + source_conf "$HESTIA/data/users/$USER/user.conf" + echo -n "$USER $PACKAGE $U_WEB_DOMAINS $U_DNS_DOMAINS $U_MAIL_DOMAINS" + echo " $U_DATABASES $U_DISK $U_BANDWIDTH $SUSPENDED $DATE" + done < <(grep '@' /etc/passwd | cut -f1 -d:) +} + +# PLAIN list function +plain_list() { + while read USER; do + if [ ! -f "$HESTIA/data/users/$USER/user.conf" ]; then + continue + fi + source_conf "$HESTIA/data/users/$USER/user.conf" + echo -ne "$USER\t$NAME\t$PACKAGE\t$WEB_TEMPLATE\t" + echo -ne "$BACKEND_TEMPLATE\t$PROXY_TEMPLATE\t$DNS_TEMPLATE\t" + echo -ne "$WEB_DOMAINS\t$WEB_ALIASES\t$DNS_DOMAINS\t$DNS_RECORDS\t" + echo -ne "$MAIL_DOMAINS\t$MAIL_ACCOUNTS\t$DATABASES\t$CRON_JOBS\t" + echo -ne "$DISK_QUOTA\t$BANDWIDTH\t$NS\t$SHELL\t$BACKUPS\t" + echo -ne "$CONTACT\t$CRON_REPORTS\t$RKEY\t$SUSPENDED\t" + echo -ne "$SUSPENDED_USERS\t$SUSPENDED_WEB\t$SUSPENDED_DNS\t" + echo -ne "$SUSPENDED_MAIL\t$SUSPENDED_DB\t$SUSPENDED_CRON\t" + echo -ne "$IP_AVAIL\t$IP_OWNED\t$U_USERS\t$U_DISK\t$U_DISK_DIRS\t" + echo -ne "$U_DISK_WEB\t$U_DISK_MAIL\t$U_DISK_DB\t$U_BANDWIDTH\t" + echo -ne "$U_WEB_DOMAINS\t$U_WEB_SSL\t$U_WEB_ALIASES\t" + echo -ne "$U_DNS_DOMAINS\t$U_DNS_RECORDS\t$U_MAIL_DOMAINS\t" + echo -ne "$U_MAIL_DKIM\t$U_MAIL_ACCOUNTS\t$U_DATABASES\t" + echo -e "$U_CRON_JOBS\t$U_BACKUPS\t$LANGUAGE\t$TIME\t$DATE\t" + done < <(grep '@' /etc/passwd | cut -f1 -d:) +} + +# CSV list function +csv_list() { + echo -n "USER,NAME,PACKAGE,WEB_TEMPLATE,BACKEND_TEMPLATE," + echo -n "PROXY_TEMPLATE,DNS_TEMPLATE,WEB_DOMAINS,WEB_ALIASES," + echo -n "DNS_DOMAINS,DNS_RECORDS,MAIL_DOMAINS,MAIL_ACCOUNTS," + echo -n "DATABASES,CRON_JOBS,DISK_QUOTA,BANDWIDTH,NS,HOME,SHELL," + echo -n "BACKUPS,CONTACT,CRON_REPORTS,RKEY,SUSPENDED,SUSPENDED_USERS," + echo -n "SUSPENDED_WEB,SUSPENDED_DNS,SUSPENDED_MAIL,SUSPENDED_DB," + echo -n "SUSPENDED_CRON,IP_AVAIL,IP_OWNED,U_USERS,U_DISK,U_DISK_DIRS," + echo -n "U_DISK_WEB,U_DISK_MAIL,U_DISK_DB,U_BANDWIDTH,U_WEB_DOMAINS," + echo -n "U_WEB_SSL,U_WEB_ALIASES,U_DNS_DOMAINS,U_DNS_RECORDS," + echo -n "U_MAIL_DOMAINS,U_MAIL_DKIM,U_MAIL_ACCOUNTS,U_DATABASES" + echo "U_CRON_JOBS,U_BACKUPS,LANGUAGE,TIME,DATE" + while read USER; do + if [ ! -f "$HESTIA/data/users/$USER/user.conf" ]; then + continue + fi + source_conf "$HESTIA/data/users/$USER/user.conf" + echo -n "$USER,\"$NAME\",$PACKAGE,$WEB_TEMPLATE," + echo -n "$BACKEND_TEMPLATE,$PROXY_TEMPLATE,$DNS_TEMPLATE," + echo -n "$WEB_DOMAINS,$WEB_ALIASES,$DNS_DOMAINS,$DNS_RECORDS," + echo -n "$MAIL_DOMAINS,$MAIL_ACCOUNTS,$DATABASES,$CRON_JOBS," + echo -n "$DISK_QUOTA,$BANDWIDTH,\"$NS\",$HOME,$SHELL,$BACKUPS," + echo -n "$CONTACT,$CRON_REPORTS,\"$RKEY\",$SUSPENDED," + echo -n "$SUSPENDED_USERS,$SUSPENDED_WEB,$SUSPENDED_DNS," + echo -n "$SUSPENDED_MAIL,$SUSPENDED_DB,$SUSPENDED_CRON,$IP_AVAIL," + echo -n "$IP_OWNED,$U_USERS,$U_DISK,$U_DISK_DIRS,$U_DISK_WEB," + echo -n "$U_DISK_MAIL,$U_DISK_DB,$U_BANDWIDTH,$U_WEB_DOMAINS," + echo -n "$U_WEB_SSL,$U_WEB_ALIASES,$U_DNS_DOMAINS,$U_DNS_RECORDS," + echo -n "$U_MAIL_DOMAINS,$U_MAIL_DKIM,$U_MAIL_ACCOUNTS,$U_DATABASES," + echo "$U_CRON_JOBS,$U_BACKUPS,$LANGUAGE,$TIME,$DATE" + done < <(grep '@' /etc/passwd | cut -f1 -d:) +} + +# Raw list function +raw_list() { + while read USER; do + if [ ! -f "$HESTIA/data/users/$USER/user.conf" ]; then + continue + fi + echo $HESTIA/data/users/$USER/user.conf + cat $HESTIA/data/users/$USER/user.conf + done < <(grep '@' /etc/passwd | cut -f1 -d:) +} + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list | column -t ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-users-stats b/bin/v-list-users-stats new file mode 100755 index 0000000..0bc8ef5 --- /dev/null +++ b/bin/v-list-users-stats @@ -0,0 +1,147 @@ +#!/bin/bash +# info: list overall user stats +# options: [FORMAT] +# +# This function for listing overall user statistics + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +format=${1-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# JSON list function +json_list() { + IFS=$'\n' + i=1 + objects=$(grep DATE $HESTIA/data/users/admin/overall_stats.log | wc -l) + echo "{" + while read str; do + parse_object_kv_list "$str" + echo -n ' "'$DATE'": { + "TIME": "'$TIME'", + "PACKAGE": "'$PACKAGE'", + "IP_OWNED": "'$IP_OWNED'", + "DISK_QUOTA": "'$DISK_QUOTA'", + "U_DISK": "'$U_DISK'", + "U_DISK_DIRS": "'$U_DISK_DIRS'", + "U_DISK_WEB": "'$U_DISK_WEB'", + "U_DISK_MAIL": "'$U_DISK_MAIL'", + "U_DISK_DB": "'$U_DISK_DB'", + "BANDWIDTH": "'$BANDWIDTH'", + "U_BANDWIDTH": "'$U_BANDWIDTH'", + "U_WEB_DOMAINS": "'$U_WEB_DOMAINS'", + "U_WEB_SSL": "'$U_WEB_SSL'", + "U_WEB_ALIASES": "'$U_WEB_ALIASES'", + "U_DNS_DOMAINS": "'$U_DNS_DOMAINS'", + "U_DNS_RECORDS": "'$U_DNS_RECORDS'", + "U_MAIL_DOMAINS": "'$U_MAIL_DOMAINS'", + "U_MAIL_DKIM": "'$U_MAIL_DKIM'", + "U_MAIL_ACCOUNTS": "'$U_MAIL_ACCOUNTS'", + "U_DATABASES": "'$U_DATABASES'", + "U_CRON_JOBS": "'$U_CRON_JOBS'", + "U_BACKUPS": "'$U_BACKUPS'", + "U_USERS": "'$U_USERS'" + }' + if [ "$i" -lt "$objects" ]; then + echo ',' + else + echo + fi + ((i++)) + done < <(cat $HESTIA/data/users/admin/overall_stats.log) + echo '}' +} + +# SHELL list function +shell_list() { + IFS=$'\n' + echo "DATE USER WEB DNS MAIL DB BACKUPS IP DISK BW" + echo "---- ---- --- --- ---- -- ------- -- ---- --" + while read str; do + parse_object_kv_list "$str" + if [ -z "$U_USERS" ]; then + U_USERS=1 + fi + echo -n "$DATE $U_USERS $U_WEB_DOMAINS $U_DNS_DOMAINS " + echo -n "$U_MAIL_DOMAINS $U_DATABASES $U_BACKUPS $IP_OWNED " + echo "$U_DISK $U_BANDWIDTH" + done < <(cat $HESTIA/data/users/admin/overall_stats.log) +} + +# PLAIN list function +plain_list() { + IFS=$'\n' + while read str; do + parse_object_kv_list "$str" + echo -ne "$DATE\t$TIME\t$PACKAGE\t$IP_OWNED\t$DISK_QUOTA\t$U_DISK\t" + echo -ne "$U_DISK_DIRS\t$U_DISK_WEB\t$U_DISK_MAIL\t$U_DISK_DB\t" + echo -ne "$BANDWIDTH\t$U_BANDWIDTH\t$U_WEB_DOMAINS\t$U_WEB_SSL\t" + echo -ne "$U_WEB_ALIASES\t$U_DNS_DOMAINS\t$U_DNS_RECORDS\t" + echo -ne "$U_MAIL_DOMAINS\t$U_MAIL_DKIM\t$U_MAIL_ACCOUNTS\t" + echo -e "$U_DATABASES\t$U_CRON_JOBS\t$U_BACKUPS\t$U_USERS" + done < <(cat $HESTIA/data/users/admin/overall_stats.log) +} + +# CSV list function +csv_list() { + IFS=$'\n' + echo -n "DATE,TIME,PACKAGE,IP_OWNED,DISK_QUOTA,U_DISK," + echo -n "U_DISK_DIRS,U_DISK_WEB,U_DISK_MAIL,U_DISK_DB," + echo -n "BANDWIDTH,U_BANDWIDTH,U_WEB_DOMAINS,U_WEB_SSL," + echo -n "U_WEB_ALIASES,U_DNS_DOMAINS,U_DNS_RECORDS," + echo -n "U_MAIL_DOMAINS,U_MAIL_DKIM,U_MAIL_ACCOUNTS," + echo "U_DATABASES,U_CRON_JOBS,U_BACKUPS,U_USERS" + + while read str; do + parse_object_kv_list "$str" + echo -n "$DATE,$TIME,$PACKAGE,$IP_OWNED,$DISK_QUOTA,$U_DISK," + echo -n "$U_DISK_DIRS,$U_DISK_WEB,$U_DISK_MAIL,$U_DISK_DB," + echo -n "$BANDWIDTH,$U_BANDWIDTH,$U_WEB_DOMAINS,$U_WEB_SSL," + echo -n "$U_WEB_ALIASES,$U_DNS_DOMAINS,$U_DNS_RECORDS," + echo -n "$U_MAIL_DOMAINS,$U_MAIL_DKIM,$U_MAIL_ACCOUNTS," + echo "$U_DATABASES,$U_CRON_JOBS,$U_BACKUPS,$U_USERS" + done < <(cat $HESTIA/data/users/admin/overall_stats.log) +} + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '0' "$#" '[FORMAT]' + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Ensure statistics are up to date +$BIN/v-update-user-stats + +# Defining config +conf="$HESTIA/data/users/admin/overall_stats.log" +if [ ! -e "$conf" ]; then + touch $conf +fi + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list | column -t ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-web-domain b/bin/v-list-web-domain new file mode 100755 index 0000000..55d7a96 --- /dev/null +++ b/bin/v-list-web-domain @@ -0,0 +1,160 @@ +#!/bin/bash +# info: list web domain parameters +# options: USER DOMAIN [FORMAT] +# +# example: v-list-web-domain admin example.com +# +# This function to obtain web domain parameters. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +format=${3-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# JSON list function +json_list() { + echo '{' + echo ' "'$DOMAIN'": { + "IP": "'$IP'", + "IP6": "'$IP6'", + "DOCUMENT_ROOT": "'$DOCROOT'", + "U_DISK": "'$U_DISK'", + "U_BANDWIDTH": "'$U_BANDWIDTH'", + "TPL": "'$TPL'", + "ALIAS": "'$ALIAS'", + "STATS": "'$STATS'", + "STATS_USER": "'$STATS_USER'", + "SSL": "'$SSL'", + "SSL_FORCE": "'$SSL_FORCE'", + "SSL_HSTS": "'$SSL_HSTS'", + "SSL_HOME": "'$SSL_HOME'", + "LETSENCRYPT": "'$LETSENCRYPT'", + "FTP_USER": "'$FTP_USER'", + "FTP_PATH": "'$FTP_PATH'", + "AUTH_USER": "'$AUTH_USER'", + "BACKEND": "'$BACKEND'", + "PROXY": "'$PROXY'", + "PROXY_EXT": "'$PROXY_EXT'", + "FASTCGI_CACHE": "'$FASTCGI_CACHE'", + "FASTCGI_DURATION": "'$FASTCGI_DURATION'", + "REDIRECT": "'$REDIRECT'", + "REDIRECT_CODE": "'$REDIRECT_CODE'", + "CUSTOM_DOCROOT": "'$CUSTOM_DOCROOT'", + "SUSPENDED": "'$SUSPENDED'", + "TIME": "'$TIME'", + "DATE": "'$DATE'" + }' + echo '}' +} + +# SHELL list function +shell_list() { + echo "DOMAIN: $DOMAIN" + echo "ALIAS: ${ALIAS//,/ }" + echo "IP: $IP" + echo "DOCUMENT_ROOT: $DOCROOT" + if [ -n "$IP6" ]; then + echo "IP6: $IP6" + fi + if [ -n "$SSL" ] && [ "$SSL" != 'no' ]; then + echo "SSL: $SSL / $SSL_HOME" + if [ -n "$LETSENCRYPT" ] && [ "$LETSENCRYPT" != 'no' ]; then + echo "LETSENCRYPT: $LETSENCRYPT" + fi + if [ -n "$SSL_FORCE" ]; then + echo "SSL_FORCE: $SSL_FORCE" + fi + if [ -n "$SSL_HSTS" ]; then + echo "SSL_HSTS: $SSL_HSTS" + fi + fi + echo "TEMPLATE: $TPL" + if [ -n "$WEB_BACKEND" ]; then + echo "BACKEND: $BACKEND" + fi + if [ -n "$PROXY_SYSTEM" ]; then + echo "PROXY: $PROXY" + echo "PROXY EXT: ${PROXY_EXT//,/ }" + fi + if [ -n "$STATS" ]; then + echo "STATS: $STATS" + fi + if [ -n "$FTP_USER" ]; then + echo "FTP_USER: ${FTP_USER//,/, }" + fi + if [ -n "$AUTH_USER" ]; then + echo "HTTP_AUTH: $AUTH_USER" + fi + echo "DISK: $U_DISK" + echo "BW: $U_BANDWIDTH" + echo "SUSPENDED: $SUSPENDED" + echo "TIME: $TIME" + echo "DATE: $DATE" +} + +# PLAIN list function +plain_list() { + echo -ne "$DOMAIN\t$IP\t$IP6\t$DOCROOT\t$U_DISK\t$U_BANDWIDTH\t$TPL\t" + echo -ne "$ALIAS\t$STATS\t$STATS_USER\t$SSL\t$SSL_FORCE\t$SSL_HSTS\t$SSL_HOME\t,$LETSENCRYPT" + echo -ne "$FTP_USER\t$FTP_PATH\t$AUTH_USER\t$BACKEND\t$PROXY\t" + echo -e "$PROXY_EXT\t$SUSPENDED\t$TIME\t$DATE" +} + +# CSV list function +csv_list() { + echo -n "DOMAIN,IP,IP6,DOCROOT,U_DISK,U_BANDWIDTH,TPL,ALIAS,STATS,STATS_USER,SSL," + echo -n "SSL_FORCE,SSL_HSTS,SSL_HOME,LETSENCRYPT,FTP_USER,FTP_PATH,AUTH_USER,BACKEND,PROXY,PROXY_EXT," + echo "SUSPENDED,TIME,DATE" + echo -n "$DOMAIN,$IP,$IP6,$DOCROOT,$U_DISK,$U_BANDWIDTH,$TPL,\"$ALIAS\",$STATS" + echo -n "\"$STATS_USER\",$SSL,$SSL_FORCE,$SSL_HSTS,$SSL_HOME,$LETSENCRYPT,\"$FTP_USER\",\"$FTP_PATH\"," + echo -n "\"$AUTH_USER\",$BACKEND,$PROXY,\"$PROXY_EXT\",$SUSPENDED,$TIME," + echo "$DATE" +} + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DOMAIN [FORMAT]' +is_format_valid 'user' 'domain' +is_object_valid 'user' 'USER' "$user" +is_object_valid 'web' 'DOMAIN' "$domain" + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Parsing domain +parse_object_kv_list $(grep "DOMAIN='$domain'" $USER_DATA/web.conf) + +if [ -n "$CUSTOM_DOCROOT" ]; then + DOCROOT="$CUSTOM_DOCROOT" +else + DOCROOT="$HOMEDIR/$user/web/$DOMAIN/public_html/" +fi + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-web-domain-accesslog b/bin/v-list-web-domain-accesslog new file mode 100755 index 0000000..61ef64a --- /dev/null +++ b/bin/v-list-web-domain-accesslog @@ -0,0 +1,95 @@ +#!/bin/bash +# info: list web domain access log +# options: USER DOMAIN [LINES] [FORMAT] +# +# example: v-list-web-domain-accesslog admin example.com +# +# This function of obtaining raw access web domain logs. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +ttl=${3-70} +format=${4-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# JSON list function +json_list() { + i=1 + objects=$(echo "$lines" | wc -l) + echo '[' + for str in $lines; do + str=$(echo "$str" | sed -e 's/"/\\"/g') + if [ "$i" -lt "$objects" ]; then + echo -e "\t\"$str\"," + else + echo -e "\t\"$str\"" + fi + ((++i)) + done + echo "]" +} + +# SHELL list function +shell_list() { + echo "$lines" +} + +# PLAIN list function +plain_list() { + echo "$lines" +} + +# CSV list function +csv_list() { + echo "LOG" + echo "$lines" +} + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DOMAIN [LINES] [FORMAT]' +is_format_valid 'user' 'domain' 'ttl' +is_object_valid 'user' 'USER' "$user" +is_object_valid 'web' 'DOMAIN' "$domain" + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Check number of output lines +if [ "$ttl" -gt '3000' ]; then + read_cmd="cat" +else + read_cmd="tail -n $ttl" +fi + +lines=$($read_cmd /var/log/$WEB_SYSTEM/domains/$domain.log) +IFS=$'\n' + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-web-domain-errorlog b/bin/v-list-web-domain-errorlog new file mode 100755 index 0000000..6a53628 --- /dev/null +++ b/bin/v-list-web-domain-errorlog @@ -0,0 +1,95 @@ +#!/bin/bash +# info: list web domain error log +# options: USER DOMAIN [LINES] [FORMAT] +# +# example: v-list-web-domain-errorlog admin acme.com +# +# This function of obtaining raw error web domain logs. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +ttl=${3-70} +format=${4-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# JSON list function +json_list() { + i=1 + objects=$(echo "$lines" | wc -l) + echo '[' + for str in $lines; do + str=$(echo "$str" | sed -e 's/"/\\"/g') + if [ "$i" -lt "$objects" ]; then + echo -e "\t\"$str\"," + else + echo -e "\t\"$str\"" + fi + ((++i)) + done + echo "]" +} + +# SHELL list function +shell_list() { + echo "$lines" +} + +# PLAIN list function +plain_list() { + echo "$lines" +} + +# CSV list function +csv_list() { + echo "LOG" + echo "$lines" +} + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DOMAIN [LINES] [FORMAT]' +is_format_valid 'user' 'domain' 'ttl' +is_object_valid 'user' 'USER' "$user" +is_object_valid 'web' 'DOMAIN' "$domain" + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Check number of output lines +if [ "$ttl" -gt '3000' ]; then + read_cmd="cat" +else + read_cmd="tail -n $ttl" +fi + +lines=$($read_cmd /var/log/$WEB_SYSTEM/domains/$domain.error.log) +IFS=$'\n' + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-web-domain-ssl b/bin/v-list-web-domain-ssl new file mode 100755 index 0000000..63b864d --- /dev/null +++ b/bin/v-list-web-domain-ssl @@ -0,0 +1,157 @@ +#!/bin/bash +# info: list web domain ssl certificate +# options: USER DOMAIN [FORMAT] +# +# example: v-list-web-domain-ssl admin wonderland.com +# +# This function of obtaining domain ssl files. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +format=${3-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# JSON list function +json_list() { + issuer=$(echo "$issuer" | sed -e 's/"/\\"/g' -e "s/%quote%/'/g") + echo '{' + echo -e "\t\"$domain\": {" + echo " \"CRT\": \"$crt\"," + echo " \"KEY\": \"$key\"," + echo " \"CA\": \"$ca\"," + echo " \"SUBJECT\": \"$subj\"," + echo " \"ALIASES\": \"$alt_dns\"," + echo " \"NOT_BEFORE\": \"$before\"," + echo " \"NOT_AFTER\": \"$after\"," + echo " \"SIGNATURE\": \"$signature\"," + echo " \"PUB_KEY\": \"$pub_key\"," + echo " \"ISSUER\": \"$issuer\"," + echo " \"SSL_FORCE\": \"$SSL_FORCE\"" + echo -e "\t}\n}" +} + +# SHELL list function +shell_list() { + if [ -n "$crt" ]; then + echo -e "$crt" + fi + if [ -n "$key" ]; then + echo -e "\n$key" + fi + if [ -n "$ca" ]; then + echo -e "\n$ca" + fi + if [ -n "$crt" ]; then + echo + echo + echo "SUBJECT: $subj" + if [ -n "$alt_dns" ]; then + echo "ALIASES: ${alt_dns//,/ }" + fi + echo "VALID FROM: $before" + echo "VALID TIL: $after" + echo "SIGNATURE: $signature" + echo "PUB_KEY: $pub_key" + echo "ISSUER: $issuer" + echo "SSL_FORCE: $SSL_FORCE" + fi +} + +# PLAIN list function +plain_list() { + if [ -n "$crt" ]; then + echo -e "$crt" + fi + if [ -n "$key" ]; then + echo -e "\n$key" + fi + if [ -n "$ca" ]; then + echo -e "\n$ca" + fi + if [ -n "$crt" ]; then + echo "$subj" + echo "${alt_dns//,/ }" + echo "$before" + echo "$after" + echo "$signature" + echo "$pub_key" + echo "$issuer" + echo "$SSL_FORCE" + fi + +} + +# CSV list function +csv_list() { + echo -n "CRT,KEY,CA,SUBJECT,ALIASES,NOT_BEFORE,NOT_AFTER,SIGNATURE," + echo "PUB_KEY,ISSUER,SSL_FORCE" + echo -n "\"$crt\",\"$key\",\"$ca\",\"$subj\",\"${alt_dns//,/ }\"," + echo "\"$before\",\"$after\",\"$signature\",\"$pub_key\",\"$issuer\",\"$SSL_FORCE\"" +} + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DOMAIN [FORMAT]' +is_format_valid 'user' 'domain' +is_object_valid 'user' 'USER' "$user" +is_object_valid 'web' 'DOMAIN' "$domain" + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Load domain data +parse_object_kv_list $(grep "DOMAIN='$domain'" $USER_DATA/web.conf) + +# Parsing domain SSL certificate +if [ -e "$USER_DATA/ssl/$domain.crt" ]; then + crt=$(cat $USER_DATA/ssl/$domain.crt | sed ':a;N;$!ba;s/\n/\\n/g') + + info=$(openssl x509 -text -in $USER_DATA/ssl/$domain.crt) + subj=$(echo "$info" | grep Subject: | sed -e "s/\"//g" -e "s/.*= //") + before=$(echo "$info" | grep Before: | sed -e "s/.*Before: //") + after=$(echo "$info" | grep "After :" | sed -e "s/.*After : //") + signature=$(echo "$info" | grep "Algorithm:" | head -n1) + signature=$(echo "$signature" | sed -e "s/.*Algorithm: //") + pub_key=$(echo "$info" | grep Public-Key: | cut -f2 -d \( | tr -d \)) + issuer=$(echo "$info" | grep Issuer: | sed -e "s/.*Issuer: //") + alt_dns=$(echo "$info" | grep DNS | sed -e 's/DNS:/\n/g' | tr -d ',') + alt_dns=$(echo "$alt_dns" | tr -d ' ' | sed -e "/^$/d") + alt_dns=$(echo "$alt_dns" | sed -e ':a;N;$!ba;s/\n/,/g') +fi + +if [ -e "$USER_DATA/ssl/$domain.key" ]; then + key=$(cat $USER_DATA/ssl/$domain.key | sed ':a;N;$!ba;s/\n/\\n/g') +fi + +if [ -e "$USER_DATA/ssl/$domain.ca" ]; then + ca=$(cat $USER_DATA/ssl/$domain.ca | sed ':a;N;$!ba;s/\n/\\n/g') +fi + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-web-domains b/bin/v-list-web-domains new file mode 100755 index 0000000..0cb683e --- /dev/null +++ b/bin/v-list-web-domains @@ -0,0 +1,148 @@ +#!/bin/bash +# info: list web domains +# options: USER [FORMAT] +# +# example: v-list-web-domains alice +# +# This function to obtain the list of all user web domains. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +format=${2-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# JSON list function +json_list() { + IFS=$'\n' + i=1 + objects=$(grep DOMAIN $USER_DATA/web.conf | wc -l) + echo "{" + while read str; do + parse_object_kv_list "$str" + # Set correct document root path + if [ -n "$CUSTOM_DOCROOT" ]; then + DOCROOT="$CUSTOM_DOCROOT" + else + DOCROOT="$HOMEDIR/$user/web/$DOMAIN/public_html/" + fi + echo -n ' "'$DOMAIN'": { + "IP": "'$IP'", + "IP6": "'$IP6'", + "DOCUMENT_ROOT": "'$DOCROOT'", + "U_DISK": "'$U_DISK'", + "U_BANDWIDTH": "'$U_BANDWIDTH'", + "TPL": "'$TPL'", + "ALIAS": "'$ALIAS'", + "STATS": "'$STATS'", + "STATS_USER": "'$STATS_USER'", + "SSL": "'$SSL'", + "SSL_HOME": "'$SSL_HOME'", + "LETSENCRYPT": "'$LETSENCRYPT'", + "FTP_USER": "'$FTP_USER'", + "FTP_PATH": "'$FTP_PATH'", + "AUTH_USER": "'$AUTH_USER'", + "BACKEND": "'$BACKEND'", + "PROXY": "'$PROXY'", + "PROXY_EXT": "'$PROXY_EXT'", + "SUSPENDED": "'$SUSPENDED'", + "TIME": "'$TIME'", + "DATE": "'$DATE'" + }' + if [ "$i" -lt "$objects" ]; then + echo ',' + else + echo + fi + ((i++)) + done < <(cat $USER_DATA/web.conf) + echo '}' +} + +# SHELL list function +shell_list() { + IFS=$'\n' + echo "DOMAIN IP TPL SSL DISK BW SPND DATE" + echo "------ -- --- --- ---- -- ---- -----" + while read str; do + parse_object_kv_list "$str" + echo "$DOMAIN $IP $TPL $SSL $U_DISK $U_BANDWIDTH $SUSPENDED $DATE" + done < <(cat $USER_DATA/web.conf) +} + +# PLAIN list function +plain_list() { + IFS=$'\n' + while read str; do + parse_object_kv_list "$str" + # Set correct document root path + if [ ! -z "$CUSTOM_DOCROOT" ]; then + DOCROOT="$CUSTOM_DOCROOT" + else + DOCROOT="$HOMEDIR/$user/web/$DOMAIN/public_html/" + fi + echo -ne "$DOMAIN\t$IP\t$IP6\t$DOCROOT\t$U_DISK\t$U_BANDWIDTH\t$TPL\t" + echo -ne "$ALIAS\t$STATS\t$STATS_USER\t$SSL\t$SSL_HOME\t$LETSENCRYPT\t" + echo -ne "$FTP_USER\t$FTP_PATH\t$AUTH_USER\t$BACKEND\t$PROXY\t" + echo -e "$PROXY_EXT\t$SUSPENDED\t$TIME\t$DATE" + done < <(cat $USER_DATA/web.conf) +} + +# CSV list function +csv_list() { + IFS=$'\n' + echo -n "DOMAIN,IP,IP6,DOCROOT,U_DISK,U_BANDWIDTH,TPL,ALIAS,STATS,STATS_USER," + echo -n "SSL,SSL_HOME,LETSENCRYPT,FTP_USER,FTP_PATH,AUTH_USER,BACKEND,PROXY," + echo "PROXY_EXT,SUSPENDED,TIME,DATE" + while read str; do + parse_object_kv_list "$str" + # Set correct document root path + if [ ! -z "$CUSTOM_DOCROOT" ]; then + DOCROOT="$CUSTOM_DOCROOT" + else + DOCROOT="$HOMEDIR/$user/web/$DOMAIN/public_html/" + fi + echo -n "$DOMAIN,$IP,$IP6,$DOCROOT,$U_DISK,$U_BANDWIDTH,$TPL," + echo -n "\"$ALIAS\",$STATS,\"$STATS_USER\",$SSL,$SSL_HOME,$LETSENCRYPT," + echo -n "\"$FTP_USER\",\"$FTP_PATH\",\"$AUTH_USER\",$BACKEND,$PROXY," + echo "\"$PROXY_EXT\",$SUSPENDED,$TIME,$DATE" + done < <(cat $USER_DATA/web.conf) +} + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'USER [FORMAT]' +is_format_valid 'user' +is_object_valid 'user' 'USER' "$user" + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list ;; +esac + +unset docroot + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-web-stats b/bin/v-list-web-stats new file mode 100755 index 0000000..01cfc9d --- /dev/null +++ b/bin/v-list-web-stats @@ -0,0 +1,84 @@ +#!/bin/bash +# info: list web statistics +# options: [FORMAT] +# labels: web panel +# +# example: v-list-web-stats +# +# This function for obtaining the list of web statistics analyzer. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +format=${1-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# JSON list function +json_list() { + objects=$(echo "$stats" | wc -w) + i=1 + echo '[' + for str in $stats; do + if [ "$i" -lt "$objects" ]; then + echo -e "\t\"$str\"," + else + echo -e "\t\"$str\"" + fi + ((++i)) + done + echo "]" +} + +# SHELL list function +shell_list() { + echo "PARSER" + echo "------" + for parser in $stats; do + echo "$parser" + done +} + +# PLAIN list function +plain_list() { + for parser in $stats; do + echo "$parser" + done +} + +# CSV list function +csv_list() { + echo "PARSER" + for parser in $stats; do + echo "$parser" + done +} + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Parsing stats system +stats=$(echo "none ${STATS_SYSTEM//,/ }") + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-web-templates b/bin/v-list-web-templates new file mode 100755 index 0000000..c19805b --- /dev/null +++ b/bin/v-list-web-templates @@ -0,0 +1,84 @@ +#!/bin/bash +# info: list web templates +# options: [FORMAT] +# +# example: v-list-web-templates +# +# This function for obtaining the list of web templates available to a user. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +format=${1-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# JSON list function +json_list() { + objects=$(echo "$templates" | wc -w) + i=1 + echo '[' + for template in $templates; do + if [ "$i" -lt "$objects" ]; then + echo -e "\t\"$template\"," + else + echo -e "\t\"$template\"" + fi + ((++i)) + done + echo "]" +} + +# SHELL list function +shell_list() { + echo "TEMPLATE" + echo "--------" + for template in $templates; do + echo "$template" + done +} + +# PLAIN list function +plain_list() { + for template in $templates; do + echo "$template" + done +} + +# CSV list function +csv_list() { + echo "TEMPLATE" + for template in $templates; do + echo "$template" + done +} + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Parsing templates +templates=$(ls -v $WEBTPL/$WEB_SYSTEM/$WEB_BACKEND/) +templates=$(echo "$templates" | grep '\.tpl' | sed 's/\.tpl$//') + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-web-templates-backend b/bin/v-list-web-templates-backend new file mode 100755 index 0000000..74a67f5 --- /dev/null +++ b/bin/v-list-web-templates-backend @@ -0,0 +1,88 @@ +#!/bin/bash +# info: listing backend templates +# options: [FORMAT] +# +# example: v-list-web-templates-backend +# +# This function for obtaining the list of available backend templates. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +format=${1-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# JSON list function +json_list() { + i=1 + objects=$(echo "$templates" | wc -w) + echo '[' + for template in $templates; do + if [ "$i" -lt "$objects" ]; then + echo -e "\t\"$template\"," + else + echo -e "\t\"$template\"" + fi + ((++i)) + done + echo "]" +} + +# SHELL list function +shell_list() { + echo "TEMPLATE" + echo "--------" + for template in $templates; do + echo "$template" + done +} + +# PLAIN list function +plain_list() { + for template in $templates; do + echo "$template" + done +} + +# CSV list function +csv_list() { + echo "TEMPLATE" + for template in $templates; do + echo "$template" + done +} + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Parsing backend templates +if [ -n "$WEB_BACKEND" ]; then + templates=$(ls -t $WEBTPL/$WEB_BACKEND \ + | cut -f1 -d . \ + | grep -v proxy_ip \ + | sort -u) +fi + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-list-web-templates-proxy b/bin/v-list-web-templates-proxy new file mode 100755 index 0000000..e2502aa --- /dev/null +++ b/bin/v-list-web-templates-proxy @@ -0,0 +1,89 @@ +#!/bin/bash +# info: listing proxy templates +# options: [FORMAT] +# +# example: v-list-web-templates-proxy +# +# This function for obtaining the list of proxy templates available to a user. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +format=${1-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# JSON list function +json_list() { + objects=$(echo "$templates" | wc -w) + i=1 + echo '[' + for template in $templates; do + if [ "$i" -lt "$objects" ]; then + echo -e "\t\"$template\"," + else + echo -e "\t\"$template\"" + fi + ((++i)) + done + echo "]" +} + +# SHELL list function +shell_list() { + echo "TEMPLATE" + echo "--------" + for template in $templates; do + echo "$template" + done +} + +# PLAIN list function +plain_list() { + for template in $templates; do + echo "$template" + done +} + +# CSV list function +csv_list() { + echo "TEMPLATE" + for template in $templates; do + echo "$template" + done +} + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Parsing proxy templates +if [ -n "$PROXY_SYSTEM" ]; then + templates=$(ls -t $WEBTPL/$PROXY_SYSTEM \ + | grep ".tpl$" \ + | cut -f1 -d . \ + | grep -v proxy_ip \ + | sort -u) +fi + +# Listing data +case $format in + json) json_list ;; + plain) plain_list ;; + csv) csv_list ;; + shell) shell_list ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-log-action b/bin/v-log-action new file mode 100755 index 0000000..fc77463 --- /dev/null +++ b/bin/v-log-action @@ -0,0 +1,62 @@ +#!/bin/bash +# info: adds action event to user or system log +# options: LOG_TYPE USER + +# Event Levels: +# info, warning, error + +# Event Categories: +# user: web, dns, mail, db, letsencrypt, pwchange, pwreset +# system: ip, firewall, service, updates, +# users, pwchange, pwreset, impersonation + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# +# Argument definition +user=$1 +event_level=$2 +export event_category=$3 +event_details=$4 + +is_common_format_valid "$event_level" "event level" + +# Validate event type input +if [ "$event_level" != "Info" ] && [ "$event_level" != "Warning" ] && [ "$event_level" != "Error" ]; then + echo "Error: Invalid event type specified." + exit 1 +fi + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +if [ "$user" = "system" ] || [ "$user" = "System" ]; then + user="system" +fi + +check_args '4' "$#" 'USER TYPE CATEGORY DETAILS' +if [ "$user" != "system" ]; then + is_format_valid 'user' + is_object_valid 'user' 'USER' "$user" +fi + +log_history "$event_details" '' "$user" + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-log-user-login b/bin/v-log-user-login new file mode 100755 index 0000000..7651fa6 --- /dev/null +++ b/bin/v-log-user-login @@ -0,0 +1,67 @@ +#!/bin/bash +# info: add user login +# options: USER IP STATUS [FINGERPRINT] + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +ip=$2 +status=$3 +session_id=$4 +user_agent=$5 +authlog="${6-no}" +reason="${7}" + +active="yes" +if [ "$status" = "failed" ]; then + active="no" +fi + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER IP SESSION_ID USER_AGENT [AUTHLOG] [REASON]' +is_format_valid 'user' 'ip' +is_common_format_valid "$session_id" "SESSION_ID" +format_no_quotes "$user_agent" "USER_AGENT" +is_common_format_valid "$authlog" "AUTHLOG" +format_no_quotes "$reason" "REASON" + +is_object_valid 'user' 'USER' "$user" + +# Generating timestamp +time_n_date=$(date +'%T %F') +time=$(echo "$time_n_date" | cut -f 1 -d \ ) +date=$(echo "$time_n_date" | cut -f 2 -d \ ) + +if [ ! -f "$USER_DATA/auth.log" ]; then + touch "$USER_DATA/auth.log" +fi + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +echo "DATE='$date' TIME='$time' IP='$ip' ACTION='login' STATUS='$status' USER_AGENT='$user_agent' SESSION='$session_id' ACTIVE='$active'" >> "$USER_DATA/auth.log" + +if [ "$authlog" = "yes" ]; then + echo "$date $time $user $ip failed to login ($reason)" >> "$HESTIA/log/auth.log" +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-log-user-logout b/bin/v-log-user-logout new file mode 100755 index 0000000..985189b --- /dev/null +++ b/bin/v-log-user-logout @@ -0,0 +1,44 @@ +#!/bin/bash +# info: Log User logout event +# options: USER FINGERPRINT + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +session_id=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER SESSION_ID' +is_format_valid 'user' +is_common_format_valid "$session_id" "Session ID" +is_object_valid 'user' 'USER' "$user" + +if [ ! -f "$USER_DATA/auth.log" ]; then + touch "$USER_DATA/auth.log" +fi + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +sed -i "s/SESSION='$session_id' ACTIVE='yes'/SESSION='$session_id' ACTIVE='no'/g" "$USER_DATA/auth.log" + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-move-fs-directory b/bin/v-move-fs-directory new file mode 100755 index 0000000..8cb6b46 --- /dev/null +++ b/bin/v-move-fs-directory @@ -0,0 +1,68 @@ +#!/bin/bash +# info: move file +# options: USER SRC_DIRECTORY DST_DIRECTORY +# +# example: v-move-fs-directory admin /home/admin/web /home/user02/ +# +# This function moved file or directory on the file system. This function +# can also be used to rename files just like normal mv command. + +user=$1 +src_dir=$2 +dst_dir=$3 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '3' "$#" 'USER SRC_DIRECTORY DST_DIRECTORY' +is_format_valid 'user' +is_object_valid 'user' 'USER' "$user" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +# Checking user homedir +homedir=$(grep "^$user:" /etc/passwd | cut -f 6 -d :) +if [ -z "$homedir" ]; then + echo "Error: user home directory doesn't exist" + exit 12 +fi + +# Checking source file +if [ ! -d "$src_dir" ]; then + echo "Error: source directory $src_dir doesn't exist" + exit 3 +fi + +# Checking source path +rpath=$(readlink -f "$src_dir") +if [ -z "$(echo $rpath | egrep "^/tmp|^$homedir")" ]; then + echo "Error: invalid source path $src_dir" + exit 2 +fi + +# Checking destination path +rpath=$(readlink -f "$dst_dir") +if [ -z "$(echo $rpath | egrep "^/tmp|^$homedir")" ]; then + echo "Error: invalid destination path $dst_dir" + exit 2 +fi + +# Moving directory +user_exec mv "$src_dir" "$dst_dir" > /dev/null 2>&1 +if [ $? -ne 0 ]; then + echo "Error: directory $src_dir was not moved" + exit 3 +fi + +# Exiting +exit diff --git a/bin/v-move-fs-file b/bin/v-move-fs-file new file mode 100755 index 0000000..714a62e --- /dev/null +++ b/bin/v-move-fs-file @@ -0,0 +1,66 @@ +#!/bin/bash +# info: move file +# options: USER SRC_FILE DST_FILE +# +# example: v-move-fs-file admin readme.txt new_readme.txt +# +# This function moved file or directory on the file system. This function +# can also be used to rename files just like normal mv command. + +user=$1 +src_file=$2 +dst_file=$3 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '3' "$#" 'USER SRC_FILE DST_FILE' +is_format_valid 'user' +is_object_valid 'user' 'USER' "$user" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +# Checking user homedir +homedir=$(grep "^$user:" /etc/passwd | cut -f 6 -d :) +if [ -z "$homedir" ]; then + echo "Error: user home directory doesn't exist" + exit 12 +fi + +# Checking source file +if [ ! -f "$src_file" ]; then + echo "Error: source file $src_file doesn't exist" + exit 3 +fi + +# Checking source path +rpath=$(readlink -f "$src_file") +if [ -z "$(echo $rpath | egrep "^/tmp|^$homedir")" ]; then + echo "Error: invalid source path $src_file" + exit 2 +fi + +# Checking destination path +rpath=$(readlink -f "$dst_file") +if [ -z "$(echo $rpath | egrep "^/tmp|^$homedir")" ]; then + echo "Error: invalid destination path $dst_file" + exit 2 +fi + +# Moving file +user_exec mv "$src_file" "$dst_file" > /dev/null 2>&1 +if [ $? -ne 0 ]; then + echo "Error: file $src_file was not moved" + exit 3 +fi + +# Exiting +exit diff --git a/bin/v-open-fs-config b/bin/v-open-fs-config new file mode 100755 index 0000000..63c1d73 --- /dev/null +++ b/bin/v-open-fs-config @@ -0,0 +1,63 @@ +#!/bin/bash +# info: open config +# options: CONFIG +# +# example: v-open-fs-config /etc/mysql/my.cnf +# +# This function opens/reads config files on the file system + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +src_file=$1 + +# Checking arguments +if [ -z "$src_file" ]; then + echo "Usage: CONFIG" + exit 1 +fi + +# Checking root permissions +if [ "$(id -u)" != '0' ]; then + echo "Error: Script can be run executed only by root" + exit 10 +fi + +# Checking file on fs +if [ ! -e "$src_file" ]; then + echo "Error: $src_file file doesn't exist" + exit 3 +fi + +# Checking path +if [ -n "$src_file" ]; then + rpath=$(readlink -f "$src_file") + services="nginx|apache|httpd|php|ftp|bind|named|exim|dovecot|spamassassin" + services="$services|clam|mysql|postgresql|pgsql|cron|ssh|fail2ban|iptables" + services="$services|my.cnf" + spath=$(echo "$rpath" | egrep "$services") + if [ -z "$spath" ]; then + echo "Error: invalid source path $src_file" + exit 2 + fi + spath=$(echo "$rpath" | egrep "/etc|/var/lib") + if [ -z "$spath" ]; then + echo "Error: invalid source path $src_file" + exit 2 + fi +fi + +# Reading conf +cat "$src_file" 2> /dev/null +if [ $? -ne 0 ]; then + echo "Error: file $src_file was not opened" + exit 3 +fi + +$BIN/v-log-action "system" "Info" "System" "Configuration file opened (File: $src_file)." + +# Exiting +exit diff --git a/bin/v-open-fs-file b/bin/v-open-fs-file new file mode 100755 index 0000000..1177c76 --- /dev/null +++ b/bin/v-open-fs-file @@ -0,0 +1,55 @@ +#!/bin/bash +# info: open file +# options: USER FILE +# +# example: v-open-fs-file admin README.md +# +# This function opens/reads files on the file system + +user=$1 +src_file=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER FILE' +is_format_valid 'user' +is_object_valid 'user' 'USER' "$user" + +# Checking user homedir +homedir=$(grep "^$user:" /etc/passwd | cut -f 6 -d :) +if [ -z "$homedir" ]; then + echo "Error: user home directory doesn't exist" + exit 12 +fi + +# Checking path +if [ -n "$src_file" ]; then + rpath=$(readlink -f "$src_file") + if [ -z "$(echo $rpath | egrep "^/tmp|^$homedir")" ]; then + echo "Error: invalid source path $src_file" + exit 2 + fi + + if [ ! -f "$src_file" ]; then + echo "Error: file not found $src_file" + exit 2 + fi +fi + +# Reading file +user_exec cat "$src_file" 2> /dev/null +if [ $? -ne 0 ]; then + echo "Error: file $src_file was not opened" + exit 3 +fi + +# Exiting +exit diff --git a/bin/v-purge-nginx-cache b/bin/v-purge-nginx-cache new file mode 100755 index 0000000..9acbba4 --- /dev/null +++ b/bin/v-purge-nginx-cache @@ -0,0 +1,78 @@ +#!/bin/bash +# info: Purge nginx cache +# options: USER DOMAIN +# +# example: v-purge-nginx-cache user domain.tld +# +# This function purges nginx cache. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +restart=$3 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/conf/hestia.conf +source $HESTIA/conf/hestia.conf +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DOMAIN [RESTART]' +is_format_valid 'user' 'domain' 'restart' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'web' 'DOMAIN' "$domain" +is_object_unsuspended 'web' 'DOMAIN' "$domain" +is_object_valid 'web' 'DOMAIN' "$domain" "$FASTCGI_CACHE" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +conf=$(grep "DOMAIN='$domain'" "$USER_DATA/web.conf") +parse_object_kv_list "$conf" + +# Purge nginx FastCGI cache +if [ -d "/var/cache/nginx/micro/$domain" ]; then + rm -rf /var/cache/nginx/micro/$domain/* +fi + +# Purge nginx proxy cache +if [ -d "/var/cache/nginx/$domain" ]; then + rm -rf /var/cache/nginx/$domain/* +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Restart services if requested +if [ "$restart" != "no" ]; then + $BIN/v-restart-web "$restart" + check_result $? "Web restart failed" > /dev/null + + $BIN/v-restart-proxy "$restart" + check_result $? "Proxy restart failed" > /dev/null + +fi + +# Logging +$BIN/v-log-action "$user" "Info" "Web" "Cache purged (Domain: $domain)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-rebuild-all b/bin/v-rebuild-all new file mode 100755 index 0000000..4e74854 --- /dev/null +++ b/bin/v-rebuild-all @@ -0,0 +1,68 @@ +#!/bin/bash +# info: rebuild all assets for a specified user +# options: USER [RESTART] +# +# This function rebuilds all assets for a user account: +# +# - Web domains +# - DNS zones +# - Mail domains +# - Databases +# - Cron Jobs +# - User account configuration + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +restart=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/rebuild.sh +source $HESTIA/func/rebuild.sh +# shellcheck source=/usr/local/hestia/func/syshealth.sh +source $HESTIA/func/syshealth.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'USER [RESTART]' +is_format_valid 'user' +is_object_valid 'user' 'USER' "$user" +check_user=$(is_object_unsuspended 'user' 'USER' "$user") +if [ -n "$check_user" ]; then + exit +fi + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Rebuild loop +$BIN/v-rebuild-web-domains "$user" "$restart" +$BIN/v-rebuild-dns-domains "$user" "$restart" +$BIN/v-rebuild-mail-domains "$user" "$restart" +$BIN/v-rebuild-databases "$user" "$restart" +$BIN/v-rebuild-cron-jobs "$user" "$restart" +$BIN/v-rebuild-user "$user" "$restart" + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-rebuild-cron-jobs b/bin/v-rebuild-cron-jobs new file mode 100755 index 0000000..66be28b --- /dev/null +++ b/bin/v-rebuild-cron-jobs @@ -0,0 +1,56 @@ +#!/bin/bash +# info: rebuild cron jobs +# options: USER [RESTART] +# +# example: v-rebuild-cron-jobs admin yes +# +# This function rebuilds system cron config file for specified user. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +restart=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'USER [RESTART]' +is_format_valid 'user' +is_system_enabled "$CRON_SYSTEM" 'CRON_SYSTEM' +is_object_valid 'user' 'USER' "$user" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Rebuild cron jobs +sync_cron_jobs + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Restarting crond +$BIN/v-restart-cron "$restart" +check_result $? "Cron restart failed" > /dev/null +$BIN/v-log-action "system" "Info" "System" "Rebuilt cron jobs (User: $user)." + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-rebuild-database b/bin/v-rebuild-database new file mode 100755 index 0000000..5f4208a --- /dev/null +++ b/bin/v-rebuild-database @@ -0,0 +1,75 @@ +#!/bin/bash +# info: rebuild databases +# options: USER DATABASE +# +# example: v-rebuild-database user user_wordpress +# +# This function for rebuilding a single database for a user + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +database=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/db.sh +source $HESTIA/func/db.sh +# shellcheck source=/usr/local/hestia/func/rebuild.sh +source $HESTIA/func/rebuild.sh +# shellcheck source=/usr/local/hestia/func/syshealth.sh +source $HESTIA/func/syshealth.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DATABASE' +is_format_valid 'user' +is_system_enabled "$DB_SYSTEM" 'DB_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_valid 'db' 'DB' "$database" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Get database values +get_database_values + +# Switching on db type +case $TYPE in + mysql) rebuild_mysql_database ;; + pgsql) rebuild_pgsql_database ;; +esac + +U_DISK_DB=$((U_DISK_DB + U_DISK)) +U_DATABASES=$((U_DATABASES + 1)) +if [ "$SUSPENDED" = 'yes' ]; then + SUSPENDED_DB=$((SUSPENDED_DB + 1)) +fi + +update_user_value "$user" '$SUSPENDED_DB' "$SUSPENDED_DB" +update_user_value "$user" '$U_DATABASES' "$U_DATABASES" +update_user_value "$user" '$U_DISK_DB' "$U_DISK_DB" + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +$BIN/v-log-action "system" "Info" "System" "Rebuilt database (User: $user, Database: $database)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-rebuild-databases b/bin/v-rebuild-databases new file mode 100755 index 0000000..7a59b52 --- /dev/null +++ b/bin/v-rebuild-databases @@ -0,0 +1,82 @@ +#!/bin/bash +# info: rebuild databases +# options: USER +# +# example: v-rebuild-databases admin +# +# This function for rebuilding of all databases of a single user. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/db.sh +source $HESTIA/func/db.sh +# shellcheck source=/usr/local/hestia/func/rebuild.sh +source $HESTIA/func/rebuild.sh +# shellcheck source=/usr/local/hestia/func/syshealth.sh +source $HESTIA/func/syshealth.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'USER' +is_format_valid 'user' +is_system_enabled "$DB_SYSTEM" 'DB_SYSTEM' +is_object_valid 'user' 'USER' "$user" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Flush counters +U_DATABASES=0 +SUSPENDED_DB=0 +U_DISK_DB=0 + +# Starting rebuild loop +for database in $(search_objects 'db' 'SUSPENDED' "no" 'DB'); do + + # Get database values + get_database_values + + # Switching on db type + case $TYPE in + mysql) rebuild_mysql_database ;; + pgsql) rebuild_pgsql_database ;; + esac + + U_DISK_DB=$((U_DISK_DB + U_DISK)) + U_DATABASES=$((U_DATABASES + 1)) + if [ "$SUSPENDED" = 'yes' ]; then + SUSPENDED_DB=$((SUSPENDED_DB + 1)) + fi +done + +update_user_value "$user" '$SUSPENDED_DB' "$SUSPENDED_DB" +update_user_value "$user" '$U_DATABASES' "$U_DATABASES" +update_user_value "$user" '$U_DISK_DB' "$U_DISK_DB" + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +$BIN/v-log-action "system" "Info" "System" "Rebuilt databases (User: $user)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-rebuild-dns-domain b/bin/v-rebuild-dns-domain new file mode 100755 index 0000000..65d753d --- /dev/null +++ b/bin/v-rebuild-dns-domain @@ -0,0 +1,105 @@ +#!/bin/bash +# info: rebuild dns domain +# options: USER DOMAIN [RESTART] [UPDATE_SERIAL] +# +# example: v-rebuild-dns-domain alice wonderland.com +# +# This function rebuilds DNS configuration files. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +restart=$3 +update_serial=${4-no} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# shellcheck source=/usr/local/hestia/func/rebuild.sh +source $HESTIA/func/rebuild.sh +# shellcheck source=/usr/local/hestia/func/syshealth.sh +source $HESTIA/func/syshealth.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DOMAIN [RESTART] [UPDATE_SERIAL]' +is_format_valid 'user' 'domain' 'restart' +is_system_enabled "$DNS_SYSTEM" 'DNS_SYSTEM' +is_object_valid 'user' 'USER' "$user" +check_user=$(is_object_unsuspended 'user' 'USER' "$user") +if [ -n "$check_user" ]; then + exit +fi +is_object_valid 'dns' 'DOMAIN' "$domain" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +user_domains=0 +user_records=0 +suspended_dns=0 +conf="$USER_DATA/dns.conf" + +# Defining user name servers +ns=$(get_user_value '$NS') +i=1 +for nameserver in ${ns//,/ }; do + eval ns$i="$nameserver" + i=$((i + 1)) +done + +# Get dns config path +if [ -e '/etc/named.conf' ]; then + dns_conf='/etc/named.conf' +fi + +if [ -e '/etc/bind/named.conf' ]; then + dns_conf='/etc/bind/named.conf' +fi + +# Deleting old user's zone +sed -i "/\/$user\/conf\/dns\/$domain.db\"/d" $dns_conf + +# Updating zone serial +if [ "$update_serial" != 'no' ]; then + update_domain_serial +fi + +syshealth_repair_dns_config +# Rebuiling zone config +rebuild_dns_domain_conf + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Updating counters +update_user_value "$user" '$U_DNS_DOMAINS' "$user_domains" +update_user_value "$user" '$U_DNS_RECORDS' "$user_records" +update_user_value "$user" '$SUSPENDED_DNS' "$suspended_dns" + +# Restarting named +$BIN/v-restart-dns "$restart" +check_result $? "Bind restart failed" > /dev/null + +# Logging +$BIN/v-log-action "system" "Info" "System" "Rebuilt DNS domain (User: $user, Domain: $domain)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-rebuild-dns-domains b/bin/v-rebuild-dns-domains new file mode 100755 index 0000000..a99c630 --- /dev/null +++ b/bin/v-rebuild-dns-domains @@ -0,0 +1,106 @@ +#!/bin/bash +# info: rebuild dns domains +# options: USER [RESTART] [UPDATE_SERIAL] +# +# example: v-rebuild-dns-domains alice +# +# This function rebuilds DNS configuration files. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +restart=$2 +update_serial=${3-no} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# shellcheck source=/usr/local/hestia/func/rebuild.sh +source $HESTIA/func/rebuild.sh +# shellcheck source=/usr/local/hestia/func/syshealth.sh +source $HESTIA/func/syshealth.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'USER [RESTART] [UPDATE_SERIAL]' +is_format_valid 'user' 'restart' +is_system_enabled "$DNS_SYSTEM" 'DNS_SYSTEM' +is_object_valid 'user' 'USER' "$user" +check_user=$(is_object_unsuspended 'user' 'USER' "$user") +if [ -n "$check_user" ]; then + exit +fi +if [ "$DNS_SYSTEM" = 'remote' ]; then + exit +fi + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +user_domains=0 +user_records=0 +suspended_dns=0 +export conf="$USER_DATA/dns.conf" + +# Defining user name servers +ns=$(get_user_value '$NS') +i=1 +for nameserver in ${ns//,/ }; do + eval ns$i="$nameserver" + i=$((i + 1)) +done + +# Get dns config path +if [ -e '/etc/named.conf' ]; then + dns_conf='/etc/named.conf' +fi + +if [ -e '/etc/bind/named.conf' ]; then + dns_conf='/etc/bind/named.conf' +fi + +# Remove old user's zone +sed -i "/\/$user\/conf\/dns/d" $dns_conf + +# Starting loop +for domain in $(search_objects 'dns' 'DOMAIN' "*" 'DOMAIN'); do + if [ "$update_serial" != 'no' ]; then + update_domain_serial + fi + syshealth_repair_dns_config + rebuild_dns_domain_conf +done + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Updating counters +update_user_value "$user" '$U_DNS_DOMAINS' "$user_domains" +update_user_value "$user" '$U_DNS_RECORDS' "$user_records" +update_user_value "$user" '$SUSPENDED_DNS' "$suspended_dns" + +# Restarting named +$BIN/v-restart-dns "$restart" +check_result $? "Bind restart failed" > /dev/null + +# Logging +$BIN/v-log-action "system" "Info" "System" "Rebuilt DNS zones (User: $user)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-rebuild-mail-domain b/bin/v-rebuild-mail-domain new file mode 100755 index 0000000..b1a13db --- /dev/null +++ b/bin/v-rebuild-mail-domain @@ -0,0 +1,92 @@ +#!/bin/bash +# info: rebuild mail domain +# options: USER DOMAIN +# +# example: v-rebuild-mail-domain user domain.tld +# +# This function rebuilds configuration files for a single domain. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +restart=${3-yes} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# shellcheck source=/usr/local/hestia/func/ip.sh +source $HESTIA/func/ip.sh +# shellcheck source=/usr/local/hestia/func/rebuild.sh +source $HESTIA/func/rebuild.sh +# shellcheck source=/usr/local/hestia/func/syshealth.sh +source $HESTIA/func/syshealth.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Define mail user +if [ "$MAIL_SYSTEM" = 'exim4' ]; then + export MAIL_USER="Debian-exim" +else + export MAIL_USER="exim" +fi + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DOMAIN' +is_format_valid 'user' 'domain' 'restart' +is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM' +is_object_valid 'user' 'USER' "$user" +check_user=$(is_object_unsuspended 'user' 'USER' "$user") +if [ -n "$check_user" ]; then + exit +fi +is_object_valid 'mail' 'DOMAIN' "$domain" + +if [ "$MAIL_SYSTEM" = 'remote' ]; then + exit +fi + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Rebuild mail domain configuration +rebuild_mail_domain_conf + +# Rebuild webmail configuration +if [ -n "$WEB_SYSTEM" ] || [ -n "$PROXY_SYSTEM" ]; then + if [ -n "$IMAP_SYSTEM" ]; then + WEBMAIL=$(get_object_value 'web' 'DOMAIN' "$domain" "$WEBMAIL") + if [ -n "$WEBMAIL" ]; then + $BIN/v-delete-mail-domain-webmail "$user" "$domain" "$restart" 'yes' + $BIN/v-add-mail-domain-webmail "$user" "$domain" "$WEBMAIL" "$restart" 'yes' + fi + fi +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Update disk usage statistics +$BIN/v-update-user-disk "$user" +$BIN/v-update-user-counters "$user" + +# Logging +$BIN/v-log-action "system" "Info" "System" "Rebuilt mail domain (User: $user, Domain: $domain)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-rebuild-mail-domains b/bin/v-rebuild-mail-domains new file mode 100755 index 0000000..01f4026 --- /dev/null +++ b/bin/v-rebuild-mail-domains @@ -0,0 +1,75 @@ +#!/bin/bash +# info: rebuild mail domains +# options: USER +# +# example: v-rebuild-mail-domains admin +# +# This function rebuilds EXIM configuration files for all mail domains. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# shellcheck source=/usr/local/hestia/func/ip.sh +source $HESTIA/func/ip.sh +# shellcheck source=/usr/local/hestia/func/rebuild.sh +source $HESTIA/func/rebuild.sh +# shellcheck source=/usr/local/hestia/func/syshealth.sh +source $HESTIA/func/syshealth.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Define mail user +if [ "$MAIL_SYSTEM" = 'exim4' ]; then + export MAIL_USER="Debian-exim" +else + export MAIL_USER="exim" +fi + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'USER' +is_format_valid 'user' +is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM' +is_object_valid 'user' 'USER' "$user" +check_user=$(is_object_unsuspended 'user' 'USER' "$user") +if [ -n "$check_user" ]; then + exit +fi +if [ "$MAIL_SYSTEM" = 'remote' ]; then + exit +fi + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Starting loop +for domain in $(search_objects 'mail' 'SUSPENDED' "*" 'DOMAIN'); do + $BIN/v-rebuild-mail-domain "$user" "$domain" "no" +done + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +$BIN/v-log-action "system" "Info" "System" "Rebuilt mail domains (User: $user)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-rebuild-user b/bin/v-rebuild-user new file mode 100755 index 0000000..9a525e0 --- /dev/null +++ b/bin/v-rebuild-user @@ -0,0 +1,74 @@ +#!/bin/bash +# info: rebuild system user +# options: USER [RESTART] +# +# example: v-rebuild-user admin yes +# +# This function rebuilds system user account. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +restart=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# shellcheck source=/usr/local/hestia/func/ip.sh +source $HESTIA/func/ip.sh +# shellcheck source=/usr/local/hestia/func/rebuild.sh +source $HESTIA/func/rebuild.sh +# shellcheck source=/usr/local/hestia/func/syshealth.sh +source $HESTIA/func/syshealth.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'USER [RESTART]' +is_format_valid 'user' 'restart' +is_object_valid 'user' 'USER' "$user" +check_user=$(is_object_unsuspended 'user' 'USER' "$user") +if [ -n "$check_user" ]; then + exit +fi + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Update disk quota +if [ "$DISK_QUOTA" = 'yes' ]; then + $BIN/v-update-user-quota "$user" +fi + +# Rebuild user +rebuild_user_conf + +# Update user counters +$BIN/v-update-user-counters "$user" + +# Update account usage statistics +$BIN/v-update-user-stats "$user" + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +$BIN/v-log-action "system" "Info" "System" "Rebuilt user profile (User: $user)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-rebuild-users b/bin/v-rebuild-users new file mode 100755 index 0000000..371e00c --- /dev/null +++ b/bin/v-rebuild-users @@ -0,0 +1,51 @@ +#!/bin/bash +# info: rebuild system users +# options: [RESTART] +# +# example: v-rebuild-users +# +# This function rebuilds user configuration for all users. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +restart=$1 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/rebuild.sh +source $HESTIA/func/rebuild.sh +# shellcheck source=/usr/local/hestia/func/syshealth.sh +source $HESTIA/func/syshealth.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Rebuild loop +for user in $($BIN/v-list-sys-users plain); do + $BIN/v-rebuild-user "$user" "$restart" +done + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-rebuild-web-domain b/bin/v-rebuild-web-domain new file mode 100755 index 0000000..ece7488 --- /dev/null +++ b/bin/v-rebuild-web-domain @@ -0,0 +1,118 @@ +#!/bin/bash +# info: rebuild web domain +# options: USER DOMAIN [RESTART] +# +# example: v-rebuild-web-domain user domain.tld +# +# This function rebuilds web configuration files. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +restart=$3 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# shellcheck source=/usr/local/hestia/func/ip.sh +source $HESTIA/func/ip.sh +# shellcheck source=/usr/local/hestia/func/rebuild.sh +source $HESTIA/func/rebuild.sh +# shellcheck source=/usr/local/hestia/func/syshealth.sh +source $HESTIA/func/syshealth.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DOMAIN [RESTART]' +is_format_valid 'user' 'domain' 'restart' +is_system_enabled "$WEB_SYSTEM" 'WEB_SYSTEM' +is_object_valid 'user' 'USER' "$user" +check_user=$(is_object_unsuspended 'user' 'USER' "$user") +if [ -n "$check_user" ]; then + exit +fi +is_object_valid 'web' 'DOMAIN' "$domain" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Deleting old web configs +if [ -e "/etc/$WEB_SYSTEM/conf.d/hestia.conf" ]; then + sed -i "/.*\/$user\/conf\/web\//d" /etc/$WEB_SYSTEM/conf.d/hestia.conf +fi + +if [ -e "$HOMEDIR/$user/conf/web/$domain/$WEB_SYSTEM.conf" ]; then + rm -f $HOMEDIR/$user/conf/web/$domain/$WEB_SYSTEM.conf + rm -f /etc/$WEB_SYSTEM/conf.d/domains/$domain.conf +fi +if [ -e "$HOMEDIR/$user/conf/web/$domain/$WEB_SYSTEM.ssl.conf" ]; then + rm $HOMEDIR/$user/conf/web/$domain/$WEB_SYSTEM.ssl.conf + rm -f /etc/$WEB_SYSTEM/conf.d/domains/$domain.ssl.conf +fi + +# Deleting old proxy configs +if [ -n "$PROXY_SYSTEM" ]; then + if [ -e "/etc/$PROXY_SYSTEM/conf.d/hestia.conf" ]; then + sed -i "/.*\/$user\/conf\/web\//d" /etc/$PROXY_SYSTEM/conf.d/hestia.conf + fi + + if [ -e "$HOMEDIR/$user/conf/web/$domain/$PROXY_SYSTEM.conf" ]; then + rm -f $HOMEDIR/$user/conf/web/$domain/$PROXY_SYSTEM.conf + rm -f /etc/$PROXY_SYSTEM/conf.d/domains/$domain.conf + fi + + if [ -e "$HOMEDIR/$user/conf/web/$domain/$PROXY_SYSTEM.ssl.conf" ]; then + rm -f $HOMEDIR/$user/conf/web/$domain/$PROXY_SYSTEM.ssl.conf + rm -f /etc/$PROXY_SYSTEM/conf.d/domains/$domain.ssl.conf + fi +fi + +# Deleting backend configs +if [ -n "$WEB_BACKEND" ]; then + template=$(get_object_value 'web' 'DOMAIN' "$domain" '$BACKEND') + if [ -z "$template" ]; then + template="default" + update_object_value 'web' 'DOMAIN' "$domain" '$BACKEND' 'default' + fi + prepare_web_backend + delete_web_backend + $BIN/v-add-web-domain-backend $user $domain $template $restart +fi + +rebuild_web_domain_conf + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Updating user counters +$BIN/v-update-user-counters "$user" + +# Restarting web server +$BIN/v-restart-web "$restart" +check_result $? "Web restart failed" > /dev/null + +$BIN/v-restart-proxy "$restart" +check_result $? "Proxy restart failed" > /dev/null + +# Logging +$BIN/v-log-action "system" "Info" "System" "Rebuilt web domain (User: $user, Domain: $domain)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-rebuild-web-domains b/bin/v-rebuild-web-domains new file mode 100755 index 0000000..e74abd1 --- /dev/null +++ b/bin/v-rebuild-web-domains @@ -0,0 +1,142 @@ +#!/bin/bash +# info: rebuild web domains +# options: USER [RESTART] +# +# example: v-rebuild-web-domains +# +# This function rebuilds web configuration files. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +restart=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# shellcheck source=/usr/local/hestia/func/ip.sh +source $HESTIA/func/ip.sh +# shellcheck source=/usr/local/hestia/func/rebuild.sh +source $HESTIA/func/rebuild.sh +# shellcheck source=/usr/local/hestia/func/syshealth.sh +source $HESTIA/func/syshealth.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'USER [RESTART]' +is_format_valid 'user' 'restart' +is_system_enabled "$WEB_SYSTEM" 'WEB_SYSTEM' +is_object_valid 'user' 'USER' "$user" +check_user=$(is_object_unsuspended 'user' 'USER' "$user") +if [ -n "$check_user" ]; then + exit +fi + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Deleting old web configs +if [ -e "/etc/$WEB_SYSTEM/conf.d/hestia.conf" ]; then + sed -i "/.*\/$user\/conf\/web\//d" /etc/$WEB_SYSTEM/conf.d/hestia.conf +fi + +if [ -e "$HOMEDIR/$user/conf/web/$domain/$WEB_SYSTEM.conf" ]; then + rm -f $HOMEDIR/$user/conf/web/$domain/$WEB_SYSTEM.conf + rm -f /etc/$WEB_SYSTEM/conf.d/domains/$domain.conf +fi +if [ -e "$HOMEDIR/$user/conf/web/$domain/$WEB_SYSTEM.ssl.conf" ]; then + rm $HOMEDIR/$user/conf/web/$domain/$WEB_SYSTEM.ssl.conf + rm -f /etc/$WEB_SYSTEM/conf.d/domains/$domain.ssl.conf +fi + +# Deleting old proxy configs +if [ -n "$PROXY_SYSTEM" ]; then + if [ -e "/etc/$PROXY_SYSTEM/conf.d/hestia.conf" ]; then + sed -i "/.*\/$user\/conf\/web\//d" /etc/$PROXY_SYSTEM/conf.d/hestia.conf + fi + + if [ -e "$HOMEDIR/$user/conf/web/$domain/$PROXY_SYSTEM.conf" ]; then + rm -f $HOMEDIR/$user/conf/web/$domain/$PROXY_SYSTEM.conf + rm -f /etc/$PROXY_SYSTEM/conf.d/domains/$domain.conf + fi + + if [ -e "$HOMEDIR/$user/conf/web/$domain/$PROXY_SYSTEM.ssl.conf" ]; then + rm -f $HOMEDIR/$user/conf/web/$domain/$PROXY_SYSTEM.ssl.conf + rm -f /etc/$PROXY_SYSTEM/conf.d/domains/$domain.ssl.conf + fi +fi + +# Create dummy php-fpm configs if missing +for php_folder in /etc/php/*; do + [ ! -d "${php_folder}/fpm/pool.d/" ] && continue + + v_php="$(basename $php_folder)" + if [ ! -f "/etc/php/${v_php}/fpm/pool.d/dummy.conf" ]; then + cp -f "$HESTIA_INSTALL_DIR/php-fpm/dummy.conf" "/etc/php/${v_php}/fpm/pool.d/" + sed -i "s/9999/99${v_php//./}/g" "/etc/php/${v_php}/fpm/pool.d/dummy.conf" + fi +done + +# Deleting backend configs +if [ -n "$WEB_BACKEND" ]; then + if [ "$WEB_BACKEND_POOL" = 'user' ]; then + prepare_web_backend + delete_web_backend + else + for domain in $($BIN/v-list-web-domains $user plain | cut -f 1); do + template=$(get_object_value 'web' 'DOMAIN' "$domain" '$BACKEND') + prepare_web_backend + delete_web_backend + done + fi +fi + +# Starting rebuild loop for each web domain +for domain in $($BIN/v-list-web-domains $user plain | cut -f 1); do + if [ -n "$WEB_BACKEND" ]; then + template=$(get_object_value 'web' 'DOMAIN' "$domain" '$BACKEND') + if [ -z "$template" ]; then + template="default" + update_object_value 'web' 'DOMAIN' "$domain" '$BACKEND' 'default' + fi + $BIN/v-add-web-domain-backend "$user" "$domain" "$template" "$restart" + fi + rebuild_web_domain_conf +done + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Updating user counters +$BIN/v-update-user-counters "$user" + +if [ "$restart" = "yes" ]; then + # Restarting web server + $BIN/v-restart-web "$restart" + check_result $? "Web restart failed" > /dev/null + + $BIN/v-restart-proxy "$restart" + check_result $? "Proxy restart failed" > /dev/null +fi + +# Logging +$BIN/v-log-action "system" "Info" "System" "Rebuilt web domains (User: $user)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-refresh-sys-theme b/bin/v-refresh-sys-theme new file mode 100755 index 0000000..1c5b47a --- /dev/null +++ b/bin/v-refresh-sys-theme @@ -0,0 +1,30 @@ +#!/bin/bash +# info: change active system theme +# options: NONE +# +# example: v-refresh-sys-theme +# +# This function for changing the currently active system theme. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Store current theme name +CURRENT_THEME=$THEME + +# Cycle theme to regenerate (helps if cache is stuck) +$BIN/v-change-sys-theme "default" +$BIN/v-change-sys-theme "$CURRENT_THEME" diff --git a/bin/v-rename-user-package b/bin/v-rename-user-package new file mode 100755 index 0000000..b060568 --- /dev/null +++ b/bin/v-rename-user-package @@ -0,0 +1,89 @@ +#!/bin/bash +# info: change package name +# options: OLD_NAME NEW_NAME [mode] +# +# example: v-rename-package package package2 +# +# This function changes the name of an existing package. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +old_name=$1 +new_name=$2 +mode=$3 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +# Ensure that package names have been passed to the script. +if [ -z "$old_name" ]; then + echo "ERROR: Current package name not specified." + exit "$E_ARGS" +fi +if [ -z "$new_name" ]; then + echo "ERROR: New package name not specified." + exit "$E_ARGS" +fi + +is_package_valid "$old_name" +is_object_format_valid "$new_name" "New package" +pkg_dir="$HESTIA/data/packages" +if [ -e "$pkg_dir/$new_name.pkg" ]; then + check_result "$E_NOTEXIST" "package $new_name exist" +fi + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +if [ -e "$HESTIA/data/packages/$old_name.pkg" ]; then + mv "$HESTIA/data/packages/$old_name.pkg" "$HESTIA/data/packages/$new_name.pkg" + # Don't leave the .sh file behind + if [ -e "$HESTIA/data/packages/$old_name.sh" ]; then + mv "$HESTIA/data/packages/$old_name.sh" "$HESTIA/data/packages/$new_name.sh" + fi + + # Update package for existing users + for user in $($BIN/v-list-users plain); do + OLD_PACKAGE=$(v-get-user-value "$user" 'PACKAGE') + if [ "$old_name" = "$OLD_PACKAGE" ]; then + if [ "$mode" == "yes" ]; then + echo "Successfully renamed package $old_name to $new_name." + fi + v-change-user-package "$user" "$new_name" + fi + done + if [ "$mode" == "yes" ]; then + echo "Successfully renamed package $old_name to $new_name." + fi +else + echo "ERROR: Specified package not found." + exit "$E_NOTEXIST" +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +$BIN/v-log-action "system" "Info" "System" "Package renamed (Value: $new_name, Previous: $old_name)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-repair-sys-config b/bin/v-repair-sys-config new file mode 100755 index 0000000..7413dbd --- /dev/null +++ b/bin/v-repair-sys-config @@ -0,0 +1,36 @@ +#!/bin/bash +# info: Restore system configuration +# options: [SYSTEM] +# +# example: v-repair-sys-config +# +# This function repairs or restores the system configuration file. + +mode=$1 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +if [ "$mode" = "restore" ]; then + syshealth_restore_system_config +fi + +if [ "$mode" = "repair" ]; then + # load config file + source_conf "$HESTIA/conf/hestia.conf" + syshealth_repair_system_config +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +$BIN/v-log-action "system" "Info" "System" "Executed $mode operation on system configuration." +log_event "$OK" "$ARGUMENTS" diff --git a/bin/v-restart-cron b/bin/v-restart-cron new file mode 100755 index 0000000..2d0e70c --- /dev/null +++ b/bin/v-restart-cron @@ -0,0 +1,68 @@ +#!/bin/bash +# info: restart cron service +# options: NONE +# +# example: v-restart-cron +# +# This function tells crond service to reread its configuration files. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +send_email_report() { + email=$(grep CONTACT $HESTIA/data/users/admin/user.conf) + email=$(echo "$email" | cut -f 2 -d "'") + tmpfile=$(mktemp) + subj="$(hostname): $CRON_SYSTEM restart failed" + systemctl status "$CRON_SYSTEM" >> $tmpfile 2>&1 + service "$CRON_SYSTEM" restart >> $tmpfile 2>&1 + cat $tmpfile | $SENDMAIL -s "$subj" $email + rm -f $tmpfile +} + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Exit +if [ -z "$CRON_SYSTEM" ] || [ "$CRON_SYSTEM" = 'remote' ]; then + exit +fi + +# Schedule restart +if [ "$1" = 'scheduled' ] || [ -z "$1" ] && [ "$SCHEDULED_RESTART" = 'yes' ]; then + sed -i "/\/$SCRIPT now/d" $HESTIA/data/queue/restart.pipe + echo "$BIN/$SCRIPT now" >> $HESTIA/data/queue/restart.pipe + exit +fi + +if [ "$1" = "no" ] || [ -z "$1" ]; then + exit +fi + +# Restart system +$BIN/v-restart-service $CRON_SYSTEM > /dev/null 2>&1 +if [ $? -ne 0 ]; then + send_email_report + check_result "$E_RESTART" "$CRON_SYSTEM restart failed" +fi + +# Update restart queue +if [ -e "$HESTIA/data/queue/restart.pipe" ]; then + sed -i "/\/$SCRIPT now/d" $HESTIA/data/queue/restart.pipe +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-restart-dns b/bin/v-restart-dns new file mode 100755 index 0000000..05b9900 --- /dev/null +++ b/bin/v-restart-dns @@ -0,0 +1,91 @@ +#!/bin/bash +# info: restart dns service +# options: NONE +# +# example: v-restart-dns +# +# This function tells BIND service to reload dns zone files. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +send_email_report() { + if [ -e '/etc/named.conf' ]; then + dns_conf='/etc/named.conf' + else + dns_conf='/etc/bind/named.conf' + fi + email=$(grep CONTACT $HESTIA/data/users/admin/user.conf) + email=$(echo "$email" | cut -f 2 -d "'") + tmpfile=$(mktemp) + subj="$(hostname): "$DNS_SYSTEM" restart failed" + /usr/sbin/named-checkconf "$dns_conf" >> $tmpfile 2>&1 + if [ "$1" == "DO_RESTART" ]; then + service "$DNS_SYSTEM" restart >> $tmpfile 2>&1 + fi + cat $tmpfile | $SENDMAIL -s "$subj" $email + rm -f $tmpfile +} + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Exit +if [ -z "$DNS_SYSTEM" ] || [ "$DNS_SYSTEM" = 'remote' ]; then + exit +fi + +if [ "$1" = "no" ]; then + exit +fi + +# Schedule restart +if [ "$1" = 'scheduled' ] || [ -z "$1" -a "$SCHEDULED_RESTART" = 'yes' ]; then + sed -i "/\/$SCRIPT now/d" $HESTIA/data/queue/restart.pipe + echo "$BIN/$SCRIPT now" >> $HESTIA/data/queue/restart.pipe + exit +fi + +if [ -e '/etc/named.conf' ]; then + dns_conf='/etc/named.conf' +else + dns_conf='/etc/bind/named.conf' +fi + +if [ ! -e "/usr/sbin/named-checkconf" ]; then + ln -s "$(which named-checkconf)" /sbin/named-checkconf +fi + +/usr/sbin/named-checkconf "$dns_conf" > /dev/null 2>&1 +if [ $? -ne 0 ]; then + send_email_report + check_result "$E_RESTART" "$DNS_SYSTEM restart failed'" +fi + +# Restart system +$BIN/v-restart-service "$DNS_SYSTEM" "$1" > /dev/null 2>&1 +if [ $? -ne 0 ]; then + send_email_report "DO_RESTART" + check_result "$E_RESTART" "$DNS_SYSTEM restart failed" +fi + +# Update restart queue +if [ -e "$HESTIA/data/queue/restart.pipe" ]; then + sed -i "/\/$SCRIPT now/d" $HESTIA/data/queue/restart.pipe +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-restart-ftp b/bin/v-restart-ftp new file mode 100755 index 0000000..df026a3 --- /dev/null +++ b/bin/v-restart-ftp @@ -0,0 +1,68 @@ +#!/bin/bash +# info: restart ftp service +# options: NONE +# +# example: v-restart-ftp +# +# This function tells ftp server to reread its configuration. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +send_email_report() { + email=$(grep CONTACT $HESTIA/data/users/admin/user.conf) + email=$(echo "$email" | cut -f 2 -d "'") + tmpfile=$(mktemp) + subj="$(hostname): $FTP_SYSTEM restart failed" + service "$FTP_SYSTEM" configtest >> $tmpfile 2>&1 + service "$FTP_SYSTEM" restart >> $tmpfile 2>&1 + cat $tmpfile | $SENDMAIL -s "$subj" $email + rm -f $tmpfile +} + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Exit +if [ -z "$FTP_SYSTEM" ] || [ "$FTP_SYSTEM" = 'remote' ]; then + exit +fi + +if [ "$1" = "no" ]; then + exit +fi + +# Schedule restart +if [ "$1" = 'scheduled' ] || [ -z "$1" ] && [ "$SCHEDULED_RESTART" = 'yes' ]; then + sed -i "/\/$SCRIPT now/d" $HESTIA/data/queue/restart.pipe + echo "$BIN/$SCRIPT now" >> $HESTIA/data/queue/restart.pipe + exit +fi + +# Restart system +$BIN/v-restart-service "$FTP_SYSTEM" "$1" > /dev/null 2>&1 +if [ $? -ne 0 ]; then + send_email_report + check_result "$E_RESTART" "$FTP_SYSTEM restart failed" +fi + +# Update restart queue +if [ -e "$HESTIA/data/queue/restart.pipe" ]; then + sed -i "/\/$SCRIPT now/d" $HESTIA/data/queue/restart.pipe +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-restart-mail b/bin/v-restart-mail new file mode 100755 index 0000000..1b8d260 --- /dev/null +++ b/bin/v-restart-mail @@ -0,0 +1,78 @@ +#!/bin/bash +# info: restart mail service +# options: [RESTART] +# +# example: v-restart-mail +# +# This function tells exim or dovecot services to reload configuration files. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +send_email_report() { + local mail_service="$1" + journalctl --no-pager --reverse --since=-1m --unit "$mail_service" >> "$tmpfile" 2>&1 + email=$(grep CONTACT $HESTIA/data/users/admin/user.conf) + email=$(echo "$email" | cut -f 2 -d "'") + subj="$(hostname): $mail_service restart failed" + cat "$tmpfile" | $SENDMAIL -s "$subj" $email + [[ -f "$tmpfile" ]] && rm -f $tmpfile +} + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Exit +if [ -z "$MAIL_SYSTEM" ] || [ "$MAIL_SYSTEM" = 'remote' ]; then + exit +fi + +if [ "$1" = "no" ]; then + exit +fi + +# Schedule restart +if [ "$1" = 'scheduled' ] || [ -z "$1" -a "$SCHEDULED_RESTART" = 'yes' ]; then + sed -i "/\/$SCRIPT now/d" $HESTIA/data/queue/restart.pipe + echo "$BIN/$SCRIPT now" >> $HESTIA/data/queue/restart.pipe + exit +fi + +tmpfile=$(mktemp) +# Restart IMAP system if present +if [ -n "$IMAP_SYSTEM" ]; then + $BIN/v-restart-service "$IMAP_SYSTEM" "$1" >> $tmpfile 2>&1 + if [ $? -ne 0 ]; then + send_email_report "$IMAP_SYSTEM" + check_result "$E_RESTART" "$IMAP_SYSTEM restart failed" + fi +fi + +# Restart mail system +$BIN/v-restart-service "$MAIL_SYSTEM" "$1" >> $tmpfile 2>&1 +if [ $? -ne 0 ]; then + send_email_report "$MAIL_SYSTEM" + check_result "$E_RESTART" "$MAIL_SYSTEM restart failed" +fi + +# Update restart queue +if [ -e "$HESTIA/data/queue/restart.pipe" ]; then + sed -i "/\/$SCRIPT now/d" $HESTIA/data/queue/restart.pipe +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +[[ -f "$tmpfile" ]] && rm -f $tmpfile +exit diff --git a/bin/v-restart-proxy b/bin/v-restart-proxy new file mode 100755 index 0000000..9ea8fec --- /dev/null +++ b/bin/v-restart-proxy @@ -0,0 +1,133 @@ +#!/bin/bash +# info: restart proxy server +# options: NONE +# +# example: v-restart-proxy [RESTART] +# +# This function reloads proxy server configuration. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +date=$(date +"%Y-%m-%d %H:%M:%S") + +send_email_report() { + email=$(grep CONTACT $HESTIA/data/users/admin/user.conf) + email=$(echo "$email" | cut -f 2 -d "'") + tmpfile=$(mktemp) + subj="$(hostname): $PROXY_SYSTEM restart failed" + nginx -t >> $tmpfile 2>&1 + + if [ "$1" == "DO_RESTART" ]; then + service "$PROXY_SYSTEM" restart >> $tmpfile 2>&1 + fi + cat "$tmpfile" | $SENDMAIL -s "$subj" "$email" + if [ "$DEBUG_MODE" = "true" ]; then + echo "[ $date | $PROXY_SYSTEM | PROXY ]" >> /var/log/hestia/debug.log 2>&1 + cat "$tmpfile" >> /var/log/hestia/debug.log 2>&1 + fi + rm -f $tmpfile +} + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Exit +if [ -z "$PROXY_SYSTEM" ] || [ "$PROXY_SYSTEM" = 'remote' ]; then + exit +fi + +if [ "$1" = "no" ]; then + exit +fi + +# Schedule restart +if [ "$1" = 'scheduled' ] || [ -z "$1" ] && [ "$SCHEDULED_RESTART" = 'yes' ]; then + sed -i "/\/$SCRIPT now/d" $HESTIA/data/queue/restart.pipe + echo "$BIN/$SCRIPT now" >> $HESTIA/data/queue/restart.pipe + exit +fi + +if [ "$1" = "updatessl" ]; then + sed -i "/\/$SCRIPT ssl/d" $HESTIA/data/queue/restart.pipe + echo "$BIN/$SCRIPT ssl" >> $HESTIA/data/queue/restart.pipe + exit +fi + +if [ -f "$HESTIA/web/inc/nginx_proxy" ]; then + # if hestia is behind default nginx, restart in background with 15 sec delay + # background restart + if [ "$1" = 'background' ]; then + # Restart system + sleep 15 + + # Preform a check if Nginx is valid as reload doesn't throw an error / exit + if [ "$DEBUG_MODE" = "true" ]; then + echo "[ $date | $PROXY_SYSTEM ]" >> /var/log/hestia/debug.log 2>&1 + service $PROXY_SYSTEM configtest >> /var/log/hestia/debug.log 2>&1 + else + service $PROXY_SYSTEM configtest > /dev/null 2>&1 + fi + if [ $? -ne 0 ]; then + send_email_report + check_result "$E_RESTART" "$PROXY_SYSTEM restart failed" + fi + + $BIN/v-restart-service $PROXY_SYSTEM > /dev/null 2>&1 + + # Update restart queue + if [ -e "$HESTIA/data/queue/restart.pipe" ]; then + sed -i "/$SCRIPT/d" $HESTIA/data/queue/restart.pipe + fi + + exit + fi + # Send to background process + nohup $BIN/v-restart-proxy 'background' &> /dev/null & +else + # Default behaviour + + # Preform a check if Nginx is valid as reload doesn't throw an error / exit + if [ "$DEBUG_MODE" = "true" ]; then + echo "[ $date | $PROXY_SYSTEM ]" >> /var/log/hestia/debug.log 2>&1 + service $PROXY_SYSTEM configtest >> /var/log/hestia/debug.log 2>&1 + else + service $PROXY_SYSTEM configtest > /dev/null 2>&1 + fi + if [ $? -ne 0 ]; then + send_email_report + check_result "$E_RESTART" "$PROXY_SYSTEM restart failed" + fi + + # Restart system + if [ "$1" = "ssl" ]; then + restart="ssl" + fi + $BIN/v-restart-service "$PROXY_SYSTEM" "$restart" > /dev/null 2>&1 + if [ $? -ne 0 ]; then + send_email_report "DO_RESTART" + check_result "$E_RESTART" "$PROXY_SYSTEM restart failed" + fi + + # Update restart queue + if [ -e "$HESTIA/data/queue/restart.pipe" ]; then + sed -i "/\/$SCRIPT now/d" $HESTIA/data/queue/restart.pipe + sed -i "/\/$SCRIPT ssl/d" $HESTIA/data/queue/restart.pipe + fi +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-restart-service b/bin/v-restart-service new file mode 100755 index 0000000..a04b665 --- /dev/null +++ b/bin/v-restart-service @@ -0,0 +1,103 @@ +#!/bin/bash +# info: restart service +# options: SERVICE [RESTART] +# +# example: v-restart-service apache2 +# +# This function restarts system service. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +service=$1 +restart=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'SERVICE [RESTART]' +is_format_valid 'service' 'restart' + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +log="/dev/null" +if [ "$DEBUG_MODE" = "true" ]; then + + log="/var/log/hestia/debug.log" +fi + +# Multi-instance service restart request handling +if [ "$service" = "php-fpm" ]; then + service_list='' + # Get installed php versions + php_versions=$($BIN/v-list-sys-php plain) + # Substitute php-fpm service name formats + for version in $php_versions; do + service_list="${service_list} php${version}-fpm" + done +else + service_list="$service" +fi + +for service in $service_list; do + if [ "$service" = "iptables" ]; then + # Run the restart rules for iptables firewall + $BIN/v-stop-firewall + $BIN/v-update-firewall + elif [ "$restart" = "ssl" ] && [ "$service" = "nginx" ]; then + service $service upgrade >> $log 2>&1 + elif [ -z "$restart" -o "$restart" = "no" ] && [ \ + "$service" = "nginx" -o \ + "$service" = "apache2" -o \ + "$service" = "exim4" -o \ + "$service" = "dovecot" -o \ + "$service" = "bind9" -o \ + "$service" = "named" -o \ + "$service" = "vsftpd" -o \ + "$service" = "php5.6-fpm" -o \ + "$service" = "php7.0-fpm" -o \ + "$service" = "php7.1-fpm" -o \ + "$service" = "php7.2-fpm" -o \ + "$service" = "php7.3-fpm" -o \ + "$service" = "php7.4-fpm" -o \ + "$service" = "php8.0-fpm" -o \ + "$service" = "php8.1-fpm" -o \ + "$service" = "php8.2-fpm" -o \ + "$service" = "proftpd" -o \ + "$service" = "ssh" -o \ + "$service" = "fail2ban" ]; then + systemctl reload-or-restart "$service" >> $log 2>&1 + else + systemctl reset-failed "$service" >> $log 2>&1 + systemctl restart "$service" >> $log 2>&1 + fi + + # Check the result of the service restart and report whether it failed. + if [ $? -ne 0 ]; then + check_result "$E_RESTART" "ERROR: Restart of $service failed." + $BIN/v-log-action "system" "Error" "System" "Service failed to restart (Name: $service)." + else + $BIN/v-log-action "system" "Info" "System" "Service restarted (Name: $service)." + fi +done + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-restart-system b/bin/v-restart-system new file mode 100755 index 0000000..35e4ab1 --- /dev/null +++ b/bin/v-restart-system @@ -0,0 +1,51 @@ +#!/bin/bash +# info: restart operating system +# options: RESTART [DELAY] +# +# example: v-restart-system yes +# +# This function restarts operating system. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +restart=$1 +delay=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'RESTART [DELAY]' + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +if [ "$restart" = 'yes' ]; then + $BIN/v-log-action "system" "Warning" "System" "System restart initiated." + if [ "$delay" ]; then + echo "The server will restart in $delay seconds..." + sleep "$delay" + fi + /sbin/reboot +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-restart-web b/bin/v-restart-web new file mode 100755 index 0000000..2ddd88f --- /dev/null +++ b/bin/v-restart-web @@ -0,0 +1,115 @@ +#!/bin/bash +# info: restart web server +# options: [RESTARRT] +# +# example: v-restart-web +# +# This function reloads web server configuration. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +date=$(date +"%Y-%m-%d %H:%M:%S") + +send_email_report() { + email=$(grep CONTACT $HESTIA/data/users/admin/user.conf) + email=$(echo "$email" | cut -f 2 -d "'") + tmpfile=$(mktemp) + subj="$(hostname): $WEB_SYSTEM restart failed" + if [ "$WEB_SYSTEM" = "apache2" ]; then + apache2ctl configtest >> "$tmpfile" 2>&1 + else + service $WEB_SYSTEM configtest >> "$tmpfile" 2>&1 + fi + if [ "$1" == "DO_RESTART" ]; then + service "$WEB_SYSTEM" restart >> "$tmpfile" 2>&1 + fi + cat "$tmpfile" | $SENDMAIL -s "$subj" "$email" + if [ "$DEBUG_MODE" = "true" ]; then + echo "[ $date | $WEB_SYSTEM | WEB ]" >> /var/log/hestia/debug.log 2>&1 + cat $tmpfile >> /var/log/hestia/debug.log 2>&1 + fi + rm -f $tmpfile +} + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Exit +if [ -z "$WEB_SYSTEM" ] || [ "$WEB_SYSTEM" = 'remote' ]; then + exit +fi + +if [ "$1" = "no" ]; then + exit +fi + +restart=$1 +# Schedule restart +if [ "$1" = 'scheduled' ] || [ -z "$1" ] && [ "$SCHEDULED_RESTART" = 'yes' ]; then + sed -i "/\/$SCRIPT now/d" $HESTIA/data/queue/restart.pipe + echo "$BIN/$SCRIPT now" >> $HESTIA/data/queue/restart.pipe + exit +fi + +if [ "$1" = "updatessl" ]; then + sed -i "/\/$SCRIPT ssl/d" $HESTIA/data/queue/restart.pipe + echo "$BIN/$SCRIPT ssl" >> $HESTIA/data/queue/restart.pipe + exit +fi + +if [ $WEB_SYSTEM = 'nginx' ]; then + if [ "$1" = "ssl" ]; then + restart="ssl" + fi + if [ "$DEBUG_MODE" = "true" ]; then + echo "[ $date | $WEB_SYSTEM | WEB ]" >> /var/log/hestia/debug.log 2>&1 + service $WEB_SYSTEM configtest >> /var/log/hestia/debug.log 2>&1 + else + service $WEB_SYSTEM configtest > /dev/null 2>&1 + fi + if [ $? -ne 0 ]; then + send_email_report + check_result "$E_RESTART" "$WEB_SYSTEM restart failed" + fi +elif [ $WEB_SYSTEM = 'apache2' ]; then + if [ "$DEBUG_MODE" = "true" ]; then + echo "[ $date | $WEB_SYSTEM | WEB ]" >> /var/log/hestia/debug.log 2>&1 + apache2ctl configtest >> /var/log/hestia/debug.log 2>&1 + else + apache2ctl configtest > /dev/null 2>&1 + fi + if [ $? -ne 0 ]; then + send_email_report + check_result "$E_RESTART" "$WEB_SYSTEM restart failed" + fi +fi + +$BIN/v-restart-service "$WEB_SYSTEM" "$restart" + +if [ $? -ne 0 ]; then + send_email_report "DO_RESTART" + check_result "$E_RESTART" "$WEB_SYSTEM restart failed" +fi + +# Update restart queue +if [ -e "$HESTIA/data/queue/restart.pipe" ]; then + sed -i "/\/$SCRIPT now/d" $HESTIA/data/queue/restart.pipe + sed -i "/\/$SCRIPT ssl/d" $HESTIA/data/queue/restart.pipe +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-restart-web-backend b/bin/v-restart-web-backend new file mode 100755 index 0000000..e3437bc --- /dev/null +++ b/bin/v-restart-web-backend @@ -0,0 +1,89 @@ +#!/bin/bash +# info: restart php interpreter +# options: NONE +# +# example: v-restart-web-backend +# +# This function reloads php interpreter configuration. + +restart=$1 +# For backward compatibility might change in the feature +version=$2 + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +send_email_report() { + email=$(grep CONTACT $HESTIA/data/users/admin/user.conf) + email=$(echo "$email" | cut -f 2 -d "'") + subj="$(hostname): $WEB_BACKEND restart failed" + cat $tmpfile | $SENDMAIL -s "$subj" $email + [[ -f "$tmpfile" ]] && rm -f $tmpfile +} + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Exit +if [ -z "$WEB_BACKEND" ] || [ "$WEB_BACKEND" = 'remote' ]; then + exit +fi + +if [ "$1" = "no" ]; then + exit +fi + +# Schedule restart +if [ "$1" = 'scheduled' ] || [ -z "$1" ] && [ "$SCHEDULED_RESTART" = 'yes' ]; then + sed -i "/\/$SCRIPT now/d" $HESTIA/data/queue/restart.pipe + echo "$BIN/$SCRIPT now" >> $HESTIA/data/queue/restart.pipe + exit +fi + +tmpfile=$(mktemp) + +if [ -z "$version" ]; then + # Substitute php-fpm service name formats + for version in $($BIN/v-list-sys-php plain); do + v_php="php$version-fpm" + if [ ! -f "/etc/php/${version}/fpm/pool.d/dummy.conf" ]; then + cp -f "$HESTIA_INSTALL_DIR/php-fpm/dummy.conf" "/etc/php/${version}/fpm/pool.d/" + sed -i "s/9999/99${version//./}/g" "/etc/php/${version}/fpm/pool.d/dummy.conf" + fi + + $BIN/v-restart-service "$v_php" "$restart" + if [ $? -ne 0 ]; then + send_email_report + check_result "$E_RESTART" "$v_php restart failed" + fi + done +else + v_php="php$version-fpm" + $BIN/v-restart-service "$v_php" "$restart" + if [ $? -ne 0 ]; then + send_email_report + check_result "$E_RESTART" "$v_php restart failed" + fi +fi + +# Update restart queue +if [ -e "$HESTIA/data/queue/restart.pipe" ]; then + sed -i "/\/$SCRIPT now/d" $HESTIA/data/queue/restart.pipe +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +[[ -f "$tmpfile" ]] && rm -f $tmpfile +exit diff --git a/bin/v-restore-cron-job b/bin/v-restore-cron-job new file mode 100755 index 0000000..74ac1d4 --- /dev/null +++ b/bin/v-restore-cron-job @@ -0,0 +1,51 @@ +#!/bin/bash +# info: restore single cron job +# options: USER BACKUP DOMAIN [NOTIFY] +# +# example: v-restore-cron-job USER BACKUP CRON [NOTIFY] +# +# This function allows the user to restore a single cron job +# from a backup archive. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +backup=$2 +cronjob=$3 +notify=$4 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +args_usage='USER BACKUP CRON [NOTIFY]' +check_args '3' "$#" "$args_usage" +is_format_valid 'user' 'backup' + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +$BIN/v-restore-user "$user" "$backup" 'no' 'no' 'no' 'no' "$cronjob" 'no' "$notify" + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-restore-database b/bin/v-restore-database new file mode 100755 index 0000000..a13c43b --- /dev/null +++ b/bin/v-restore-database @@ -0,0 +1,51 @@ +#!/bin/bash +# info: restore single database +# options: USER BACKUP DATABASE [NOTIFY] +# +# example: v-restore-database USER BACKUP DATABASE [NOTIFY] +# +# This function allows the user to restore a single database +# from a backup archive. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +backup=$2 +database=$3 +notify=$4 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +args_usage='USER BACKUP DATABASE [NOTIFY]' +check_args '3' "$#" "$args_usage" +is_format_valid 'user' 'backup' + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +$BIN/v-restore-user "$user" "$backup" 'no' 'no' 'no' "$database" 'no' 'no' "$notify" + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-restore-dns-domain b/bin/v-restore-dns-domain new file mode 100755 index 0000000..54a6bd5 --- /dev/null +++ b/bin/v-restore-dns-domain @@ -0,0 +1,51 @@ +#!/bin/bash +# info: restore single dns domain +# options: USER BACKUP DOMAIN [NOTIFY] +# +# example: v-restore-dns-domain USER BACKUP DOMAIN [NOTIFY] +# +# This function allows the user to restore a single DNS domain +# from a backup archive. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +backup=$2 +domain=$3 +notify=$4 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +args_usage='USER BACKUP DOMAIN [NOTIFY]' +check_args '3' "$#" "$args_usage" +is_format_valid 'user' 'backup' + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +$BIN/v-restore-user "$user" "$backup" 'no' "$domain" 'no' 'no' 'no' 'no' "$notify" + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-restore-mail-domain b/bin/v-restore-mail-domain new file mode 100755 index 0000000..551594d --- /dev/null +++ b/bin/v-restore-mail-domain @@ -0,0 +1,51 @@ +#!/bin/bash +# info: restore single mail domain +# options: USER BACKUP DOMAIN [NOTIFY] +# +# example: v-restore-mail-domain USER BACKUP DOMAIN [NOTIFY] +# +# This function allows the user to restore a single mail domain +# from a backup archive. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +backup=$2 +domain=$3 +notify=$4 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +args_usage='USER BACKUP DOMAIN [NOTIFY]' +check_args '3' "$#" "$args_usage" +is_format_valid 'user' 'backup' + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +$BIN/v-restore-user "$user" "$backup" 'no' 'no' "$domain" 'no' 'no' 'no' "$notify" + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-restore-user b/bin/v-restore-user new file mode 100755 index 0000000..289a4ba --- /dev/null +++ b/bin/v-restore-user @@ -0,0 +1,947 @@ +#!/bin/bash +# info: restore user +# options: USER BACKUP [WEB] [DNS] [MAIL] [DB] [CRON] [UDIR] [NOTIFY] +# +# example: v-restore-user admin 2019-04-22_01-00-00.tar +# +# This function for restoring user from backup. To be able to restore the backup, +# the archive needs to be placed in /backup. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +backup=$2 +web=$3 +dns=$4 +mail=$5 +db=$6 +cron=$7 +udir=$8 +notify=${9-no} + +# Define backup dir +if [ -z "$BACKUP" ]; then + BACKUP=/backup +fi + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/backup.sh +source $HESTIA/func/backup.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# shellcheck source=/usr/local/hestia/func/ip.sh +source $HESTIA/func/ip.sh +# shellcheck source=/usr/local/hestia/func/db.sh +source $HESTIA/func/db.sh +# shellcheck source=/usr/local/hestia/func/rebuild.sh +source $HESTIA/func/rebuild.sh +# shellcheck source=/usr/local/hestia/func/syshealth.sh +source $HESTIA/func/syshealth.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +args_usage='USER BACKUP [WEB] [DNS] [MAIL] [DB] [CRON] [UDIR] [NOTIFY]' +check_args '2' "$#" "$args_usage" +is_format_valid 'user' 'backup' + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Check if backup folder exists and have the correct permission +if [[ ! -d "$BACKUP" ]]; then + mkdir -p "$BACKUP" +fi +if [ $(stat -c %a "$BACKUP") != 755 ]; then + chmod 755 "$BACKUP" +fi + +# Checking local backup +if [ ! -e "$BACKUP/$backup" ]; then + if [[ "$BACKUP_SYSTEM" =~ "sftp" ]] && [ -z "$downloaded" ]; then + sftp_download "$backup" + downloaded='yes' + fi + if [[ "$BACKUP_SYSTEM" =~ "ftp" ]] && [ -z "$downloaded" ]; then + ftp_download "$backup" + downloaded='yes' + fi + if [[ "$BACKUP_SYSTEM" =~ "b2" ]] && [ -z "$downloaded" ]; then + b2_download "$backup" + downloaded='yes' + fi + if [[ "$BACKUP_SYSTEM" =~ "rclone" ]] && [ -z "$downloaded" ]; then + rclone_download "$backup" + downloaded='yes' + fi + if [ -z "$downloaded" ]; then + check_result "$E_NOTEXIST" "backup file $backup doesn't exist in '${BACKUP}' folder" + fi +fi + +if [ ! -e "$BACKUP/$backup" ]; then + check_result "$E_NOTEXIST" "backup file $backup doesn't exist in '${BACKUP}' folder" +fi + +# Checking user existence on the server +check_user=$(is_object_valid 'user' 'USER' "$user") +if [ -z "$check_user" ]; then + is_object_unsuspended 'user' 'USER' "$user" + subj="$user → restore failed" + email=$(get_user_value '$CONTACT') +else + create_user="yes" + email=$(grep CONTACT $HESTIA/data/users/admin/user.conf | cut -f2 -d \') +fi + +# Checking available disk space +disk_usage=$(df $BACKUP | tail -n1 | tr ' ' '\n' | grep % | cut -f 1 -d %) +if [ "$disk_usage" -ge "$BACKUP_DISK_LIMIT" ]; then + echo "Error: Not enough disk space" | $SENDMAIL -s "$subj" $email $notify + sed -i "/ $user /d" $HESTIA/data/queue/backup.pipe + check_result "$E_DISK" "Not enough disk space" +fi + +# Checking load average +la=$(cat /proc/loadavg | cut -f 1 -d ' ' | cut -f 1 -d '.') +i=0 +while [ "$la" -ge "$BACKUP_LA_LIMIT" ]; do + echo -e "$(date "+%F %T") Load Average $la" + sleep 60 + if [ "$i" -ge "15" ]; then + la_error="LoadAverage $la is above threshold" + echo "Error: $la_error" | $SENDMAIL -s "$subj" $email $notify + sed -i "/ $user /d" $HESTIA/data/queue/backup.pipe + check_result "$E_LA" "$la_error" + fi + la=$(cat /proc/loadavg | cut -f 1 -d ' ' | cut -f 1 -d '.') + ((++i)) +done + +if [ -z "$BACKUP_TEMP" ]; then + BACKUP_TEMP=$BACKUP +fi + +# Creating temporary directory +tmpdir=$(mktemp -p $BACKUP_TEMP -d) +if [ "$?" -ne 0 ]; then + echo "Can't create tmp dir $tmpdir" | $SENDMAIL -s "$subj" $email $notify + sed -i "/ $user /d" $HESTIA/data/queue/backup.pipe + check_result "$E_NOTEXIST" "Can't create tmp dir" +fi + +# Set default backup source system +backup_system="hestia" +backup_mode="gzip" + +# Check if it is a Vesta backup +if tar -tf "$BACKUP/$backup" ./vesta > /dev/null 2>&1; then + backup_system="vesta" +fi + +if tar -tf "$BACKUP/$backup" ./.zstd > /dev/null 2>&1; then + backup_mode="zstd" +fi + +# Restoring user account +if [ "$create_user" = 'yes' ]; then + + # Add check if user already exists as Linux User + getent passwd "$user" > /dev/null 2>&1 + if [ "$?" == 0 ]; then + check_result "$E_EXISTS" "User already exists" + fi + + echo "-- USER --" | tee $tmpdir/restore.log + echo -e "$(date "+%F %T") $user" | tee -a $tmpdir/restore.log + + # Unpacking user container + tar xf "$BACKUP/$backup" -C "$tmpdir" --no-wildcards "./$backup_system" 2> /dev/null + if [ "$?" -ne 0 ]; then + rm -rf $tmpdir + echo "Can't unpack user container" | $SENDMAIL -s "$subj" $email $notify + sed -i "/ $user /d" $HESTIA/data/queue/backup.pipe + check_result "$E_PARSING" "Can't unpack user container" + fi + + # Restoring user.conf + mkdir $USER_DATA + cp $tmpdir/$backup_system/user.conf $USER_DATA/ + cp -r $tmpdir/$backup_system/ssl $USER_DATA/ > /dev/null 2>&1 + cp $tmpdir/$backup_system/backup-excludes.conf $USER_DATA/ > /dev/null 2>&1 + + # Rebuilding user + rebuild_user_conf +fi + +# Unpacking pam container +chown "$user" "$tmpdir" +tar xf $BACKUP/$backup -C $tmpdir ./pam +if [ "$?" -ne 0 ]; then + rm -rf $tmpdir + echo "Can't unpack PAM container" | $SENDMAIL -s "$subj" $email $notify + sed -i "/ $user /d" $HESTIA/data/queue/backup.pipe + check_result "$E_PARSING" "Can't unpack PAM container" +fi +old_user=$(cut -f 1 -d : $tmpdir/pam/passwd) +old_uid=$(cut -f 3 -d : $tmpdir/pam/passwd) +new_uid=$(grep "^$user:" /etc/passwd | cut -f 3 -d :) + +# Restoring web domains +if [ "$web" != 'no' ] && [ -n "$WEB_SYSTEM" ]; then + echo -e "\n-- WEB --" | tee -a $tmpdir/restore.log + + # Creating web domain restore list + backup_domains=$(tar -tf $BACKUP/$backup | grep "^./web") + if [ "$backup_mode" = "zstd" ]; then + backup_domains=$(echo "$backup_domains" | grep domain_data.tar.zst) + else + backup_domains=$(echo "$backup_domains" | grep domain_data.tar.gz) + fi + backup_domains=$(echo "$backup_domains" | cut -f 3 -d /) + if [ -z "$web" ] || [ "$web" = '*' ]; then + domains="$backup_domains" + else + echo "$web" | tr ',' '\n' > $tmpdir/selected.txt + domains=$(echo "$backup_domains" | egrep -x -f $tmpdir/selected.txt) + fi + + # Restoring web domain + for domain in $domains; do + echo -e "$(date "+%F %T") $domain" | tee -a $tmpdir/restore.log + + # Cleanup previous domain keys + unset -v DOMAIN IP IP6 ALIAS TPL SSL SSL_HOME LETSENCRYPT FTP_USER FTP_MD5 BACKEND PROXY PROXY_EXT STATS STATS_USER STATS_CRYPT U_DISK CUSTOM_DOCROOT CUSTOM_PHPROOT + + # Checking domain existence + check_config=$(grep "DOMAIN='$domain'" $USER_DATA/web.conf) + if [ -z "$check_config" ]; then + check_new=$(is_domain_new 'web' $domain) + if [ -n "$check_new" ]; then + rm -rf $tmpdir + error="$domain belongs to another user" + echo "$error" | $SENDMAIL -s "$subj" $email $notify + sed -i "/ $user /d" $HESTIA/data/queue/backup.pipe + check_result "$E_PARSING" "$error" + fi + fi + + # Unpacking domain container + tar xf $BACKUP/$backup -C $tmpdir ./web/$domain + if [ "$?" -ne 0 ]; then + rm -rf $tmpdir + error="Can't unpack $domain web container" + echo "$error" | $SENDMAIL -s "$subj" $email $notify + sed -i "/ $user /d" $HESTIA/data/queue/backup.pipe + check_result "$E_PARSING" "$error" + fi + + # Restoring web.conf + if [ -z "$check_config" ]; then + parse_object_kv_list $(cat $tmpdir/web/$domain/$backup_system/web.conf) + + # Deleting conflicting aliases + for dom_alias in ${ALIAS//,/ }; do + check_new=$(is_domain_new 'web' $dom_alias) + if [ -n "$check_new" ]; then + ALIAS=$(echo "$ALIAS" \ + | sed "s/,/\n/g" \ + | sed "s/^$dom_alias$//g" \ + | sed "/^$/d" \ + | sed ':a;N;$!ba;s/\n/,/g') + fi + done + + # Checking IP address + check_ip=$(is_ip_valid $IP $user) + if [ -n "$check_ip" ]; then + local_ip='' + get_user_ip $user + old_ip=$IP + IP=$ip + fi + + # Checking web template + check_tpl=$(is_web_template_valid $TPL) + if [ -n "$check_tpl" ]; then + TPL='default' + fi + + # Checking proxy template + check_proxy_tpl=$(is_proxy_template_valid $PROXY) + if [ -n "$check_proxy_tpl" ]; then + PROXY='default' + fi + + # Checking backend template + check_backend_tpl=$(is_backend_template_valid $BACKEND) + if [ -n "$check_backend_tpl" ]; then + BACKEND='default' + fi + + if [ -n "$CUSTOM_DOCROOT" ]; then + CUSTOM_DOCROOT=$(echo "$CUSTOM_DOCROOT" | sed -e "s|/home/${old_user}/web/|/home/${user}/web/|g") + fi + if [ -n "$CUSTOM_PHPROOT" ]; then + CUSTOM_PHPROOT=$(echo "$CUSTOM_PHPROOT" | sed -e "s|/home/${old_user}/web/|/home/${user}/web/|g") + fi + + # Converting FTP users + if [ -n "$FTP_USER" ]; then + FTP_USER=$(echo "$FTP_USER" | sed -e "s/${old_user}_//") + FTP_USER="${user}_${FTP_USER}" + fi + + # Copying SSL certificates + if [ "$SSL" = 'yes' ]; then + + if [ -f "$tmpdir/web/$domain/$backup_system/$domain.crt" ]; then + for crt in $(ls $tmpdir/web/$domain/$backup_system | grep -E '^'$domain'\.(crt|key|ca|pem)$'); do + cp -f "$tmpdir/web/$domain/$backup_system/$crt" "$USER_DATA/ssl/" + done + elif [ -f "$tmpdir/web/$domain/conf/ssl.$domain.crt" ]; then + certificates=$(ls $tmpdir/web/$domain/conf | grep ssl) + certificates=$(echo "$certificates" | grep $domain) + for crt in $certificates; do + crt=$(echo $crt | sed -e "s/ssl.//") + cp -f $tmpdir/web/$domain/conf/ssl.$crt $USER_DATA/ssl/$crt + done + fi + fi + + # Merging web.conf keys + str="DOMAIN='$domain' IP='$IP' IP6='$IP6' ALIAS='$ALIAS'" + str="$str CUSTOM_DOCROOT='$CUSTOM_DOCROOT' CUSTOM_PHPROOT='$CUSTOM_PHPROOT'" + str="$str REDIRECT='$REDIRECT' REDIRECT_CODE='$REDIRECT_CODE'" + str="$str FASTCGI_CACHE='$FASTCGI_CACHE' FASTCGI_DURATION='$FASTCGI_DURATION'" + str="$str TPL='$TPL' SSL='$SSL' SSL_HOME='$SSL_HOME' SSL_HSTS='$SSL_HSTS'" + str="$str SSL_FORCE='$SSL_FORCE' LETSENCRYPT='$LETSENCRYPT' FTP_USER='$FTP_USER'" + str="$str FTP_MD5='$FTP_MD5' FTP_PATH='$FTP_PATH'" + str="$str BACKEND='$BACKEND' PROXY='$PROXY'" + str="$str PROXY_EXT='$PROXY_EXT' STATS='$STATS'" + str="$str STATS_USER='$STATS_USER' STATS_CRYPT='$STATS_CRYPT'" + str="$str U_DISK='$U_DISK' U_BANDWIDTH='0' SUSPENDED='no'" + str="$str TIME='$(date +%T)' DATE='$(date +%F)'" + echo $str >> $USER_DATA/web.conf + + # Rebuilding backend + if [ -n "$WEB_BACKEND" ]; then + $BIN/v-add-web-domain-backend $user $domain $BACKEND + fi + fi + + # Restoring custom user config + # Except certificates, .conf files + if [ ! -d "$HOMEDIR/$user/conf/web/$domain/" ]; then + mkdir -p $HOMEDIR/$user/conf/web/$domain/ + fi + for file in $tmpdir/web/$domain/conf/*; do + if [[ "$file" == *.ca ]] || [[ "$file" == *.crt ]] || [[ "$file" == *.key ]] || [[ "$file" == *.pem ]] || [[ "$file" == *.conf ]]; then + continue + fi + if grep "fastcgi_pass" "$file"; then + # Do not allow to run php under a different user + continue + fi + filename=$(basename "$file") + cp -f "$file" "$HOMEDIR/$user/conf/web/$domain/$filename" + done + + # Rebuilding vhost to prevent user overwrite default config changes not ideal + rebuild_web_domain_conf + + # Restoring web domain data + if [ -d "$HOMEDIR/$user/web/$domain/public_html" ]; then + rm -rf $HOMEDIR/$user/web/$domain/public_html/* + fi + chmod u+w "$HOMEDIR/$user/web/$domain" + [[ -d $HOMEDIR/$user/web/$domain/stats ]] && chmod u+w "$HOMEDIR/$user/web/$domain/stats" + + if [ "$backup_mode" = "zstd" ]; then + user_exec tar -I pzstd -xpf $tmpdir/web/$domain/domain_data.tar.zst \ + -C "$HOMEDIR/$user/web/$domain/" \ + --anchored \ + --exclude='logs/*' + else + user_exec tar -xzpf $tmpdir/web/$domain/domain_data.tar.gz \ + -C "$HOMEDIR/$user/web/$domain/" \ + --anchored \ + --exclude='logs/*' + fi + + if [ "$?" -ne 0 ]; then + rm -rf $tmpdir + error="Can't unpack $domain data tarball" + echo "$error" | $SENDMAIL -s "$subj" $email $notify + sed -i "/ $user /d" $HESTIA/data/queue/backup.pipe + check_result "$E_PARSING" "$error" + fi + + # Re-chowning files if uid differs + if [ "$old_uid" -ne "$new_uid" ]; then + find $HOMEDIR/$user/web/$domain/ -user $old_uid \ + -exec chown -h $user:$user {} \; + fi + + # Rebuilding web config for the second time to make sure ftp users keep working + rebuild_web_domain_conf + done + + # Adding user to traffic queue + sed -i "/ $user /d" $HESTIA/data/queue/traffic.pipe + echo "$BIN/v-update-web-domains-traff $user" >> $HESTIA/data/queue/traffic.pipe + + # Restarting web server + $BIN/v-restart-web + check_result $? "Web restart failed" + if [ -n "$PROXY_SYSTEM" ]; then + $BIN/v-restart-proxy + check_result $? "Proxy restart failed" + fi +fi + +# Restoring DNS domains +if [ "$dns" != 'no' ] && [ -n "$DNS_SYSTEM" ]; then + echo -e "\n-- DNS --" | tee -a $tmpdir/restore.log + + # Creating dns domain restore list + backup_domains=$(tar -tf $BACKUP/$backup | grep "^./dns") + backup_domains=$(echo "$backup_domains" | grep "dns.conf$") + backup_domains=$(echo "$backup_domains" | cut -f 3 -d /) + if [ -z "$dns" ] || [ "$dns" = '*' ]; then + domains="$backup_domains" + else + echo "$dns" | tr ',' '\n' > $tmpdir/selected.txt + domains=$(echo "$backup_domains" | egrep -x -f $tmpdir/selected.txt) + fi + + # Restoring DNS domain + for domain in $domains; do + echo -e "$(date "+%F %T") $domain" | tee -a $tmpdir/restore.log + domain_idn="$domain" + # Cleanup previous config keys + unset -v DOMAIN IP TPL TTL EXP SOA RECORDS DNSSEC KEY SLAVE MASTER + + # Checking domain existence + check_config=$(grep "DOMAIN='$domain'" $USER_DATA/dns.conf) + if [ -z "$check_config" ]; then + check_new=$(is_domain_new 'dns' $domain) + if [ -n "$check_new" ]; then + rm -rf $tmpdir + error="$domain belongs to another user" + echo "$error" | $SENDMAIL -s "$subj" $email $notify + sed -i "/ $user /d" $HESTIA/data/queue/backup.pipe + check_result "$E_PARSING" "$error" + fi + fi + + # Unpacking domain container + tar xf $BACKUP/$backup -C $tmpdir ./dns/$domain + if [ "$?" -ne 0 ]; then + rm -rf $tmpdir + error="Can't unpack $domain dns container" + echo "$error" | $SENDMAIL -s "$subj" $email $notify + sed -i "/ $user /d" $HESTIA/data/queue/backup.pipe + check_result "$E_PARSING" "$error" + fi + + # Restoring dns.conf + if [ -z "$check_config" ]; then + parse_object_kv_list $(cat $tmpdir/dns/$domain/$backup_system/dns.conf) + + # Checking IP address + check_ip=$(is_ip_valid $IP $user) + if [ -n "$check_ip" ]; then + export local_ip='' + get_user_ip $user + old_ip=$IP + IP=$ip + fi + + # Checking DNS template + check_tpl=$(is_dns_template_valid $TPL) + if [ -n "$check_tpl" ]; then + TPL='default' + fi + + # Merging dns.conf keys + str="DOMAIN='$domain' IP='$IP' TPL='$TPL' TTL='$TTL' EXP='$EXP'" + str="$str SOA='$SOA' RECORDS='$RECORDS' DNSSEC='$DNSSEC'" + str="$str KEY='$KEY' SLAVE='$SLAVE' MASTER='$MASTER' SUSPENDED='no'" + str="$str TIME='$(date +%T)' DATE='$(date +%F)'" + echo $str >> $USER_DATA/dns.conf + fi + + if [ "$DNSSEC" = "yes" ]; then + format_domain_idn + # Probably need to change the cache dir for RHEL + if [ -f "/etc/redhat-release" ]; then + cp $tmpdir/dns/$domain/conf/keys/* /var/cache/named/ + chown named:named /var/cache/named/K$domain_idn* + chmod 644 /var/cache/named/K$domain_idn* + else + cp $tmpdir/dns/$domain/conf/keys/* /var/cache/bind/ + chown bind:bind /var/cache/bind/K$domain_idn* + chmod 644 /var/cache/bind/K$domain_idn* + fi + fi + + # Restoring DNS records + cp -f $tmpdir/dns/$domain/$backup_system/$domain.conf $USER_DATA/dns/ + + # Update IP in records + if [ -n "$old_ip" ]; then + sed -i s/$old_ip/$IP/g $USER_DATA/dns/$domain.conf + fi + + # Rebuilding DNS domain + rebuild_dns_domain_conf + + # Updating dns-cluster queue + if [ -n "$DNS_CLUSTER" ]; then + cmd="$BIN/v-add-remote-dns-domain $user $domain yes" + echo "$cmd" >> $HESTIA/data/queue/dns-cluster.pipe + fi + done + + # Restarting DNS + $BIN/v-restart-dns + check_result $? "DNS restart failed" +fi + +# Restoring mail domains +if [ "$mail" != 'no' ] && [ -n "$MAIL_SYSTEM" ]; then + echo -e "\n-- MAIL --" | tee -a $tmpdir/restore.log + + # Creating mail domain restore list + backup_domains=$(tar -tf $BACKUP/$backup | grep "^./mail") + backup_domains=$(echo "$backup_domains" | grep "mail.conf$") + backup_domains=$(echo "$backup_domains" | cut -f 3 -d /) + if [ -z "$mail" ] || [ "$mail" = '*' ]; then + domains="$backup_domains" + else + echo "$mail" | tr ',' '\n' > $tmpdir/selected.txt + domains=$(echo "$backup_domains" | egrep -x -f $tmpdir/selected.txt) + fi + + # Checking exim username for later chowning + exim_user="exim" + check_exim_username=$(grep -c '^Debian-exim:' /etc/passwd) + if [ "$check_exim_username" -eq 1 ]; then + exim_user="Debian-exim" + fi + + # Restoring DNS domain + for domain in $domains; do + echo -e "$(date "+%F %T") $domain" | tee -a $tmpdir/restore.log + + # Checking domain existence + check_config=$(grep "DOMAIN='$domain'" $USER_DATA/mail.conf) + if [ -z "$check_config" ]; then + check_new=$(is_domain_new 'mail' $domain) + if [ -n "$check_new" ]; then + rm -rf $tmpdir + error="$domain belongs to another user" + echo "$error" | $SENDMAIL -s "$subj" $email $notify + sed -i "/ $user /d" $HESTIA/data/queue/backup.pipe + check_result "$E_PARSING" "$error" + fi + fi + + # Unpacking domain container + tar xf $BACKUP/$backup -C $tmpdir ./mail/$domain + + if [ "$?" -ne 0 ]; then + rm -rf $tmpdir + error="Can't unpack $domain mail container" + echo "$error" | $SENDMAIL -s "$subj" $email $notify + sed -i "/ $user /d" $HESTIA/data/queue/backup.pipe + check_result "$E_PARSING" "$error" + fi + + # Restoring mail.conf + if [ -z "$check_config" ]; then + cat $tmpdir/mail/$domain/$backup_system/mail.conf >> $USER_DATA/mail.conf + fi + + # Restoring DKIM + if [ -e "$tmpdir/mail/$domain/$backup_system/$domain.pem" ]; then + cp -f $tmpdir/mail/$domain/$backup_system/$domain.pem $USER_DATA/mail/ + cp -f $tmpdir/mail/$domain/$backup_system/$domain.pub $USER_DATA/mail/ + fi + + # Restore SSL + check_config=$(grep "DOMAIN='$domain'" $USER_DATA/mail.conf | grep -o "SSL='yes'") + if [ -n "$check_config" ]; then + if [ ! -e "$HESTIA/data/users/$user/ssl/" ]; then + mkdir -p $HESTIA/data/users/$user/ssl/ + fi + + if [ ! -e "$HOMEDIR/$user/conf/mail/$domain/ssl/" ]; then + mkdir -p $HOMEDIR/$user/conf/mail/$domain/ssl/ + fi + + # Add certificate to Hestia user configuration data directory + if [ -f $tmpdir/mail/$domain/$backup_system/ssl/$domain.crt ]; then + cp -f $tmpdir/mail/$domain/$backup_system/ssl/$domain.crt $USER_DATA/ssl/mail.$domain.crt + cp -f $tmpdir/mail/$domain/$backup_system/ssl/$domain.key $USER_DATA/ssl/mail.$domain.key + cp -f $tmpdir/mail/$domain/$backup_system/ssl/$domain.crt $USER_DATA/ssl/mail.$domain.pem + if [ -e "$tmpdir/mail/$domain/$backup_system/ssl/$domain.ca" ]; then + cp -f $tmpdir/mail/$domain/$backup_system/ssl/$domain.ca $USER_DATA/ssl/mail.$domain.ca + echo >> $USER_DATA/ssl/mail.$domain.pem + cat $USER_DATA/ssl/mail.$domain.ca >> $USER_DATA/ssl/mail.$domain.pem + fi + elif [ -f "$tmpdir/mail/$domain/conf/ssl/$domain.crt" ]; then + cp -f $tmpdir/mail/$domain/conf/ssl/$domain.crt $USER_DATA/ssl/mail.$domain.crt + cp -f $tmpdir/mail/$domain/conf/ssl/$domain.key $USER_DATA/ssl/mail.$domain.key + cp -f $tmpdir/mail/$domain/conf/ssl/$domain.crt $USER_DATA/ssl/mail.$domain.pem + if [ -e "$tmpdir/mail/$domain/conf/ssl/$domain.ca" ]; then + cp -f $tmpdir/mail/$domain/conf/ssl/$domain.ca $USER_DATA/ssl/mail.$domain.ca + echo >> $USER_DATA/ssl/mail.$domain.pem + cat $USER_DATA/ssl/mail.$domain.ca >> $USER_DATA/ssl/mail.$domain.pem + fi + + fi + + chmod 660 $USER_DATA/ssl/mail.$domain.* + + # Add certificate to user home directory + cp -f $USER_DATA/ssl/mail.$domain.crt $HOMEDIR/$user/conf/mail/$domain/ssl/$domain.crt + cp -f $USER_DATA/ssl/mail.$domain.key $HOMEDIR/$user/conf/mail/$domain/ssl/$domain.key + cp -f $USER_DATA/ssl/mail.$domain.pem $HOMEDIR/$user/conf/mail/$domain/ssl/$domain.pem + if [ -e "$USER_DATA/ssl/mail.$domain.ca" ]; then + cp -f $USER_DATA/ssl/mail.$domain.ca $HOMEDIR/$user/conf/mail/$domain/ssl/$domain.ca + fi + + if [ ! -d /etc/dovecot/conf.d/domains ]; then + mkdir /etc/dovecot/conf.d/domains + fi + + # Add domain SSL configuration to dovecot + if [ -f /etc/dovecot/conf.d/domains/$domain.conf ]; then + rm -f /etc/dovecot/conf.d/domains/$domain.conf + fi + + echo "" >> /etc/dovecot/conf.d/domains/$domain.conf + echo "local_name mail.$domain {" >> /etc/dovecot/conf.d/domains/$domain.conf + echo " ssl_cert = <$HOMEDIR/$user/conf/mail/$domain/ssl/$domain.pem" >> /etc/dovecot/conf.d/domains/$domain.conf + echo " ssl_key = <$HOMEDIR/$user/conf/mail/$domain/ssl/$domain.key" >> /etc/dovecot/conf.d/domains/$domain.conf + echo "}" >> /etc/dovecot/conf.d/domains/$domain.conf + + if [ ! -d /usr/local/hestia/ssl/mail ]; then + mkdir /usr/local/hestia/ssl/mail + fi + + # Add domain SSL configuration to exim4 + # Cleanup broken symlinks + find /usr/local/hestia/ssl/mail -xtype l -delete + + ln -s -f $HOMEDIR/$user/conf/mail/$domain/ssl/$domain.pem /usr/local/hestia/ssl/mail/mail.$domain.crt + ln -s -f $HOMEDIR/$user/conf/mail/$domain/ssl/$domain.key /usr/local/hestia/ssl/mail/mail.$domain.key + + # Set correct permissions on certificates + chmod 750 $HOMEDIR/$user/conf/mail/$domain/ssl + chown -R $MAIL_USER:mail $HOMEDIR/$user/conf/mail/$domain/ssl + chmod 0644 $HOMEDIR/$user/conf/mail/$domain/ssl/* + chown -h $user:mail $HOMEDIR/$user/conf/mail/$domain/ssl/* + chmod -R 0644 /usr/local/hestia/ssl/mail/* + chown -h $user:mail /usr/local/hestia/ssl/mail/* + fi + + # Restoring email accounts + cp -f $tmpdir/mail/$domain/$backup_system/$domain.conf $USER_DATA/mail/ + + domain_idn=$domain + format_domain_idn + + if [ ! -d "$HOMEDIR/$user/mail/$domain_idn" ]; then + mkdir $HOMEDIR/$user/mail/$domain_idn + fi + + # Current Hestia store email in the $HOMEDIR/$user/mail/$domain_idn + chmod u+w "$HOMEDIR/$user/mail/$domain_idn" + chown $user:$user "$HOMEDIR/$user/mail/$domain_idn" + + # Restoring emails + if [ $backup_mode = 'zstd' ]; then + if [ -e "$tmpdir/mail/$domain/accounts.tar.zst" ]; then + $BIN/v-extract-fs-archive "$user" "$tmpdir/mail/$domain/accounts.tar.zst" "$HOMEDIR/$user/mail/$domain_idn/" + if [ "$?" -ne 0 ]; then + rm -rf $tmpdir + error="Can't unpack $domain mail account container" + echo "$error" | $SENDMAIL -s "$subj" $email $notify + sed -i "/ $user /d" $HESTIA/data/queue/backup.pipe + check_result "$E_PARSING" "$error" + fi + + # Chowning as owner needs to be user:mail instead of user:user + find $HOMEDIR/$user/mail/$domain_idn -user $user \ + -exec chown -h $user:mail {} \; + fi + else + if [ -e "$tmpdir/mail/$domain/accounts.tar.gz" ]; then + $BIN/v-extract-fs-archive "$user" "$tmpdir/mail/$domain/accounts.tar.gz" "$HOMEDIR/$user/mail/$domain_idn/" + if [ "$?" -ne 0 ]; then + rm -rf $tmpdir + error="Can't unpack $domain mail account container" + echo "$error" | $SENDMAIL -s "$subj" $email $notify + sed -i "/ $user /d" $HESTIA/data/queue/backup.pipe + check_result "$E_PARSING" "$error" + fi + + # Chowning as owner needs to be user:mail instead of user:user + find $HOMEDIR/$user/mail/$domain_idn -user $user \ + -exec chown -h $user:mail {} \; + fi + fi + # Chowning mail conf files to exim user + if [ -d "$HOMEDIR/$user/conf/mail/$domain" ]; then + find $HOMEDIR/$user/conf/mail/$domain -user root \ + -exec chown $exim_user {} \; + fi + + $BIN/v-rebuild-mail-domain $user $domain + + done + + # Restarting web server + $BIN/v-restart-web + check_result $? "Web restart failed" + if [ -n "$PROXY_SYSTEM" ]; then + $BIN/v-restart-proxy + check_result $? "Proxy restart failed" + fi +fi + +# Restoring databases +if [ "$db" != 'no' ] && [ -n "$DB_SYSTEM" ]; then + echo -e "\n-- DB --" | tee -a $tmpdir/restore.log + + # Creating database restore list + backup_databases=$(tar -tf $BACKUP/$backup | grep "^./db") + backup_databases=$(echo "$backup_databases" | grep db.conf) + backup_databases=$(echo "$backup_databases" | cut -f 3 -d / | sort -u) + if [ -z "$db" ] || [ "$db" = '*' ]; then + databases="$backup_databases" + else + echo "$db" | tr ',' '\n' > $tmpdir/selected.txt + databases=$(echo "$backup_databases" | egrep -x -f $tmpdir/selected.txt) + fi + + # Restoring database + for database in $databases; do + echo -e "$(date "+%F %T") $database" | tee -a $tmpdir/restore.log + + # Cleanup previous config keys + unset -v DB DBUSER MD5 HOST TYPE CHARSET U_DISK + + # Checking database existence + check_config=$(grep "DB='$database'" $USER_DATA/db.conf) + + # Unpacking database container + tar xf $BACKUP/$backup -C $tmpdir ./db/$database + if [ "$?" -ne 0 ]; then + rm -rf $tmpdir + error="Can't unpack $database database container" + echo "$error" | $SENDMAIL -s "$subj" $email $notify + sed -i "/ $user /d" $HESTIA/data/queue/backup.pipe + check_result "$E_PARSING" "$error" + fi + + # Restore database config + if [ -z "$check_config" ]; then + parse_object_kv_list $(cat $tmpdir/db/$database/$backup_system/db.conf) + + if [ -z "$MD5" ]; then + echo "Warning!: Database ${DB} backup does not contain a password for user ${DBUSER}." + echo "- Please use the web interface to set a password after the restore process finishes." + fi + + DB=$(echo "$DB" | sed -e "s/${old_user}_//") + DB="${user}_${DB}" + DBUSER=$(echo "$DBUSER" | sed -e "s/${old_user}_//") + DBUSER="${user}_${DBUSER}" + str="DB='$DB' DBUSER='$DBUSER' MD5='$MD5' HOST='$HOST'" + str="$str TYPE='$TYPE' CHARSET='$CHARSET' U_DISK='$U_DISK'" + str="$str SUSPENDED='no' TIME='$(date +%T)' DATE='$(date +%F)'" + echo $str >> $USER_DATA/db.conf + else + parse_object_kv_list $(grep "DB='$database'" $USER_DATA/db.conf) + fi + + # Unzipping database dump + if [ $backup_mode = 'zstd' ]; then + pzstd -d $tmpdir/db/$database/$database.*.sql.zst + else + gzip -d $tmpdir/db/$database/$database.*.sql.gz + fi + + # Importing database dump + database_dump="$tmpdir/db/$database/$database.$TYPE.sql" + case $TYPE in + mysql) + delete_mysql_database + rebuild_mysql_database + import_mysql_database $database_dump + ;; + pgsql) + delete_pgsql_database + rebuild_pgsql_database + import_pgsql_database $database_dump + ;; + esac + done +fi + +# Restoring cron jobs +if [ "$cron" != 'no' ] && [ -n "$CRON_SYSTEM" ]; then + echo -e "\n-- CRON --" | tee -a $tmpdir/restore.log + + # Unpacking cron container + tar xf $BACKUP/$backup -C $tmpdir ./cron + if [ "$?" -ne 0 ]; then + rm -rf $tmpdir + error="Can't unpack cron container" + echo "$error" | $SENDMAIL -s "$subj" $email $notify + sed -i "/ $user /d" $HESTIA/data/queue/backup.pipe + check_result "$E_PARSING" "$error" + fi + + sed -i 's/\r//g' $tmpdir/cron/cron.conf + jobs=$(wc -l $tmpdir/cron/cron.conf | cut -f 1 -d' ') + if [ "$jobs" -eq 1 ]; then + echo -e "$(date "+%F %T") $jobs cron job" | tee -a $tmpdir/restore.log + else + echo -e "$(date "+%F %T") $jobs cron jobs" | tee -a $tmpdir/restore.log + fi + + # Replace paths from vesta to hestia + if [ "$backup_system" == 'vesta' ] && [ "$user" == 'admin' ]; then + sed -i 's/vesta/hestia/g' $tmpdir/cron/cron.conf + fi + + # Restoring cron jobs + cp $tmpdir/cron/cron.conf $USER_DATA/cron.conf + + # Rebuilding cron jobs + sync_cron_jobs + + # Restarting cron + $BIN/v-restart-cron + check_result $? "CRON restart failed" +fi + +# Restoring user files and directories +if [ "$udir" != 'no' ]; then + echo -e "\n-- USER FILES --" | tee -a $tmpdir/restore.log + + # Unpacking user dir container + if [ -n "$(tar -tf $BACKUP/$backup | grep './user_dir')" ]; then + + # Creating user dir restore list + backup_dirs=$(tar -tf $BACKUP/$backup | grep "^./user_dir") + if [ $backup_mode = 'zstd' ]; then + backup_dirs=$(echo "$backup_dirs" | grep tar.zst) + backup_dirs=$(echo "$backup_dirs" | cut -f 3 -d /) + backup_dirs=$(echo "$backup_dirs" | sed "s/.tar.zst//") + else + backup_dirs=$(echo "$backup_dirs" | grep tar.gz) + backup_dirs=$(echo "$backup_dirs" | cut -f 3 -d /) + backup_dirs=$(echo "$backup_dirs" | sed "s/.tar.gz//") + fi + if [ -z "$udir" ] || [ "$udir" = '*' ]; then + user_dirs="$backup_dirs" + else + echo "$udir" | tr ',' '\n' > $tmpdir/selected.txt + user_dirs=$(echo "$backup_dirs" | egrep -x -f $tmpdir/selected.txt) + fi + + for user_dir in $user_dirs; do + echo -e "$(date "+%F %T") $user_dir" | tee -a $tmpdir/restore.log + if [ $backup_mode = 'zstd' ]; then + tar xf "$BACKUP/$backup" -C "$tmpdir" --no-wildcards "./user_dir/$user_dir.tar.zst" + else + tar xf "$BACKUP/$backup" -C "$tmpdir" --no-wildcards "./user_dir/$user_dir.tar.gz" + fi + if [ "$?" -ne 0 ]; then + rm -rf $tmpdir + error="Can't unpack $user_dir user dir container" + echo "$error" | $SENDMAIL -s "$subj" $email $notify + sed -i "/ $user /d" $HESTIA/data/queue/backup.pipe + check_result "$E_PARSING" "$error" + fi + + chown "$user" "$tmpdir/user_dir" + chown "$user" "$HOMEDIR/$user" + [ -e "$HOMEDIR/$user/$user_dir" ] && chown "$user" "$HOMEDIR/$user/$user_dir" + if [ $backup_mode = 'zstd' ]; then + $BIN/v-extract-fs-archive "$user" "$tmpdir/user_dir/$user_dir.tar.zst" "$HOMEDIR/$user" + else + $BIN/v-extract-fs-archive "$user" "$tmpdir/user_dir/$user_dir.tar.gz" "$HOMEDIR/$user" + fi + cmdstatus="$?" + chown root:root "$HOMEDIR/$user" + if [ "$cmdstatus" -ne 0 ]; then + rm -rf $tmpdir + error="Can't unpack $user_dir user dir container" + echo "$error" | $SENDMAIL -s "$subj" $email $notify + sed -i "/ $user /d" $HESTIA/data/queue/backup.pipe + check_result "$E_PARSING" "$error" + fi + + # Re-chowning files if uid differs + if [ "$old_uid" -ne "$new_uid" ]; then + find $HOMEDIR/$user/$user_dir -user $old_uid \ + -exec chown -h $user:$user {} \; + fi + done + fi +fi + +# Create tmp/ +mkdir -p $HOMEDIR/$user/tmp +chmod 700 $HOMEDIR/$user/tmp +chown -R $user:$user $HOMEDIR/$user/tmp + +# Delete Hestia File manager key +rm -f $HOMEDIR/$user/.ssh/hst-filemanager-key + +# Sending mail notification +subj="$user → restore has been completed" +cat $tmpdir/restore.log | $SENDMAIL -s "$subj" $email $notify + +# Send notification to panel +$BIN/v-add-user-notification "$user" "Backup restored successfully" "

Archive: $backup

" + +# Deleting temporary data +rm -rf $tmpdir + +# Cleaning restore queue +sed -i "/v-restore-user $user /d" $HESTIA/data/queue/backup.pipe + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Update user counters +$BIN/v-update-user-counters $user +$BIN/v-update-user-counters admin +$BIN/v-update-sys-ip-counters + +# Logging +$BIN/v-log-action "system" "Info" "Backup" "Restored backup contents (User: $user, Archive: $backup)." +$BIN/v-log-action "$user" "Info" "Backup" "Restored backup contents (Archive: $backup)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-restore-web-domain b/bin/v-restore-web-domain new file mode 100755 index 0000000..288e047 --- /dev/null +++ b/bin/v-restore-web-domain @@ -0,0 +1,51 @@ +#!/bin/bash +# info: restore single web domain +# options: USER BACKUP DOMAIN [NOTIFY] +# +# example: v-restore-web-domain USER BACKUP DOMAIN [NOTIFY] +# +# This function allows the user to restore a single web domain +# from a backup archive. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +backup=$2 +domain=$3 +notify=$4 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +args_usage='USER BACKUP DOMAIN [NOTIFY]' +check_args '3' "$#" "$args_usage" +is_format_valid 'user' 'backup' + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +$BIN/v-restore-user "$user" "$backup" "$domain" 'no' 'no' 'no' 'no' 'no' "$notify" + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-revoke-api-key b/bin/v-revoke-api-key new file mode 100755 index 0000000..0b2720b --- /dev/null +++ b/bin/v-revoke-api-key @@ -0,0 +1,56 @@ +#!/bin/bash +# info: revokes api key +# options: [HASH] +# +# example: v-revoke-api-key mykey +# +# This function removes a key from in $HESTIA/data/keys/ + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +hash=$1 + +args_usage='HASH' +check_args '1' "$#" "$args_usage" +is_format_valid 'hash' + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +if [ ! -d "$HESTIA/data/keys/" ]; then + exit "$E_NOTEXIST" +fi + +if [[ -e "$HESTIA/data/keys/$hash" ]]; then + rm $HESTIA/data/keys/$hash +else + exit "$E_NOTEXIST" +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +$BIN/v-log-action "system" "Info" "System" "System API key revoked (Key: $hash)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-run-cli-cmd b/bin/v-run-cli-cmd new file mode 100755 index 0000000..7400061 --- /dev/null +++ b/bin/v-run-cli-cmd @@ -0,0 +1,93 @@ +#!/bin/bash +# info: run cli command +# options: USER CMD [ARG...] +# +# example: v-run-cli-cmd user composer require package +# +# This function runs a limited list of cli commands with dropped privileges as the specific hestia user + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +user=$1 +clicmd=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER CMD [ARGS]' +is_format_valid 'user' +is_object_valid 'user' 'USER' "$user" + +# Checking user homedir +homedir=$(grep "^$user:" /etc/passwd | cut -f 6 -d :) +if [ -z "$homedir" ]; then + check_result "$E_NOTEXIST" "Error: user home directory doesn't exist" +fi + +if [ "$clicmd" = "composer" ]; then + clicmd="$homedir/.composer/composer" +fi + +if [ "$clicmd" = "wp" ]; then + clicmd="$homedir/.wp-cli/wp" +fi + +if [ -z "$(which "$clicmd")" ]; then + check_result "$E_NOTEXIST" "Cli command does not exist $clicmd" +fi +basecmd="$(basename "$clicmd")" +if [ "$basecmd" != 'ps' -a \ + "$basecmd" != 'ls' -a \ + "$basecmd" != 'tar' -a \ + "$basecmd" != 'zip' -a \ + "$basecmd" != 'unzip' -a \ + "$basecmd" != 'gzip' -a \ + "$basecmd" != 'gunzip' -a \ + "$basecmd" != 'mkdir' -a \ + "$basecmd" != 'find' -a \ + "$basecmd" != 'id' -a \ + "$basecmd" != 'grep' -a \ + "$basecmd" != 'egrep' -a \ + "$basecmd" != 'sed' -a \ + "$basecmd" != 'cat' -a \ + "$basecmd" != 'php5.6' -a \ + "$basecmd" != 'php7.0' -a \ + "$basecmd" != 'php7.1' -a \ + "$basecmd" != 'php7.2' -a \ + "$basecmd" != 'php7.3' -a \ + "$basecmd" != 'php7.4' -a \ + "$basecmd" != 'php8.0' -a \ + "$basecmd" != 'php8.1' -a \ + "$basecmd" != 'php8.2' -a \ + "$basecmd" != 'php' -a \ + "$basecmd" != "wp" -a \ + "$basecmd" != 'composer' ]; then + check_result "$E_FORBIDEN" "Error: Cli command not enabled" +fi + +all_scriptargs=("$@") +for ((I = 3; I <= $#; I++)); do + cmdArgs="$cmdArgs ${all_scriptargs[${I} - 1]}" +done + +runuser -u "$user" -- $clicmd $cmdArgs 2>&1 +if [ $? -ne 0 ]; then + echo "Error: cmd exited with errors" + exit 3 +fi + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-schedule-letsencrypt-domain b/bin/v-schedule-letsencrypt-domain new file mode 100755 index 0000000..c3ae4ce --- /dev/null +++ b/bin/v-schedule-letsencrypt-domain @@ -0,0 +1,68 @@ +#!/bin/bash +# info: adding cronjob for letsencrypt cetificate installation +# options: USER DOMAIN [ALIASES] +# +# example: v-schedule-letsencrypt-domain admin example.com www.example.com +# +# This function adds cronjob for letsencrypt ssl certificate installation + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +aliases=$3 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DOMAIN [ALIASES]' +is_format_valid 'user' 'domain' 'aliases' +is_system_enabled "$WEB_SYSTEM" 'WEB_SYSTEM' +is_system_enabled "$WEB_SSL" 'SSL_SUPPORT' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'web' 'DOMAIN' "$domain" +is_object_unsuspended 'web' 'DOMAIN' "$domain" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Parsing domain aliases +if [ -z "$aliases" ]; then + get_domain_values 'web' + aliases="$ALIAS" +fi + +# Adding cronjob scheduler for LE +$BIN/v-add-cron-letsencrypt-job + +# Adding LE task +echo "$BIN/v-add-letsencrypt-domain $user $domain '$aliases' no yes" \ + >> $HESTIA/data/queue/letsencrypt.pipe + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-schedule-user-backup b/bin/v-schedule-user-backup new file mode 100755 index 0000000..5286844 --- /dev/null +++ b/bin/v-schedule-user-backup @@ -0,0 +1,53 @@ +#!/bin/bash +# info: schedule user backup creation +# options: USER +# +# example: v-schedule-user-backup admin +# +# This function for scheduling user backup creation. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'USER' +is_format_valid 'user' +is_system_enabled "$BACKUP_SYSTEM" 'BACKUP_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_backup_enabled +is_backup_scheduled 'backup' + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Adding backup task to the queue +log=$HESTIA/log/backup.log +echo "$BIN/v-backup-user $user yes >> $log 2>&1" >> $HESTIA/data/queue/backup.pipe + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-schedule-user-backup-download b/bin/v-schedule-user-backup-download new file mode 100755 index 0000000..8f67db8 --- /dev/null +++ b/bin/v-schedule-user-backup-download @@ -0,0 +1,53 @@ +#!/bin/bash +# info: Schedule a backup +# options: USER BACKUP +# +# example: v-schedule-user-backup-download admin 2019-04-22_01-00-00.tar +# +# This function for scheduling user backup creation. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +backup=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# shellcheck source=/usr/local/hestia/func/db.sh +source $HESTIA/func/db.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER BACKUP' +is_format_valid 'user' 'backup' + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Adding backup task to the queue +echo "$BIN/v-download-backup $user $backup 2>&1" >> $HESTIA/data/queue/backup.pipe + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-schedule-user-restore b/bin/v-schedule-user-restore new file mode 100755 index 0000000..7ceb205 --- /dev/null +++ b/bin/v-schedule-user-restore @@ -0,0 +1,62 @@ +#!/bin/bash +# info: schedule user backup restoration +# options: USER BACKUP [WEB] [DNS] [MAIL] [DB] [CRON] [UDIR] +# +# example: v-schedule-user-restore 2019-04-22_01-00-00.tar +# +# This function for scheduling user backup restoration. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +backup=$2 +web=$3 +dns=$4 +mail=$5 +db=$6 +cron=$7 +udir=$8 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER BACKUP [WEB] [DNS] [MAIL] [DB] [CRON] [UDIR]' +is_format_valid 'user' +is_system_enabled "$BACKUP_SYSTEM" 'BACKUP_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_backup_enabled +is_backup_scheduled 'restore' + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Adding restore task to the queue +log=$HESTIA/log/restore.log +options="'$web' '$dns' '$mail' '$db' '$cron' '$udir'" +echo "$BIN/v-restore-user $user $backup $options yes >> $log 2>&1" >> $HESTIA/data/queue/backup.pipe + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +$BIN/v-log-action "system" "Info" "Backup" "Restore of backup archive requested (User: $user, Archive: $backup)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-search-command b/bin/v-search-command new file mode 100755 index 0000000..421b60b --- /dev/null +++ b/bin/v-search-command @@ -0,0 +1,58 @@ +#!/bin/bash +# info: search for available commands +# options: ARG1 [ARG...] +# +# example: v-search-command web +# +# This function searches for available Hestia Control Panel commands +# and returns results based on the specified criteria. +# Originally developed for VestaCP by Federico Krum +# + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# +if [ $# -eq 0 ]; then + echo "ERROR: No search arguments specified." + echo "Usage: v-search-command ARG1 [ARG2] [ARG...]" + exit 1 +fi + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +SearchResults=$(ls -a $BIN/ | sort) +TotalItems=$(ls -a $BIN/ | sort | wc -l) + +for i; do + SearchResults=$(echo $SearchResults | tr " " "\n" | grep $i) + FoundItems=$(echo $SearchResults | tr " " "\n" | grep $i | wc -l) +done + +if [ -z "$SearchResults" ]; then + echo "No available commands were found matching the specified criteria." + echo "There are a total of $TotalItems commands available." +else + echo "Command Search Results" + echo "=================================" + echo $SearchResults | tr " " "\n" + echo "=================================" + echo "Found $FoundItems matching items in $TotalItems commands." +fi +exit diff --git a/bin/v-search-domain-owner b/bin/v-search-domain-owner new file mode 100755 index 0000000..9eb7fde --- /dev/null +++ b/bin/v-search-domain-owner @@ -0,0 +1,62 @@ +#!/bin/bash +# info: search domain owner +# options: DOMAIN [TYPE] +# +# example: v-search-domain-owner acme.com +# +# This function that allows to find user objects. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +domain=$1 +type=${2-any} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'DOMAIN [TYPE]' + +is_format_valid 'domain' + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Define conf +case $type in + web) conf="$HESTIA/data/users/*/web.conf" ;; + dns) conf="$HESTIA/data/users/*/dns.conf" ;; + mail) conf="$HESTIA/data/users/*/mail.conf" ;; + *) conf="$HESTIA/data/users/*/*.conf" ;; +esac + +owner=$(grep -H "DOMAIN='$domain'" $conf | head -n 1 | cut -f7 -d '/') +if [ -z "$owner" ]; then + exit "$E_NOTEXIST" +fi + +echo "$owner" + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +#log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-search-fs-object b/bin/v-search-fs-object new file mode 100755 index 0000000..c2b2efe --- /dev/null +++ b/bin/v-search-fs-object @@ -0,0 +1,60 @@ +#!/bin/bash +# info: search file or directory +# options: USER OBJECT [PATH] +# +# example: v-search-fs-object admin hello.txt +# +# This function search files and directories on the file system + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +user=$1 +object=$2 +path=$3 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER OBJECT [PATH]' +is_format_valid 'user' +is_object_valid 'user' 'USER' "$user" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +# Checking user homedir +homedir=$(grep "^$user:" /etc/passwd | cut -f 6 -d :) +if [ -z $homedir ]; then + echo "Error: user home directory doesn't exist" + exit 12 +fi + +# Checking path +if [ -n "$path" ]; then + rpath=$(readlink -f "$path") + if [ -z "$(echo $rpath | grep $homedir)" ]; then + echo "Error: invalid path $path" + exit 2 + fi +else + path=$homedir +fi + +# Listing directory +user_exec find "$path" -name "$object" \ + -printf "%y|%m|%TY-%Tm-%Td|%TH:%TM|%u|%g|%s|%P\n" 2> /dev/null +# -printf "%y|%m|%TY-%Tm-%Td|%TH:%TM:%TS|%u|%g|%s|%P\n" 2>/dev/null + +# Exiting +exit $? diff --git a/bin/v-search-object b/bin/v-search-object new file mode 100755 index 0000000..730c82c --- /dev/null +++ b/bin/v-search-object @@ -0,0 +1,269 @@ +#!/bin/bash +# info: search objects +# options: OBJECT [FORMAT] +# +# example: v-search-object example.com json +# +# This function that allows to find system objects. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +object=$1 +format=${2-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/conf/hestia.conf +source $HESTIA/conf/hestia.conf +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +# Json list function +json_list_search() { + echo '{' + fileds_count=$(echo $fields | wc -w) + while read line; do + eval $line + if [ -n "$list_data" ]; then + echo -e ' },' + fi + i=1 + IFS=' ' + for field in $fields; do + eval value=\"$field\" + value=$(echo "$value" | sed -e 's/"/\\"/g' -e "s/%quote%/'/g") + if [ $i -eq 1 ]; then + ((++i)) + echo -e "\t\"$value\": {" + else + if [ $i -lt "$fileds_count" ]; then + ((++i)) + echo -e "\t\t\"${field//$/}\": \"${value//,/, }\"," + else + echo -e "\t\t\"${field//$/}\": \"${value//,/, }\"" + list_data=1 + fi + fi + done + done < $conf + if [ -n "$list_data" ]; then + echo -e ' }' + fi + echo -e '}' +} + +# Shell list function +shell_list_search() { + if [ -z "$nohead" ]; then + echo "${fields//$/}" + for a in $fields; do + echo -e "------ \c" + done + echo + fi + while read line; do + eval $line + eval echo "$fields" | sed "s/%quote%/'/g" + done < $conf +} + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'OBJECT [FORMAT]' +is_format_valid 'object' + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +conf=$(mktemp) +i=0 +OLD_IFS=$IFS +IFS=$'\n' + +# User loop +for user in $($BIN/v-list-sys-users plain); do + # Search query + search=$(grep "$object" \ + $HESTIA/data/users/$user/web.conf \ + $HESTIA/data/users/$user/dns.conf \ + $HESTIA/data/users/$user/dns/*.conf \ + $HESTIA/data/users/$user/mail.conf \ + $HESTIA/data/users/$user/mail/*.conf \ + $HESTIA/data/users/$user/db.conf \ + $HESTIA/data/users/$user/cron.conf 2> /dev/null) + + for row in $search; do + # Initialise variable + key='' + result='' + dom_alias='' + suspended='' + object_link='' + object_parent='' + object_time='' + object_date='' + + # Parsing result + type=$(echo $row | cut -f 1 -d : | cut -f 8 -d /) + data=$(echo $row | cut -f 2,3,4,5 -d :) + eval "$data" + + # Check WEB domain + if [ "$type" = 'web.conf' ]; then + if [ -n "$(echo $DOMAIN | grep $object)" ]; then + # Check domain alias + check_alias="$(echo $ALIAS | tr ',' '\n' | grep $object)" + if [ -n "$check_alias" ]; then + dom_alias=$(echo $check_alias | tr ' ' ',') + fi + key="DOMAIN" + result="$DOMAIN" + suspended=$SUSPENDED + object_time=$TIME + object_date=$DATE + ((i++)) + else + check_alias="$(echo $ALIAS | tr ',' '\n' | grep $object)" + if [ -n "$check_alias" ]; then + key="DOMAIN" + result="$DOMAIN" + object_parent="$DOMAIN" + dom_alias=$(echo $check_alias | tr ' ' ',') + suspended=$SUSPENDED + object_time=$TIME + object_date=$DATE + ((i++)) + fi + fi + fi + + # DNS + if [ "$type" = 'dns.conf' ]; then + if [ -n "$(echo $DOMAIN | grep $object)" ]; then + key="DOMAIN" + result="$DOMAIN" + suspended=$SUSPENDED + object_time=$TIME + object_date=$DATE + ((i++)) + fi + fi + + # DNS Records + if [ "$type" = 'dns' ]; then + if [ -n "$(echo $RECORD | grep $object)" ]; then + key="RECORD" + result="$RECORD.$DOMAIN" + suspended=$SUSPENDED + object_link=$ID + object_parent=$DOMAIN + object_time=$TIME + object_date=$DATE + ((i++)) + fi + fi + + # MAIL + if [ "$type" = 'mail.conf' ]; then + if [ -n "$(echo $DOMAIN | grep $object)" ]; then + key="DOMAIN" + result="$DOMAIN" + suspended=$SUSPENDED + object_time=$TIME + object_date=$DATE + ((i++)) + fi + fi + + # Mail Accounts + if [ "$type" = 'mail' ]; then + type='mail' + if [ -n "$(echo $ACCOUNT | grep $object)" ]; then + key="ACCOUNT" + dom="$(echo $row | cut -f 1 -d : | cut -f 9 -d / | sed 's/.conf//')" + result="$ACCOUNT@$dom" + suspended=$SUSPENDED + object_link=$ACCOUNT + object_parent=$dom + object_time=$TIME + object_date=$DATE + ((i++)) + fi + fi + + # DB + if [ "$type" = 'db.conf' ]; then + if [ -n "$(echo $DB | grep $object)" ]; then + key="DATABASE" + result="$DB" + suspended=$SUSPENDED + object_time=$TIME + object_date=$DATE + ((i++)) + fi + fi + + # Cron Jobs + if [ "$type" = 'cron.conf' ]; then + if [ -n "$(echo $CMD | grep $object)" ]; then + key="JOB" + result="$CMD" + suspended=$SUSPENDED + object_link=$JOB + object_parent=$JOB + object_time=$TIME + object_date=$DATE + ((i++)) + fi + fi + + if [ -n "$result" ]; then + type=$(echo $type | cut -f1 -d \.) + str="ID='$i' USER='$user' TYPE='$type' KEY='$key'" + str="$str RESULT='$result' ALIAS='$dom_alias'" + str="$str LINK='$object_link' PARENT='$object_parent'" + str="$str SUSPENDED='$suspended' TIME='$object_time'" + str="$str DATE='$object_date'" + echo $str >> $conf + fi + done +done +IFS=$OLD_IFS + +# Defining fileds to select +fields='$ID $USER $TYPE $KEY $RESULT $ALIAS $LINK $PARENT $SUSPENDED $TIME' +fields="$fields \$DATE" + +# Listing domains +case $format in + json) json_list_search ;; + plain) + nohead=1 + shell_list_search + ;; + shell) + fields='$USER~$TYPE~$KEY~$RESULT~$ALIAS' + shell_list_search | column -t -s '~' + ;; + *) check_args '1' '0' 'OBJECT [FORMAT]' ;; +esac + +rm $conf + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-search-user-object b/bin/v-search-user-object new file mode 100755 index 0000000..7aed122 --- /dev/null +++ b/bin/v-search-user-object @@ -0,0 +1,270 @@ +#!/bin/bash +# info: search objects +# options: USER OBJECT [FORMAT] +# +# example: v-search-user-object admin example.com json +# +# This function that allows to find user objects. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +object=$2 +format=${3-shell} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +# Json list function +json_list_search() { + echo '{' + fileds_count=$(echo $fields | wc -w) + while read line; do + eval "$line" + if [ -n "$list_data" ]; then + echo -e ' },' + fi + i=1 + IFS=' ' + for field in $fields; do + eval value=\"$field\" + value=$(echo "$value" | sed -e 's/"/\\"/g' -e "s/%quote%/'/g") + if [ $i -eq 1 ]; then + ((++i)) + echo -e "\t\"$value\": {" + else + if [ $i -lt "$fileds_count" ]; then + ((++i)) + echo -e "\t\t\"${field//$/}\": \"${value//,/, }\"," + else + echo -e "\t\t\"${field//$/}\": \"${value//,/, }\"" + list_data=1 + fi + fi + done + done < $conf + if [ -n "$list_data" ]; then + echo -e ' }' + fi + echo -e '}' +} + +# Shell list function +shell_list_search() { + if [ -z "$nohead" ]; then + echo "${fields//$/}" + for a in $fields; do + echo -e "------ \c" + done + echo + fi + while read line; do + eval $line + eval echo "$fields" | sed "s/%quote%/'/g" + done < $conf +} + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER OBJECT [FORMAT]' +is_format_valid 'user' 'object' +is_object_valid 'user' 'USER' "$user" + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +conf=$(mktemp) +i=0 +OLD_IFS=$IFS +IFS=$'\n' + +# Search query +search=$(grep "$object" \ + $HESTIA/data/users/$user/web.conf \ + $HESTIA/data/users/$user/dns.conf \ + $HESTIA/data/users/$user/dns/*.conf \ + $HESTIA/data/users/$user/mail.conf \ + $HESTIA/data/users/$user/mail/*.conf \ + $HESTIA/data/users/$user/db.conf \ + $HESTIA/data/users/$user/cron.conf 2> /dev/null) + +for row in $search; do + # Initialise variable + key='' + result='' + dom_alias='' + suspended='' + object_link='' + object_parent='' + object_time='' + object_date='' + + # Parsing result + type=$(echo $row | cut -f 1 -d : | cut -f 8 -d /) + data=$(echo $row | cut -f 2,3,4,5 -d :) + eval "$data" + + # Check WEB domain + if [ "$type" = 'web.conf' ]; then + if [ -n "$(echo $DOMAIN | grep $object)" ]; then + # Check domain alias + check_alias="$(echo $ALIAS | tr ',' '\n' | grep $object)" + if [ -n "$check_alias" ]; then + dom_alias=$(echo $check_alias | tr ' ' ',') + fi + key="DOMAIN" + result="$DOMAIN" + suspended=$SUSPENDED + object_time=$TIME + object_date=$DATE + ((i++)) + else + check_alias="$(echo $ALIAS | tr ',' '\n' | grep $object)" + if [ -n "$check_alias" ]; then + key="DOMAIN" + result="$DOMAIN" + object_parent="$DOMAIN" + dom_alias=$(echo $check_alias | tr ' ' ',') + suspended=$SUSPENDED + object_time=$TIME + object_date=$DATE + ((i++)) + fi + fi + fi + + # DNS + if [ "$type" = 'dns.conf' ]; then + if [ -n "$(echo $DOMAIN | grep $object)" ]; then + key="DOMAIN" + result="$DOMAIN" + suspended=$SUSPENDED + object_time=$TIME + object_date=$DATE + ((i++)) + fi + fi + + # DNS Records + if [ "$type" = 'dns' ]; then + if [ -n "$(echo $RECORD | grep $object)" ]; then + key="RECORD" + result="$RECORD.$DOMAIN" + suspended=$SUSPENDED + object_link=$ID + object_parent=$DOMAIN + object_time=$TIME + object_date=$DATE + ((i++)) + fi + fi + + # MAIL + if [ "$type" = 'mail.conf' ]; then + if [ -n "$(echo $DOMAIN | grep $object)" ]; then + key="DOMAIN" + result="$DOMAIN" + suspended=$SUSPENDED + object_time=$TIME + object_date=$DATE + ((i++)) + fi + fi + + # Mail Accounts + if [ "$type" = 'mail' ]; then + type='mail' + if [ -n "$(echo $ACCOUNT | grep $object)" ]; then + key="ACCOUNT" + dom="$(echo $row | cut -f 1 -d : | cut -f 9 -d / | sed 's/.conf//')" + result="$ACCOUNT@$dom" + suspended=$SUSPENDED + object_link=$ACCOUNT + object_parent=$dom + object_time=$TIME + object_date=$DATE + ((i++)) + fi + fi + + # DB + if [ "$type" = 'db.conf' ]; then + if [ -n "$(echo $DB | grep $object)" ]; then + key="DATABASE" + result="$DB" + suspended=$SUSPENDED + object_time=$TIME + object_date=$DATE + ((i++)) + fi + fi + + # Cron Jobs + if [ "$type" = 'cron.conf' ]; then + if [ -n "$(echo $CMD | grep $object)" ]; then + key="JOB" + result="$CMD" + suspended=$SUSPENDED + object_link=$JOB + object_parent=$JOB + object_time=$TIME + object_date=$DATE + ((i++)) + fi + fi + + if [ -n "$result" ]; then + type=$(echo $type | cut -f1 -d \.) + str="ID='$i' USER='$user' TYPE='$type' KEY='$key'" + str="$str RESULT='$result' ALIAS='$dom_alias'" + str="$str LINK='$object_link' PARENT='$object_parent'" + str="$str SUSPENDED='$suspended' TIME='$object_time'" + str="$str DATE='$object_date'" + echo $str >> $conf + fi +done + +IFS=$OLD_IFS + +# Defining fileds to select +fields='$ID $USER $TYPE $KEY $RESULT $ALIAS $LINK $PARENT $SUSPENDED $TIME' +fields="$fields \$DATE" + +# Listing domains +case $format in + json) json_list_search ;; + plain) + nohead=1 + shell_list_search + ;; + shell) + fields='$USER~$TYPE~$KEY~$RESULT~$ALIAS' + shell_list | column -t -s '~' + ;; + *) check_args '2' '0' 'USER OBJECT [FORMAT]' ;; +esac + +rm $conf + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +#log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-start-service b/bin/v-start-service new file mode 100755 index 0000000..6ef8f8a --- /dev/null +++ b/bin/v-start-service @@ -0,0 +1,65 @@ +#!/bin/bash +# info: start service +# options: SERVICE +# +# example: v-start-service mysql +# +# This function starts system service. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +service=$1 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'SERVICE' +is_format_valid 'service' + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +if [ "$service" = "php-fpm" ]; then + for php_ver in $(multiphp_versions); do + service_list="${service_list} php${php_ver}-fpm" + done +else + service_list="$service" +fi + +for service in $service_list; do + if [ "$service" = "iptables" ]; then + $BIN/v-update-firewall + else + systemctl start "$service" + result=$? + if [ "$result" -ne 0 ]; then + $BIN/v-log-action "system" "Error" "System" "Service failed to start (Name: $service)." + else + $BIN/v-log-action "system" "Info" "System" "Service started (Name: $service)." + fi + fi + check_result $? "ERROR: $service start failed" "$E_RESTART" +done + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-stop-firewall b/bin/v-stop-firewall new file mode 100755 index 0000000..4ac6d2a --- /dev/null +++ b/bin/v-stop-firewall @@ -0,0 +1,104 @@ +#!/bin/bash +# info: stop system firewall +# options: NONE +# +# example: v-stop-firewall +# +# This function stops iptables + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Defining absolute path for iptables +iptables="/sbin/iptables" + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/firewall.sh +source $HESTIA/func/firewall.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Self heal iptables links +heal_iptables_links + +# Creating temporary file +tmp="$(mktemp)" + +# Flushing INPUT chain +echo "$iptables -P INPUT ACCEPT" >> $tmp +echo "$iptables -F INPUT" >> $tmp + +# Deleting hestia chain +echo "$iptables -X hestia" >> $tmp + +# Deleting custom chains +IFS=$'\n' +for chain in $(cat $HESTIA/data/firewall/chains.conf 2> /dev/null); do + parse_object_kv_list "$chain" + echo "$iptables -F fail2ban-$CHAIN" >> $tmp + echo "$iptables -X fail2ban-$CHAIN" >> $tmp +done + +# Applying rules +bash $tmp 2> /dev/null + +# Deleting temporary file +rm -f $tmp + +# Clean up and saving rules to the master iptables file +if [ -d "/etc/sysconfig" ]; then + /sbin/iptables-save | sed -e 's/[[0-9]\+:[0-9]\+]/[0:0]/g' -e '/^-A fail2ban-[A-Z]\+ -s .\+$/d' > /etc/sysconfig/iptables +else + /sbin/iptables-save | sed -e 's/[[0-9]\+:[0-9]\+]/[0:0]/g' -e '/^-A fail2ban-[A-Z]\+ -s .\+$/d' > /etc/iptables.rules + iptablesversion="$(iptables --version | head -1 | awk '{print $2}' | cut -f -2 -d .)" + sd_unit="/lib/systemd/system/hestia-iptables.service" + if [ ! -e "$sd_unit" ]; then + echo "[Unit]" >> $sd_unit + echo "Description=Loading Hestia firewall rules" >> $sd_unit + echo "DefaultDependencies=no" >> $sd_unit + echo "Wants=network-pre.target local-fs.target" >> $sd_unit + echo "Before=network-pre.target" >> $sd_unit + echo "After=local-fs.target" >> $sd_unit + echo "" >> $sd_unit + echo "[Service]" >> $sd_unit + echo "Type=oneshot" >> $sd_unit + echo "RemainAfterExit=yes" >> $sd_unit + echo "ExecStartPre=-${HESTIA}/bin/v-update-firewall-ipset load" >> $sd_unit + if [ "$iptablesversion" = "v1.6" ]; then + echo "ExecStart=/sbin/iptables-restore /etc/iptables.rules" >> $sd_unit + else + echo "ExecStart=/sbin/iptables-restore --wait=10 /etc/iptables.rules" >> $sd_unit + fi + echo "" >> $sd_unit + echo "[Install]" >> $sd_unit + echo "WantedBy=multi-user.target" >> $sd_unit + systemctl -q daemon-reload + fi + systemctl -q is-enabled hestia-iptables 2> /dev/null && systemctl -q disable hestia-iptables + if [ -z "$FIREWALL_SYSTEM" ]; then + rm -f $sd_unit + systemctl -q daemon-reload + fi +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-stop-service b/bin/v-stop-service new file mode 100755 index 0000000..558fb0b --- /dev/null +++ b/bin/v-stop-service @@ -0,0 +1,69 @@ +#!/bin/bash +# info: stop service +# options: SERVICE +# +# example: v-stop-service apache2 +# +# This function stops system service. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +service=$1 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'SERVICE' +is_format_valid 'service' + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +if [ "$service" = "php-fpm" ]; then + for php_ver in $(multiphp_versions); do + service_list="${service_list} php${php_ver}-fpm" + done +else + service_list="$service" +fi + +for service in $service_list; do + if [ "$service" = "iptables" ]; then + $BIN/v-stop-firewall + else + systemctl stop "$service" + result=$? + if [ "$result" -ne 0 ]; then + $BIN/v-log-action "system" "Error" "System" "Service failed to stop (Name: $service)." + else + $BIN/v-log-action "system" "Info" "System" "Service stopped (Name: $service)." + fi + fi + check_result $? "ERROR: $service stop failed" "$E_RESTART" + +done + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-suspend-cron-job b/bin/v-suspend-cron-job new file mode 100755 index 0000000..32e0a2e --- /dev/null +++ b/bin/v-suspend-cron-job @@ -0,0 +1,62 @@ +#!/bin/bash +# info: suspend cron job +# options: USER JOB [RESTART] +# +# example: v-suspend-cron-job admin 5 yes +# +# This function suspends a certain job of the cron scheduler. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +job=$2 +restart=$3 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER JOB [RESTART]' +is_format_valid 'user' 'job' +is_object_valid 'user' 'USER' "$user" +is_object_valid 'cron' 'JOB' "$job" +is_object_unsuspended 'cron' 'JOB' "$job" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Suspending job +update_object_value 'cron' 'JOB' "$job" '$SUSPENDED' 'yes' +increase_user_value "$user" '$SUSPENDED_CRON' + +# Sync system cron with user +sync_cron_jobs + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Restarting crond +$BIN/v-restart-cron "$restart" +check_result $? "Cron restart failed" > /dev/null + +# Logging +$BIN/v-log-action "system" "Info" "Cron Jobs" "Cron job suspended (Job: $job)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-suspend-cron-jobs b/bin/v-suspend-cron-jobs new file mode 100755 index 0000000..675726c --- /dev/null +++ b/bin/v-suspend-cron-jobs @@ -0,0 +1,56 @@ +#!/bin/bash +# info: Suspending sys cron jobs +# options: USER [RESTART] +# +# example: v-suspend-cron-jobs admin +# +# This function suspends all user cron jobs. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +restart=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'USER' +is_format_valid 'user' +is_object_valid 'user' 'USER' "$user" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Suspendn all jobs +for job in $(search_objects 'cron' 'SUSPENDED' 'no' 'JOB'); do + $BIN/v-suspend-cron-job "$user" "$job" 'no' +done + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Restarting crond +$BIN/v-restart-cron "$restart" +check_result $? "Cron restart failed" > /dev/null + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-suspend-database b/bin/v-suspend-database new file mode 100755 index 0000000..2d7e065 --- /dev/null +++ b/bin/v-suspend-database @@ -0,0 +1,67 @@ +#!/bin/bash +# info: suspend database +# options: USER DATABASE +# +# example: v-suspend-database admin admin_wordpress_db +# +# This function for suspending a certain user database. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +database=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/db.sh +source $HESTIA/func/db.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DATABASE' +is_format_valid 'user' 'database' +is_system_enabled "$DB_SYSTEM" 'DB_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'db' 'DB' "$database" +is_object_unsuspended 'db' 'DB' "$database" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Get database values +get_database_values + +# Switching on db type +case $TYPE in + mysql) suspend_mysql_database ;; + pgsql) suspend_pgsql_database ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Updating db value +update_object_value 'db' 'DB' "$database" '$SUSPENDED' 'yes' +increase_user_value "$user" '$SUSPENDED_DB' + +# Logging +$BIN/v-log-action "system" "Info" "Database" "Suspended database (User: $user, Database: $database)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-suspend-database-host b/bin/v-suspend-database-host new file mode 100755 index 0000000..9d4920a --- /dev/null +++ b/bin/v-suspend-database-host @@ -0,0 +1,52 @@ +#!/bin/bash +# info: suspend database server +# options: TYPE HOST +# +# example: v-suspend-database-host mysql localhost +# +# This function for suspending a database server. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +type=$1 +host=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'TYPE HOST' +is_format_valid 'type' 'host' +is_system_enabled "$DB_SYSTEM" 'DB_SYSTEM' +is_object_valid "../../conf/$type" 'HOST' "$host" +is_object_unsuspended "../../conf/$type" 'HOST' "$host" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Suspend database creation on a server +update_object_value "../../conf/$type" 'HOST' "$host" '$SUSPENDED' 'yes' + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-suspend-databases b/bin/v-suspend-databases new file mode 100755 index 0000000..318de06 --- /dev/null +++ b/bin/v-suspend-databases @@ -0,0 +1,52 @@ +#!/bin/bash +# info: suspend databases +# options: USER +# +# example: v-suspend-databases admin +# +# This function for suspending of all databases of a single user. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'USER' +is_format_valid 'user' +is_system_enabled "$DB_SYSTEM" 'DB_SYSTEM' +is_object_valid 'user' 'USER' "$user" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Starting suspend loop +for database in $(search_objects 'db' 'SUSPENDED' "no" 'DB'); do + $BIN/v-suspend-database "$user" "$database" +done + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-suspend-dns-domain b/bin/v-suspend-dns-domain new file mode 100755 index 0000000..e00dc2e --- /dev/null +++ b/bin/v-suspend-dns-domain @@ -0,0 +1,74 @@ +#!/bin/bash +# info: suspend dns domain +# options: USER DOMAIN [RESTART] +# +# example: v-suspend-dns-domain alice acme.com +# +# This function suspends a certain user's domain. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 +restart="$3" + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn +# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ? + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DOMAIN [RESTART]' +is_format_valid 'user' 'domain' +is_system_enabled "$DNS_SYSTEM" 'DNS_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_valid 'dns' 'DOMAIN' "$domain" +is_object_unsuspended 'dns' 'DOMAIN' "$domain" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Deleting system configs +if [[ "$DNS_SYSTEM" =~ named|bind ]]; then + if [ -e '/etc/named.conf' ]; then + dns_conf='/etc/named.conf' + else + dns_conf='/etc/bind/named.conf' + fi + + sed -i "/\/$user\/conf\/dns\/$domain.db\"/d" $dns_conf +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Adding suspend in config +update_object_value 'dns' 'DOMAIN' "$domain" '$SUSPENDED' 'yes' +sed -i "s/SUSPENDED='no'/SUSPENDED='yes'/g" "$USER_DATA/dns/$domain.conf" +increase_user_value "$user" '$SUSPENDED_DNS' + +# Logging +$BIN/v-log-action "system" "Info" "DNS" "Suspended DNS zone (User: $user, Domain: $domain)" +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-suspend-dns-domains b/bin/v-suspend-dns-domains new file mode 100755 index 0000000..7c3067d --- /dev/null +++ b/bin/v-suspend-dns-domains @@ -0,0 +1,53 @@ +#!/bin/bash +# info: suspend dns domains +# options: USER [RESTART] +# +# example: v-suspend-dns-domains admin yes +# +# This function suspends all user's DNS domains. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +restart=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'USER [RESTART]' +is_format_valid 'user' +is_system_enabled "$DNS_SYSTEM" 'DNS_SYSTEM' +is_object_valid 'user' 'USER' "$user" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Starting suspend loop +for domain in $(search_objects 'dns' 'SUSPENDED' "no" 'DOMAIN'); do + $BIN/v-suspend-dns-domain "$user" "$domain" 'no' +done + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-suspend-dns-record b/bin/v-suspend-dns-record new file mode 100755 index 0000000..69b4019 --- /dev/null +++ b/bin/v-suspend-dns-record @@ -0,0 +1,83 @@ +#!/bin/bash +# info: suspend dns domain record +# options: USER DOMAIN ID [RESTART] +# +# example: v-suspend-dns-record alice wonderland.com 42 yes +# +# This function suspends a certain domain record. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 +id=$3 +restart=$4 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn +# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ? + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '3' "$#" 'USER DOMAIN ID [RESTART]' +is_format_valid 'user' 'domain' 'id' +is_system_enabled "$DNS_SYSTEM" 'DNS_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_valid 'dns' 'DOMAIN' "$domain" +is_object_unsuspended 'dns' 'DOMAIN' "$domain" +is_object_valid "dns/$domain" 'ID' "$id" +is_object_unsuspended "dns/$domain" 'ID' "$id" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +update_object_value "dns/$domain" 'ID' "$id" '$SUSPENDED' "yes" + +# Update serial +update_domain_serial +# Updating zone +if [[ "$DNS_SYSTEM" =~ named|bind ]]; then + # Do full rebuild due DNS SEC + rebuild_dns_domain_conf +fi + +# Updating dns-cluster queue +if [ "$DNS_CLUSTER" = "yes" ]; then + # Check for first sync + dlock=$(grep "domain $user $domain" $HESTIA/data/queue/dns-cluster.pipe) + if [ -z "$dlock" ]; then + cmd="$BIN/v-add-remote-dns-record $user $domain $id" + echo "$cmd" >> $HESTIA/data/queue/dns-cluster.pipe + fi +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +$BIN/v-log-action "system" "Info" "DNS" "Suspended DNS record (User: $user, Domain: $domain, Record: $id)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-suspend-domain b/bin/v-suspend-domain new file mode 100755 index 0000000..af6c80b --- /dev/null +++ b/bin/v-suspend-domain @@ -0,0 +1,93 @@ +#!/bin/bash +# info: suspend web/dns/mail domain +# options: USER DOMAIN +# +# example: v-suspend-domain admin example.com +# +# This function suspends web/dns/mail domain. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +restart="${3-yes}" + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DOMAIN' +is_format_valid 'user' 'domain' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Working on Web domain +if [ -n "$WEB_SYSTEM" ]; then + str=$(grep "DOMAIN='$domain'" "$USER_DATA/web.conf" | grep "SUSPENDED='no") + if [ -n "$str" ]; then + domain_found='yes' + $BIN/v-suspend-web-domain "$user" "$domain" "no" + check_result $? "can't suspend web" > /dev/null + fi +fi + +# Working on DNS domain +if [ -n "$DNS_SYSTEM" ]; then + str=$(grep "DOMAIN='$domain'" "$USER_DATA/dns.conf" | grep "SUSPENDED='no") + if [ -n "$str" ]; then + domain_found='yes' + $BIN/v-suspend-dns-domain "$user" "$domain" "no" + check_result $? "can't suspend dns" > /dev/null + fi +fi + +# Working on Mail domain +if [ -n "$MAIL_SYSTEM" ]; then + str=$(grep "DOMAIN='$domain'" "$USER_DATA/mail.conf" | grep "SUSPENDED='no") + if [ -n "$str" ]; then + domain_found='yes' + $BIN/v-suspend-mail-domain "$user" "$domain" "no" + check_result $? "can't suspend mail" > /dev/null + fi +fi + +# Checking domain search result +if [ -z "$domain_found" ]; then + echo "Error: domain $domain doesn't exist" + log_event "$E_NOTEXIST" "$ARGUMENTS" + exit "$E_NOTEXIST" +fi + +# Restarting services +$BIN/v-restart-web "$restart" +check_result $? "can't restart web" > /dev/null + +$BIN/v-restart-proxy "$restart" +check_result $? "can't restart proxy" > /dev/null + +$BIN/v-restart-dns "$restart" +check_result $? "can't restart dns" > /dev/null + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-suspend-firewall-rule b/bin/v-suspend-firewall-rule new file mode 100755 index 0000000..a9af876 --- /dev/null +++ b/bin/v-suspend-firewall-rule @@ -0,0 +1,55 @@ +#!/bin/bash +# info: suspend firewall rule +# options: RULE +# +# example: v-suspend-firewall-rule 7 +# +# This function suspends a certain firewall rule. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +rule=$1 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'RULE' +is_format_valid 'rule' +is_system_enabled "$FIREWALL_SYSTEM" 'FIREWALL_SYSTEM' +is_object_valid '../../data/firewall/rules' 'RULE' "$rule" +is_object_unsuspended '../../data/firewall/rules' 'RULE' "$rule" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Suspending rule +update_object_value ../../data/firewall/rules RULE "$rule" '$SUSPENDED' yes + +# Updating system firewall +$BIN/v-update-firewall + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +$BIN/v-log-action "system" "Info" "Firewall" "Suspended firewall rule (Rule: $rule)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-suspend-mail-account b/bin/v-suspend-mail-account new file mode 100755 index 0000000..12f079f --- /dev/null +++ b/bin/v-suspend-mail-account @@ -0,0 +1,76 @@ +#!/bin/bash +# info: suspend mail account +# options: USER DOMAIN ACCOUNT +# +# example: v-suspend-mail-account admin acme.com bob +# +# This function suspends mail account. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 +account=$3 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn +# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ? + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '3' "$#" 'USER DOMAIN ACCOUNT' +is_format_valid 'user' 'domain' 'account' +is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'mail' 'DOMAIN' "$domain" +is_object_unsuspended 'mail' 'DOMAIN' "$domain" +is_object_valid "mail/$domain" 'ACCOUNT' "$account" +is_object_unsuspended "mail/$domain" 'ACCOUNT' "$account" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +if [[ "$MAIL_SYSTEM" =~ exim ]]; then + quota=$(get_object_value "mail/$domain" 'ACCOUNT' "$account" '$QUOTA') + if [ "$quota" = 'unlimited' ]; then + quota=0 + fi + sed -i "/^$account:/d" "$HOMEDIR/$user/conf/mail/$domain/passwd" + str="$account:SUSPENDED:$user:mail::$HOMEDIR/$user::userdb_quota_rule=*:storage=${quota}M" + echo "$str" >> "$HOMEDIR/$user/conf/mail/$domain/passwd" +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Update config +update_object_value "mail/$domain" 'ACCOUNT' "$account" '$SUSPENDED' 'yes' + +# Logging +$BIN/v-log-action "system" "Info" "Mail" "Suspended mail account (User: $user, Account: $account@$domain)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-suspend-mail-accounts b/bin/v-suspend-mail-accounts new file mode 100755 index 0000000..a227542 --- /dev/null +++ b/bin/v-suspend-mail-accounts @@ -0,0 +1,59 @@ +#!/bin/bash +# info: suspend all mail domain accounts +# options: USER DOMAIN +# +# example: v-suspend-mail-accounts admin example.com +# +# This function suspends all mail domain accounts. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn +# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ? + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DOMAIN' +is_format_valid 'user' 'domain' +is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'mail' 'DOMAIN' "$domain" +is_object_unsuspended 'mail' 'DOMAIN' "$domain" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Starting suspend loop +for account in $(search_objects "mail/$domain" 'SUSPENDED' "no" 'ACCOUNT'); do + $BIN/v-suspend-mail-account "$user" "$domain" "$account" +done + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-suspend-mail-domain b/bin/v-suspend-mail-domain new file mode 100755 index 0000000..a75a513 --- /dev/null +++ b/bin/v-suspend-mail-domain @@ -0,0 +1,73 @@ +#!/bin/bash +# info: suspend mail domain +# options: USER DOMAIN +# +# example: v-suspend-mail-domain admin domain.com +# +# This function suspends mail domain. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn +# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ? + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DOMAIN' +is_format_valid 'user' 'domain' +is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'mail' 'DOMAIN' "$domain" +is_object_unsuspended 'mail' 'DOMAIN' "$domain" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Deleting symbolic link +if [[ "$MAIL_SYSTEM" =~ exim ]]; then + rm -f /etc/$MAIL_SYSTEM/domains/$domain +fi + +# Removing webmail configuration +$BIN/v-delete-mail-domain-webmail $user $domain 'yes' + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Updating config +update_object_value 'mail' 'DOMAIN' "$domain" '$SUSPENDED' 'yes' +sed -i "s/SUSPENDED='no'/SUSPENDED='yes'/g" "$USER_DATA/mail/$domain.conf" +increase_user_value "$user" '$SUSPENDED_MAIL' + +# Logging +$BIN/v-log-action "system" "Info" "Mail" "Suspended mail domain (User: $user, Domain: $domain)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-suspend-mail-domains b/bin/v-suspend-mail-domains new file mode 100755 index 0000000..dbf2ff7 --- /dev/null +++ b/bin/v-suspend-mail-domains @@ -0,0 +1,54 @@ +#!/bin/bash +# info: suspend mail domains +# options: USER +# +# example: v-suspend-mail-domains admin +# +# This function suspends all user's MAIL domains. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'USER' +is_format_valid 'user' +is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM' +is_object_valid 'user' 'USER' "$user" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Starting suspend loop +for domain in $(search_objects 'mail' 'SUSPENDED' "no" 'DOMAIN'); do + $BIN/v-suspend-mail-domain "$user" "$domain" +done + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-suspend-remote-dns-host b/bin/v-suspend-remote-dns-host new file mode 100755 index 0000000..6110e02 --- /dev/null +++ b/bin/v-suspend-remote-dns-host @@ -0,0 +1,51 @@ +#!/bin/bash +# info: suspend remote dns server +# options: HOST +# +# example: v-suspend-remote-dns-host hostname.tld +# +# This function for suspending remote dns server. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +host=$1 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'HOST' +is_format_valid 'host' +is_system_enabled "$DNS_SYSTEM" 'DNS_SYSTEM' +is_object_valid "../../conf/dns-cluster" 'HOST' "$host" +is_object_unsuspended "../../conf/dns-cluster" 'HOST' "$host" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Unsuspend remote dns server +update_object_value "../../conf/dns-cluster" 'HOST' "$host" '$SUSPENDED' 'yes' + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-suspend-user b/bin/v-suspend-user new file mode 100755 index 0000000..e64cb32 --- /dev/null +++ b/bin/v-suspend-user @@ -0,0 +1,105 @@ +#!/bin/bash +# info: suspend user +# options: USER [RESTART] +# +# example: v-suspend-user alice yes +# +# This function suspends a certain user and all his objects. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +restart=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'USER [RESTART]' +is_format_valid 'user' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +if [ "$user" = 'admin' ]; then + exit +fi + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Do not restrict access to SFTP/FTP/SSH if POLICY_USER_VIEW_SUSPENDED is set to yes +if [ -z "$POLICY_USER_VIEW_SUSPENDED" ] || [ "$POLICY_USER_VIEW_SUSPENDED" = 'no' ]; then + # Adding '!' in front of the password + /usr/sbin/usermod --lock "$user" + + # Suspending ftp accounts + for ftp in $(grep "^${user}_" /etc/passwd | cut -f 1 -d :); do + /usr/sbin/usermod --lock "$ftp" 2> /dev/null + done +fi + +# Suspending web domains +if [ -n "$WEB_SYSTEM" ] && [ "$WEB_SYSTEM" != 'no' ]; then + $BIN/v-suspend-web-domains "$user" "no" +fi + +# Suspending mail domains +if [ -n "$MAIL_SYSTEM" ] && [ "$MAIL_SYSTEM" != 'no' ]; then + $BIN/v-suspend-mail-domains "$user" "no" +fi + +# Suspending dns domains +if [ -n "$DNS_SYSTEM" ] && [ "$DNS_SYSTEM" != 'no' ]; then + $BIN/v-suspend-dns-domains "$user" "no" +fi + +# Suspending datbabases +if [ -n "$DB_SYSTEM" ] && [ "$DB_SYSTEM" != 'no' ]; then + $BIN/v-suspend-databases "$user" +fi + +# Suspending cron jobs +if [ -n "$CRON_SYSTEM" ] && [ "$CRON_SYSTEM" != 'no' ]; then + $BIN/v-suspend-cron-jobs "$user" "no" +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Restarting system services +$BIN/v-restart-web "$restart" +check_result $? "Web restart failed" > /dev/null + +$BIN/v-restart-proxy "$restart" +check_result $? "Proxy restart failed" > /dev/null + +$BIN/v-restart-dns "$restart" +check_result $? "DNS restart failed" > /dev/null + +$BIN/v-restart-cron "$restart" +check_result $? "Cron restart failed" > /dev/null + +# Changing suspend value +update_user_value "$user" '$SUSPENDED' 'yes' +increase_user_value 'admin' '$SUSPENDED_USERS' + +# Logging +$BIN/v-log-action "system" "Info" "Users" "Suspended user account (Name: $user)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-suspend-web-domain b/bin/v-suspend-web-domain new file mode 100755 index 0000000..406ed63 --- /dev/null +++ b/bin/v-suspend-web-domain @@ -0,0 +1,104 @@ +#!/bin/bash +# info: suspend web domain +# options: USER DOMAIN [RESTART] +# +# example: v-suspend-web-domain admin example.com yes +# +# This function for suspending the site's operation. After blocking it all +# visitors will be redirected to a web page explaining the reason of suspend. +# By blocking the site the content of all its directories remains untouched. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 +restart=$3 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# shellcheck source=/usr/local/hestia/func/ip.sh +source $HESTIA/func/ip.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn +# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ? + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DOMAIN [RESTART]' +is_format_valid 'user' 'domain' +is_system_enabled "$WEB_SYSTEM" 'WEB_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_valid 'web' 'DOMAIN' "$domain" +is_object_unsuspended 'web' 'DOMAIN' "$domain" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Parsing domain values +get_domain_values 'web' +SUSPENDED='yes' +local_ip=$(get_real_ip $IP) + +# Preparing domain values for the template substitution +prepare_web_domain_values + +# Rebuilding vhost +del_web_config "$WEB_SYSTEM" "$TPL.tpl" +add_web_config "$WEB_SYSTEM" "$TPL.tpl" +if [ "$SSL" = 'yes' ]; then + del_web_config "$WEB_SYSTEM" "$TPL.stpl" + add_web_config "$WEB_SYSTEM" "$TPL.stpl" +fi + +# Rebuilding proxy configuration +if [ -n "$PROXY_SYSTEM" ] && [ -n "$PROXY" ]; then + del_web_config "$PROXY_SYSTEM" "$PROXY.tpl" + add_web_config "$PROXY_SYSTEM" "$PROXY.tpl" + if [ "$SSL" = 'yes' ]; then + del_web_config "$PROXY_SYSTEM" "$PROXY.stpl" + add_web_config "$PROXY_SYSTEM" "$PROXY.stpl" + fi +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Updating config +update_object_value 'web' 'DOMAIN' "$domain" '$SUSPENDED' 'yes' +increase_user_value "$user" '$SUSPENDED_WEB' + +# Update global configuration files +$BIN/v-rebuild-web-domain "$user" "$domain" 'no' + +# Restarting web server +$BIN/v-restart-web "$restart" +check_result $? "Web restart failed" > /dev/null + +$BIN/v-restart-proxy "$restart" +check_result $? "Proxy restart failed" > /dev/null + +# Logging +$BIN/v-log-action "system" "Info" "Web" "Suspended web domain (User: $user, Domain: $domain)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-suspend-web-domains b/bin/v-suspend-web-domains new file mode 100755 index 0000000..4b9b12d --- /dev/null +++ b/bin/v-suspend-web-domains @@ -0,0 +1,62 @@ +#!/bin/bash +# info: suspend web domains +# options: USER [RESTART] +# +# example: v-suspend-web-domains bob +# +# This function of suspending all user's sites. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +restart=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'USER [RESTART]' +is_format_valid 'user' +is_system_enabled "$WEB_SYSTEM" 'WEB_SYSTEM' +is_object_valid 'user' 'USER' "$user" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Starting suspend loop +for domain in $(search_objects 'web' 'SUSPENDED' "no" 'DOMAIN'); do + $BIN/v-suspend-web-domain "$user" "$domain" 'no' +done + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Restarting web server +$BIN/v-restart-web "$restart" +check_result $? "Web restart failed" > /dev/null + +$BIN/v-restart-proxy "$restart" +check_result $? "Proxy restart failed" > /dev/null + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-sync-dns-cluster b/bin/v-sync-dns-cluster new file mode 100755 index 0000000..6b796e4 --- /dev/null +++ b/bin/v-sync-dns-cluster @@ -0,0 +1,124 @@ +#!/bin/bash +# info: synchronize dns domains +# options: HOST +# +# This function synchronise all dns domains. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +host=$1 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/remote.sh +source $HESTIA/func/remote.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +is_format_valid 'host' +is_system_enabled "$DNS_CLUSTER" 'DNS_CLUSTER' +is_procces_running +remote_dns_health_check 'no_email' + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Selecting remote hosts +IFS=$'\n' +if [ -z $host ]; then + hosts=$(cat $HESTIA/conf/dns-cluster.conf | grep "SUSPENDED='no'") +else + hosts=$(grep "HOST='$host'" $HESTIA/conf/dns-cluster.conf) +fi + +# Starting cluster loop +for cluster in $hosts; do + + # Reset user, password and hash vars + clear_dns_cluster_settings + + # Parsing host values + parse_object_kv_list "$cluster" + + # Wiping remote domains + cluster_cmd v-delete-dns-domains-src $DNS_USER $HOSTNAME no + check_result $? "$HOST connection failed" $E_CONNECT + + # Syncing user domains + user_list=$(ls -d $HESTIA/data/users/*/ | sed "s#$HESTIA/data/users/##" | sed s"/.$//" | grep -v "dns-cluster") + for user in $user_list; do + USER_DATA="$HESTIA/data/users/$user" + ROLE=$(get_user_value '$ROLE') + if [ "$ROLE" != "dns-cluster" ]; then + for str in $(cat $HESTIA/data/users/$user/dns.conf); do + unset $SLAVE + parse_object_kv_list "$str" + if [ "$SLAVE" != "yes" ]; then + if [ "$DNS_CLUSTER_SYSTEM" != "hestia-zone" ]; then + # Syncing domain index + + cluster_cmd v-insert-dns-domain "$DNS_USER" "$str" "$HOSTNAME" ' ' "no" + check_result $? "$HOST connection failed" "$E_CONNECT" + + # Syncing domain records + tmp_file="/tmp/vst-sync.$DOMAIN" + cluster_file "$HESTIA/data/users/$user/dns/$DOMAIN.conf" "$tmp_file" + check_result $? "$HOST connection failed" "$E_CONNECT" + + cluster_cmd v-insert-dns-records "$DNS_USER" "$DOMAIN" "$tmp_file" 'no' + check_result $? "$HOST connection failed" "$E_CONNECT" + fi + if [ "$DNS_CLUSTER_SYSTEM" = "hestia-zone" ]; then + str=$(echo "$str" | sed "s/SLAVE='no'/SLAVE='yes'/g") + str=$(echo "$str" | sed "s/SLAVE=''/SLAVE='yes'/g") + + ip=$(ip addr | grep 'inet ' | grep global | head -n1 | awk '{print $2}' | cut -f1 -d/) + source_conf $HESTIA/data/ips/$ip + if [ -z $NAT ]; then + str=$(echo "$str" | sed "s/MASTER=''/MASTER='$ip'/g") + else + str=$(echo "$str" | sed "s/MASTER=''/MASTER='$NAT'/g") + fi + + # Syncing domain data + cluster_cmd v-insert-dns-domain $DNS_USER "$str" $HOSTNAME $flush 'no' + check_result $? "$HOST connection failed" "$E_CONNECT" + + cluster_cmd v-rebuild-dns-domain "$DNS_USER" "$DOMAIN" + rndc notify $DOMAIN > /dev/null 2>&1 + fi + fi + done + fi + done + if [ "$DNS_CLUSTER_SYSTEM" != "hestia-zone" ]; then + # Rebuilding dns zones + cluster_cmd v-rebuild-dns-domains "$DNS_USER" "yes" "no" + check_result $? "$TYPE connection to $HOST failed" "$E_CONNECT" + fi +done + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Flushing dns-cluster queue +rm -f $HESTIA/data/queue/dns-cluster.pipe +touch $HESTIA/data/queue/dns-cluster.pipe +chmod 660 $HESTIA/data/queue/dns-cluster.pipe + +exit diff --git a/bin/v-unsuspend-cron-job b/bin/v-unsuspend-cron-job new file mode 100755 index 0000000..1300a04 --- /dev/null +++ b/bin/v-unsuspend-cron-job @@ -0,0 +1,62 @@ +#!/bin/bash +# info: unsuspend cron job +# options: USER JOB [RESTART] +# +# example: v-unsuspend-cron-job admin 7 yes +# +# This function unsuspend certain cron job. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +job=$2 +restart="${3-yes}" + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER JOB [RESTART]' +is_format_valid 'user' 'job' 'restart' +is_object_valid 'user' 'USER' "$user" +is_object_valid 'cron' 'JOB' "$job" +is_object_suspended 'cron' 'JOB' "$job" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Unsuspending job +update_object_value 'cron' 'JOB' "$job" '$SUSPENDED' 'no' +decrease_user_value "$user" '$SUSPENDED_CRON' + +# Sync system cron with user +sync_cron_jobs + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Restarting crond +$BIN/v-restart-cron "$restart" +check_result $? "Cron restart failed" > /dev/null + +# Logging +$BIN/v-log-action "system" "Info" "Cron Jobs" "Unsuspended cron job (User: $user, Job: $job)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-unsuspend-cron-jobs b/bin/v-unsuspend-cron-jobs new file mode 100755 index 0000000..6526c74 --- /dev/null +++ b/bin/v-unsuspend-cron-jobs @@ -0,0 +1,56 @@ +#!/bin/bash +# info: unsuspend sys cron +# options: USER [RESTART] +# +# example: v-unsuspend-cron-jobs admin no +# +# This function unsuspends all suspended cron jobs. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +restart=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'USER [RESTART]' +is_format_valid 'user' +is_object_valid 'user' 'USER' "$user" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Unsuspendning jobs +for job in $(search_objects 'cron' 'SUSPENDED' 'yes' 'JOB'); do + $BIN/v-unsuspend-cron-job "$user" "$job" 'no' +done + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Restarting crond +$BIN/v-restart-cron "$restart" +check_result $? "Cron restart failed" > /dev/null + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-unsuspend-database b/bin/v-unsuspend-database new file mode 100755 index 0000000..f1a02c8 --- /dev/null +++ b/bin/v-unsuspend-database @@ -0,0 +1,66 @@ +#!/bin/bash +# info: unsuspend database +# options: USER DATABASE +# +# example: v-unsuspend-database admin mydb +# +# This function for unsuspending database. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +database=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/db.sh +source $HESTIA/func/db.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DATABASE' +is_format_valid 'user' 'database' +is_system_enabled "$DB_SYSTEM" 'DB_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_valid 'db' 'DB' "$database" +is_object_suspended 'db' 'DB' "$database" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Get database values +get_database_values + +# Switching on db type +case $TYPE in + mysql) unsuspend_mysql_database ;; + pgsql) unsuspend_pgsql_database ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Updating db value +update_object_value 'db' 'DB' "$database" '$SUSPENDED' 'no' +decrease_user_value "$user" '$SUSPENDED_DB' + +# Logging +$BIN/v-log-action "system" "Info" "Database" "Unsuspended database (User: $user, Database: $database)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-unsuspend-database-host b/bin/v-unsuspend-database-host new file mode 100755 index 0000000..3963e47 --- /dev/null +++ b/bin/v-unsuspend-database-host @@ -0,0 +1,52 @@ +#!/bin/bash +# info: unsuspend database server +# options: TYPE HOST +# +# example: v-unsuspend-database-host mysql localhost +# +# This function for unsuspending a database server. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +type=$1 +host=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'TYPE HOST' +is_format_valid 'type' 'host' +is_system_enabled "$DB_SYSTEM" 'DB_SYSTEM' +is_object_valid "../../conf/$type" 'HOST' "$host" +is_object_suspended "../../conf/$type" 'HOST' "$host" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Unsuspend database creation on a server +update_object_value "../../conf/$type" 'HOST' "$host" '$SUSPENDED' 'no' + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-unsuspend-databases b/bin/v-unsuspend-databases new file mode 100755 index 0000000..08b1d49 --- /dev/null +++ b/bin/v-unsuspend-databases @@ -0,0 +1,52 @@ +#!/bin/bash +# info: unsuspend databases +# options: USER +# +# This function for unsuspending all user's databases. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/db.sh +source $HESTIA/func/db.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'USER' +is_format_valid 'user' +is_system_enabled "$DB_SYSTEM" 'DB_SYSTEM' +is_object_valid 'user' 'USER' "$user" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Starting unsuspend loop +for database in $(search_objects 'db' 'SUSPENDED' "yes" 'DB'); do + $BIN/v-unsuspend-database "$user" "$database" +done + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-unsuspend-dns-domain b/bin/v-unsuspend-dns-domain new file mode 100755 index 0000000..b4a865e --- /dev/null +++ b/bin/v-unsuspend-dns-domain @@ -0,0 +1,78 @@ +#!/bin/bash +# info: unsuspend dns domain +# options: USER DOMAIN +# +# example: v-unsuspend-dns-domain alice wonderland.com +# +# This function unsuspends a certain user's domain. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn +# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ? + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DOMAIN' +is_format_valid 'user' 'domain' +is_system_enabled "$DNS_SYSTEM" 'DNS_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_valid 'dns' 'DOMAIN' "$domain" +is_object_suspended 'dns' 'DOMAIN' "$domain" + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Creating system configs +if [[ "$DNS_SYSTEM" =~ named|bind ]]; then + if [ -e '/etc/named.conf' ]; then + dns_conf='/etc/named.conf' + dns_group='named' + else + dns_conf='/etc/bind/named.conf' + dns_group='bind' + fi + + # Adding zone in named.conf + named="zone \"$domain_idn\" {type master; file" + named="$named \"$HOMEDIR/$user/conf/dns/$domain.db\";};" + echo "$named" >> $dns_conf +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Unsuspending domain in config +update_object_value 'dns' 'DOMAIN' "$domain" '$SUSPENDED' 'no' +decrease_user_value "$user" '$SUSPENDED_DNS' +sed -i "s/SUSPENDED='yes'/SUSPENDED='no'/g" $USER_DATA/dns/$domain.conf + +# Logging +$BIN/v-log-action "system" "Info" "DNS" "Unsuspended DNS zone (User: $user, Domain: $domain)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-unsuspend-dns-domains b/bin/v-unsuspend-dns-domains new file mode 100755 index 0000000..9d21a8b --- /dev/null +++ b/bin/v-unsuspend-dns-domains @@ -0,0 +1,53 @@ +#!/bin/bash +# info: unsuspend dns domains +# options: USER [RESTART] +# +# example: v-unsuspend-dns-domains alice +# +# This function unsuspends all user's DNS domains. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +restart=${3-no} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'USER [RESTART]' +is_format_valid 'user' +is_system_enabled "$DNS_SYSTEM" 'DNS_SYSTEM' +is_object_valid 'user' 'USER' "$user" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Starting unsuspend loop +for domain in $(search_objects 'dns' 'SUSPENDED' "yes" 'DOMAIN'); do + $BIN/v-unsuspend-dns-domain "$user" "$domain" "$restart" +done + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-unsuspend-dns-record b/bin/v-unsuspend-dns-record new file mode 100755 index 0000000..f22b6f6 --- /dev/null +++ b/bin/v-unsuspend-dns-record @@ -0,0 +1,82 @@ +#!/bin/bash +# info: unsuspend dns domain record +# options: USER DOMAIN ID [RESTART] +# +# example: v-unsuspend-dns-record admin example.com 33 +# +# This function unsuspends a certain domain record. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 +id=$3 +restart=$4 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn +# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ? + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '3' "$#" 'USER DOMAIN ID [RESTART]' +is_format_valid 'user' 'domain' 'id' +is_system_enabled "$DNS_SYSTEM" 'DNS_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_valid 'dns' 'DOMAIN' "$domain" +is_object_unsuspended 'dns' 'DOMAIN' "$domain" +is_object_valid "dns/$domain" 'ID' "$id" + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +update_object_value "dns/$domain" 'ID' "$id" '$SUSPENDED' "no" + +# Update serial +update_domain_serial +# Updating zone +if [[ "$DNS_SYSTEM" =~ named|bind ]]; then + # Do full rebuild due DNS SEC + rebuild_dns_domain_conf +fi + +# Updating dns-cluster queue +if [ "$DNS_CLUSTER" = "yes" ]; then + # Check for first sync + dlock=$(grep "domain $user $domain" $HESTIA/data/queue/dns-cluster.pipe) + if [ -z "$dlock" ]; then + cmd="$BIN/v-add-remote-dns-record $user $domain $id" + echo "$cmd" >> $HESTIA/data/queue/dns-cluster.pipe + fi +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +$BIN/v-log-action "system" "Info" "DNS" "Unsuspended DNS record (User: $user, Domain: $domain, Record: $id)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-unsuspend-domain b/bin/v-unsuspend-domain new file mode 100755 index 0000000..8e15d88 --- /dev/null +++ b/bin/v-unsuspend-domain @@ -0,0 +1,92 @@ +#!/bin/bash +# info: unsuspend web/dns/mail domain +# options: USER DOMAIN +# +# example: v-unsuspend-domain admin acme.com +# +# This function unsuspends web/dns/mail domain. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +restart="${3-yes}" + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DOMAIN' +is_format_valid 'user' 'domain' +is_object_valid 'user' 'USER' "$user" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Working on Web domain +if [ -n "$WEB_SYSTEM" ]; then + str=$(grep "DOMAIN='$domain'" $USER_DATA/web.conf | grep "SUSPENDED='yes") + if [ -n "$str" ]; then + domain_found='yes' + $BIN/v-unsuspend-web-domain "$user" "$domain" 'no' + check_result $? "can't suspend web" > /dev/null + fi +fi + +# Working on DNS domain +if [ -n "$DNS_SYSTEM" ]; then + str=$(grep "DOMAIN='$domain'" $USER_DATA/dns.conf | grep "SUSPENDED='yes") + if [ -n "$str" ]; then + domain_found='yes' + $BIN/v-unsuspend-dns-domain "$user" "$domain" 'no' + check_result $? "can't suspend dns" > /dev/null + fi +fi + +# Working on Mail domain +if [ -n "$MAIL_SYSTEM" ]; then + str=$(grep "DOMAIN='$domain'" $USER_DATA/mail.conf | grep "SUSPENDED='yes") + if [ -n "$str" ]; then + domain_found='yes' + $BIN/v-unsuspend-mail-domain "$user" "$domain" "no" + check_result $? "can't suspend mail" > /dev/null + fi +fi + +# Checking domain search result +if [ -z "$domain_found" ]; then + echo "Error: domain $domain doesn't exist" + log_event "$E_NOTEXIST" "$ARGUMENTS" + exit $E_NOTEXIST +fi + +# Restarting services +$BIN/v-restart-web "$restart" +check_result $? "can't restart web" > /dev/null + +$BIN/v-restart-proxy "$restart" +check_result $? "can't restart proxy" > /dev/null + +$BIN/v-restart-dns "$restart" +check_result $? "can't restart dns" > /dev/null + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-unsuspend-firewall-rule b/bin/v-unsuspend-firewall-rule new file mode 100755 index 0000000..548b37b --- /dev/null +++ b/bin/v-unsuspend-firewall-rule @@ -0,0 +1,55 @@ +#!/bin/bash +# info: unsuspend firewall rule +# options: RULE +# +# example: v-unsuspend-firewall-rule 7 +# +# This function unsuspends a certain firewall rule. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +rule=$1 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'RULE' +is_format_valid 'rule' +is_system_enabled "$FIREWALL_SYSTEM" 'FIREWALL_SYSTEM' +is_object_valid '../../data/firewall/rules' 'RULE' "$rule" +is_object_suspended '../../data/firewall/rules' 'RULE' "$rule" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Suspending rule +update_object_value ../../data/firewall/rules RULE "$rule" '$SUSPENDED' "no" + +# Updating system firewall +$BIN/v-update-firewall + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +$BIN/v-log-action "system" "Info" "Firewall" "Unsuspended firewall rule (Rule: $rule)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-unsuspend-mail-account b/bin/v-unsuspend-mail-account new file mode 100755 index 0000000..d1b084a --- /dev/null +++ b/bin/v-unsuspend-mail-account @@ -0,0 +1,77 @@ +#!/bin/bash +# info: unsuspend mail account +# options: USER DOMAIN ACCOUNT +# +# example: v-unsuspend-mail-account admin acme.com tester +# +# This function unsuspends mail account. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 +account=$3 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn +# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ? + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '3' "$#" 'USER DOMAIN ACCOUNT' +is_format_valid 'user' 'domain' 'account' +is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'mail' 'DOMAIN' "$domain" +is_object_unsuspended 'mail' 'DOMAIN' "$domain" +is_object_valid "mail/$domain" 'ACCOUNT' "$account" +is_object_suspended "mail/$domain" 'ACCOUNT' "$account" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +if [[ "$MAIL_SYSTEM" =~ exim ]]; then + md5=$(get_object_value "mail/$domain" 'ACCOUNT' "$account" '$MD5') + quota=$(get_object_value "mail/$domain" 'ACCOUNT' "$account" '$QUOTA') + if [ "$quota" = 'unlimited' ]; then + quota=0 + fi + sed -i "/^$account:/d" $HOMEDIR/$user/conf/mail/$domain/passwd + str="$account:$md5:$user:mail::$HOMEDIR/$user::userdb_quota_rule=*:storage=${quota}M" + echo $str >> $HOMEDIR/$user/conf/mail/$domain/passwd +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Update config +update_object_value "mail/$domain" 'ACCOUNT' "$account" '$SUSPENDED' 'no' + +# Logging +$BIN/v-log-action "system" "Info" "Mail" "Unsuspended mail account (User: $user, Account: $account@$domain)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-unsuspend-mail-accounts b/bin/v-unsuspend-mail-accounts new file mode 100755 index 0000000..2ef82a3 --- /dev/null +++ b/bin/v-unsuspend-mail-accounts @@ -0,0 +1,59 @@ +#!/bin/bash +# info: unsuspend all mail domain accounts +# options: USER DOMAIN +# +# example: v-unsuspend-mail-accounts admin acme.com +# +# This function unsuspends all mail domain accounts. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn +# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ? + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DOMAIN' +is_format_valid 'user' 'domain' +is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'mail' 'DOMAIN' "$domain" +is_object_unsuspended 'mail' 'DOMAIN' "$domain" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Starting unsuspend loop +for account in $(search_objects "mail/$domain" 'SUSPENDED' 'yes' 'ACCOUNT'); do + $BIN/v-unsuspend-mail-account "$user" "$domain" "$account" +done + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-unsuspend-mail-domain b/bin/v-unsuspend-mail-domain new file mode 100755 index 0000000..6e231eb --- /dev/null +++ b/bin/v-unsuspend-mail-domain @@ -0,0 +1,79 @@ +#!/bin/bash +# info: unsuspend mail domain +# options: USER DOMAIN +# +# example: v-unsuspend-mail-domain user02 acme.com +# +# This function unsuspends mail domain. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 +restart=${3-yes} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn +# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ? + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DOMAIN' +is_format_valid 'user' 'domain' +is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_valid 'mail' 'DOMAIN' "$domain" +is_object_suspended 'mail' 'DOMAIN' "$domain" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Add symbolic link +if [[ "$MAIL_SYSTEM" =~ exim ]]; then + ln -s $HOMEDIR/$user/conf/mail/$domain /etc/$MAIL_SYSTEM/domains/ +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Updating config +update_object_value 'mail' 'DOMAIN' "$domain" '$SUSPENDED' 'no' +sed -i "s/SUSPENDED='yes'/SUSPENDED='no'/g" $USER_DATA/mail/$domain.conf +decrease_user_value "$user" '$SUSPENDED_MAIL' + +# Enable webmail access +if [ -n "$IMAP_SYSTEM" ]; then + if [ -n "$WEBMAIL_SYSTEM" ]; then + for client in ${WEBMAIL_SYSTEM//,/ }; do + webmail="$client" + done + $BIN/v-add-mail-domain-webmail "$user" "$domain" "$webmail" "$restart" + fi +fi +# Logging +$BIN/v-log-action "system" "Info" "Mail" "Unsuspended mail domain (User: $user, Domain: $domain)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-unsuspend-mail-domains b/bin/v-unsuspend-mail-domains new file mode 100755 index 0000000..b071b12 --- /dev/null +++ b/bin/v-unsuspend-mail-domains @@ -0,0 +1,54 @@ +#!/bin/bash +# info: unsuspend mail domains +# options: USER +# +# example: v-unsuspend-mail-domains admin +# +# This function unsuspends all user's MAIL domains. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'USER' +is_format_valid 'user' +is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM' +is_object_valid 'user' 'USER' "$user" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Starting unsuspend loop +for domain in $(search_objects 'mail' 'SUSPENDED' "yes" 'DOMAIN'); do + $BIN/v-unsuspend-mail-domain "$user" "$domain" +done + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-unsuspend-remote-dns-host b/bin/v-unsuspend-remote-dns-host new file mode 100755 index 0000000..ec67220 --- /dev/null +++ b/bin/v-unsuspend-remote-dns-host @@ -0,0 +1,51 @@ +#!/bin/bash +# info: unsuspend remote dns server +# options: HOST +# +# example: v-unsuspend-remote-dns-host hosname.com +# +# This function for unsuspending remote dns server. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +host=$1 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'HOST' +is_format_valid 'host' +is_system_enabled "$DNS_SYSTEM" 'DNS_SYSTEM' +is_object_valid "../../conf/dns-cluster" 'HOST' "$host" +is_object_suspended "../../conf/dns-cluster" 'HOST' "$host" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Unsuspend remote dns server +update_object_value "../../conf/dns-cluster" 'HOST' "$host" '$SUSPENDED' 'no' + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-unsuspend-user b/bin/v-unsuspend-user new file mode 100755 index 0000000..b0d41d7 --- /dev/null +++ b/bin/v-unsuspend-user @@ -0,0 +1,104 @@ +#!/bin/bash +# info: unsuspend user +# options: USER [RESTART] +# +# example: v-unsuspend-user bob +# +# This function unsuspends user and all his objects. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +restart=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'USER' +is_format_valid 'user' +is_object_valid 'user' 'USER' "$user" +if [ "$user" = 'admin' ]; then + exit +fi + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Do not restrict access to SFTP/FTP/SSH if POLICY_USER_VIEW_SUSPENDED is set to yes +if [ -z "$POLICY_USER_VIEW_SUSPENDED" ] || [ "$POLICY_USER_VIEW_SUSPENDED" = 'no' ]; then + # Deleting '!' in front of the password + /usr/sbin/usermod --unlock $user + + # Unsuspending ftp accounts + for ftp in $(grep "^${user}_" /etc/passwd | cut -f 1 -d :); do + /usr/sbin/usermod --unlock $ftp 2> /dev/null + done +fi + +# Changing suspend value +update_user_value "$user" '$SUSPENDED' 'no' +decrease_user_value 'admin' '$SUSPENDED_USERS' + +# Unsuspending web domains +if [ -n "$WEB_SYSTEM" ] && [ "$WEB_SYSTEM" != 'no' ]; then + $BIN/v-unsuspend-web-domains "$user" "no" +fi + +# Unsuspending dns domains +if [ -n "$DNS_SYSTEM" ] && [ "$DNS_SYSTEM" != 'no' ]; then + $BIN/v-unsuspend-dns-domains "$user" "no" +fi + +# Unsuspending mail domains +if [ -n "$MAIL_SYSTEM" ] && [ "$MAIL_SYSTEM" != 'no' ]; then + $BIN/v-unsuspend-mail-domains "$user" "no" +fi + +# Unsuspending datbabases +if [ -n "$DB_SYSTEM" ] && [ "$DB_SYSTEM" != 'no' ]; then + $BIN/v-unsuspend-databases "$user" +fi + +# Unsuspending cron jobs +if [ -n "$CRON_SYSTEM" ] && [ "$CRON_SYSTEM" != 'no' ]; then + $BIN/v-unsuspend-cron-jobs "$user" "no" +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Restarting system services +$BIN/v-restart-web "$restart" +check_result $? "Web restart failed" > /dev/null + +$BIN/v-restart-proxy "$restart" +check_result $? "Proxy restart failed" > /dev/null + +$BIN/v-restart-dns "$restart" +check_result $? "DNS restart failed" > /dev/null + +$BIN/v-restart-cron "$restart" +check_result $? "Cron restart failed" > /dev/null + +# Logging +$BIN/v-log-action "system" "Info" "Users" "Unsuspended user account (User: $user)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-unsuspend-web-domain b/bin/v-unsuspend-web-domain new file mode 100755 index 0000000..8571c12 --- /dev/null +++ b/bin/v-unsuspend-web-domain @@ -0,0 +1,110 @@ +#!/bin/bash +# info: unsuspend web domain +# options: USER DOMAIN [RESTART] +# +# example: v-unsuspend-web-domain admin acme.com +# +# This function of unsuspending the domain. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 +restart=$3 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# shellcheck source=/usr/local/hestia/func/ip.sh +source $HESTIA/func/ip.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn +# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ? + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DOMAIN [RESTART]' +is_format_valid 'user' 'domain' +is_system_enabled "$WEB_SYSTEM" 'WEB_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_valid 'web' 'DOMAIN' "$domain" +is_object_suspended 'web' 'DOMAIN' "$domain" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Parsing domain values +get_domain_values 'web' +SUSPENDED='no' +local_ip=$(get_real_ip $IP) + +# Preparing domain values for the template substitution +prepare_web_domain_values + +# Rebuilding vhost +del_web_config "$WEB_SYSTEM" "$TPL.tpl" +add_web_config "$WEB_SYSTEM" "$TPL.tpl" +if [ "$SSL" = 'yes' ]; then + del_web_config "$WEB_SYSTEM" "$TPL.stpl" + add_web_config "$WEB_SYSTEM" "$TPL.stpl" +fi + +# Rebuilding proxy configuration +if [ -n "$PROXY_SYSTEM" ] && [ -n "$PROXY" ]; then + del_web_config "$PROXY_SYSTEM" "$PROXY.tpl" + add_web_config "$PROXY_SYSTEM" "$PROXY.tpl" + if [ "$SSL" = 'yes' ]; then + del_web_config "$PROXY_SYSTEM" "$PROXY.stpl" + add_web_config "$PROXY_SYSTEM" "$PROXY.stpl" + fi +fi + +# Rebuilding backend configuration +if [ -n "$WEB_BACKEND" ]; then + prepare_web_backend "$BACKEND" + delete_web_backend + template=$(get_object_value 'web' 'DOMAIN' "$domain" '$BACKEND') + $BIN/v-add-web-domain-backend $user $domain $template $restart +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Updating config +update_object_value 'web' 'DOMAIN' "$domain" '$SUSPENDED' 'no' +decrease_user_value "$user" '$SUSPENDED_WEB' + +# Update global configuration files +$BIN/v-rebuild-web-domain "$user" "$domain" 'no' + +# Restarting web server +$BIN/v-restart-web "$restart" +check_result $? "Web restart failed" > /dev/null + +$BIN/v-restart-proxy "$restart" +check_result $? "Proxy restart failed" > /dev/null + +# Logging +$BIN/v-log-action "system" "Info" "Web" "Unsuspended web domain (User: $user, Domain: $domain)." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-unsuspend-web-domains b/bin/v-unsuspend-web-domains new file mode 100755 index 0000000..2bf8432 --- /dev/null +++ b/bin/v-unsuspend-web-domains @@ -0,0 +1,62 @@ +#!/bin/bash +# info: unsuspend web domains +# options: USER [RESTART] +# +# example: v-unsuspend-web-domains admin +# +# This function of unsuspending all user's sites. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +restart=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'USER [RESTART]' +is_format_valid 'user' +is_system_enabled "$WEB_SYSTEM" 'WEB_SYSTEM' +is_object_valid 'user' 'USER' "$user" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Starting unsuspend loop +for domain in $(search_objects 'web' 'SUSPENDED' "yes" 'DOMAIN'); do + $BIN/v-unsuspend-web-domain "$user" "$domain" 'no' +done + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Restarting web server +$BIN/v-restart-web "$restart" +check_result $? "Web restart failed" > /dev/null + +$BIN/v-restart-proxy "$restart" +check_result $? "Proxy restart failed" > /dev/null + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-update-database-disk b/bin/v-update-database-disk new file mode 100755 index 0000000..a03eab1 --- /dev/null +++ b/bin/v-update-database-disk @@ -0,0 +1,61 @@ +#!/bin/bash +# info: update database disk usage +# options: USER DATABASE +# +# example: v-update-database-disk admin wp_db +# +# This function recalculates disk usage for specific database. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +database=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/db.sh +source $HESTIA/func/db.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DATABASE' +is_format_valid 'user' 'database' +is_system_enabled "$DB_SYSTEM" 'DB_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_valid 'db' 'DB' "$database" + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Get database values +get_database_values + +# Switching on db type +case $TYPE in + mysql) get_mysql_disk_usage ;; + pgsql) get_pgsql_disk_usage ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Updating disk usage +update_object_value 'db' 'DB' "$database" '$U_DISK' "$usage" +recalc_user_disk_usage + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-update-databases-disk b/bin/v-update-databases-disk new file mode 100755 index 0000000..8e01a32 --- /dev/null +++ b/bin/v-update-databases-disk @@ -0,0 +1,49 @@ +#!/bin/bash +# info: update databases disk usage +# options: USER +# +# example: v-update-databases-disk admin +# +# This function recalculates disk usage for all user databases. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'USER' +is_format_valid 'user' +is_system_enabled "$DB_SYSTEM" 'DB_SYSTEM' +is_object_valid 'user' 'USER' "$user" + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Starting update loop +for database in $($BIN/v-list-databases $user plain | cut -f 1); do + $BIN/v-update-database-disk "$user" "$database" +done + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-update-dns-templates b/bin/v-update-dns-templates new file mode 100755 index 0000000..a8a74c5 --- /dev/null +++ b/bin/v-update-dns-templates @@ -0,0 +1,39 @@ +#!/bin/bash +# info: update dns templates +# options: [RESTART] +# +# example: v-update-dns-templates +# +# This function for obtaining updated dns templates from Hestia package. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +restart=$1 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Update templates +cp -rf $HESTIA_COMMON_DIR/templates/dns $HESTIA/data/templates/ + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +$BIN/v-log-action "system" "Info" "Updates" "Default DNS zone templates updated." +exit diff --git a/bin/v-update-firewall b/bin/v-update-firewall new file mode 100755 index 0000000..1c7d743 --- /dev/null +++ b/bin/v-update-firewall @@ -0,0 +1,215 @@ +#!/bin/bash +# info: update system firewall rules +# options: NONE +# +# example: v-update-firewall +# +# This function updates iptables rules + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Defining absolute path for iptables and modprobe +iptables="/sbin/iptables" +modprobe="/sbin/modprobe" +sysctl="/sbin/sysctl" + +# Includes +source /etc/profile.d/hestia.sh +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/firewall.sh +source $HESTIA/func/firewall.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +is_system_enabled "$FIREWALL_SYSTEM" 'FIREWALL_SYSTEM' + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Self heal iptables links +heal_iptables_links + +# Checking local IPv4 rules +rules="$HESTIA/data/firewall/rules.conf" + +if [ ! -e "$rules" ]; then + exit +fi + +# Checking conntrack module avaiabilty +$modprobe nf_conntrack > /dev/null 2>&1 +if [ $? -ne 0 ]; then + $sysctl net.netfilter.nf_conntrack_max > /dev/null 2>&1 + if [ $? -ne 0 ]; then + conntrack='no' + fi +fi + +$modprobe nf_conntrack_ftp > /dev/null 2>&1 +if [ $? -ne 0 ]; then + conntrack_ftp='no' +fi + +# Checking custom OpenSSH port +sshport=$(grep '^Port ' /etc/ssh/sshd_config | head -1 | cut -d ' ' -f 2) +if [[ "$sshport" =~ ^[0-9]+$ ]] && [ "$sshport" -ne "22" ]; then + sed -i "s/PORT='22'/PORT=\'$sshport\'/" $rules +fi + +# Load ipset lists before adding Hestia iptables rules +$BIN/v-update-firewall-ipset load + +# Creating temporary file +tmp="$(mktemp)" + +# Flushing INPUT chain +echo "$iptables -P INPUT ACCEPT" >> $tmp +echo "$iptables -F INPUT" >> $tmp + +# Enabling stateful support +if [ "$conntrack" != 'no' ] || grep --quiet container=lxc /proc/1/environ; then + str="$iptables -A INPUT -m state" + str="$str --state ESTABLISHED,RELATED -j ACCEPT" + echo "$str" >> $tmp +fi + +ips="$(ls $HESTIA/data/ips)" +# Handling local traffic +for ip in $ips; do + echo "$iptables -A INPUT -s $ip -j ACCEPT" >> $tmp +done +echo "$iptables -A INPUT -s 127.0.0.1 -j ACCEPT" >> $tmp + +# Pasring iptables rules +IFS=$'\n' +for line in $(sort -r -n -k 2 -t \' $rules); do + parse_object_kv_list "$line" + if [ "$SUSPENDED" = 'no' ]; then + proto="-p $PROTOCOL" + port="--dport $PORT" + state="" + action="-j $ACTION" + + if [[ "$IP" =~ ^ipset: ]]; then + ipset_name="${IP#ipset:}" + $(v-list-firewall-ipset plain | grep "^$ipset_name\s" > /dev/null) || log_event $E_NOTEXIST "IPset IP list ($ipset_name) not found" + ip="-m set --match-set '${ipset_name}' src" + else + ip="-s $IP" + fi + + # Adding multiport module + if [[ "$PORT" =~ ,|-|: ]]; then + port="-m multiport --dports ${PORT//-/:}" + fi + + # Accepting all dst ports + if [[ "$PORT" = "0" ]] || [ "$PROTOCOL" = 'ICMP' ]; then + port="" + fi + + # Checking FTP for contrack module + if [ "$TYPE" = "FTP" ] || [ "$PORT" = '21' ]; then + if [ "$conntrack_ftp" != 'no' ]; then + state="-m conntrack --ctstate NEW" + else + port="-m multiport --dports 20,21,12000:12100" + fi + ftp="yes" + fi + + # Adding firewall rule + echo "$iptables -A INPUT $proto $port $ip $state $action" >> $tmp + fi +done + +# Switching chain policy to DROP +echo "$iptables -P INPUT DROP" >> $tmp + +# Adding hestia chain +echo "$iptables -N hestia" >> $tmp + +# Applying rules +bash $tmp 2> /dev/null + +# Deleting temporary file +rm -f $tmp + +# Checking custom trigger +if [ -x "$HESTIA/data/firewall/custom.sh" ]; then + bash $HESTIA/data/firewall/custom.sh +fi + +# Checking fail2ban support +if [ -n "$FIREWALL_EXTENSION" ]; then + for chain in $(cat $HESTIA/data/firewall/chains.conf 2> /dev/null); do + parse_object_kv_list "$chain" + if [[ "$PORT" =~ ,|-|: ]]; then + port="-m multiport --dports $PORT" + else + port="--dport $PORT" + fi + echo "$iptables -N fail2ban-$CHAIN" >> $tmp + echo "$iptables -F fail2ban-$CHAIN" >> $tmp + echo "$iptables -I fail2ban-$CHAIN -s 0.0.0.0/0 -j RETURN" >> $tmp + echo "$iptables -I INPUT -p $PROTOCOL $port -j fail2ban-$CHAIN" >> $tmp + done + bash $tmp 2> /dev/null + rm -f $tmp + + for ban in $(cat $HESTIA/data/firewall/banlist.conf 2> /dev/null); do + parse_object_kv_list "$ban" + echo -n "$iptables -I fail2ban-$CHAIN 1 -s $IP" >> $tmp + echo " -j REJECT --reject-with icmp-port-unreachable" >> $tmp + done + bash $tmp 2> /dev/null + rm -f $tmp +fi + +# Clean up and saving rules to the master iptables file +if [ -d "/etc/sysconfig" ]; then + /sbin/iptables-save | sed -e 's/[[0-9]\+:[0-9]\+]/[0:0]/g' -e '/^-A fail2ban-[A-Z]\+ -s .\+$/d' > /etc/sysconfig/iptables +else + /sbin/iptables-save | sed -e 's/[[0-9]\+:[0-9]\+]/[0:0]/g' -e '/^-A fail2ban-[A-Z]\+ -s .\+$/d' > /etc/iptables.rules + iptablesversion="$(iptables --version | head -1 | awk '{print $2}' | cut -f -2 -d .)" + sd_unit="/lib/systemd/system/hestia-iptables.service" + if [ ! -e "$sd_unit" ]; then + echo "[Unit]" >> $sd_unit + echo "Description=Loading Hestia firewall rules" >> $sd_unit + echo "DefaultDependencies=no" >> $sd_unit + echo "Wants=network-pre.target local-fs.target" >> $sd_unit + echo "Before=network-pre.target" >> $sd_unit + echo "After=local-fs.target" >> $sd_unit + echo "" >> $sd_unit + echo "[Service]" >> $sd_unit + echo "Type=oneshot" >> $sd_unit + echo "RemainAfterExit=yes" >> $sd_unit + echo "ExecStartPre=-${HESTIA}/bin/v-update-firewall-ipset load" >> $sd_unit + if [ "$iptablesversion" = "v1.6" ]; then + echo "ExecStart=/sbin/iptables-restore /etc/iptables.rules" >> $sd_unit + else + echo "ExecStart=/sbin/iptables-restore --wait=10 /etc/iptables.rules" >> $sd_unit + fi + echo "" >> $sd_unit + echo "[Install]" >> $sd_unit + echo "WantedBy=multi-user.target" >> $sd_unit + systemctl -q daemon-reload + fi + systemctl -q is-enabled hestia-iptables 2> /dev/null || systemctl -q enable hestia-iptables +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-update-firewall-ipset b/bin/v-update-firewall-ipset new file mode 100755 index 0000000..a613fcc --- /dev/null +++ b/bin/v-update-firewall-ipset @@ -0,0 +1,69 @@ +#!/bin/bash +# info: update firewall ipset +# options: [REFRESH] +# +# example: v-update-firewall-ipset +# +# This function creates ipset lists and updates the lists if they are expired or ondemand + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +refresh=${1:-no} + +# Includes +source /etc/profile.d/hestia.sh +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +is_refresh_ipset_format_valid "$refresh" 'Refresh IP lists (load/yes/no)' +is_system_enabled "$FIREWALL_SYSTEM" 'FIREWALL_SYSTEM' + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +ipset_hstobject='../../data/firewall/ipset' + +for ipset_name in $(search_objects "$ipset_hstobject" 'SUSPENDED' 'no' 'LISTNAME' 2> /dev/null); do + + ipset_time="$(get_object_value "$ipset_hstobject" 'LISTNAME' "$ipset_name" '$TIME')" + ipset_date="$(get_object_value "$ipset_hstobject" 'LISTNAME' "$ipset_name" '$DATE')" + ipset_au="$(get_object_value "$ipset_hstobject" 'LISTNAME' "$ipset_name" '$AUTOUPDATE')" + + if [ "$ipset_au" = 'no' ] || [ "$refresh" = 'load' ]; then + # Load existing ip list files in the kernel but don't auto update them + # The "load" refresh option is only used by hestia-iptables systemd service + $BIN/v-add-firewall-ipset "$ipset_name" + continue + fi + + last_updated_ts=$(date -d "$ipset_date $ipset_time" +%s) + now=$(date +%s) + hours_since_update=$(((now - last_updated_ts) / (60 * 60))) + + if [[ "$hours_since_update" -lt 24 ]] && [ "$refresh" = 'no' ]; then + # Load existing ip list files in the kernel but don't auto update them + $BIN/v-add-firewall-ipset "$ipset_name" + continue + fi + + $BIN/v-add-firewall-ipset "$ipset_name" '' '' '' 'yes' +done + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-update-host-certificate b/bin/v-update-host-certificate new file mode 100755 index 0000000..048a3f6 --- /dev/null +++ b/bin/v-update-host-certificate @@ -0,0 +1,95 @@ +#!/bin/bash +# info: update host certificate for hestia +# options: USER HOSTNAME +# +# example: v-update-host-certificate admin example.com +# +# This function updates the SSL certificate used for Hestia Control Panel. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +whoami=$(whoami) +if [ "$whoami" != "root" ] && [ "$whoami" != "admin" ]; then + echo "Error: this script must be run as root or admin." + exit 1 +fi + +# Argument definition +user=$1 +hostname=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/ip.sh +source $HESTIA/func/ip.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" '[USER] [HOSTNAME]' +is_format_valid 'user' +is_domain_format_valid "$hostname" "hostname" +is_system_enabled "$WEB_SYSTEM" 'WEB_SYSTEM' +is_system_enabled "$WEB_SSL" 'SSL_SUPPORT' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'web' 'DOMAIN' "$hostname" +is_object_unsuspended 'web' 'DOMAIN' "$hostname" + +if [ ! -f "/home/$user/conf/web/$hostname/ssl/$hostname.pem" ]; then + echo "Error: domain $hostname does not have an SSL certificate." + exit 1 +fi + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Copy hostnames certificates from user dir +cp /home/$user/conf/web/$hostname/ssl/$hostname.pem $HESTIA/ssl/certificate.crt +cp /home/$user/conf/web/$hostname/ssl/$hostname.key $HESTIA/ssl/certificate.key + +# Enable fallback support for mail domains that do not support SSL +if [[ "$MAIL_SYSTEM" =~ exim ]]; then + # Checking exim username for later chowning + exim_user="exim" + check_exim_username=$(grep -c '^Debian-exim:' /etc/passwd) + if [ "$check_exim_username" -eq 1 ]; then + exim_user="Debian-exim" + fi + + # Assign exim permissions to certificate + chown $exim_user:mail $HESTIA/ssl/certificate.crt + chown $exim_user:mail $HESTIA/ssl/certificate.key +fi + +# Add UPDATE_HOSTNAME_SSL if not exist +if [ -z "$UPDATE_HOSTNAME_SSL" ]; then + echo "UPDATE_HOSTNAME_SSL='yes'" >> "$HESTIA/conf/hestia.conf" +fi + +# Restart services +$BIN/v-restart-mail +$BIN/v-restart-ftp +$BIN/v-restart-service "hestia" + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +$BIN/v-log-action "system" "Info" "System" "System SSL certificate updated (Host: $hostname)." +log_event "$OK" "$ARGUMENTS" + +exit 0 diff --git a/bin/v-update-letsencrypt-ssl b/bin/v-update-letsencrypt-ssl new file mode 100755 index 0000000..2a69c3e --- /dev/null +++ b/bin/v-update-letsencrypt-ssl @@ -0,0 +1,175 @@ +#!/bin/bash +# info: update letsencrypt ssl certificates +# options: NONE +# +# example: v-update-letsencrypt-ssl +# +# This function for renew letsencrypt expired ssl certificate for all users + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/syshealth.sh +source $HESTIA/func/syshealth.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Set LE counter +lecounter=0 +max_LE_failures=30 +days_valid_setting=31 +if [ "$LE_STAGING" = "yes" ]; then + # Overwrite setting to allow testing for renewal to be done easier + days_valid_setting=181 +fi + +# Checking user certificates +for user in $($BIN/v-list-sys-users plain); do + USER_DATA=$HESTIA/data/users/$user + + for domain in $(search_objects 'web' 'LETSENCRYPT' 'yes' 'DOMAIN'); do + # Clear any keys related to web domains + sanitize_config_file "web" + domain_suspended="$(get_object_value 'web' 'DOMAIN' "$domain" '$SUSPENDED')" + if [ "$domain_suspended" = "yes" ]; then + continue + fi + + fail_counter="$(get_object_value 'web' 'DOMAIN' "$domain" '$LETSENCRYPT_FAIL_COUNT')" + if [[ "$fail_counter" -gt "$max_LE_failures" ]]; then + continue + fi + + crt_data=$(openssl x509 -text -in $USER_DATA/ssl/$domain.crt) + not_after=$(echo "$crt_data" | grep "Not After" | cut -f 2,3,4 -d :) + expiration=$(date -d "$not_after" +%s) + now=$(date +%s) + seconds_valid=$((expiration - now)) + days_valid=$((seconds_valid / 86400)) + if [[ "$days_valid" -lt "$days_valid_setting" ]]; then + if [ $lecounter -gt 0 ]; then + sleep 10 + fi + ((lecounter++)) + aliases=$(echo "$crt_data" | grep DNS:) + aliases=$(echo "$aliases" | sed -e "s/DNS://g" -e "s/,//g") + aliases=$(echo "$aliases" | tr ' ' '\n' | sed "/^$/d") + aliases=$(echo "$aliases" | egrep -v "^$domain,?$") + aliases=$(echo "$aliases" | sed -e ':a;N;$!ba;s/\n/,/g') + + # Parsing domain + parse_object_kv_list $(grep "DOMAIN='$domain'" $USER_DATA/web.conf) + + # Split aliases into array + IFS=',' read -r -a ALIASES <<< "$ALIAS" + + # Unset f_aliases + f_aliases='' + + # Loop through all crt aliases + for alias in ${aliases//,/ }; do + # Validate if the alias still exists in web.conf + if [[ ",$ALIAS," =~ ,$alias, ]]; then + f_aliases+="$alias," + fi + done + + # Remove leading comma + if [[ ${f_aliases: -1} = ',' ]]; then f_aliases=${f_aliases::-1}; fi + + # Write the filtered alias list to the default var + aliases=$f_aliases + + msg=$($BIN/v-add-letsencrypt-domain "$user" "$domain" "$aliases") + if [ $? -ne 0 ]; then + echo "$msg" + log_event "$E_INVALID" "$domain $msg" + $BIN/v-log-action "$user" "Error" "Web" "Let's Encrypt SSL certificate update failed (Domain: $domain)." + if [ -z "$fail_counter" ]; then + add_object_key "web" 'DOMAIN' "$domain" 'LETSENCRYPT_FAIL_COUNT' 'LETSENCRYPT' + fi + ((fail_counter++)) + update_object_value 'web' 'DOMAIN' "$domain" '$LETSENCRYPT_FAIL_COUNT' "$fail_counter" + else + $BIN/v-log-action "$user" "Info" "Web" "Let's Encrypt SSL certificate renewed (Domain: $domain)." + fi + + if [ -n "$UPDATE_HOSTNAME_SSL" ] && [ "$UPDATE_HOSTNAME_SSL" = "yes" ]; then + hostname=$(hostname -f) + if [ "$hostname" = "$domain" ]; then + $BIN/v-update-host-certificate "$user" "$domain" + fi + fi + + fi + done + + for domain in $(search_objects 'mail' 'LETSENCRYPT' 'yes' 'DOMAIN'); do + + domain_suspended="$(get_object_value 'mail' 'DOMAIN' "$domain" '$SUSPENDED')" + if [ "$domain_suspended" = "yes" ]; then + continue + fi + + fail_counter="$(get_object_value 'mail' 'DOMAIN' "$domain" '$LETSENCRYPT_FAIL_COUNT')" + if [[ "$fail_counter" -gt "$max_LE_failures" ]]; then + continue + fi + + crt_data=$(openssl x509 -text -in $USER_DATA/ssl/mail.$domain.crt) + not_after=$(echo "$crt_data" | grep "Not After" | cut -f 2,3,4 -d :) + expiration=$(date -d "$not_after" +%s) + now=$(date +%s) + seconds_valid=$((expiration - now)) + days_valid=$((seconds_valid / 86400)) + if [[ "$days_valid" -lt 31 ]]; then + if [ $lecounter -gt 0 ]; then + sleep 10 + fi + ((lecounter++)) + msg=$($BIN/v-add-letsencrypt-domain "$user" "$domain" "" "yes") + if [ $? -ne 0 ]; then + echo "$msg" + $BIN/v-log-action "$user" "Error" "Web" "Let's Encrypt SSL certificate update failed (Domain: $domain)." + log_event "$E_INVALID" "$domain $msg" + if [ -z "$fail_counter" ]; then + add_object_key "mail" 'DOMAIN' "$domain" 'LETSENCRYPT_FAIL_COUNT' 'LETSENCRYPT' + fi + ((fail_counter++)) + update_object_value 'mail' 'DOMAIN' "$domain" '$LETSENCRYPT_FAIL_COUNT' "$fail_counter" + else + $BIN/v-log-action "$user" "Info" "Web" "Let's Encrypt SSL certificate renewed (Domain: $domain)." + fi + fi + done + +done + +# Restart related services +$BIN/v-restart-web +$BIN/v-restart-mail + +if [ -n "$PROXY_SYSTEM" ]; then + $BIN/v-restart-proxy +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +log_event "$OK" "$EVENT" + +exit diff --git a/bin/v-update-mail-domain-disk b/bin/v-update-mail-domain-disk new file mode 100755 index 0000000..30f3984 --- /dev/null +++ b/bin/v-update-mail-domain-disk @@ -0,0 +1,71 @@ +#!/bin/bash +# info: update mail domain disk usage +# options: USER DOMAIN +# +# example: v-update-mail-domain-disk admin example.com +# +# This function updates domain disk usage. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn +# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ? + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DOMAIN' +is_format_valid 'user' 'domain' +is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_valid 'mail' 'DOMAIN' "$domain" +if [ -z "$MAIL_SYSTEM" ] || [ "$MAIL_SYSTEM" = 'remote' ]; then + exit +fi + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Starting loop +dom_disk=0 +for account in $($BIN/v-list-mail-accounts $user $domain plain | cut -f 1); do + home_dir=$HOMEDIR/$user/mail/$domain/$account + if [ -e "$home_dir" ]; then + udisk=$(nice -n 19 du -shm $home_dir | cut -f 1) + else + udisk=0 + fi + update_object_value "mail/$domain" 'ACCOUNT' "$account" '$U_DISK' "$udisk" + dom_disk=$((dom_disk + udisk)) +done + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +update_object_value 'mail' 'DOMAIN' "$domain" '$U_DISK' "$dom_disk" +recalc_user_disk_usage + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-update-mail-domain-ssl b/bin/v-update-mail-domain-ssl new file mode 100755 index 0000000..ab11d61 --- /dev/null +++ b/bin/v-update-mail-domain-ssl @@ -0,0 +1,103 @@ +#!/bin/bash +# info: updating ssl certificate for domain +# options: USER DOMAIN SSL_DIR [RESTART] +# +# example: v-update-mail-domain-ssl admin domain.com /home/admin/tmp +# +# This function updates the SSL certificate for a domain. Parameter ssl_dir is a path +# to directory where 2 or 3 ssl files can be found. Certificate file +# domain.tld.crt and its key domain.tld.key are mandatory. Certificate +# authority domain.tld.ca file is optional. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 +ssl_dir=$3 +restart=$4 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# shellcheck source=/usr/local/hestia/func/ip.sh +source $HESTIA/func/ip.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn +# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ? + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '3' "$#" 'USER DOMAIN SSL_DIR [RESTART]' +is_format_valid 'user' 'domain' 'ssl_dir' +is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'mail' 'DOMAIN' "$domain" +is_object_unsuspended 'mail' 'DOMAIN' "$domain" +is_object_value_exist 'mail' 'DOMAIN' "$domain" '$SSL' +is_web_domain_cert_valid + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Deleting old certificate +rm -f $HOMEDIR/$user/conf/web/$domain/ssl/mail.$domain.* +rm -f $USER_DATA/ssl/mail.$domain.* + +# Add certificate to Hestia user configuration data directory +if [ -f "$ssl_dir/$domain.crt" ]; then + cp -f $ssl_dir/$domain.crt $USER_DATA/ssl/mail.$domain.crt + cp -f $ssl_dir/$domain.key $USER_DATA/ssl/mail.$domain.key + cp -f $ssl_dir/$domain.crt $USER_DATA/ssl/mail.$domain.pem + if [ -e "$ssl_dir/$domain.ca" ]; then + cp -f $ssl_dir/$domain.ca $USER_DATA/ssl/mail.$domain.ca + echo >> $USER_DATA/ssl/mail.$domain.pem + cat $USER_DATA/ssl/mail.$domain.ca >> $USER_DATA/ssl/mail.$domain.pem + fi +fi + +chmod 660 $USER_DATA/ssl/mail.$domain.* + +# Add certificate to user home directory +cp -f $USER_DATA/ssl/mail.$domain.crt $HOMEDIR/$user/conf/mail/$domain/ssl/$domain.crt +cp -f $USER_DATA/ssl/mail.$domain.key $HOMEDIR/$user/conf/mail/$domain/ssl/$domain.key +cp -f $USER_DATA/ssl/mail.$domain.pem $HOMEDIR/$user/conf/mail/$domain/ssl/$domain.pem +if [ -e "$USER_DATA/ssl/mail.$domain.ca" ]; then + cp -f $USER_DATA/ssl/mail.$domain.ca $HOMEDIR/$user/conf/mail/$domain/ssl/$domain.ca +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Restarting mail server +$BIN/v-restart-mail "$restart" +check_result $? "Mail restart failed" > /dev/null + +# Restarting web server +$BIN/v-restart-web "$restart" +check_result $? "Web restart failed" > /dev/null + +$BIN/v-restart-proxy "$restart" +check_result $? "Proxy restart failed" > /dev/null + +# Logging +$BIN/v-log-action "$user" "Info" "Mail" "SSL certificate updated (Domain: $domain)." +log_event "$OK" "$EVENT" + +exit diff --git a/bin/v-update-mail-domains-disk b/bin/v-update-mail-domains-disk new file mode 100755 index 0000000..3b91d07 --- /dev/null +++ b/bin/v-update-mail-domains-disk @@ -0,0 +1,65 @@ +#!/bin/bash +# info: calculate disk usage for all mail domains +# options: USER +# +# example: v-update-mail-domains-disk admin +# +# This function calculates disk usage for all mail domains. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'USER' +is_format_valid 'user' +is_system_enabled "$MAIL_SYSTEM" 'MAIL_SYSTEM' +is_object_valid 'user' 'USER' "$user" +if [ -z "$MAIL_SYSTEM" ] || [ "$MAIL_SYSTEM" = 'remote' ]; then + exit +fi + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Starting loop +for domain in $($BIN/v-list-mail-domains $user plain | cut -f 1); do + dom_disk=0 + for account in $($BIN/v-list-mail-accounts $user $domain plain | cut -f 1); do + home_dir=$HOMEDIR/$user/mail/$domain/$account + if [ -e "$home_dir" ]; then + udisk=$(nice -n 19 du -shm $home_dir | cut -f 1) + else + udisk=0 + fi + update_object_value "mail/$domain" 'ACCOUNT' "$account" '$U_DISK' "$udisk" + dom_disk=$((dom_disk + udisk)) + done + update_object_value 'mail' 'DOMAIN' "$domain" '$U_DISK' "$dom_disk" +done + +recalc_user_disk_usage + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-update-mail-templates b/bin/v-update-mail-templates new file mode 100755 index 0000000..13c095e --- /dev/null +++ b/bin/v-update-mail-templates @@ -0,0 +1,53 @@ +#!/bin/bash +# info: update mail templates +# options: [RESTART] [SKIP] +# +# example: v-update-mail-templates +# +# This function for obtaining updated webmail templates from Hestia package. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +restart=$1 +skip=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Update templates +cp -rf $HESTIA_INSTALL_DIR/templates/mail $HESTIA/data/templates/ + +# Rebuild mail domains if mail services are enabled +if [ -z "$skip" ]; then + if [ -n "$MAIL_SYSTEM" ]; then + for user in $($BIN/v-list-sys-users plain); do + $BIN/v-rebuild-mail-domains "$user" no + done + fi +fi +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +if [ -n "$restart" ] || [ "$restart" == "yes" ]; then + # Restarting web server + $BIN/v-restart-web "$restart" + check_result $? "restart" > /dev/null 2>&1 + + $BIN/v-restart-proxy "$restart" + check_result $? "restart" > /dev/null 2>&1 +fi +$BIN/v-log-action "system" "Info" "Updates" "Default mail domain templates updated." +exit diff --git a/bin/v-update-sys-defaults b/bin/v-update-sys-defaults new file mode 100755 index 0000000..6953c44 --- /dev/null +++ b/bin/v-update-sys-defaults @@ -0,0 +1,44 @@ +#!/bin/bash +# info: update default key database +# options: [SYSTEM] +# +# example: v-update-sys-defaults +# example: v-update-sys-defaults user +# +# This function updates the known key/value pair database + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +system=$1 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/syshealth.sh +source $HESTIA/func/syshealth.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +if [ -n "$system" ]; then + syshealth_update_${system}_config_format +else + syshealth_update_web_config_format + syshealth_update_mail_config_format + syshealth_update_dns_config_format + syshealth_update_db_config_format + syshealth_update_user_config_format +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +log_event "$OK" "$ARGUMENTS" diff --git a/bin/v-update-sys-hestia b/bin/v-update-sys-hestia new file mode 100755 index 0000000..57604fc --- /dev/null +++ b/bin/v-update-sys-hestia @@ -0,0 +1,63 @@ +#!/bin/bash +# info: update hestia package/configs +# options: PACKAGE +# +# example: v-update-sys-hestia hestia-php +# +# This function runs as apt update trigger. It pulls shell script from hestia +# server and runs it. (hestia, hestia-nginx and hestia-php are valid options) + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +package=$1 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +# Checking arg number +check_args '1' "$#" 'PACKAGE' +is_hestia_package "hestia hestia-nginx hestia-php" "$package" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Update repo +if [ -f '/etc/redhat-release' ]; then + dnf makecache +else + apt-get update -o Dir::Etc::sourcelist="sources.list.d/hestia.list" \ + -o Dir::Etc::sourceparts="-" -o APT::Get::List-Cleanup="0" -qq +fi + +# Update hestia package +if [ -f '/etc/redhat-release' ]; then + dnf install $package -q > /dev/null 2>&1 +else + apt-get install $package -qq > /dev/null 2>&1 +fi +check_result $? "$package update failed" "$E_UPDATE" + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-update-sys-hestia-all b/bin/v-update-sys-hestia-all new file mode 100755 index 0000000..aba29cf --- /dev/null +++ b/bin/v-update-sys-hestia-all @@ -0,0 +1,37 @@ +#!/bin/bash +# info: update all hestia packages +# options: NONE +# +# example: v-update-sys-hestia-all +# +# This function of updating all hestia packages + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Starting update loop +for package in hestia hestia-nginx hestia-php; do + $BIN/v-update-sys-hestia "$package" +done + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-update-sys-hestia-git b/bin/v-update-sys-hestia-git new file mode 100755 index 0000000..47c0680 --- /dev/null +++ b/bin/v-update-sys-hestia-git @@ -0,0 +1,385 @@ +#!/bin/bash +# info: Install update from Git repository +# options: REPOSITORY BRANCH INSTALL +# +# example: v-update-sys-hestia-git hestiacp staging/beta install +# # Will download from the hestiacp repository +# # Pulls code from staging/beta branch +# # install: installs package immediately +# # install-auto: installs package and schedules automatic updates from Git +# +# Downloads and compiles/installs packages from GitHub repositories + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" +# define NodeJS version for download (required for building JS/CSS) +nodejs_ver="20" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +# Detect and install NodeJS if necessary +if [ -z $(which "node") ]; then + read -p "NodeJS not found. Install now to proceed? [Y/n] " answer + if [ "$answer" = 'y' ] || [ "$answer" = 'Y' ]; then + curl -fsSL "https://deb.nodesource.com/setup_$nodejs_ver.x" | bash - &&\ + sudo apt-get install -y nodejs + else + exit 0 + fi +fi + +# Define download function +download_file() { + local url=$1 + local destination=$2 + local force=$3 + + # Default destination is the current working directory + local dstopt="" + + if [ ! -z "$(echo "$url" | grep -E "\.(gz|gzip|bz2|zip|xz)$")" ]; then + # When an archive file is downloaded it will be first saved localy + dstopt="--directory-prefix=$ARCHIVE_DIR" + local is_archive="true" + local filename="${url##*/}" + if [ -z "$filename" ]; then + echo >&2 "[!] No filename was found in url, exiting ($url)" + exit 1 + fi + if [ ! -z "$force" ] && [ -f "$ARCHIVE_DIR/$filename" ]; then + rm -f $ARCHIVE_DIR/$filename + fi + elif [ ! -z "$destination" ]; then + # Plain files will be written to specified location + dstopt="-O $destination" + fi + # check for corrupted archive + if [ -f "$ARCHIVE_DIR/$filename" ] && [ "$is_archive" = "true" ]; then + tar -tzf "$ARCHIVE_DIR/$filename" > /dev/null 2>&1 + if [ $? -ne 0 ]; then + echo >&2 "[!] Archive $ARCHIVE_DIR/$filename is corrupted, redownloading" + rm -f $ARCHIVE_DIR/$filename + fi + fi + + if [ ! -f "$ARCHIVE_DIR/$filename" ]; then + [ "$HESTIA_DEBUG" ] && echo >&2 DEBUG: wget $url -q $dstopt --show-progress --progress=bar:force --limit-rate=3m + wget $url -q $dstopt --show-progress --progress=bar:force --limit-rate=3m + if [ $? -ne 0 ]; then + echo >&2 "[!] Archive $ARCHIVE_DIR/$filename is corrupted and exit script" + rm -f $ARCHIVE_DIR/$filename + exit 1 + fi + fi + + if [ ! -z "$destination" ] && [ "$is_archive" = "true" ]; then + if [ "$destination" = "-" ]; then + cat "$ARCHIVE_DIR/$filename" + elif [ -d "$(dirname $destination)" ]; then + cp "$ARCHIVE_DIR/$filename" "$destination" + fi + fi +} + +get_branch_file() { + local filename=$1 + local destination=$2 + [ "$HESTIA_DEBUG" ] && echo >&2 DEBUG: Get branch file "$filename" to "$destination" + if [ "$use_src_folder" == 'true' ]; then + if [ -z "$destination" ]; then + [ "$HESTIA_DEBUG" ] && echo >&2 DEBUG: cp -f "$SRC_DIR/$filename" ./ + cp -f "$SRC_DIR/$filename" ./ + else + [ "$HESTIA_DEBUG" ] && echo >&2 DEBUG: cp -f "$SRC_DIR/$filename" "$destination" + cp -f "$SRC_DIR/$filename" "$destination" + fi + else + download_file "https://raw.githubusercontent.com/$REPO/$branch/$filename" "$destination" $3 + fi +} + +# Set compiling directory +BUILD_DIR='/tmp/hestiacp-src' +INSTALL_DIR='/tmp/hestia-src' +SRC_DIR="$(cd "$(dirname "$0")/.." && pwd)" +ARCHIVE_DIR="/tmp/hestia-src/archive/" +architecture="$(arch)" +if [ $architecture == 'aarch64' ]; then + BUILD_ARCH='arm64' +else + BUILD_ARCH='amd64' +fi +RPM_DIR="$BUILD_DIR/rpm/" +DEB_DIR="$BUILD_DIR/deb/" +if [ -f '/etc/redhat-release' ]; then + BUILD_RPM=true + BUILD_DEB=false + OSTYPE='rhel' +else + BUILD_RPM=false + BUILD_DEB=true + OSTYPE='debian' +fi + +# Set command variables +fork=$1 +branch=$2 +install=$3 + +# Allow the use of username:branch instead of username branch +# Both fork and branch names can't contain a : anyway +if [ -z "$branch" ]; then + branch=$(echo "$fork" | cut -d ":" -f2) + fork=$(echo "$fork" | cut -d ":" -f1) +fi + +# Set Version for compiling +BUILD_VER=$(curl -s https://raw.githubusercontent.com/$fork/hestiacp/$branch/src/deb/hestia/control | grep "Version:" | cut -d' ' -f2) +HESTIA_V="${BUILD_VER}_${BUILD_ARCH}" + +# Create build directories +rm -rf $BUILD_DIR +mkdir -p $DEB_DIR +mkdir -p $ARCHIVE_DIR + +# Set package dependencies for compiling +SOFTWARE='build-essential libxml2-dev libz-dev libcurl4-gnutls-dev unzip openssl libssl-dev pkg-config setpriv' + +# Define a timestamp function +timestamp() { + date +%s +} + +# Warning prompt to be used if auto-install flag is not specified +warning_message() { + echo "" + echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + echo "WARNING - Development builds should not be installed on" + echo "systems with live production data without understanding" + echo "the potential risks that are involved!" + echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + echo "" +} + +# Build installation +install_build() { + # Install all available packages + echo "Installing packages..." + if [ "$OSTYPE" = 'rhel' ]; then + for i in $RPM_DIR/*.rpm; do + dnf -y install $i + if [ $? -ne 0 ]; then + exit 1 + fi + done + else + for i in $DEB_DIR/*.deb; do + dpkg -i $i + if [ $? -ne 0 ]; then + exit 1 + fi + done + fi + unset $answer + # Remove temporary files + rm -rf $BUILD_DIR +} + +# Set install flags +if [ -n "$fork" ]; then + fork_check=$(curl -s --head -w %{http_code} https://raw.githubusercontent.com/$fork/hestiacp/main/src/deb/hestia/control -o /dev/null) + if [ "$fork_check" -ne "200" ]; then + echo "ERROR: invalid repository name specified." + exit 1 + else + echo "[!] Download code from GitHub repository: $fork" + fi +else + fork="hestiacp" +fi + +if [ -n "$branch" ]; then + echo https://raw.githubusercontent.com/$fork/hestiacp/$branch/src/deb/hestia/control + branch_check=$(curl -s --head -w %{http_code} https://raw.githubusercontent.com/$fork/hestiacp/$branch/src/deb/hestia/control -o /dev/null) + if [ $branch_check -ne "200" ]; then + echo "ERROR: invalid branch name specified." + exit 1 + else + $BIN/v-change-sys-config-value 'RELEASE_BRANCH' "$branch" + echo "[!] Changed system release branch to: $branch." + fi +else + source /usr/local/hestia/conf/hestia.conf + branch=$RELEASE_BRANCH + branch_check=$(curl -s --head -w %{http_code} https://raw.githubusercontent.com/$fork/hestiacp/$branch/src/deb/hestia/control -o /dev/null) + if [ "$branch_check" -ne "200" ]; then + echo "ERROR: invalid branch name specified." + exit 1 + fi +fi + +if [ -z "$branch" ]; then + echo "ERROR: No branch detected." + exit +fi +REPO="$fork/hestiacp" +# Forward slashes in branchname are replaced with dashes to match foldername in github archive. +branch_dash=$(echo "$branch" | sed 's/\//-/g') + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Install needed software +if [ "$OSTYPE" = 'rhel' ]; then + # Set package dependencies for compiling + SOFTWARE=' rpm-build wget tar git curl unzip' + + echo "Updating system DNF repositories..." + dnf install -y -q 'dnf-command(config-manager)' + dnf install -y -q dnf-plugins-core + dnf config-manager --set-enabled powertools > /dev/null 2>&1 + dnf config-manager --set-enabled PowerTools > /dev/null 2>&1 + dnf upgrade -y -q + echo "Installing dependencies for compilation..." + dnf install -y -q $SOFTWARE +else + # Set package dependencies for compiling + SOFTWARE='build-essential wget tar git curl unzip' + + echo "Updating system APT repositories..." + apt-get -qq update > /dev/null 2>&1 + echo "Installing dependencies for compilation..." + apt-get -qq install -y $SOFTWARE > /dev/null 2>&1 + + # Fix for Debian PHP Envroiment + if [ $BUILD_ARCH == "amd64" ]; then + if [ ! -L /usr/local/include/curl ]; then + ln -s /usr/include/x86_64-linux-gnu/curl /usr/local/include/curl + fi + fi +fi + +# Set git repository raw path +GIT_REP='https://raw.githubusercontent.com/'$REPO'/'$branch'/src/deb' + +# Generate Links for sourcecode +HESTIA_ARCHIVE_LINK='https://github.com/'$REPO'/archive/'$branch'.tar.gz' +echo $HESTIA_ARCHIVE_LINK + +echo "Building Hestia Control Panel package..." + +BUILD_DIR_HESTIA=$BUILD_DIR/hestia_$HESTIA_V + +# Change to build directory +cd $BUILD_DIR + +if [ "$KEEPBUILD" != 'true' ] || [ ! -d "$BUILD_DIR_HESTIA" ]; then + # Check if target directory exist + if [ -d $BUILD_DIR_HESTIA ]; then + rm -r $BUILD_DIR_HESTIA + fi + + # Create directory + mkdir -p $BUILD_DIR_HESTIA +fi + +cd $BUILD_DIR +rm -rf $BUILD_DIR/hestiacp-$branch_dash +# Download and unpack source files +if [ "$use_src_folder" == 'true' ]; then + [ "$HESTIA_DEBUG" ] && echo DEBUG: cp -rf "$SRC_DIR/" $BUILD_DIR/hestiacp-$branch_dash + cp -rf "$SRC_DIR/" $BUILD_DIR/hestiacp-$branch_dash +elif [ -d $SRC_DIR ]; then + download_file $HESTIA_ARCHIVE_LINK '-' 'fresh' | tar xz +fi + +mkdir -p $BUILD_DIR_HESTIA/usr/local/hestia + +# Move needed directories +cd $BUILD_DIR/hestiacp-$branch_dash + +npm install +npm run build + +cp -rf bin func install web $BUILD_DIR_HESTIA/usr/local/hestia/ + +# Set permissions +find $BUILD_DIR_HESTIA/usr/local/hestia/ -type f -exec chmod -x {} \; + +# Allow send email via /usr/local/hestia/web/inc/mail-wrapper.php via cli +chmod +x $BUILD_DIR_HESTIA/usr/local/hestia/web/inc/mail-wrapper.php +# Allow the executable to be executed +chmod +x $BUILD_DIR_HESTIA/usr/local/hestia/bin/* +find $BUILD_DIR_HESTIA/usr/local/hestia/install/ \( -name '*.sh' \) -exec chmod +x {} \; +chmod -x $BUILD_DIR_HESTIA/usr/local/hestia/install/*.sh +chown -R root:root $BUILD_DIR_HESTIA + +if [ "$BUILD_DEB" = true ]; then + # Get Debian package files + mkdir -p $BUILD_DIR_HESTIA/DEBIAN + get_branch_file 'src/deb/hestia/control' "$BUILD_DIR_HESTIA/DEBIAN/control" + if [ "$BUILD_ARCH" != "amd64" ]; then + sed -i "s/amd64/${BUILD_ARCH}/g" "$BUILD_DIR_HESTIA/DEBIAN/control" + fi + get_branch_file 'src/deb/hestia/copyright' "$BUILD_DIR_HESTIA/DEBIAN/copyright" + get_branch_file 'src/deb/hestia/preinst' "$BUILD_DIR_HESTIA/DEBIAN/preinst" + get_branch_file 'src/deb/hestia/postinst' "$BUILD_DIR_HESTIA/DEBIAN/postinst" + chmod +x $BUILD_DIR_HESTIA/DEBIAN/postinst + chmod +x $BUILD_DIR_HESTIA/DEBIAN/preinst + + echo Building Hestia DEB + dpkg-deb -Zxz --build $BUILD_DIR_HESTIA $DEB_DIR +fi + +if [ "$BUILD_RPM" = true ]; then + # Get RHEL package files + get_branch_file 'src/rpm/hestia/hestia.spec' "${BUILD_DIR_HESTIA}/hestia.spec" + sed -i "s/%HESTIA-VERSION%/${HESTIA_V}/g" "${BUILD_DIR_HESTIA}/hestia.spec" + get_branch_file 'src/rpm/hestia/hestia.service' "${BUILD_DIR_HESTIA}/hestia.service" + + # Build RPM package + mkdir -p $BUILD_DIR/rpmbuild + echo Building Hestia RPM + rpmbuild -bb --define "sourcedir $BUILD_DIR_HESTIA" --buildroot=$BUILD_DIR/rpmbuild/ ${BUILD_DIR_HESTIA}/hestia.spec > ${BUILD_DIR_HESTIA}.rpm.log + cp ~/rpmbuild/RPMS/$(arch)/hestia-*.rpm $RPM_DIR + rm ~/rpmbuild/RPMS/$(arch)/hestia-*.rpm + rm -rf $BUILD_DIR/rpmbuild +fi + +# clear up the source folder +if [ "$KEEPBUILD" != 'true' ]; then + rm -r $BUILD_DIR_HESTIA + rm -rf hestiacp-$branch_dash +fi +cd $BUILD_DIR/hestiacp-$branch_dash + +# Installation steps +if [ "$install" = "install" ] || [ "$install" = "yes" ] || [ "$install" = "install-auto" ]; then + install_build + if [ "$install" = "install-auto" ]; then + $BIN/v-add-cron-hestia-autoupdate git + fi +else + warning_message + read -p "Do you wish to proceed with the installation? [y/n] " answer + if [ "$answer" = 'y' ] || [ "$answer" = 'Y' ]; then + install_build + unset $answer + else + echo "Installation of development build aborted." + echo "Removing temporary files..." + rm -rf $BUILD_DIR + unset "$answer" + echo "" + fi +fi diff --git a/bin/v-update-sys-ip b/bin/v-update-sys-ip new file mode 100755 index 0000000..1d3720c --- /dev/null +++ b/bin/v-update-sys-ip @@ -0,0 +1,182 @@ +#!/bin/bash +# info: update system IP +# options: NONE +# +# example: v-update-sys-ip +# # Intended for internal usage +# +# This function scans configured IP in the system and register them with Hestia +# internal database. This call is intended for use on vps servers, where IP is +# set by hypervisor. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/ip.sh +source $HESTIA/func/ip.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Listing system IP addresses +nics="$(ip -d -j link show | jq -r '.[] | if .link_type == "loopback" then empty else .ifname end')" + +for nic in $nics; do + nic_type="$(ip -d -j link show "$nic" | jq -r '.[].linkinfo.info_kind')" + if [ "$nic_type" = "bridge" ]; then + break + fi + nic_ipv4s="$(ip -4 -d -j addr show "$nic" | jq -r '.[] | select(length > 0) | .addr_info[] | if .scope == "global" then .local else empty end')" + if [ -z "$ips" ]; then + ips="$nic_ipv4s" + else + ips="$ips $nic_ipv4s" + fi +done + +v_ips="$(ls $HESTIA/data/ips/)" +ip_num="$(echo "$ips" | wc -w)" +v_ip_num="$(echo "$v_ips" | wc -w)" + +# Checking primary IP change +if [ "$ip_num" -eq "1" ] && [ "$v_ip_num" -eq "1" ]; then + if [ -n "$v_ips" ] && [ "$ips" != "$v_ips" ]; then + new_ip="$ips" + old_ip="$v_ips" + fi +fi + +# Updating configs +if [ -n "$old_ip" ]; then + mv $HESTIA/data/ips/$old_ip $HESTIA/data/ips/$new_ip + + # Generating timestamp + new_timestamp + + # Updating IP's values + ip="$new_ip" + interface="$(ip -d -j addr show | jq --arg IP "$ip" -r '.[] | if .addr_info[].local == $IP then .ifname else empty end')" + prefixlen="$(ip -d -j addr show | jq --arg IP "$ip" -r '.[].addr_info[] | if .local == $IP then .prefixlen else empty end')" + netmask="$(convert_cidr "$prefixlen")" + update_ip_value '$INTERFACE' "$interface" + update_ip_value '$NETMASK' "$netmask" + update_ip_value '$TIME' "$time" + update_ip_value '$DATE' "$date" + + # Updating PROXY + if [ -n "$PROXY_SYSTEM" ]; then + cd /etc/$PROXY_SYSTEM/conf.d + if [ -e "$old_ip.conf" ]; then + mv $old_ip.conf $new_ip.conf + sed -i "s/$old_ip/$new_ip/g" $new_ip.conf + fi + fi + + # Updating WEB + if [ -n "$WEB_SYSTEM" ]; then + cd /etc/$WEB_SYSTEM/conf.d + + if [ -e "$old_ip.conf" ]; then + mv $old_ip.conf $new_ip.conf + sed -i "s/$old_ip/$new_ip/g" $new_ip.conf + fi + + for user in $($BIN/v-list-sys-users plain); do + sed -i "s/$old_ip/$new_ip/g" $HESTIA/data/users/$user/web.conf + $BIN/v-rebuild-web-domains "$user" no + done + + if [ -e "/etc/apache2/mods-available/remoteip.conf" ]; then + sed -i "s/$old_ip/$new_ip/g" /etc/apache2/mods-available/remoteip.conf + fi + + if [ -e "/etc/apache2/mods-enabled/rpaf.conf" ]; then + sed -i "s/$old_ip/$new_ip/g" /etc/apache2/mods-enabled/rpaf.conf + fi + + $BIN/v-restart-proxy + $BIN/v-restart-web + fi + + # Updating MAIL + if [ -n "$IMAP_SYSTEM" ]; then + for user in $($BIN/v-list-sys-users plain); do + $BIN/v-rebuild-mail-domains "$user" no + done + $BIN/v-restart-mail + fi + + # Updating DNS + if [ -n "$DNS_SYSTEM" ]; then + for user in $($BIN/v-list-sys-users plain); do + sed -i "s/$old_ip/$new_ip/g" $HESTIA/data/users/$user/dns.conf + sed -i "s/$old_ip/$new_ip/g" $HESTIA/data/users/$user/dns/*.conf + $BIN/v-rebuild-dns-domains "$user" no + done + $BIN/v-restart-dns + fi + + # Updating FTP + if [ -n "$FTP_SYSTEM" ] && [ "$FTP_SYSTEM" = 'vsftpd' ]; then + ftp_conf="$(find /etc/ -maxdepth 2 -name $FTP_SYSTEM.conf)" + if [ -n "$ftp_conf" ]; then + sed -i "s/$old_ip/$new_ip/g" "$ftp_conf" + $BIN/v-restart-ftp + fi + fi + + # Updating firewall + if [ -n "$FIREWALL_SYSTEM" ]; then + sed -i "s/$old_ip/$new_ip/g" $HESTIA/data/firewall/*.conf + $BIN/v-update-firewall + fi +fi + +# Adding system IP +for ip in $ips; do + check_ip="$(ip addr list | grep -w "$ip")" + if [ ! -e "$HESTIA/data/ips/$ip" ] && [ -n "$check_ip" ]; then + interface="$(ip -d -j addr show | jq --arg IP "$ip" -r '.[] | if .addr_info[].local == $IP then .ifname else empty end')" + prefixlen="$(ip -d -j addr show | jq --arg IP "$ip" -r '.[].addr_info[] | if .local == $IP then .prefixlen else empty end')" + netmask="$(convert_cidr "$prefixlen")" + $BIN/v-add-sys-ip "$ip" "$netmask" "$interface" + elif [ -e "/etc/nginx/conf.d/$ip.conf" ]; then + process_http2_directive "/etc/nginx/conf.d/$ip.conf" + fi +done + +# Updating NAT +pub_ipv4="$(curl -fsLm5 --retry 2 --ipv4 https://ip.hestiacp.com/)" +if [ ! -e "$HESTIA/data/ips/$pub_ipv4" ]; then + if [ -z "$(grep -R "$pub_ipv4" $HESTIA/data/ips/)" ]; then + ip="$(ls -t $HESTIA/data/ips/ | head -n1)" + $BIN/v-change-sys-ip-nat "$ip" "$pub_ipv4" + fi +fi + +# Updating IP usage counters +$BIN/v-update-sys-ip-counters + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-update-sys-ip-counters b/bin/v-update-sys-ip-counters new file mode 100755 index 0000000..fbb3c93 --- /dev/null +++ b/bin/v-update-sys-ip-counters @@ -0,0 +1,70 @@ +#!/bin/bash +# info: update IP usage counters +# options: IP +# +# example: v-update-sys-ip-counters +# +# Function updates usage U_WEB_ADOMAINS and U_SYS_USERS counters. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +ip="$1" + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/ip.sh +source $HESTIA/func/ip.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '0' "$#" 'IP' +if [ -n "$ip" ]; then + is_format_valid 'ip' + is_ip_valid +fi + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Creating user_list +if [ -z "$ip" ]; then + ip_list="$(ls $HESTIA/data/ips/)" +else + ip_list="$ip" +fi + +# Updating user stats +for ip in $ip_list; do + + # Calculate usage + ip_usage="$(grep -H "$ip" $HESTIA/data/users/*/web.conf)" + web_domains="$(echo "$ip_usage" | sed '/^$/d' | wc -l)" + sys_users="$(echo "$ip_usage" | cut -f7 -d/ | sort -u | tr '\n' ',' | sed "s/,$//g")" + + # Update counters + update_ip_value '$U_WEB_DOMAINS' "$web_domains" + update_ip_value '$U_SYS_USERS' "$sys_users" +done + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-update-sys-queue b/bin/v-update-sys-queue new file mode 100755 index 0000000..4e45716 --- /dev/null +++ b/bin/v-update-sys-queue @@ -0,0 +1,62 @@ +#!/bin/bash +# info: update system queue +# options: PIPE +# +# example: v-update-sys-queue +# +# This function is responsible queue processing. Restarts of services, +# scheduled backups, web log parsing and other heavy resource consuming +# operations are handled by this script. It helps to optimize system behaviour. +# In a nutshell Apache will be restarted only once even if 10 domains are +# added or deleted. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# +# Argument definition +queue=$1 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'QUEUE' + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +b_task=$(ps auxf | grep -v "grep" | grep "$BIN/v-update-sys-queue backup") +b_task=$(echo "$b_task" | grep -v sudo | wc -l) +d_task=$(ps auxf | grep -v "grep" | grep "$BIN/v-update-sys-queue dns") +d_task=$(echo "$d_task" | grep -v sudo | wc -l) +if [ "$b_task" -gt 2 ] || [ "$d_task" -gt 2 ]; then + exit +fi + +# Defining pipe functions +case $queue in + restart) bash $HESTIA/data/queue/$queue.pipe > /dev/null 2>&1 ;; + webstats) bash $HESTIA/data/queue/$queue.pipe > /dev/null 2>&1 ;; + backup) bash $HESTIA/data/queue/$queue.pipe > /dev/null 2>&1 ;; + disk) bash $HESTIA/data/queue/$queue.pipe > /dev/null 2>&1 ;; + daily) bash $HESTIA/data/queue/$queue.pipe > /dev/null 2>&1 ;; + traffic) bash $HESTIA/data/queue/$queue.pipe > /dev/null 2>&1 ;; + dns-cluster) bash $HESTIA/data/queue/$queue.pipe > /dev/null 2>&1 ;; + letsencrypt) bash $HESTIA/data/queue/$queue.pipe > /dev/null 2>&1 ;; + *) check_args '1' '0' 'QUEUE' ;; +esac + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-update-sys-rrd b/bin/v-update-sys-rrd new file mode 100755 index 0000000..7d374ee --- /dev/null +++ b/bin/v-update-sys-rrd @@ -0,0 +1,134 @@ +#!/bin/bash +# info: update system rrd charts +# options: NONE +# +# example: v-update-sys-rrd +# +# This function is wrapper for all rrd functions. It updates all +# v-update-sys-rrd_* at once. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Checking rrddir +if [ ! -d "$RRD" ]; then + mkdir -p $RRD +fi + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Checking daily period +if [ -e "$RRD/daily.rrd" ]; then + mtime=$(stat -c "%Y" $RRD/daily.rrd) + ctime=$(date +%s) + dtime=$((ctime - mtime)) + # Update every 5 minute + if [ "$dtime" -gt '290' ]; then + touch $RRD/daily.rrd + periods="$periods daily" + fi +else + touch $RRD/daily.rrd + periods="$periods daily" +fi + +# Checking weekly period +if [ -e "$RRD/weekly.rrd" ]; then + mtime=$(stat -c "%Y" $RRD/weekly.rrd) + ctime=$(date +%s) + dtime=$((ctime - mtime)) + # Update every hour + if [ "$dtime" -gt '3590' ]; then + touch $RRD/weekly.rrd + periods="$periods weekly" + fi +else + touch $RRD/weekly.rrd + periods="$periods weekly" +fi + +# Checking monthly period +if [ -e "$RRD/monthly.rrd" ]; then + mtime=$(stat -c "%Y" $RRD/monthly.rrd) + ctime=$(date +%s) + dtime=$((ctime - mtime)) + # Update every 6 hours + if [ "$dtime" -gt '21590' ]; then + touch $RRD/monthly.rrd + periods="$periods monthly" + fi +else + touch $RRD/monthly.rrd + periods="$periods monthly" +fi + +# Checking yearly period +if [ -e "$RRD/yearly.rrd" ]; then + mtime=$(stat -c "%Y" $RRD/yearly.rrd) + ctime=$(date +%s) + dtime=$((ctime - mtime)) + # Update every 12 hours + if [ "$dtime" -gt '43190' ]; then + touch $RRD/yearly.rrd + periods="$periods yearly" + fi +else + touch $RRD/yearly.rrd + periods="$periods yearly" +fi + +# Updateing system stats +for period in $periods; do + + $BIN/v-update-sys-rrd-la "$period" > /dev/null 2>&1 + $BIN/v-update-sys-rrd-net "$period" > /dev/null 2>&1 + $BIN/v-update-sys-rrd-mem "$period" > /dev/null 2>&1 + $BIN/v-update-sys-rrd-ssh "$period" > /dev/null 2>&1 + + # Updating web stats + if [ -n "$WEB_SYSTEM" ]; then + $BIN/v-update-sys-rrd-$WEB_SYSTEM "$period" > /dev/null 2>&1 + fi + + if [ -n "$PROXY_SYSTEM" ]; then + $BIN/v-update-sys-rrd-$PROXY_SYSTEM "$period" > /dev/null 2>&1 + fi + + # Updating mail stats + if [ -n "$MAIL_SYSTEM" ] && [ "$MAIL_SYSTEM" != 'no' ]; then + $BIN/v-update-sys-rrd-mail "$period" > /dev/null 2>&1 + fi + + # Updating ftp stats + if [ -n "$FTP_SYSTEM" ] && [ "$FTP_SYSTEM" != 'no' ]; then + $BIN/v-update-sys-rrd-ftp "$period" > /dev/null 2>&1 + fi + + # Updating db stats + if [ -n "$DB_SYSTEM" ] && [ "$DB_SYSTEM" != 'no' ]; then + for type in ${DB_SYSTEM//,/ }; do + # Switching on db type + case $type in + mysql) $BIN/v-update-sys-rrd-mysql "$period" > /dev/null 2>&1 ;; + pgsql) $BIN/v-update-sys-rrd-pgsql "$period" > /dev/null 2>&1 ;; + esac + done + fi +done + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-update-sys-rrd-apache2 b/bin/v-update-sys-rrd-apache2 new file mode 100755 index 0000000..402ea1a --- /dev/null +++ b/bin/v-update-sys-rrd-apache2 @@ -0,0 +1,122 @@ +#!/bin/bash +# info: update apache2 rrd +# options: PERIOD +# +# example: v-update-sys-rrd-apache2 +# +# This function is for updating apache rrd database and graphic. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +period=${1-daily} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Switching on time period +case $period in + daily) + start='-1d' + end='now' + grid='MINUTE:30:HOUR:1:HOUR:4:0:%H:%M' + ;; + weekly) + start='-7d' + end='now' + grid='HOUR:8:DAY:1:DAY:1:0:%a %d' + ;; + monthly) + start='-1m' + end='now' + grid='WEEK:1:WEEK:1:WEEK:1:0:%b %d' + ;; + yearly) + start='-1y' + end='now' + grid='MONTH:1:YEAR:1:MONTH:2:2419200:%b' + ;; + *) exit $E_RRD ;; +esac + +# Checking directory +if [ ! -d "$RRD/web" ]; then + mkdir $RRD/web +fi + +# Checking database +if [ ! -e "$RRD/web/apache2.rrd" ]; then + # Adding database + rrdtool create $RRD/web/apache2.rrd --step $RRD_STEP \ + DS:A:GAUGE:600:U:U \ + RRA:AVERAGE:0.5:1:600 \ + RRA:AVERAGE:0.5:6:700 \ + RRA:AVERAGE:0.5:24:775 \ + RRA:AVERAGE:0.5:288:797 \ + RRA:MAX:0.5:1:600 \ + RRA:MAX:0.5:6:700 \ + RRA:MAX:0.5:24:775 \ + RRA:MAX:0.5:288:797 +fi + +# Parsing data +if [ "$period" = 'daily' ]; then + server_status=$(wget -qO- http://localhost:8081/server-status \ + | grep 'currently being processed' \ + | cut -f 2 -d '>' \ + | sed 's/requests currently being processed, //' \ + | cut -f 1,2 -d ' ') + active=$(echo "$server_status" | cut -f 1 -d ' ') + idle=$(echo "$server_status" | cut -f 1 -d ' ') + a=$((active + idle)) + + # Updating rrd database + rrdtool update $RRD/web/apache2.rrd N:$a +fi + +# Updating rrd graph +rrdtool graph $RRD/web/$period-apache2.png \ + --imgformat PNG \ + --height="150" \ + --width="670" \ + --start "$start" \ + --end "$end" \ + --vertical-label "Connections" \ + --x-grid "$grid" \ + -c "BACK#ffffff" \ + -c "SHADEA#ffffff" \ + -c "SHADEB#ffffff" \ + -c "FONT#555555" \ + -c "CANVAS#302c2d" \ + -c "GRID#666666" \ + -c "MGRID#AAAAAA" \ + -c "FRAME#302c2d" \ + -c "ARROW#FFFFFF" \ + DEF:a=$RRD/web/apache2.rrd:A:AVERAGE \ + COMMENT:'\r' \ + LINE1:a#fefda0:"Connections " \ + GPRINT:a:'LAST:Current\:''%8.0lf' \ + GPRINT:a:'MIN:Min\:''%8.0lf' \ + GPRINT:a:'MAX:Max\:''%8.0lf\j' &> /dev/null +result=$? + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +if [ "$result" -ne 0 ]; then + exit $E_RRD +fi + +exit diff --git a/bin/v-update-sys-rrd-ftp b/bin/v-update-sys-rrd-ftp new file mode 100755 index 0000000..73aba60 --- /dev/null +++ b/bin/v-update-sys-rrd-ftp @@ -0,0 +1,117 @@ +#!/bin/bash +# info: update ftp rrd +# options: PERIOD +# +# example: v-update-sys-rrd-ftp +# +# This function is for updating ftpd rrd database and graphic. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +period=${1-daily} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/conf/hestia.conf +source $HESTIA/conf/hestia.conf + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Switching on time period +case $period in + daily) + start='-1d' + end='now' + grid='MINUTE:30:HOUR:1:HOUR:4:0:%H:%M' + ;; + weekly) + start='-7d' + end='now' + grid='HOUR:8:DAY:1:DAY:1:0:%a %d' + ;; + monthly) + start='-1m' + end='now' + grid='WEEK:1:WEEK:1:WEEK:1:0:%b %d' + ;; + yearly) + start='-1y' + end='now' + grid='MONTH:1:YEAR:1:MONTH:2:2419200:%b' + ;; + *) exit "$E_RRD" ;; +esac + +# Checking directory +if [ ! -d "$RRD/ftp" ]; then + mkdir $RRD/ftp +fi + +# Checking database +if [ ! -e "$RRD/ftp/ftp.rrd" ]; then + # Adding database + rrdtool create $RRD/ftp/ftp.rrd --step $RRD_STEP \ + DS:A:GAUGE:600:U:U \ + RRA:AVERAGE:0.5:1:600 \ + RRA:AVERAGE:0.5:6:700 \ + RRA:AVERAGE:0.5:24:775 \ + RRA:AVERAGE:0.5:288:797 \ + RRA:MAX:0.5:1:600 \ + RRA:MAX:0.5:6:700 \ + RRA:MAX:0.5:24:775 \ + RRA:MAX:0.5:288:797 +fi + +# Parsing data +if [ "$period" = 'daily' ]; then + a=0 + a=$(ps aux | grep "$FTP_SYSTEM" | grep -v grep | grep -v nobody \ + | grep -v root | wc -l) + + # Updating rrd database + rrdtool update $RRD/ftp/ftp.rrd N:$a +fi + +# Updating rrd graph +rrdtool graph $RRD/ftp/$period-ftp.png \ + --imgformat PNG \ + --height="150" \ + --width="670" \ + --start "$start" \ + --end "$end" \ + --vertical-label "Connections" \ + --x-grid "$grid" \ + -c "BACK#ffffff" \ + -c "SHADEA#ffffff" \ + -c "SHADEB#ffffff" \ + -c "FONT#555555" \ + -c "CANVAS#302c2d" \ + -c "GRID#666666" \ + -c "MGRID#AAAAAA" \ + -c "FRAME#302c2d" \ + -c "ARROW#FFFFFF" \ + DEF:a=$RRD/ftp/ftp.rrd:A:AVERAGE \ + COMMENT:'\r' \ + LINE1:a#fefda0:"Users " \ + GPRINT:a:'LAST:Current\:''%8.0lf' \ + GPRINT:a:'MIN:Min\:''%8.0lf' \ + GPRINT:a:'MAX:Max\:''%8.0lf\j' &> /dev/null +result=$? + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +if [ "$result" -ne 0 ]; then + exit "$E_RRD" +fi + +exit diff --git a/bin/v-update-sys-rrd-httpd b/bin/v-update-sys-rrd-httpd new file mode 100755 index 0000000..9dedf46 --- /dev/null +++ b/bin/v-update-sys-rrd-httpd @@ -0,0 +1,122 @@ +#!/bin/bash +# info: update httpd rrd +# options: PERIOD +# +# example: v-update-sys-rrd-httpd +# +# This function is for updating apache rrd database and graphic. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +period=${1-daily} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Switching on time period +case $period in + daily) + start='-1d' + end='now' + grid='MINUTE:30:HOUR:1:HOUR:4:0:%H:%M' + ;; + weekly) + start='-7d' + end='now' + grid='HOUR:8:DAY:1:DAY:1:0:%a %d' + ;; + monthly) + start='-1m' + end='now' + grid='WEEK:1:WEEK:1:WEEK:1:0:%b %d' + ;; + yearly) + start='-1y' + end='now' + grid='MONTH:1:YEAR:1:MONTH:2:2419200:%b' + ;; + *) exit "$E_RRD" ;; +esac + +# Checking directory +if [ ! -d "$RRD/web" ]; then + mkdir $RRD/web +fi + +# Checking database +if [ ! -e "$RRD/web/httpd.rrd" ]; then + # Adding database + rrdtool create $RRD/web/httpd.rrd --step $RRD_STEP \ + DS:A:GAUGE:600:U:U \ + RRA:AVERAGE:0.5:1:600 \ + RRA:AVERAGE:0.5:6:700 \ + RRA:AVERAGE:0.5:24:775 \ + RRA:AVERAGE:0.5:288:797 \ + RRA:MAX:0.5:1:600 \ + RRA:MAX:0.5:6:700 \ + RRA:MAX:0.5:24:775 \ + RRA:MAX:0.5:288:797 +fi + +# Parsing data +if [ "$period" = 'daily' ]; then + server_status=$(wget -qO- http://localhost:8081/server-status \ + | grep 'currently being processed' \ + | cut -f 2 -d '>' \ + | sed 's/requests currently being processed, //' \ + | cut -f 1,2 -d ' ') + active=$(echo "$server_status" | cut -f 1 -d ' ') + idle=$(echo "$server_status" | cut -f 1 -d ' ') + a=$((active + idle)) + + # Updating rrd database + rrdtool update $RRD/web/httpd.rrd N:$a +fi + +# Updating rrd graph +rrdtool graph $RRD/web/$period-httpd.png \ + --imgformat PNG \ + --height="150" \ + --width="670" \ + --start "$start" \ + --end "$end" \ + --vertical-label "Connections" \ + --x-grid "$grid" \ + -c "BACK#ffffff" \ + -c "SHADEA#ffffff" \ + -c "SHADEB#ffffff" \ + -c "FONT#555555" \ + -c "CANVAS#302c2d" \ + -c "GRID#666666" \ + -c "MGRID#AAAAAA" \ + -c "FRAME#302c2d" \ + -c "ARROW#FFFFFF" \ + DEF:a=$RRD/web/httpd.rrd:A:AVERAGE \ + COMMENT:'\r' \ + LINE1:a#fefda0:"Connections " \ + GPRINT:a:'LAST:Current\:''%8.0lf' \ + GPRINT:a:'MIN:Min\:''%8.0lf' \ + GPRINT:a:'MAX:Max\:''%8.0lf\j' &> /dev/null +result=$? + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +if [ "$result" -ne 0 ]; then + exit "$E_RRD" +fi + +exit diff --git a/bin/v-update-sys-rrd-la b/bin/v-update-sys-rrd-la new file mode 100755 index 0000000..ccc227c --- /dev/null +++ b/bin/v-update-sys-rrd-la @@ -0,0 +1,123 @@ +#!/bin/bash +# info: update load average rrd +# options: PERIOD +# +# example: v-update-sys-rrd-la +# +# This function is for updating load average rrd database and graphic. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +period=${1-daily} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Switching on time period +case $period in + daily) + start='-1d' + end='now' + grid='MINUTE:30:HOUR:1:HOUR:4:0:%H:%M' + ;; + weekly) + start='-7d' + end='now' + grid='HOUR:8:DAY:1:DAY:1:0:%a %d' + ;; + monthly) + start='-1m' + end='now' + grid='WEEK:1:WEEK:1:WEEK:1:0:%b %d' + ;; + yearly) + start='-1y' + end='now' + grid='MONTH:1:YEAR:1:MONTH:2:2419200:%b' + ;; + *) exit "$E_RRD" ;; +esac + +# Checking directory +if [ ! -d "$RRD/la" ]; then + mkdir $RRD/la +fi + +# Checking database +if [ ! -e "$RRD/la/la.rrd" ]; then + # Adding database + rrdtool create $RRD/la/la.rrd --step $RRD_STEP \ + DS:LA:GAUGE:600:U:U \ + DS:PR:GAUGE:600:U:U \ + RRA:AVERAGE:0.5:1:600 \ + RRA:AVERAGE:0.5:6:700 \ + RRA:AVERAGE:0.5:24:775 \ + RRA:AVERAGE:0.5:288:797 \ + RRA:MAX:0.5:1:600 \ + RRA:MAX:0.5:6:700 \ + RRA:MAX:0.5:24:775 \ + RRA:MAX:0.5:288:797 +fi + +# Parsing data +if [ "$period" = 'daily' ]; then + loadavg=$(cat /proc/loadavg) + la=$(echo "$loadavg" | cut -f 2 -d ' ') + pr=$(ps auxh | wc -l) + + # Updating rrd database + rrdtool update $RRD/la/la.rrd N:${la//./}:$pr +fi + +# Updating graph +rrdtool graph $RRD/la/$period-la.png \ + --imgformat PNG \ + --height="150" \ + --width="670" \ + --start "$start" \ + --end "$end" \ + --vertical-label "Points" \ + --x-grid "$grid" \ + -c "BACK#ffffff" \ + -c "SHADEA#ffffff" \ + -c "SHADEB#ffffff" \ + -c "FONT#555555" \ + -c "CANVAS#302c2d" \ + -c "GRID#666666" \ + -c "MGRID#AAAAAA" \ + -c "FRAME#777777" \ + -c "ARROW#555555" \ + DEF:la=$RRD/la/la.rrd:LA:AVERAGE \ + DEF:pr=$RRD/la/la.rrd:PR:AVERAGE \ + COMMENT:'\r' \ + AREA:la#C8EA2E:"LA * 100" \ + GPRINT:la:'LAST: Current\:''%8.0lf' \ + GPRINT:la:'MIN: Min\:''%8.0lf' \ + GPRINT:la:'MAX: Max\:''%8.0lf\j' \ + LINE1:pr#1c74cd:"Procs # " \ + GPRINT:pr:'LAST:Current\:''%8.0lf' \ + GPRINT:pr:'MIN:Min\:''%8.0lf' \ + GPRINT:pr:'MAX:Max\:''%8.0lf\j' &> /dev/null +result=$? + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +if [ "$result" -ne 0 ]; then + exit "$E_RRD" +fi + +exit diff --git a/bin/v-update-sys-rrd-mail b/bin/v-update-sys-rrd-mail new file mode 100755 index 0000000..e0df4eb --- /dev/null +++ b/bin/v-update-sys-rrd-mail @@ -0,0 +1,116 @@ +#!/bin/bash +# info: update mail rrd +# options: PERIOD +# +# example: v-update-sys-rrd-mail +# +# This function is for updating mail rrd database and graphic. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +period=${1-daily} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Switching on time period +case $period in + daily) + start='-1d' + end='now' + grid='MINUTE:30:HOUR:1:HOUR:4:0:%H:%M' + ;; + weekly) + start='-7d' + end='now' + grid='HOUR:8:DAY:1:DAY:1:0:%a %d' + ;; + monthly) + start='-1m' + end='now' + grid='WEEK:1:WEEK:1:WEEK:1:0:%b %d' + ;; + yearly) + start='-1y' + end='now' + grid='MONTH:1:YEAR:1:MONTH:2:2419200:%b' + ;; + *) exit "$E_RRD" ;; +esac + +# Checking directory +if [ ! -d "$RRD/mail" ]; then + mkdir $RRD/mail +fi + +# Checking database +if [ ! -e "$RRD/mail/mail.rrd" ]; then + # Adding database + rrdtool create $RRD/mail/mail.rrd --step $RRD_STEP \ + DS:A:GAUGE:600:U:U \ + RRA:AVERAGE:0.5:1:600 \ + RRA:AVERAGE:0.5:6:700 \ + RRA:AVERAGE:0.5:24:775 \ + RRA:AVERAGE:0.5:288:797 \ + RRA:MAX:0.5:1:600 \ + RRA:MAX:0.5:6:700 \ + RRA:MAX:0.5:24:775 \ + RRA:MAX:0.5:288:797 +fi + +# Parsing data +if [ "$period" = 'daily' ]; then + a=0 + a=$(exim -bpc) + + # Updating rrd database + rrdtool update $RRD/mail/mail.rrd N:$a +fi + +# Updating daily graph +rrdtool graph $RRD/mail/$period-mail.png \ + --imgformat PNG \ + --height="150" \ + --width="670" \ + --start "$start" \ + --end "$end" \ + --vertical-label "Queue Size" \ + --x-grid "$grid" \ + -c "BACK#ffffff" \ + -c "SHADEA#ffffff" \ + -c "SHADEB#ffffff" \ + -c "FONT#555555" \ + -c "CANVAS#302c2d" \ + -c "GRID#666666" \ + -c "MGRID#AAAAAA" \ + -c "FRAME#302c2d" \ + -c "ARROW#FFFFFF" \ + DEF:a=$RRD/mail/mail.rrd:A:AVERAGE \ + COMMENT:'\r' \ + LINE1:a#fefda0:"Emails " \ + GPRINT:a:'LAST:Current\:''%8.0lf' \ + GPRINT:a:'MIN:Min\:''%8.0lf' \ + GPRINT:a:'MAX:Max\:''%8.0lf\j' &> /dev/null +result=$? + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +if [ "$result" -ne 0 ]; then + exit "$E_RRD" +fi + +exit diff --git a/bin/v-update-sys-rrd-mem b/bin/v-update-sys-rrd-mem new file mode 100755 index 0000000..79f53a2 --- /dev/null +++ b/bin/v-update-sys-rrd-mem @@ -0,0 +1,140 @@ +#!/bin/bash +# info: update memory rrd +# options: PERIOD +# +# example: v-update-sys-rrd-mem +# +# This function is for updating memory rrd database and graphic. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +period=${1-daily} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Switching on time period +case $period in + daily) + start='-1d' + end='now' + grid='MINUTE:30:HOUR:1:HOUR:4:0:%H:%M' + ;; + weekly) + start='-7d' + end='now' + grid='HOUR:8:DAY:1:DAY:1:0:%a %d' + ;; + monthly) + start='-1m' + end='now' + grid='WEEK:1:WEEK:1:WEEK:1:0:%b %d' + ;; + yearly) + start='-1y' + end='now' + grid='MONTH:1:YEAR:1:MONTH:2:2419200:%b' + ;; + *) exit "$E_RRD" ;; +esac + +# Checking directory +if [ ! -d "$RRD/mem" ]; then + mkdir $RRD/mem +fi + +# Checking database +if [ -e "$RRD/mem/mem.rrd" ]; then + rrd_check=$(rrdtool info $RRD/mem/mem.rrd | grep "FREE") + if [ -z "$rrd_check" ]; then + rm -f $RRD/mem/mem.rrd + fi +fi +if [ ! -e "$RRD/mem/mem.rrd" ]; then + # Adding database + rrdtool create $RRD/mem/mem.rrd --step $RRD_STEP \ + DS:RAM:GAUGE:600:U:U \ + DS:SWAP:GAUGE:600:U:U \ + DS:FREE:GAUGE:600:U:U \ + RRA:AVERAGE:0.5:1:600 \ + RRA:AVERAGE:0.5:6:700 \ + RRA:AVERAGE:0.5:24:775 \ + RRA:AVERAGE:0.5:288:797 \ + RRA:MAX:0.5:1:600 \ + RRA:MAX:0.5:6:700 \ + RRA:MAX:0.5:24:775 \ + RRA:MAX:0.5:288:797 +fi + +# Parsing data +if [ "$period" = 'daily' ]; then + mem=$(LC_ALL=C free -m) + used=$(echo "$mem" | grep Mem | awk '{print $3}') + if [ -z "$(echo "$mem" | grep available)" ]; then + free=$(echo "$mem" | grep buffers/cache | awk '{print $4}') + else + free=$(echo "$mem" | grep Mem | awk '{print $7}') + fi + swap=$(echo "$mem" | grep Swap | awk '{print $3}') + + # Updating rrd + rrdtool update $RRD/mem/mem.rrd N:$used:$swap:$free +fi + +# Updating rrd graph +rrdtool graph $RRD/mem/$period-mem.png \ + --imgformat PNG \ + --height="150" \ + --width="670" \ + --start "$start" \ + --end "$end" \ + --vertical-label "Mbytes" \ + --x-grid "$grid" \ + -c "BACK#ffffff" \ + -c "SHADEA#ffffff" \ + -c "SHADEB#ffffff" \ + -c "FONT#555555" \ + -c "CANVAS#302c2d" \ + -c "GRID#666666" \ + -c "MGRID#AAAAAA" \ + -c "FRAME#302c2d" \ + -c "ARROW#FFFFFF" \ + DEF:used=$RRD/mem/mem.rrd:RAM:AVERAGE \ + DEF:swap=$RRD/mem/mem.rrd:SWAP:AVERAGE \ + DEF:free=$RRD/mem/mem.rrd:FREE:AVERAGE \ + COMMENT:'\r' \ + AREA:used#867995:"USED" \ + GPRINT:used:'LAST: Current\:''%8.0lf' \ + GPRINT:used:'MIN: Min\:''%8.0lf' \ + GPRINT:used:'MAX: Max\:''%8.0lf\j' \ + LINE1:free#1c74cd:"FREE" \ + GPRINT:free:'LAST: Current\:''%8.0lf' \ + GPRINT:free:'MIN: Min\:''%8.0lf' \ + GPRINT:free:'MAX: Max\:''%8.0lf\j' \ + LINE2:swap#f57900:"SWAP" \ + GPRINT:swap:'LAST:Current\:''%8.0lf' \ + GPRINT:swap:'MIN:Min\:''%8.0lf' \ + GPRINT:swap:'MAX:Max\:''%8.0lf\j' &> /dev/null +result=$? + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +if [ "$result" -ne 0 ]; then + exit "$E_RRD" +fi + +exit diff --git a/bin/v-update-sys-rrd-mysql b/bin/v-update-sys-rrd-mysql new file mode 100755 index 0000000..ea41bb4 --- /dev/null +++ b/bin/v-update-sys-rrd-mysql @@ -0,0 +1,147 @@ +#!/bin/bash +# info: update MySQL rrd +# options: PERIOD +# +# example: v-update-sys-rrd-mysql +# +# This function is for updating mysql rrd database and graphic. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +period=${1-daily} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/db.sh +source $HESTIA/func/db.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Switching on time period +case $period in + daily) + start='-1d' + end='now' + grid='MINUTE:30:HOUR:1:HOUR:4:0:%H:%M' + ;; + weekly) + start='-7d' + end='now' + grid='HOUR:8:DAY:1:DAY:1:0:%a %d' + ;; + monthly) + start='-1m' + end='now' + grid='WEEK:1:WEEK:1:WEEK:1:0:%b %d' + ;; + yearly) + start='-1y' + end='now' + grid='MONTH:1:YEAR:1:MONTH:2:2419200:%b' + ;; + *) exit "$E_RRD" ;; +esac + +# Checking directory +if [ ! -d "$RRD/db" ]; then + mkdir $RRD/db +fi + +# Parsing db hosts +conf="$HESTIA/conf/mysql.conf" +hosts=$(grep HOST "$conf" | awk '{print $1}' | cut -f 2 -d \') +check_row=$(echo "$hosts" | wc -l) +if [ 0 -eq "$check_row" ]; then + exit +fi + +# Parsing excludes +for exclude in $(echo ${RRD_MYSQL_EXCLUDE//,/ }); do + hosts=$(echo "$hosts" | grep -vw "$exclude") +done + +for host in $hosts; do + # Checking database + if [ ! -e "$RRD/db/mysql_$host.rrd" ]; then + # Adding database + rrdtool create $RRD/db/mysql_$host.rrd --step $RRD_STEP \ + DS:A:COUNTER:600:U:U \ + DS:S:COUNTER:600:U:U \ + RRA:AVERAGE:0.5:1:600 \ + RRA:AVERAGE:0.5:6:700 \ + RRA:AVERAGE:0.5:24:775 \ + RRA:AVERAGE:0.5:288:797 \ + RRA:MAX:0.5:1:600 \ + RRA:MAX:0.5:6:700 \ + RRA:MAX:0.5:24:775 \ + RRA:MAX:0.5:288:797 + fi + + if [ "$period" = 'daily' ]; then + mysql_connect "$host" + query='SHOW GLOBAL STATUS' + status=$(mysql_query "$query" 2> /dev/null) + if [ $? -ne 0 ]; then + active=0 + slow=0 + else + active=$(echo "$status" | grep 'Queries' | cut -f 2) + slow=$(echo "$status" | grep 'Slow_queries' | cut -f 2) + fi + + # Updating rrd + rrdtool update $RRD/db/mysql_$host.rrd N:$active:$slow + fi + + # Updating daily graph + rrdtool graph $RRD/db/$period-mysql_$host.png \ + --imgformat PNG \ + --height="150" \ + --width="670" \ + --start "$start" \ + --end "$end" \ + --vertical-label "Queries" \ + --x-grid "$grid" \ + -c "BACK#ffffff" \ + -c "SHADEA#ffffff" \ + -c "SHADEB#ffffff" \ + -c "FONT#555555" \ + -c "CANVAS#302c2d" \ + -c "GRID#666666" \ + -c "MGRID#AAAAAA" \ + -c "FRAME#302c2d" \ + -c "ARROW#FFFFFF" \ + DEF:a=$RRD/db/mysql_$host.rrd:A:AVERAGE \ + DEF:s=$RRD/db/mysql_$host.rrd:S:AVERAGE \ + COMMENT:'\r' \ + LINE1:a#fefda0:"Queries" \ + GPRINT:a:'LAST: Current\:''%8.0lf' \ + GPRINT:a:'MIN: Min\:''%8.0lf' \ + GPRINT:a:'MAX: Max\:''%8.0lf\j' \ + AREA:s#f57900:"Slow " \ + GPRINT:s:'LAST:Current\:''%8.0lf' \ + GPRINT:s:'MIN:Min\:''%8.0lf' \ + GPRINT:s:'MAX:Max\:''%8.0lf\j' &> /dev/null + result=$? + + if [ "$result" -ne 0 ]; then + exit "$E_RRD" + fi + +done + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-update-sys-rrd-net b/bin/v-update-sys-rrd-net new file mode 100755 index 0000000..78fe369 --- /dev/null +++ b/bin/v-update-sys-rrd-net @@ -0,0 +1,140 @@ +#!/bin/bash +# info: update network rrd +# options: PERIOD +# +# example: v-update-sys-rrd-net +# +# This function is for updating network usage rrd database and graphic. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +period=${1-daily} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Switching on time period +case $period in + daily) + start='-1d' + end='now' + grid='MINUTE:30:HOUR:1:HOUR:4:0:%H:%M' + ;; + weekly) + start='-7d' + end='now' + grid='HOUR:8:DAY:1:DAY:1:0:%a %d' + ;; + monthly) + start='-1m' + end='now' + grid='WEEK:1:WEEK:1:WEEK:1:0:%b %d' + ;; + yearly) + start='-1y' + end='now' + grid='MONTH:1:YEAR:1:MONTH:2:2419200:%b' + ;; + *) exit "$E_RRD" ;; +esac + +# Checking directory +if [ ! -d "$RRD/net" ]; then + mkdir $RRD/net +fi + +# Parsing network interfaces +ndev=$(cat /proc/net/dev) +ifaces=$(echo "$ndev" | grep : | cut -f 1 -d : | sed "s/ //g") + +# Parsing excludes +if [ -z "$RRD_IFACE_EXCLUDE" ]; then + RRD_IFACE_EXCLUDE='lo,docker0,br-.*,veth.*' +fi +for exclude in $(echo ${RRD_IFACE_EXCLUDE//,/ }); do + ifaces=$(echo "$ifaces" | grep -vw "$exclude") +done + +for iface in $ifaces; do + # Checking database + if [ ! -e "$RRD/net/$iface.rrd" ]; then + # Adding database + rrdtool create $RRD/net/$iface.rrd --step $RRD_STEP \ + DS:RX:COUNTER:600:U:U \ + DS:TX:COUNTER:600:U:U \ + RRA:AVERAGE:0.5:1:600 \ + RRA:AVERAGE:0.5:6:700 \ + RRA:AVERAGE:0.5:24:775 \ + RRA:AVERAGE:0.5:288:797 \ + RRA:MAX:0.5:1:600 \ + RRA:MAX:0.5:6:700 \ + RRA:MAX:0.5:24:775 \ + RRA:MAX:0.5:288:797 + fi + + # Parsing device stats + if [ "$period" = 'daily' ]; then + x=$(echo "$ndev" | sed "s/^ *//" | grep "^$iface:" | sed "s/:/ /") + rx=$(echo "$x" | awk '{print $2}') + tx=$(echo "$x" | awk '{print $10}') + + # Updating rrd database + rrdtool update $RRD/net/$iface.rrd N:$rx:$tx + fi + + # Updating rrd graph + rrdtool graph $RRD/net/$period-$iface.png \ + --imgformat PNG \ + --height="150" \ + --width="670" \ + --start "$start" \ + --end "$end" \ + --vertical-label "KBytes" \ + --x-grid "$grid" \ + -c "BACK#ffffff" \ + -c "SHADEA#ffffff" \ + -c "SHADEB#ffffff" \ + -c "FONT#555555" \ + -c "CANVAS#302c2d" \ + -c "GRID#666666" \ + -c "MGRID#AAAAAA" \ + -c "FRAME#302c2d" \ + -c "ARROW#FFFFFF" \ + DEF:inoctets=$RRD/net/$iface.rrd:RX:AVERAGE \ + DEF:outoctets=$RRD/net/$iface.rrd:TX:AVERAGE \ + "CDEF:in=inoctets,8,*" \ + "CDEF:out=outoctets,8,*" \ + COMMENT:'\r' \ + AREA:in#C8EA2E:"Input (rx) " \ + GPRINT:in:'LAST: Current\:''%8.0lf' \ + GPRINT:in:'MIN: Min\:''%8.0lf' \ + GPRINT:in:'MAX: Max\:''%8.0lf\j' \ + LINE1:out#1c74cd:"Output (tx)" \ + GPRINT:out:'LAST:Current\:''%8.0lf' \ + GPRINT:out:'MIN:Min\:''%8.0lf' \ + GPRINT:out:'MAX:Max\:''%8.0lf\j' &> /dev/null + result=$? + + if [ "$result" -ne 0 ]; then + exit "$E_RRD" + fi + +done + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-update-sys-rrd-nginx b/bin/v-update-sys-rrd-nginx new file mode 100755 index 0000000..e12487d --- /dev/null +++ b/bin/v-update-sys-rrd-nginx @@ -0,0 +1,115 @@ +#!/bin/bash +# info: update nginx rrd +# options: PERIOD +# +# example: v-update-sys-rrd-nginx +# +# This function is for updating nginx rrd database and graphic. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +period=${1-daily} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Switching on time period +case $period in + daily) + start='-1d' + end='now' + grid='MINUTE:30:HOUR:1:HOUR:4:0:%H:%M' + ;; + weekly) + start='-7d' + end='now' + grid='HOUR:8:DAY:1:DAY:1:0:%a %d' + ;; + monthly) + start='-1m' + end='now' + grid='WEEK:1:WEEK:1:WEEK:1:0:%b %d' + ;; + yearly) + start='-1y' + end='now' + grid='MONTH:1:YEAR:1:MONTH:2:2419200:%b' + ;; + *) exit "$E_RRD" ;; +esac + +# Checking directory +if [ ! -d "$RRD/web" ]; then + mkdir "$RRD/web" +fi + +# Checking database +if [ ! -e "$RRD/web/nginx.rrd" ]; then + # Adding database + rrdtool create $RRD/web/nginx.rrd --step $RRD_STEP \ + DS:A:GAUGE:600:U:U \ + RRA:AVERAGE:0.5:1:600 \ + RRA:AVERAGE:0.5:6:700 \ + RRA:AVERAGE:0.5:24:775 \ + RRA:AVERAGE:0.5:288:797 \ + RRA:MAX:0.5:1:600 \ + RRA:MAX:0.5:6:700 \ + RRA:MAX:0.5:24:775 \ + RRA:MAX:0.5:288:797 +fi + +# Parsing data +if [ "$period" = 'daily' ]; then + a=$(wget -qO- http://localhost:8084/ | head -n1 | cut -f 3 -d ' ') + + # Updating rrd database + rrdtool update $RRD/web/nginx.rrd N:$a +fi + +# Updating rrd graph +rrdtool graph $RRD/web/$period-nginx.png \ + --imgformat PNG \ + --height="150" \ + --width="670" \ + --start "$start" \ + --end "$end" \ + --vertical-label "Connections" \ + --x-grid "$grid" \ + -c "BACK#ffffff" \ + -c "SHADEA#ffffff" \ + -c "SHADEB#ffffff" \ + -c "FONT#555555" \ + -c "CANVAS#302c2d" \ + -c "GRID#666666" \ + -c "MGRID#AAAAAA" \ + -c "FRAME#302c2d" \ + -c "ARROW#FFFFFF" \ + DEF:a=$RRD/web/nginx.rrd:A:AVERAGE \ + COMMENT:'\r' \ + LINE1:a#fefda0:"Connections " \ + GPRINT:a:'LAST:Current\:''%8.0lf' \ + GPRINT:a:'MIN:Min\:''%8.0lf' \ + GPRINT:a:'MAX:Max\:''%8.0lf\j' &> /dev/null +result=$? + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +if [ "$result" -ne 0 ]; then + exit "$E_RRD" +fi + +exit diff --git a/bin/v-update-sys-rrd-pgsql b/bin/v-update-sys-rrd-pgsql new file mode 100755 index 0000000..653a97e --- /dev/null +++ b/bin/v-update-sys-rrd-pgsql @@ -0,0 +1,164 @@ +#!/bin/bash +# info: update PostgreSQL rrd +# options: PERIOD +# +# example: v-update-sys-rrd-pgsql +# +# This function is for updating postgresql rrd database and graphic. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +period=${1-daily} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Switching on time period +case $period in + daily) + start='-1d' + end='now' + grid='MINUTE:30:HOUR:1:HOUR:4:0:%H:%M' + ;; + weekly) + start='-7d' + end='now' + grid='HOUR:8:DAY:1:DAY:1:0:%a %d' + ;; + monthly) + start='-1m' + end='now' + grid='WEEK:1:WEEK:1:WEEK:1:0:%b %d' + ;; + yearly) + start='-1y' + end='now' + grid='MONTH:1:YEAR:1:MONTH:2:2419200:%b' + ;; + *) exit "$E_RRD" ;; +esac + +# Checking directory +if [ ! -d "$RRD/db" ]; then + mkdir $RRD/db +fi + +# Parsing db hosts +conf="$HESTIA/conf/pgsql.conf" +hosts=$(grep HOST $conf | awk '{print $1}' | cut -f 2 -d \') +check_row=$(echo "$hosts" | wc -l) +if [ 0 -eq "$check_row" ]; then + exit +fi + +# Parsing excludes +for exclude in $(echo ${RRD_PGSQL_EXCLUDE//,/ }); do + hosts=$(echo "$hosts" | grep -vw "$exclude") +done + +for host in $hosts; do + # Checking database + if [ ! -e "$RRD/db/pgsql_$host.rrd" ]; then + # Adding database + rrdtool create $RRD/db/pgsql_$host.rrd --step $RRD_STEP \ + DS:A:GAUGE:600:U:U \ + DS:T:COUNTER:600:U:U \ + RRA:AVERAGE:0.5:1:600 \ + RRA:AVERAGE:0.5:6:700 \ + RRA:AVERAGE:0.5:24:775 \ + RRA:AVERAGE:0.5:288:797 \ + RRA:MAX:0.5:1:600 \ + RRA:MAX:0.5:6:700 \ + RRA:MAX:0.5:24:775 \ + RRA:MAX:0.5:288:797 + fi + + if [ "$period" = 'daily' ]; then + # Defining host credentials + host_str=$(grep "HOST='$host'" $conf) + for key in $host_str; do + eval ${key%%=*}=${key#*=} + done + + export PGPASSWORD="$PASSWORD" + sql="psql -h $HOST -U $USER" + + # Checking empty vars + if [ -z $HOST ] || [ -z $USER ] || [ -z $PASSWORD ]; then + echo "Error: config is broken" + log_event "$E_PARSING" "$ARGUMENTS" + exit "$E_PARSING" + fi + + # Parsing data + q='SELECT SUM(xact_commit + xact_rollback), SUM(numbackends) + FROM pg_stat_database;' + status=$($sql -d postgres -c "$q" 2> /dev/null) + code="$?" + if [ '0' -ne "$code" ]; then + active=0 + slow=0 + else + active=$(echo "$status" | head -n 3 | tail -n 1 | awk '{print $3}') + trans=$(echo "$status" | head -n 3 | tail -n 1 | awk '{print $1}') + fi + + # Updating rrd + export PGPASSWORD='pgsql' + rrdtool update $RRD/db/pgsql_$host.rrd N:$active:$trans + fi + + # Updating rrd graph + rrdtool graph $RRD/db/$period-pgsql_$host.png \ + --imgformat PNG \ + --height="150" \ + --width="670" \ + --start "$start" \ + --end "$end" \ + --vertical-label "Queries" \ + --x-grid "$grid" \ + -c "BACK#ffffff" \ + -c "SHADEA#ffffff" \ + -c "SHADEB#ffffff" \ + -c "FONT#555555" \ + -c "CANVAS#302c2d" \ + -c "GRID#666666" \ + -c "MGRID#AAAAAA" \ + -c "FRAME#302c2d" \ + -c "ARROW#FFFFFF" \ + DEF:a=$RRD/db/pgsql_$host.rrd:A:AVERAGE \ + DEF:t=$RRD/db/pgsql_$host.rrd:T:AVERAGE \ + COMMENT:'\r' \ + LINE1:a#fefda0:"Queries " \ + GPRINT:a:'LAST: Current\:''%8.0lf' \ + GPRINT:a:'MIN: Min\:''%8.0lf' \ + GPRINT:a:'MAX: Max\:''%8.0lf\j' \ + LINE2:t#f57900:"Transactions" \ + GPRINT:t:'LAST:Current\:''%8.0lf' \ + GPRINT:t:'MIN:Min\:''%8.0lf' \ + GPRINT:t:'MAX:Max\:''%8.0lf\j' &> /dev/null + result=$? + + if [ "$result" -ne 0 ]; then + exit "$E_RRD" + fi + +done + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +exit diff --git a/bin/v-update-sys-rrd-ssh b/bin/v-update-sys-rrd-ssh new file mode 100755 index 0000000..6784c21 --- /dev/null +++ b/bin/v-update-sys-rrd-ssh @@ -0,0 +1,116 @@ +#!/bin/bash +# info: update ssh rrd +# options: PERIOD +# +# example: v-update-sys-rrd-ssh +# +# This function is for updating ssh rrd database and graphic. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +period=${1-daily} + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Switching on time period +case $period in + daily) + start='-1d' + end='now' + grid='MINUTE:30:HOUR:1:HOUR:4:0:%H:%M' + ;; + weekly) + start='-7d' + end='now' + grid='HOUR:8:DAY:1:DAY:1:0:%a %d' + ;; + monthly) + start='-1m' + end='now' + grid='WEEK:1:WEEK:1:WEEK:1:0:%b %d' + ;; + yearly) + start='-1y' + end='now' + grid='MONTH:1:YEAR:1:MONTH:2:2419200:%b' + ;; + *) exit "$E_RRD" ;; +esac + +# Checking directory +if [ ! -d "$RRD/ssh" ]; then + mkdir $RRD/ssh +fi + +# Checking database +if [ ! -e "$RRD/ssh/ssh.rrd" ]; then + # Adding database + rrdtool create $RRD/ssh/ssh.rrd --step "$RRD_STEP" \ + DS:A:GAUGE:600:U:U \ + RRA:AVERAGE:0.5:1:600 \ + RRA:AVERAGE:0.5:6:700 \ + RRA:AVERAGE:0.5:24:775 \ + RRA:AVERAGE:0.5:288:797 \ + RRA:MAX:0.5:1:600 \ + RRA:MAX:0.5:6:700 \ + RRA:MAX:0.5:24:775 \ + RRA:MAX:0.5:288:797 +fi + +# Parsing data +if [ "$period" = 'daily' ]; then + a=0 + a=$(ps auxf | grep sshd | grep -v grep | grep -v '/usr/sbin/' | wc -l) + + # Updating rrd database + rrdtool update "$RRD/ssh/ssh.rrd" "N:$a" +fi + +# Updating daily graph +rrdtool graph $RRD/ssh/$period-ssh.png \ + --imgformat PNG \ + --height="150" \ + --width="670" \ + --start "$start" \ + --end "$end" \ + --vertical-label "Connections" \ + --x-grid "$grid" \ + -c "BACK#ffffff" \ + -c "SHADEA#ffffff" \ + -c "SHADEB#ffffff" \ + -c "FONT#555555" \ + -c "CANVAS#302c2d" \ + -c "GRID#666666" \ + -c "MGRID#AAAAAA" \ + -c "FRAME#302c2d" \ + -c "ARROW#FFFFFF" \ + DEF:a=$RRD/ssh/ssh.rrd:A:AVERAGE \ + COMMENT:'\r' \ + LINE1:a#fefda0:"Users " \ + GPRINT:a:'LAST:Current\:''%8.0lf' \ + GPRINT:a:'MIN:Min\:''%8.0lf' \ + GPRINT:a:'MAX:Max\:''%8.0lf\j' &> /dev/null +result=$? + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +if [ "$result" -ne 0 ]; then + exit "$E_RRD" +fi + +exit diff --git a/bin/v-update-user-backup-exclusions b/bin/v-update-user-backup-exclusions new file mode 100755 index 0000000..110413c --- /dev/null +++ b/bin/v-update-user-backup-exclusions @@ -0,0 +1,83 @@ +#!/bin/bash +# info: update backup exclusion list +# options: USER FILE +# +# example: v-update-user-backup-exclusions admin /tmp/backup_exclusions +# +# This function for updating backup exclusion list + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +vfile=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +is_file_available() { + if [ ! -e "$vfile" ]; then + check_result "$E_NOTEXIST" "file $vfile doesn't exist" + fi +} + +is_file_valid() { + exclude="[!|#|$|^|&|(|)|{|}|<|>|?|\|\"|;|%|\`]" + if [[ "$(cat $vfile)" =~ $exclude ]]; then + check_result "$E_INVALID" "invalid characters in the exlusion list" + fi +} + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER FILE' +is_format_valid 'user' +is_object_valid 'user' 'USER' "$user" +is_file_available +is_file_valid + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Flush variables +WEB='' +DNS='' +MAIL='' +DB='' +CRON='' +USER='' + +# Source exclusion list +source_conf "$vfile" + +# Updating exlusion list +echo "WEB='$WEB'" > $USER_DATA/backup-excludes.conf +echo "DNS='$DNS'" >> $USER_DATA/backup-excludes.conf +echo "MAIL='$MAIL'" >> $USER_DATA/backup-excludes.conf +echo "DB='$DB'" >> $USER_DATA/backup-excludes.conf +echo "CRON='$CRON'" >> $USER_DATA/backup-excludes.conf +echo "USER='$USER'" >> $USER_DATA/backup-excludes.conf +chmod 660 $USER_DATA/backup-excludes.conf + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +$BIN/v-log-action "$user" "Info" "Backups" "Updated backup exclusion list." +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-update-user-counters b/bin/v-update-user-counters new file mode 100755 index 0000000..ef4a066 --- /dev/null +++ b/bin/v-update-user-counters @@ -0,0 +1,232 @@ +#!/bin/bash +# info: update user usage counters +# options: USER +# +# example: v-update-user-counters admin +# +# Function updates usage counters like U_WEB_DOMAINS, U_MAIL_ACCOUNTS, etc. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '0' "$#" 'USER' +if [ -n "$user" ]; then + is_format_valid 'user' + is_object_valid 'user' 'USER' "$user" +fi + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Creating user_list +if [ -z "$user" ]; then + user_list=$($BIN/v-list-sys-users plain) +else + user_list="$user" +fi + +# Updating user stats +for user in $user_list; do + USER_DATA=$HESTIA/data/users/$user + # Cleaning counters + SUSPENDED_USERS=0 + SUSPENDED_WEB=0 + SUSPENDED_DNS=0 + SUSPENDED_MAIL=0 + SUSPENDED_DB=0 + SUSPENDED_CRON=0 + IP_AVAIL=0 + IP_OWNED=0 + U_USERS=0 + U_DISK=0 + U_DISK_DIRS=$(get_user_value '$U_DISK_DIRS') + if [ -z "$U_DISK_DIRS" ]; then + U_DISK_DIRS=0 + fi + DISK=$((DISK + U_DISK_DIRS)) + U_DISK_WEB=0 + U_DISK_MAIL=0 + U_DISK_DB=0 + BANDWIDTH=0 + U_BANDWIDTH=0 + U_WEB_DOMAINS=0 + U_WEB_SSL=0 + U_WEB_ALIASES=0 + U_DNS_DOMAINS=0 + U_DNS_RECORDS=0 + U_MAIL_DOMAINS=0 + U_MAIL_DKIM=0 + U_MAIL_ACCOUNTS=0 + U_DATABASES=0 + U_CRON_JOBS=0 + U_BACKUPS=0 + + # New IFS + IFS=$'\n' + + # Checking users + if [ "$user" = 'admin' ]; then + spnd=$(grep "SUSPENDED='yes'" $HESTIA/data/users/*/user.conf | wc -l) + SUSPENDED_USERS=$spnd + U_USERS=$($BIN/v-list-sys-users plain | wc -l) + fi + + ips=$(ls $HESTIA/data/ips) + # Checking ip + for ip in $ips; do + source $HESTIA/data/ips/$ip + if [ "$OWNER" = "$user" ]; then + IP_OWNED=$((IP_OWNED + 1)) + IP_AVAIL=$((IP_AVAIL + 1)) + fi + if [ "$OWNER" = 'admin' ] && [ "$STATUS" = 'shared' ]; then + IP_AVAIL=$((IP_AVAIL + 1)) + fi + done + if [ "$user" = 'admin' ]; then + IP_AVAIL=$(ls $HESTIA/data/ips | wc -l) + fi + + # Checking web system + U_WEB_DOMAINS=0 + if [ -f $USER_DATA/web.conf ]; then + for domain_str in $(cat $USER_DATA/web.conf); do + parse_object_kv_list "$domain_str" + U_DISK_WEB=$((U_DISK_WEB + U_DISK)) + U_WEB_DOMAINS=$((U_WEB_DOMAINS + 1)) + + if [ "$SSL" = 'yes' ]; then + U_WEB_SSL=$((U_WEB_SSL + 1)) + fi + if [ "$SUSPENDED" = 'yes' ]; then + SUSPENDED_WEB=$((SUSPENDED_WEB + 1)) + fi + if [ -n "$ALIAS" ]; then + aliases=$(echo "$ALIAS" | tr ',' '\n' | wc -l) + U_WEB_ALIASES=$((U_WEB_ALIASES + aliases)) + fi + BANDWIDTH=$((BANDWIDTH + U_BANDWIDTH)) + done + DISK=$((DISK + U_DISK_WEB)) + fi + + # Checking dns system + if [ -f $USER_DATA/dns.conf ]; then + for domain_str in $(cat $USER_DATA/dns.conf); do + parse_object_kv_list "$domain_str" + U_DNS_DOMAINS=$((U_DNS_DOMAINS + 1)) + records=$(wc -l $USER_DATA/dns/$DOMAIN.conf | cut -f 1 -d ' ') + U_DNS_RECORDS=$((U_DNS_RECORDS + records)) + if [ "$SUSPENDED" = 'yes' ]; then + SUSPENDED_DNS=$((SUSPENDED_DNS + 1)) + fi + update_object_value 'dns' 'DOMAIN' "$DOMAIN" '$RECORDS' "$records" + done + fi + + # Checking mail system + if [ -f $USER_DATA/mail.conf ]; then + for domain_str in $(cat $USER_DATA/mail.conf); do + parse_object_kv_list "$domain_str" + U_DISK_MAIL=$((U_DISK_MAIL + U_DISK)) + U_MAIL_DOMAINS=$((U_MAIL_DOMAINS + 1)) + accounts=$(wc -l $USER_DATA/mail/$DOMAIN.conf | cut -f 1 -d ' ') + U_MAIL_ACCOUNTS=$((U_MAIL_ACCOUNTS + accounts)) + if [ "$DKIM" = 'yes' ]; then + U_MAIL_DKIM=$((U_MAIL_DKIM + 1)) + fi + if [ "$SUSPENDED" = 'yes' ]; then + SUSPENDED_MAIL=$((SUSPENDED_MAIL + 1)) + fi + update_object_value 'mail' 'DOMAIN' "$DOMAIN" '$ACCOUNTS' "$accounts" + done + DISK=$((DISK + U_DISK_MAIL)) + fi + + # Checking db system + if [ -f $USER_DATA/db.conf ]; then + for db_str in $(cat $USER_DATA/db.conf); do + parse_object_kv_list "$db_str" + U_DISK_DB=$((U_DISK_DB + U_DISK)) + U_DATABASES=$((U_DATABASES + 1)) + if [ "$SUSPENDED" = 'yes' ]; then + SUSPENDED_DB=$((SUSPENDED_DB + 1)) + fi + done + DISK=$((DISK + U_DISK_DB)) + fi + + # Checking cron system + if [ -f $USER_DATA/cron.conf ]; then + for cron_str in $(cat $USER_DATA/cron.conf); do + parse_object_kv_list "$cron_str" + U_CRON_JOBS=$((U_CRON_JOBS + 1)) + if [ "$SUSPENDED" = 'yes' ]; then + SUSPENDED_CRON=$((SUSPENDED_CRON + 1)) + fi + done + fi + + # Checking backup + if [ -f $USER_DATA/backup.conf ]; then + for backup_str in $(cat $USER_DATA/backup.conf); do + U_BACKUPS=$((U_BACKUPS + 1)) + done + fi + + # Update values + U_DISK=$DISK + U_BANDWIDTH=$BANDWIDTH + update_user_value "$user" '$SUSPENDED_USERS' "$SUSPENDED_USERS" + update_user_value "$user" '$SUSPENDED_WEB' "$SUSPENDED_WEB" + update_user_value "$user" '$SUSPENDED_DNS' "$SUSPENDED_DNS" + update_user_value "$user" '$SUSPENDED_MAIL' "$SUSPENDED_MAIL" + update_user_value "$user" '$SUSPENDED_DB' "$SUSPENDED_DB" + update_user_value "$user" '$SUSPENDED_CRON' "$SUSPENDED_CRON" + update_user_value "$user" '$IP_AVAIL' "$IP_AVAIL" + update_user_value "$user" '$IP_OWNED' "$IP_OWNED" + update_user_value "$user" '$U_USERS' "$U_USERS" + update_user_value "$user" '$U_DISK' "$U_DISK" + update_user_value "$user" '$U_DISK_DIRS' "$U_DISK_DIRS" + update_user_value "$user" '$U_DISK_WEB' "$U_DISK_WEB" + update_user_value "$user" '$U_DISK_MAIL' "$U_DISK_MAIL" + update_user_value "$user" '$U_DISK_DB' "$U_DISK_DB" + update_user_value "$user" '$U_BANDWIDTH' "$U_BANDWIDTH" + update_user_value "$user" '$U_WEB_DOMAINS' "$U_WEB_DOMAINS" + update_user_value "$user" '$U_WEB_SSL' "$U_WEB_SSL" + update_user_value "$user" '$U_WEB_ALIASES' "$U_WEB_ALIASES" + update_user_value "$user" '$U_DNS_DOMAINS' "$U_DNS_DOMAINS" + update_user_value "$user" '$U_DNS_RECORDS' "$U_DNS_RECORDS" + update_user_value "$user" '$U_MAIL_DOMAINS' "$U_MAIL_DOMAINS" + update_user_value "$user" '$U_MAIL_DKIM' "$U_MAIL_DKIM" + update_user_value "$user" '$U_MAIL_ACCOUNTS' "$U_MAIL_ACCOUNTS" + update_user_value "$user" '$U_DATABASES' "$U_DATABASES" + update_user_value "$user" '$U_CRON_JOBS' "$U_CRON_JOBS" + update_user_value "$user" '$U_BACKUPS' "$U_BACKUPS" +done + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-update-user-disk b/bin/v-update-user-disk new file mode 100755 index 0000000..94cb160 --- /dev/null +++ b/bin/v-update-user-disk @@ -0,0 +1,60 @@ +#!/bin/bash +# info: update user disk usage +# options: USER +# +# example: v-update-user-disk admin +# +# The functions recalculates disk usage and updates database. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'USER' +is_format_valid 'user' +is_object_valid 'user' 'USER' "$user" + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Saving old IFS +OLDIFS=$IFS +IFS=$(echo -en "\n\b") + +#Starting update disk space excluding web, mail, conf directory +disk_usage='0' +disk_usage=$(du -shm $HOMEDIR/$user --exclude $HOMEDIR/$user/web --exclude $HOMEDIR/$user/mail --exclude $HOMEDIR/$user/conf | cut -f 1) + +# Restoring old IFS +IFS=$OLDIFS + +# Updating disk value in config +update_user_value "$user" '$U_DISK_DIRS' "$disk_usage" + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Recalculating user disk space +recalc_user_disk_usage + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-update-user-package b/bin/v-update-user-package new file mode 100755 index 0000000..44da010 --- /dev/null +++ b/bin/v-update-user-package @@ -0,0 +1,50 @@ +#!/bin/bash +# info: update user package +# options: PACKAGE +# +# example: v-update-user-package default +# +# This function propagates package to connected users. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +package=$1 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'PACKAGE' +is_format_valid 'package' +is_package_valid + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +for user in $($BIN/v-list-sys-users plain); do + check_package=$(grep "PACKAGE='$package'" $USER_DATA/$user/user.conf) + if [ -n "$check_package" ]; then + $BIN/v-change-user-package "$user" "$package" 'yes' + fi +done + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-update-user-quota b/bin/v-update-user-quota new file mode 100755 index 0000000..f14fe5b --- /dev/null +++ b/bin/v-update-user-quota @@ -0,0 +1,59 @@ +#!/bin/bash +# info: update user disk quota +# options: USER +# +# example: v-update-user-quota alice +# +# The functions upates disk quota for specific user + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '1' "$#" 'USER' +is_format_valid 'user' +is_object_valid 'user' 'USER' "$user" + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Update disk quota +# Hard quota quals package value. Soft quota equals 90% of package value. +quota=$(get_user_value '$DISK_QUOTA') +soft=$(echo "$quota * 1024" | bc | cut -f 1 -d .) +hard=$(echo "$quota * 1024" | bc | cut -f 1 -d .) + +# Searching home mount point +mnt=$(df -P /home | awk '{print $6}' | tail -n1) + +# Checking unlimited quota +if [ "$quota" = 'unlimited' ]; then + setquota $user 0 0 0 0 $mnt 2> /dev/null +else + setquota $user $soft $hard 0 0 $mnt 2> /dev/null +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-update-user-stats b/bin/v-update-user-stats new file mode 100755 index 0000000..46f0d97 --- /dev/null +++ b/bin/v-update-user-stats @@ -0,0 +1,172 @@ +#!/bin/bash +# info: update user statistics +# options: USER +# +# example: v-update-user-stats admin +# +# Function logs user parameters into statistics database. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 + +# Importing system environment as we run this script +# mostly by cron wich not read it by itself +source /etc/profile + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '0' "$#" 'USER' +if [ ! -z "$user" ]; then + is_format_valid 'user' + is_object_valid 'user' 'USER' "$user" +fi + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Creating user_list +if [ -z "$user" ]; then + user_list=$($BIN/v-list-sys-users plain) + update_overall_stats='yes' +else + user_list="$user" +fi + +# Reset overall statistics +TOTAL_IP_OWNED=0 +TOTAL_U_DISK=0 +TOTAL_U_DISK_DIRS=0 +TOTAL_U_DISK_WEB=0 +TOTAL_U_DISK_MAIL=0 +TOTAL_U_DISK_DB=0 +TOTAL_U_BANDWIDTH=0 +TOTAL_U_WEB_DOMAINS=0 +TOTAL_U_WEB_SSL=0 +TOTAL_U_WEB_ALIASES=0 +TOTAL_U_DNS_DOMAINS=0 +TOTAL_U_DNS_RECORDS=0 +TOTAL_U_MAIL_DOMAINS=0 +TOTAL_U_MAIL_DKIM=0 +TOTAL_U_MAIL_ACCOUNTS=0 +TOTAL_U_DATABASES=0 +TOTAL_U_CRON_JOBS=0 +TOTAL_U_BACKUPS=0 +TOTAL_USERS=0 + +# Updating user stats +for user in $user_list; do + USER_DATA=$HESTIA/data/users/$user + if [ ! -f "$HESTIA/data/users/$user/user.conf" ]; then + continue + fi + USER_DATA=$HESTIA/data/users/$user + source $USER_DATA/user.conf + next_month=$(date +'%m/01/%y' -d "$(date +%Y-%m-15) 1 month") + DATE=$(date -d "$next_month -1day" +%F) + + # Compiling report string + s="DATE='$DATE' TIME='$TIME' PACKAGE='$PACKAGE' IP_OWNED='$IP_OWNED'" + s="$s DISK_QUOTA='$DISK_QUOTA' U_DISK='$U_DISK'" + s="$s U_DISK_DIRS='$U_DISK_DIRS' U_DISK_WEB='$U_DISK_WEB'" + s="$s U_DISK_MAIL='$U_DISK_MAIL' U_DISK_DB='$U_DISK_DB'" + s="$s BANDWIDTH='$BANDWIDTH' U_BANDWIDTH='$U_BANDWIDTH'" + s="$s U_WEB_DOMAINS='$U_WEB_DOMAINS' U_WEB_SSL='$U_WEB_SSL'" + s="$s U_WEB_ALIASES='$U_WEB_ALIASES' U_DNS_DOMAINS='$U_DNS_DOMAINS'" + s="$s U_DNS_RECORDS='$U_DNS_RECORDS' U_MAIL_DOMAINS='$U_MAIL_DOMAINS'" + s="$s U_MAIL_DKIM='$U_MAIL_DKIM' U_MAIL_ACCOUNTS='$U_MAIL_ACCOUNTS'" + s="$s U_DATABASES='$U_DATABASES' U_CRON_JOBS='$U_CRON_JOBS'" + s="$s U_BACKUPS='$U_BACKUPS'" + + # Updating user stats log + stats="$USER_DATA/stats.log" + + # Checking duplicates + check_month=$(grep --no-messages -n "DATE='$DATE'" $stats | cut -f 1 -d :) + if [ -z "$check_month" ]; then + # Updating as there no duplicates + echo "$s" >> $stats + else + # Replacing string with new data + sed -i "$check_month s/.*/$s/" $stats + fi + chmod 660 $stats + + # Increase overall counters + TOTAL_IP_OWNED=$((TOTAL_IP_OWNED + IP_OWNED)) + TOTAL_U_DISK=$((TOTAL_U_DISK + U_DISK)) + TOTAL_U_DISK_DIRS=$((TOTAL_U_DISK_DIRS + U_DISK_DIRS)) + TOTAL_U_DISK_WEB=$((TOTAL_U_DISK_WEB + U_DISK_WEB)) + TOTAL_U_DISK_MAIL=$((TOTAL_U_DISK_MAIL + U_DISK_MAIL)) + TOTAL_U_DISK_DB=$((TOTAL_U_DISK_DB + U_DISK_DB)) + TOTAL_U_BANDWIDTH=$((TOTAL_U_BANDWIDTH + U_BANDWIDTH)) + TOTAL_U_WEB_DOMAINS=$((TOTAL_U_WEB_DOMAINS + U_WEB_DOMAINS)) + TOTAL_U_WEB_SSL=$((TOTAL_U_WEB_SSL + U_WEB_SSL)) + TOTAL_U_WEB_ALIASES=$((TOTAL_U_WEB_ALIASES + U_WEB_ALIASES)) + TOTAL_U_DNS_DOMAINS=$((TOTAL_U_DNS_DOMAINS + U_DNS_DOMAINS)) + TOTAL_U_DNS_RECORDS=$((TOTAL_U_DNS_RECORDS + U_DNS_RECORDS)) + TOTAL_U_MAIL_DOMAINS=$((TOTAL_U_MAIL_DOMAINS + U_MAIL_DOMAINS)) + TOTAL_U_MAIL_DKIM=$((TOTAL_U_MAIL_DKIM + U_MAIL_DKIM)) + TOTAL_U_MAIL_ACCOUNTS=$((TOTAL_U_MAIL_ACCOUNTS + U_MAIL_ACCOUNTS)) + TOTAL_U_DATABASES=$((TOTAL_U_DATABASES + U_DATABASES)) + TOTAL_U_CRON_JOBS=$((TOTAL_U_CRON_JOBS + U_CRON_JOBS)) + TOTAL_U_BACKUPS=$((TOTAL_U_BACKUPS + U_BACKUPS)) + TOTAL_USERS=$((TOTAL_USERS + 1)) + +done + +if [ "$update_overall_stats" = 'yes' ]; then + # Updating overall stats + stats="$HESTIA/data/users/admin/overall_stats.log" + + s="DATE='$DATE' TIME='$TIME' PACKAGE='default' IP_OWNED='$TOTAL_IP_OWNED'" + s="$s DISK_QUOTA='0' U_DISK='$TOTAL_U_DISK' U_DISK_DIRS='$TOTAL_U_DISK_DIRS'" + s="$s U_DISK_WEB='$TOTAL_U_DISK_WEB' U_DISK_MAIL='$TOTAL_U_DISK_MAIL'" + s="$s U_DISK_DB='$TOTAL_U_DISK_DB' BANDWIDTH='0'" + s="$s U_BANDWIDTH='$TOTAL_U_BANDWIDTH' U_WEB_DOMAINS='$TOTAL_U_WEB_DOMAINS'" + s="$s U_WEB_SSL='$TOTAL_U_WEB_SSL' U_WEB_ALIASES='$TOTAL_U_WEB_ALIASES'" + s="$s U_DNS_DOMAINS='$TOTAL_U_DNS_DOMAINS'" + s="$s U_DNS_RECORDS='$TOTAL_U_DNS_RECORDS'" + s="$s U_MAIL_DOMAINS='$TOTAL_U_MAIL_DOMAINS'" + s="$s U_MAIL_DKIM='$TOTAL_U_MAIL_DKIM'" + s="$s U_MAIL_ACCOUNTS='$TOTAL_U_MAIL_ACCOUNTS'" + s="$s U_DATABASES='$TOTAL_U_DATABASES'" + s="$s U_CRON_JOBS='$TOTAL_U_CRON_JOBS' U_BACKUPS='$TOTAL_U_BACKUPS'" + s="$s U_USERS='$TOTAL_USERS'" + + # Checking duplicates + check_month=$(grep --no-messages -n "DATE='$DATE'" $stats | cut -f 1 -d :) + if [ -z "$check_month" ]; then + # Updating as there no duplicates + echo "$s" >> $stats + else + # Replacing string with new data + sed -i "$check_month s/.*/$s/" $stats + fi + chmod 660 $stats +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-update-web-domain-disk b/bin/v-update-web-domain-disk new file mode 100755 index 0000000..1894119 --- /dev/null +++ b/bin/v-update-web-domain-disk @@ -0,0 +1,66 @@ +#!/bin/bash +# info: update disk usage for domain +# options: USER DOMAIN +# +# example: v-update-web-domain-disk alice wonderland.com +# +# This function recalculates disk usage for specific webdomain. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn +# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ? + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DOMAIN' +is_format_valid 'user' 'domain' +is_system_enabled "$WEB_SYSTEM" 'WEB_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_valid 'web' 'DOMAIN' "$domain" + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Defining home directory +home_dir="$HOMEDIR/$user/web/$domain/" + +# Checking home directory exist +if [ -e "$home_dir" ]; then + disk_usage=$(nice -n 19 du -shm $home_dir | cut -f 1) +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Updating disk value in config +update_object_value 'web' 'DOMAIN' "$domain" '$U_DISK' "$disk_usage" +recalc_user_disk_usage + +# Logging +log_event "$OK" "$ARGUMENTS" + +exit diff --git a/bin/v-update-web-domain-ssl b/bin/v-update-web-domain-ssl new file mode 100755 index 0000000..9cf2c39 --- /dev/null +++ b/bin/v-update-web-domain-ssl @@ -0,0 +1,97 @@ +#!/bin/bash +# info: updating ssl certificate for domain +# options: USER DOMAIN SSL_DIR [RESTART] +# +# example: v-update-web-domain-ssl admin domain.com /home/admin/tmp +# +# This function updates the SSL certificate for a domain. Parameter ssl_dir is a path +# to directory where 2 or 3 ssl files can be found. Certificate file +# domain.tld.crt and its key domain.tld.key are mandatory. Certificate +# authority domain.tld.ca file is optional. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 +ssl_dir=$3 +restart=$4 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# shellcheck source=/usr/local/hestia/func/ip.sh +source $HESTIA/func/ip.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn +# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ? + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '3' "$#" 'USER DOMAIN SSL_DIR [RESTART]' +is_format_valid 'user' 'domain' 'ssl_dir' +is_system_enabled "$WEB_SYSTEM" 'WEB_SYSTEM' +is_system_enabled "$WEB_SSL" 'SSL_SUPPORT' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'web' 'DOMAIN' "$domain" +is_object_unsuspended 'web' 'DOMAIN' "$domain" +is_object_value_exist 'web' 'DOMAIN' "$domain" '$SSL' +is_web_domain_cert_valid + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +# Deleting old certificate +rm -f $HOMEDIR/$user/conf/web/$domain/ssl/$domain.* +rm -f $USER_DATA/ssl/$domain.* + +# Adding certificate to user data directory +cp -f $ssl_dir/$domain.crt $USER_DATA/ssl/$domain.crt +cp -f $ssl_dir/$domain.key $USER_DATA/ssl/$domain.key +cp -f $ssl_dir/$domain.crt $USER_DATA/ssl/$domain.pem +if [ -e "$ssl_dir/$domain.ca" ]; then + cp -f $ssl_dir/$domain.ca $USER_DATA/ssl/$domain.ca + echo >> $USER_DATA/ssl/$domain.pem + cat $USER_DATA/ssl/$domain.ca >> $USER_DATA/ssl/$domain.pem +fi +chmod 660 $USER_DATA/ssl/$domain.* + +# Adding certificate to user dir +cp -f $USER_DATA/ssl/$domain.crt $HOMEDIR/$user/conf/web/$domain/ssl/$domain.crt +cp -f $USER_DATA/ssl/$domain.key $HOMEDIR/$user/conf/web/$domain/ssl/$domain.key +cp -f $USER_DATA/ssl/$domain.pem $HOMEDIR/$user/conf/web/$domain/ssl/$domain.pem +if [ -e "$USER_DATA/ssl/$domain.ca" ]; then + cp -f $USER_DATA/ssl/$domain.ca $HOMEDIR/$user/conf/web/$domain/ssl/$domain.ca +fi + +#----------------------------------------------------------# +# Hestia # +#----------------------------------------------------------# + +# Restarting web server +$BIN/v-restart-web "$restart" +check_result $? "Web restart failed" > /dev/null + +$BIN/v-restart-proxy "$restart" +check_result $? "Proxy restart failed" > /dev/null + +# Logging +$BIN/v-log-action "$user" "Info" "Web" "SSL certificate updated (Domain: $domain)." +log_event "$OK" "$EVENT" + +exit diff --git a/bin/v-update-web-domain-stat b/bin/v-update-web-domain-stat new file mode 100755 index 0000000..6720e70 --- /dev/null +++ b/bin/v-update-web-domain-stat @@ -0,0 +1,147 @@ +#!/bin/bash +# info: update domain statistics +# options: USER DOMAIN +# +# example: v-update-web-domain-stat alice acme.com +# +# This function runs log analyser for specific webdomain. + +#----------------------------------------------------------# +# Variables & Functions # +#----------------------------------------------------------# + +# Argument definition +user=$1 +domain=$2 +domain_idn=$2 + +# Includes +# shellcheck source=/etc/hestiacp/hestia.conf +source /etc/hestiacp/hestia.conf +# shellcheck source=/usr/local/hestia/func/main.sh +source $HESTIA/func/main.sh +# shellcheck source=/usr/local/hestia/func/domain.sh +source $HESTIA/func/domain.sh +# load config file +source_conf "$HESTIA/conf/hestia.conf" + +# Additional argument formatting +format_domain +format_domain_idn + +#----------------------------------------------------------# +# Verifications # +#----------------------------------------------------------# + +check_args '2' "$#" 'USER DOMAIN' +is_format_valid 'user' 'domain' +is_system_enabled "$WEB_SYSTEM" 'WEB_SYSTEM' +is_object_valid 'user' 'USER' "$user" +is_object_unsuspended 'user' 'USER' "$user" +is_object_valid 'web' 'DOMAIN' "$domain" +is_object_unsuspended 'web' 'DOMAIN' "$domain" +is_object_value_exist 'web' 'DOMAIN' "$domain" '$STATS' + +#----------------------------------------------------------# +# Action # +#----------------------------------------------------------# + +get_domain_values 'web' + +# Checking config +config="$HOMEDIR/$user/conf/web/$domain/$STATS.conf" +if [ ! -e "$config" ]; then + check_result $E_NOTEXISTS "$config doesn't exist" +fi + +# Checking statistics directory +dir="$HOMEDIR/$user/web/$domain/stats" +if [ ! -e "$dir" ]; then + mkdir -p $dir +fi + +# Defining functions +build_awstats() { + if [ -d "/etc/sysconfig" ]; then + awstats="/usr/share/awstats/wwwroot/cgi-bin/awstats.pl" + wwwroot="/usr/share/awstats/wwwroot" + if [ ! -e "$awstats" ]; then + awstats="/var/www/awstats/awstats.pl" + wwwroot="/var/www/awstats" + fi + else + awstats="/usr/lib/cgi-bin/awstats.pl" + wwwroot="/usr/share/awstats" + fi + opts="-config=$domain_idn -staticlinks -update -output" + month=$(date "+%Y-%m") + output='alldomains allhosts lasthosts unknownip allrobots lastrobots + urldetail urlentry urlexit osdetail browserdetail unknownbrowser + unknownos refererse refererpages keyphrases keywords errors404' + + # Checking statistics directory + if [ ! -e "$dir/$month" ]; then + mkdir -p $dir/$month + fi + + # Logo check + if [ ! -e "$dir/logo.svg" ]; then + cp -r $HESTIA/web/images/logo.svg $dir/ + fi + + # Icon directory check + if [ ! -e "$dir/icon" ]; then + cp -r $wwwroot/icon $dir/ + fi + + # Creating main awstats page + $awstats $opts | sed "s%awstats.$domain.%%g" > $dir/$month/index.html + + # Creating suplemental awstats pages + for format in $output; do + $awstats $opts=$format \ + | sed "s%awstats.$domain.%%g" > $dir/$month/$format.html + done + + # Creating index page + cat $WEBTPL/awstats/index.tpl | sed "s/%month%/$month/g" > $dir/index.html + + # Creating navigation page + months=$(find $dir -type d | sed -e "s%$dir/%%g" -e "s%$dir%%g" \ + | grep -v icon | sort -r) + for link in $months; do + year=$(echo $link | cut -f 1 -d \-) + month=$(echo $link | cut -f 2 -d \- | sed -e "s/^0//") + case "$month" in + 1) month='January' ;; + 2) month='February' ;; + 3) month='March' ;; + 4) month='April' ;; + 5) month='May' ;; + 6) month='June' ;; + 7) month='July' ;; + 8) month='August' ;; + 9) month='September' ;; + 10) month='October' ;; + 11) month='November' ;; + 12) month='December' ;; + esac + select_m="$select_m