From f4bb9e2e2ed78a1d34b8942dabd9d4df091a25a4 Mon Sep 17 00:00:00 2001 From: Stefan Date: Fri, 25 Oct 2024 01:44:26 +0200 Subject: [PATCH] Auto-commit on 2024-10-25 01:44:26 by pcx3 --- configuration/bind9/zone_template.txt | 2 +- .../docker/compose/new-docker-compose.yml | 16 + .../mysql/initialize/0.4/mariadb_plans.sql | 195 + .../mysql/initialize/0.4/mysql_plans.sql | 195 + .../nginx/vhosts/openpanel_proxy.conf | 2 +- configuration/openadmin/config/services.json | 6 + configuration/openpanel/conf/openpanel.config | 4 +- configuration/skeleton/notifications.yaml | 17 + integrations/cpanel-import/README.md | 63 +- .../cpanel-import/cp-import-my-version.sh | 1074 ++++++ integrations/cpanel-import/cp-import.sh | 718 ++-- integrations/cpanel-import/cpanel_import.py | 35 - .../templates/cpanel-import.html | 19 - integrations/digitalocean/.github/CODEOWNERS | 1 - .../digitalocean/.github/CONTRIBUTING.md | 27 - integrations/digitalocean/.gitignore | 43 - templates/admini/README.md | 1 - .../admini/apache_nginx_conf_editor.html | 122 + templates/admini/autoinstaller.html | 174 + templates/admini/base.html | 1248 +++++++ templates/admini/cronjobs.html | 1045 ++++++ .../{.gitkeep => custom_code/custom.css} | 0 templates/admini/custom_code/custom.js | 1 + templates/admini/custom_code/in_footer.html | 1 + templates/admini/custom_code/in_header.html | 1 + templates/admini/dashboard/dashboard.html | 1244 +++++++ .../dashboard/knowledge_base_articles.json | 1 + .../knowledge_base_articles_default.json | 11 + .../admini/databases/edit_mysql_config.html | 186 + templates/admini/databases/mysql.html | 743 ++++ templates/admini/databases/processlist.html | 37 + templates/admini/databases/remote_mysql.html | 191 + templates/admini/domains/domains.html | 892 +++++ templates/admini/domains/edit_dns_zone.html | 752 ++++ templates/admini/domains/edit_vhost.html | 19 + templates/admini/domains/logs.html | 25 + templates/admini/domains/logs_single.html | 1 + templates/admini/elasticsearch.html | 280 ++ templates/admini/emails/accounts.html | 395 ++ templates/admini/emails/single_account.html | 511 +++ templates/admini/error_pages/404.html | 1 + templates/admini/error_pages/500.html | 1 + templates/admini/files/backup.html | 540 +++ templates/admini/files/disk_usage.html | 255 ++ templates/admini/files/edit_file.html | 179 + templates/admini/files/filemanager.html | 2385 +++++++++++++ templates/admini/files/fix_permissions.html | 101 + templates/admini/files/ftp.html | 530 +++ templates/admini/files/inodes.html | 228 ++ templates/admini/flarum.html | 708 ++++ templates/admini/ip_blocker.html | 153 + templates/admini/malware_scanner.html | 163 + templates/admini/manager/.gitkeep | 0 templates/admini/manager/flarum.html | 1017 ++++++ templates/admini/manager/nodejs.html | 865 +++++ templates/admini/manager/python.html | 863 +++++ templates/admini/manager/wordpress.html | 2229 ++++++++++++ templates/admini/mautic.html | 710 ++++ templates/admini/memcached.html | 320 ++ templates/admini/partials/_shortcuts.html | 259 ++ templates/admini/partials/notifications.html | 42 + templates/admini/partials/pagespeed.html | 200 ++ .../admini/partials/phpmyadmin_link.html | 89 + templates/admini/partials/screenshot.html | 18 + templates/admini/partials/sidebar.html | 936 +++++ templates/admini/php/ini_editor.html | 71 + templates/admini/php/settings.html | 516 +++ templates/admini/pm2.html | 535 +++ templates/admini/process_manager.html | 114 + templates/admini/redis.html | 321 ++ templates/admini/sites.html | 68 + templates/admini/ssh.html | 214 ++ templates/admini/ssl.html | 384 ++ templates/admini/system/general.html | 139 + templates/admini/system/modsecurity.html | 208 ++ templates/admini/system/server_info.html | 129 + templates/admini/system/services_status.html | 311 ++ templates/admini/system/timezone.html | 78 + templates/admini/terminal/landing.html | 15 + templates/admini/terminal/running.html | 55 + templates/admini/user/account.html | 279 ++ templates/admini/user/activity.html | 372 ++ .../admini/user/forgot_password.html_TODO | 101 + templates/admini/user/history_usage.html | 250 ++ templates/admini/user/login.html | 189 + templates/admini/user/loginlog.html | 105 + templates/admini/user/notifications.html | 28 + templates/admini/user/stats.html | 184 + templates/admini/user/twofa_settings.html | 187 + templates/admini/websites.html | 3164 +++++++++++++++++ templates/admini/wordpress.html | 984 +++++ templates/tabler/README.md | 1 - templates/tabler/backups.html | 2962 +++++++++++++++ templates/tabler/base.html | 1123 ++++++ templates/tabler/cluster.html | 61 + .../tabler/dashboard/cpu_per_core_usage.html | 156 + templates/tabler/dashboard/dashboard.html | 687 ++++ templates/tabler/dashboard/get_started.html | 70 + .../tabler/dashboard/openpanel_news.html | 131 + .../tabler/dashboard/try_enterprise.html | 92 + templates/tabler/dashboard/usage_graphs.html | 170 + templates/tabler/domains/domains.html | 271 ++ templates/tabler/domains/logs.html | 25 + templates/tabler/domains/logs_single.html | 1 + templates/tabler/emails/accounts.html | 94 + templates/tabler/emails/data/.gitkeep | 1 + .../emails/mailserver_is_not_installed.html | 13 + .../tabler/emails/mailserver_is_stopped.html | 43 + templates/tabler/emails/queue.html | 1 + templates/tabler/emails/reports.html | 4 + templates/tabler/emails/settings.html | 1176 ++++++ templates/tabler/emails/webmail.html | 31 + templates/tabler/license.html | 287 ++ templates/tabler/license_error.html | 77 + templates/tabler/login.html | 216 ++ templates/tabler/notifications.html | 674 ++++ templates/tabler/plans.html | 1897 ++++++++++ templates/tabler/security/csf.html | 17 + .../tabler/security/firewall_settings.html | 912 +++++ .../tabler/security/modsecurity_settings.html | 839 +++++ templates/tabler/server/crons.html | 104 + templates/tabler/server/root_password.html | 80 + templates/tabler/server/ssh.html | 170 + templates/tabler/server/timezone.html | 77 + .../tabler/services/docker_settings.html | 387 ++ templates/tabler/services/ftp.html | 176 + templates/tabler/services/logs.html | 113 + templates/tabler/services/nginx.html | 348 ++ templates/tabler/services/resources.html | 106 + templates/tabler/services/status.html | 277 ++ templates/tabler/settings/admin.html | 472 +++ templates/tabler/settings/api.html | 306 ++ templates/tabler/settings/general.html | 585 +++ templates/tabler/settings/settings.html | 153 + templates/tabler/settings/user.html | 331 ++ templates/tabler/system/404.html | 62 + templates/tabler/system/cpu_mem.html | 129 + templates/tabler/system/custom.html | 1 + .../tabler/system/email_system_report.html | 327 ++ templates/tabler/system/email_template.html | 355 ++ templates/tabler/system/new_user_email.html | 162 + templates/tabler/terms.html | 152 + templates/tabler/users/add.html | 203 ++ templates/tabler/users/all.html | 212 ++ .../tabler/users/import/display_users.html | 38 + .../tabler/users/import/import_users.html | 19 + .../users/import/list_import_cp_logs.html | 162 + templates/tabler/users/single.html | 1492 ++++++++ translations/install.sh | 8 +- 149 files changed, 50757 insertions(+), 373 deletions(-) create mode 100644 configuration/mysql/initialize/0.4/mariadb_plans.sql create mode 100644 configuration/mysql/initialize/0.4/mysql_plans.sql create mode 100644 configuration/skeleton/notifications.yaml create mode 100644 integrations/cpanel-import/cp-import-my-version.sh delete mode 100644 integrations/cpanel-import/cpanel_import.py delete mode 100644 integrations/cpanel-import/templates/cpanel-import.html delete mode 100644 integrations/digitalocean/.github/CODEOWNERS delete mode 100644 integrations/digitalocean/.github/CONTRIBUTING.md delete mode 100644 integrations/digitalocean/.gitignore delete mode 100644 templates/admini/README.md create mode 100644 templates/admini/apache_nginx_conf_editor.html create mode 100644 templates/admini/autoinstaller.html create mode 100644 templates/admini/base.html create mode 100644 templates/admini/cronjobs.html rename templates/admini/{.gitkeep => custom_code/custom.css} (100%) create mode 100644 templates/admini/custom_code/custom.js create mode 100644 templates/admini/custom_code/in_footer.html create mode 100644 templates/admini/custom_code/in_header.html create mode 100644 templates/admini/dashboard/dashboard.html create mode 100644 templates/admini/dashboard/knowledge_base_articles.json create mode 100644 templates/admini/dashboard/knowledge_base_articles_default.json create mode 100644 templates/admini/databases/edit_mysql_config.html create mode 100644 templates/admini/databases/mysql.html create mode 100644 templates/admini/databases/processlist.html create mode 100644 templates/admini/databases/remote_mysql.html create mode 100644 templates/admini/domains/domains.html create mode 100644 templates/admini/domains/edit_dns_zone.html create mode 100644 templates/admini/domains/edit_vhost.html create mode 100644 templates/admini/domains/logs.html create mode 100644 templates/admini/domains/logs_single.html create mode 100644 templates/admini/elasticsearch.html create mode 100644 templates/admini/emails/accounts.html create mode 100644 templates/admini/emails/single_account.html create mode 100644 templates/admini/error_pages/404.html create mode 100644 templates/admini/error_pages/500.html create mode 100644 templates/admini/files/backup.html create mode 100644 templates/admini/files/disk_usage.html create mode 100644 templates/admini/files/edit_file.html create mode 100644 templates/admini/files/filemanager.html create mode 100644 templates/admini/files/fix_permissions.html create mode 100644 templates/admini/files/ftp.html create mode 100644 templates/admini/files/inodes.html create mode 100644 templates/admini/flarum.html create mode 100644 templates/admini/ip_blocker.html create mode 100644 templates/admini/malware_scanner.html create mode 100644 templates/admini/manager/.gitkeep create mode 100644 templates/admini/manager/flarum.html create mode 100644 templates/admini/manager/nodejs.html create mode 100644 templates/admini/manager/python.html create mode 100644 templates/admini/manager/wordpress.html create mode 100644 templates/admini/mautic.html create mode 100644 templates/admini/memcached.html create mode 100644 templates/admini/partials/_shortcuts.html create mode 100644 templates/admini/partials/notifications.html create mode 100644 templates/admini/partials/pagespeed.html create mode 100644 templates/admini/partials/phpmyadmin_link.html create mode 100644 templates/admini/partials/screenshot.html create mode 100644 templates/admini/partials/sidebar.html create mode 100644 templates/admini/php/ini_editor.html create mode 100644 templates/admini/php/settings.html create mode 100644 templates/admini/pm2.html create mode 100644 templates/admini/process_manager.html create mode 100644 templates/admini/redis.html create mode 100644 templates/admini/sites.html create mode 100644 templates/admini/ssh.html create mode 100644 templates/admini/ssl.html create mode 100644 templates/admini/system/general.html create mode 100644 templates/admini/system/modsecurity.html create mode 100644 templates/admini/system/server_info.html create mode 100644 templates/admini/system/services_status.html create mode 100644 templates/admini/system/timezone.html create mode 100644 templates/admini/terminal/landing.html create mode 100644 templates/admini/terminal/running.html create mode 100644 templates/admini/user/account.html create mode 100644 templates/admini/user/activity.html create mode 100644 templates/admini/user/forgot_password.html_TODO create mode 100644 templates/admini/user/history_usage.html create mode 100644 templates/admini/user/login.html create mode 100644 templates/admini/user/loginlog.html create mode 100644 templates/admini/user/notifications.html create mode 100644 templates/admini/user/stats.html create mode 100644 templates/admini/user/twofa_settings.html create mode 100644 templates/admini/websites.html create mode 100644 templates/admini/wordpress.html delete mode 100644 templates/tabler/README.md create mode 100644 templates/tabler/backups.html create mode 100644 templates/tabler/base.html create mode 100644 templates/tabler/cluster.html create mode 100644 templates/tabler/dashboard/cpu_per_core_usage.html create mode 100644 templates/tabler/dashboard/dashboard.html create mode 100644 templates/tabler/dashboard/get_started.html create mode 100644 templates/tabler/dashboard/openpanel_news.html create mode 100644 templates/tabler/dashboard/try_enterprise.html create mode 100644 templates/tabler/dashboard/usage_graphs.html create mode 100644 templates/tabler/domains/domains.html create mode 100644 templates/tabler/domains/logs.html create mode 100644 templates/tabler/domains/logs_single.html create mode 100644 templates/tabler/emails/accounts.html create mode 100644 templates/tabler/emails/data/.gitkeep create mode 100644 templates/tabler/emails/mailserver_is_not_installed.html create mode 100644 templates/tabler/emails/mailserver_is_stopped.html create mode 100644 templates/tabler/emails/queue.html create mode 100644 templates/tabler/emails/reports.html create mode 100644 templates/tabler/emails/settings.html create mode 100644 templates/tabler/emails/webmail.html create mode 100644 templates/tabler/license.html create mode 100644 templates/tabler/license_error.html create mode 100644 templates/tabler/login.html create mode 100644 templates/tabler/notifications.html create mode 100644 templates/tabler/plans.html create mode 100644 templates/tabler/security/csf.html create mode 100644 templates/tabler/security/firewall_settings.html create mode 100644 templates/tabler/security/modsecurity_settings.html create mode 100644 templates/tabler/server/crons.html create mode 100644 templates/tabler/server/root_password.html create mode 100644 templates/tabler/server/ssh.html create mode 100644 templates/tabler/server/timezone.html create mode 100644 templates/tabler/services/docker_settings.html create mode 100644 templates/tabler/services/ftp.html create mode 100644 templates/tabler/services/logs.html create mode 100644 templates/tabler/services/nginx.html create mode 100644 templates/tabler/services/resources.html create mode 100644 templates/tabler/services/status.html create mode 100644 templates/tabler/settings/admin.html create mode 100644 templates/tabler/settings/api.html create mode 100644 templates/tabler/settings/general.html create mode 100644 templates/tabler/settings/settings.html create mode 100644 templates/tabler/settings/user.html create mode 100644 templates/tabler/system/404.html create mode 100644 templates/tabler/system/cpu_mem.html create mode 100644 templates/tabler/system/custom.html create mode 100644 templates/tabler/system/email_system_report.html create mode 100644 templates/tabler/system/email_template.html create mode 100644 templates/tabler/system/new_user_email.html create mode 100644 templates/tabler/terms.html create mode 100644 templates/tabler/users/add.html create mode 100644 templates/tabler/users/all.html create mode 100644 templates/tabler/users/import/display_users.html create mode 100644 templates/tabler/users/import/import_users.html create mode 100644 templates/tabler/users/import/list_import_cp_logs.html create mode 100644 templates/tabler/users/single.html diff --git a/configuration/bind9/zone_template.txt b/configuration/bind9/zone_template.txt index d7c3a5b0..e01cda8e 100644 --- a/configuration/bind9/zone_template.txt +++ b/configuration/bind9/zone_template.txt @@ -1,6 +1,6 @@ $TTL 1h @ IN SOA {ns1}. {ns2}. ( - 2024101501 ; Serial number + 2024102401 ; Serial number 1h ; Refresh interval 15m ; Retry interval 1w ; Expire interval diff --git a/configuration/docker/compose/new-docker-compose.yml b/configuration/docker/compose/new-docker-compose.yml index b6aeef00..3cfad780 100644 --- a/configuration/docker/compose/new-docker-compose.yml +++ b/configuration/docker/compose/new-docker-compose.yml @@ -19,12 +19,26 @@ services: cpus: 1.0 oom_kill_disable: true + # Malware Scanner used from user panel + clamav: + image: clamav/clamav:latest + container_name: clamav + volumes: + - /home:/home + - ./clamav-db:/var/lib/clamav + restart: unless-stopped + environment: + - CLAMD_STARTUP_DELAY=30 + mem_limit: 0.25g + cpus: 0.25 + # OpenPanel service running on port 2083 openpanel: image: openpanel/openpanel container_name: openpanel depends_on: - openpanel_mysql + #- clamav cap_add: - NET_ADMIN - SYS_MODULE @@ -53,6 +67,8 @@ services: - /etc/openpanel/openpanel/custom_code/custom.css:/usr/local/panel/static/css/custom.css - /etc/openpanel/openpanel/custom_code/custom.js:/usr/local/panel/static/js/custom.js - /etc/openpanel/openpanel/conf/knowledge_base_articles.json:/etc/openpanel/openpanel/conf/knowledge_base_articles.json + # localization + - /etc/openpanel/openpanel/translations/:/etc/openpanel/openpanel/translations/ network_mode: host mem_limit: 1g cpus: 1.0 diff --git a/configuration/mysql/initialize/0.4/mariadb_plans.sql b/configuration/mysql/initialize/0.4/mariadb_plans.sql new file mode 100644 index 00000000..819b2b5c --- /dev/null +++ b/configuration/mysql/initialize/0.4/mariadb_plans.sql @@ -0,0 +1,195 @@ +-- MySQL dump 10.13 Distrib 8.0.36, for Linux (x86_64) +-- +-- Host: localhost Database: panel +-- ------------------------------------------------------ +-- Server version 8.0.36-0ubuntu0.22.04.1 + +SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; +START TRANSACTION; +SET time_zone = "+00:00"; + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8mb4 */; + +-- +-- Database: `panel` +-- + +-- -------------------------------------------------------- + +-- +-- Table structure for table `domains` +-- + +CREATE TABLE `domains` ( + `domain_id` int NOT NULL, + `domain_name` varchar(255) NOT NULL, + `domain_url` varchar(255) NOT NULL, + `user_id` int DEFAULT NULL, + `php_version` varchar(255) DEFAULT '8.2' +) ENGINE=InnoDB DEFAULT CHARSET=latin1; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `plans` +-- + +CREATE TABLE `plans` ( + `id` int NOT NULL, + `name` varchar(255) NOT NULL, + `description` text, + `domains_limit` int NOT NULL, + `websites_limit` int NOT NULL, + `email_limit` int NOT NULL DEFAULT 0, + `ftp_limit` int NOT NULL DEFAULT 0, + `disk_limit` text NOT NULL, + `inodes_limit` bigint NOT NULL, + `db_limit` int NOT NULL, + `cpu` varchar(50) DEFAULT NULL, + `ram` varchar(50) DEFAULT NULL, + `docker_image` varchar(50) DEFAULT NULL, + `bandwidth` int DEFAULT NULL, + `storage_file` text DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + + +-- +-- Dumping data for table `plans` +-- + +LOCK TABLES `plans` WRITE; +/*!40000 ALTER TABLE `plans` DISABLE KEYS */; +INSERT INTO `plans` VALUES (1,'ubuntu_nginx_mysql','Unlimited disk space and Nginx',0,10,0,0,'10 GB',1000000,0,'1','1g','openpanel/nginx',100,'0 GB'),(2,'ubuntu_apache_mysql','Unlimited disk space and Apache',0,10,0,0,'10 GB',1000000,0,'1','1g','openpanel/apache',100,'0 GB'),(3,'ubuntu_apache_mariadb','Unlimited disk space and Apache+MariaDB',0,10,0,0,'10 GB',1000000,0,'1','1g','openpanel/apache-mariadb',100,'0 GB'),(4,'ubuntu_nginx_mariadb','Unlimited disk space and Nginx+MariaDB',0,10,0,0,'10 GB',1000000,0,'1','1g','openpanel/nginx-mariadb',100,'0 GB'); +/*!40000 ALTER TABLE `plans` ENABLE KEYS */; +UNLOCK TABLES; + + + + +-- -------------------------------------------------------- + +-- +-- Table structure for table `sites` +-- + +CREATE TABLE `sites` ( + `id` int NOT NULL, + `site_name` varchar(255) DEFAULT NULL, + `domain_id` int DEFAULT NULL, + `admin_email` varchar(255) DEFAULT NULL, + `version` varchar(20) DEFAULT NULL, + `created_date` datetime DEFAULT CURRENT_TIMESTAMP, + `type` varchar(50) DEFAULT NULL, + `ports` int DEFAULT NULL, + `path` varchar(255) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `users` +-- + +CREATE TABLE `users` ( + `id` int NOT NULL, + `username` varchar(255) NOT NULL, + `password` varchar(255) NOT NULL, + `email` varchar(255) NOT NULL, + `services` varchar(255) CHARACTER SET latin1 COLLATE latin1_swedish_ci DEFAULT '1,2,3,4,5,6,7,8,9,10,11,12', + `user_domains` varchar(255) NOT NULL DEFAULT '', + `twofa_enabled` tinyint(1) DEFAULT '0', + `otp_secret` varchar(255) DEFAULT NULL, + `plan` varchar(255) CHARACTER SET latin1 COLLATE latin1_swedish_ci DEFAULT NULL, + `registered_date` timestamp NULL DEFAULT CURRENT_TIMESTAMP, + `server` varchar(255) DEFAULT 'default', + `plan_id` int DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1; + +-- +-- Indexes for dumped tables +-- + +-- +-- Indexes for table `domains` +-- +ALTER TABLE `domains` + ADD PRIMARY KEY (`domain_id`), + ADD KEY `user_id` (`user_id`); + +-- +-- Indexes for table `plans` +-- +ALTER TABLE `plans` + ADD PRIMARY KEY (`id`); + +-- +-- Indexes for table `sites` +-- +ALTER TABLE `sites` + ADD PRIMARY KEY (`id`), + ADD KEY `fk_sites_domain` (`domain_id`); + +-- +-- Indexes for table `users` +-- +ALTER TABLE `users` + ADD PRIMARY KEY (`id`), + ADD KEY `fk_plan_id` (`plan_id`); + +-- +-- AUTO_INCREMENT for dumped tables +-- + +-- +-- AUTO_INCREMENT for table `domains` +-- +ALTER TABLE `domains` + MODIFY `domain_id` int NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=1; + +-- +-- AUTO_INCREMENT for table `plans` +-- +ALTER TABLE `plans` + MODIFY `id` int NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=5; + +-- +-- AUTO_INCREMENT for table `sites` +-- +ALTER TABLE `sites` + MODIFY `id` int NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=1; + +-- +-- AUTO_INCREMENT for table `users` +-- +ALTER TABLE `users` + MODIFY `id` int NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=1; + +-- +-- Constraints for dumped tables +-- + +-- +-- Constraints for table `domains` +-- +ALTER TABLE `domains` + ADD CONSTRAINT `domains_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`); + +-- +-- Constraints for table `sites` +-- +ALTER TABLE `sites` + ADD CONSTRAINT `fk_sites_domain` FOREIGN KEY (`domain_id`) REFERENCES `domains` (`domain_id`); + +-- +-- Constraints for table `users` +-- +ALTER TABLE `users` + ADD CONSTRAINT `fk_plan_id` FOREIGN KEY (`plan_id`) REFERENCES `plans` (`id`) ON DELETE SET NULL; +COMMIT; + +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; diff --git a/configuration/mysql/initialize/0.4/mysql_plans.sql b/configuration/mysql/initialize/0.4/mysql_plans.sql new file mode 100644 index 00000000..8f87d303 --- /dev/null +++ b/configuration/mysql/initialize/0.4/mysql_plans.sql @@ -0,0 +1,195 @@ +-- MySQL dump 10.13 Distrib 8.0.36, for Linux (x86_64) +-- +-- Host: localhost Database: panel +-- ------------------------------------------------------ +-- Server version 8.0.36-0ubuntu0.22.04.1 + +SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; +START TRANSACTION; +SET time_zone = "+00:00"; + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8mb4 */; + +-- +-- Database: `panel` +-- + +-- -------------------------------------------------------- + +-- +-- Table structure for table `domains` +-- + +CREATE TABLE `domains` ( + `domain_id` int NOT NULL, + `domain_name` varchar(255) NOT NULL, + `domain_url` varchar(255) NOT NULL, + `user_id` int DEFAULT NULL, + `php_version` varchar(255) DEFAULT '8.2' +) ENGINE=InnoDB DEFAULT CHARSET=latin1; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `plans` +-- + +CREATE TABLE `plans` ( + `id` int NOT NULL, + `name` varchar(255) NOT NULL, + `description` text, + `domains_limit` int NOT NULL, + `websites_limit` int NOT NULL, + `email_limit` int NOT NULL DEFAULT 0, + `ftp_limit` int NOT NULL DEFAULT 0, + `disk_limit` text NOT NULL, + `inodes_limit` bigint NOT NULL, + `db_limit` int NOT NULL, + `cpu` varchar(50) DEFAULT NULL, + `ram` varchar(50) DEFAULT NULL, + `docker_image` varchar(50) DEFAULT NULL, + `bandwidth` int DEFAULT NULL, + `storage_file` text DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + + +-- +-- Dumping data for table `plans` +-- + +LOCK TABLES `plans` WRITE; +/*!40000 ALTER TABLE `plans` DISABLE KEYS */; +INSERT INTO `plans` VALUES (1,'ubuntu_nginx_mysql','Unlimited disk space and Nginx',0,10,0,0,'10 GB',1000000,0,'1','1g','openpanel/nginx',100,'0 GB'),(2,'ubuntu_apache_mysql','Unlimited disk space and Apache',0,10,0,0,'10 GB',1000000,0,'1','1g','openpanel/apache',100,'0 GB'); +/*!40000 ALTER TABLE `plans` ENABLE KEYS */; +UNLOCK TABLES; + + + + +-- -------------------------------------------------------- + +-- +-- Table structure for table `sites` +-- + +CREATE TABLE `sites` ( + `id` int NOT NULL, + `site_name` varchar(255) DEFAULT NULL, + `domain_id` int DEFAULT NULL, + `admin_email` varchar(255) DEFAULT NULL, + `version` varchar(20) DEFAULT NULL, + `created_date` datetime DEFAULT CURRENT_TIMESTAMP, + `type` varchar(50) DEFAULT NULL, + `ports` int DEFAULT NULL, + `path` varchar(255) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `users` +-- + +CREATE TABLE `users` ( + `id` int NOT NULL, + `username` varchar(255) NOT NULL, + `password` varchar(255) NOT NULL, + `email` varchar(255) NOT NULL, + `services` varchar(255) CHARACTER SET latin1 COLLATE latin1_swedish_ci DEFAULT '1,2,3,4,5,6,7,8,9,10,11,12', + `user_domains` varchar(255) NOT NULL DEFAULT '', + `twofa_enabled` tinyint(1) DEFAULT '0', + `otp_secret` varchar(255) DEFAULT NULL, + `plan` varchar(255) CHARACTER SET latin1 COLLATE latin1_swedish_ci DEFAULT NULL, + `registered_date` timestamp NULL DEFAULT CURRENT_TIMESTAMP, + `server` varchar(255) DEFAULT 'default', + `plan_id` int DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1; + +-- +-- Indexes for dumped tables +-- + +-- +-- Indexes for table `domains` +-- +ALTER TABLE `domains` + ADD PRIMARY KEY (`domain_id`), + ADD KEY `user_id` (`user_id`); + +-- +-- Indexes for table `plans` +-- +ALTER TABLE `plans` + ADD PRIMARY KEY (`id`); + +-- +-- Indexes for table `sites` +-- +ALTER TABLE `sites` + ADD PRIMARY KEY (`id`), + ADD KEY `fk_sites_domain` (`domain_id`); + +-- +-- Indexes for table `users` +-- +ALTER TABLE `users` + ADD PRIMARY KEY (`id`), + ADD KEY `fk_plan_id` (`plan_id`); + +-- +-- AUTO_INCREMENT for dumped tables +-- + +-- +-- AUTO_INCREMENT for table `domains` +-- +ALTER TABLE `domains` + MODIFY `domain_id` int NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=1; + +-- +-- AUTO_INCREMENT for table `plans` +-- +ALTER TABLE `plans` + MODIFY `id` int NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=3; + +-- +-- AUTO_INCREMENT for table `sites` +-- +ALTER TABLE `sites` + MODIFY `id` int NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=1; + +-- +-- AUTO_INCREMENT for table `users` +-- +ALTER TABLE `users` + MODIFY `id` int NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=1; + +-- +-- Constraints for dumped tables +-- + +-- +-- Constraints for table `domains` +-- +ALTER TABLE `domains` + ADD CONSTRAINT `domains_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`); + +-- +-- Constraints for table `sites` +-- +ALTER TABLE `sites` + ADD CONSTRAINT `fk_sites_domain` FOREIGN KEY (`domain_id`) REFERENCES `domains` (`domain_id`); + +-- +-- Constraints for table `users` +-- +ALTER TABLE `users` + ADD CONSTRAINT `fk_plan_id` FOREIGN KEY (`plan_id`) REFERENCES `plans` (`id`) ON DELETE SET NULL; +COMMIT; + +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; diff --git a/configuration/nginx/vhosts/openpanel_proxy.conf b/configuration/nginx/vhosts/openpanel_proxy.conf index efb5ff17..8bf8bee0 100644 --- a/configuration/nginx/vhosts/openpanel_proxy.conf +++ b/configuration/nginx/vhosts/openpanel_proxy.conf @@ -10,5 +10,5 @@ location /openadmin { # roundcube location /webmail { - return 301 https://webmail.localhost/; + return 301 http://127.0.0.1/; } diff --git a/configuration/openadmin/config/services.json b/configuration/openadmin/config/services.json index c8c92f7d..5669654d 100644 --- a/configuration/openadmin/config/services.json +++ b/configuration/openadmin/config/services.json @@ -53,6 +53,12 @@ "on_dashboard": true, "real_name": "openpanel_dns" }, + { + "name": "Malware Scanner", + "type": "docker", + "on_dashboard": false, + "real_name": "clamav" + }, { "name": "SSL", "type": "docker", diff --git a/configuration/openpanel/conf/openpanel.config b/configuration/openpanel/conf/openpanel.config index cd6fd982..e209878a 100644 --- a/configuration/openpanel/conf/openpanel.config +++ b/configuration/openpanel/conf/openpanel.config @@ -23,9 +23,7 @@ ns3= ns4= email= logout_url= -enabled_modules=dns,favorites,phpmyadmin,temporary_links,ssh,crons,backups,wordpress,pm2,disk_usage,inodes,usage,terminal,services,webserver,fix_permissions,process_manager,ip_blocker,redis,memcached,login_history,activity,twofa,domains_visitors - -available_modules=malware_scan, elasticsearch +enabled_modules=dns,favorites,phpmyadmin,temporary_links,ssh,crons,backups,wordpress,flarum,pm2,disk_usage,inodes,usage,terminal,services,webserver,fix_permissions,process_manager,ip_blocker,redis,memcached,login_history,activity,twofa,domains_visitors [USERS] password_reset=no diff --git a/configuration/skeleton/notifications.yaml b/configuration/skeleton/notifications.yaml new file mode 100644 index 00000000..64de4e60 --- /dev/null +++ b/configuration/skeleton/notifications.yaml @@ -0,0 +1,17 @@ +notify_account_login=1 +notify_account_login_for_known_netblock=1 +notify_account_login_notification_disabled=1 +notify_autossl_expiry=0 +notify_autossl_expiry_coverage=0 +notify_autossl_renewal_coverage=0 +notify_autossl_renewal_coverage_reduced=0 +notify_autossl_renewal_uncovered_domains=0 +notify_contact_address_change=1 +notify_contact_address_change_notification_disabled=1 +notify_disk_limit=1 +notify_email_quota_limit=1 +notify_password_change=1 +notify_password_change_notification_disabled=1 +notify_ssl_expiry=1 +notify_twofactorauth_change=1 +notify_twofactorauth_change_notification_disabled=1 diff --git a/integrations/cpanel-import/README.md b/integrations/cpanel-import/README.md index bb205b03..8e5d32d9 100644 --- a/integrations/cpanel-import/README.md +++ b/integrations/cpanel-import/README.md @@ -1,4 +1,4 @@ -# cPanel 2 OpenPanel user import +# cPanel 2 OpenPanel account import Free OpenPanel module to import cPanel backup in OpenPanel Maintained by [CodeWithJuber](https://github.com/CodeWithJuber) @@ -6,43 +6,37 @@ Maintained by [CodeWithJuber](https://github.com/CodeWithJuber) ## Features Currently suported for import: +``` +├─ DOMAINS: +│ ├─ Primary domain, Addons, Aliases and Subdomains +│ ├─ SSL certificates +│ ├─ Domains access logs (Apache domlogs) +│ └─ DNS zones +├─ WEBSITES: +│ └─ WordPress instalations from WPToolkit & Softaculous +├─ DATABASES: +│ ├─ Remote access to MySQL +│ └─ MySQL databases, users and grants +├─ PHP: +│ └─ Installed version from Cloudlinux PHP Selector +├─ FILES +├─ CRONS +├─ SSH +│ ├─ Remote SSH access +│ ├─ SSH password +│ └─ SSH keys +└─ ACCOUNT + ├─ Notification preferences + ├─ cPanel account creation date + └─ locale -- files and folders -- mysql databases, users and grants -- domains -- dns zones -- php version -- wp sites -- cronjobs - -todo: - -- ftp accounts -- email accounts -- nodejs/python apps -- postgresql -- ssh keys -- ssl certificates - -Steps: - - -# cPanel to OpenPanel Migration Script - -This script automates the process of migrating a cPanel backup to OpenPanel server. It handles various cPanel backup formats and restores essential components of the user's account. - -## Features - -- Supports multiple cPanel backup formats (cpmove, full backup, tar.gz, tgz, tar, zip) -- Restores user account details, domains, and hosting plan settings -- Migrates websites, databases, domains, SSL certificates, and DNS zones -- Handles PHP version settings and cron jobs -- Restores SSH access and file permissions +***emails, ftp, nodejs/python, postgres are not yet supported*** +``` ## Usage -1. Run the script with sudo privileges: +Run the script with sudo privileges: ``` git clone https://github.com/stefanpejcic/cPanel-to-OpenPanel @@ -55,7 +49,8 @@ bash cPanel-to-OpenPanel/cp-import.sh --backup-location /path/to/cpanel_backup.f ## Parameters - `--backup-location`: Path to the cPanel backup file (required) -- `--plan-name`: Name of the hosting plan in OpenPanel (required) +- `--plan-name`: Name of the hosting plan in OpenPanel (required) +- `--dry-run`: extract archive and display data without actually importing account (optional) ## Important Notes diff --git a/integrations/cpanel-import/cp-import-my-version.sh b/integrations/cpanel-import/cp-import-my-version.sh new file mode 100644 index 00000000..dc05721a --- /dev/null +++ b/integrations/cpanel-import/cp-import-my-version.sh @@ -0,0 +1,1074 @@ +#!/bin/bash +pid=$$ +script_dir=$(dirname "$0") +timestamp="$(date +'%Y-%m-%d_%H-%M-%S')" #used by log file name +start_time=$(date +%s) #used to calculate elapsed time at the end + +set -eo pipefail + +############################################################### +# HELPER FUNCTIONS + +usage() { + echo "Usage: $0 --backup-location --plan-name [--dry-run]" + echo "" + echo "Example: $0 --backup-location /home/backup-7.29.2024_13-22-32_stefan.tar.gz --plan-name default_plan_nginx --dry-run" + exit 1 +} + +log() { + local message="$1" + local timestamp=$(date +'%Y-%m-%d %H:%M:%S') + echo "[$timestamp] $message" | tee -a "$log_file" +} + +DEBUG=true # Set this to true to enable debug logging + +debug_log() { + if [ "$DEBUG" = true ]; then + log "DEBUG: $1" + fi +} +handle_error() { + log "FATAL ERROR: An error occurred in function '$1' on line $2" + cleanup + exit 1 +} + +trap 'handle_error "${FUNCNAME[-1]}" "$LINENO"' ERR + +cleanup() { + log "Cleaning up temporary files and directories" + rm -rf "$backup_dir" +} + +define_data_and_log() { + local backup_location="" + local plan_name="" + DRY_RUN=false + + # Parse command-line arguments + while [ "$1" != "" ]; do + case $1 in + --backup-location ) shift + backup_location=$1 + ;; + --plan-name ) shift + plan_name=$1 + ;; + --dry-run ) DRY_RUN=true + ;; + --post-hook ) shift + post_hook=$1 + ;; + * ) usage + esac + shift + done + + # Validate required parameters + if [ -z "$backup_location" ] || [ -z "$plan_name" ]; then + usage + fi + + # Format log file and ensure log directory exists + base_name="$(basename "$backup_location")" + base_name_no_ext="${base_name%.*}" + local log_dir="/var/log/openpanel/admin/imports" + mkdir -p "$log_dir" + log_file="$log_dir/${base_name_no_ext}_$(date +'%Y-%m-%d_%H-%M-%S').log" + + # Run the main function and pass plan_name + echo "Import started, log file: $log_file" + + main "$plan_name" +} + +command_exists() { + command -v "$1" >/dev/null 2>&1 +} + +install_dependencies() { + log "Checking and installing dependencies..." + + install_needed=false + + # needed commands + declare -A commands=( + ["tar"]="tar" + ["parallel"]="parallel" + ["rsync"]="rsync" + ["unzip"]="unzip" + ["jq"]="jq" + ["mysql"]="mysql-client" + ["wget"]="wget" + ["curl"]="curl" + ) + + for cmd in "${!commands[@]}"; do + if ! command_exists "$cmd"; then + install_needed=true + break + fi + done + + # If installation is needed, update package list and install missing packages + if [ "$install_needed" = true ]; then + log "Updating package manager..." + + # Hold kernel packages to prevent upgrades + sudo apt-mark hold linux-image-generic linux-headers-generic + + # Update package list without upgrading + sudo apt-get update -y >/dev/null 2>&1 + + for cmd in "${!commands[@]}"; do + if ! command_exists "$cmd"; then + log "Installing ${commands[$cmd]}" + # Install package without upgrading or installing recommended packages + sudo apt-get install -y --no-upgrade --no-install-recommends "${commands[$cmd]}" >/dev/null 2>&1 + fi + done + + # Unhold kernel packages + sudo apt-mark unhold linux-image-generic linux-headers-generic + + log "Dependencies installed successfully." + else + log "All required dependencies are already installed." + fi +} +get_server_ipv4(){ + # Get server ipv4 from ip.openpanel.co or ifconfig.me + new_ip=$(curl --silent --max-time 2 -4 https://ip.openpanel.co || wget --timeout=2 -qO- https://ip.openpanel.co || curl --silent --max-time 2 -4 https://ifconfig.me) + + # if no internet, get the ipv4 from the hostname -I + if [ -z "$new_ip" ]; then + new_ip=$(ip addr|grep 'inet '|grep global|head -n1|awk '{print $2}'|cut -f1 -d/) + fi +} + +validate_plan_exists(){ + if ! opencli plan-list --json | grep -qw "$plan_name"; then + log "FATAL ERROR: Plan name '$plan_name' does not exist." + exit 1 + fi +} + +############################################################### +# MAIN FUNCTIONS + +# CHECK EXTENSION AND DETERMINE SIZE +check_if_valid_cp_backup(){ + local backup_location="$1" + + ARCHIVE_SIZE=$(stat -c%s "$backup_location") + + # Identify the backup type + local backup_filename=$(basename "$backup_location") + extraction_command="" + + case "$backup_filename" in + cpmove-*.tar.gz) + log "Identified cpmove backup" + extraction_command="tar -xzf" + EXTRACTED_SIZE=$(($ARCHIVE_SIZE * 2)) + ;; + backup-*.tar.gz) + log "Identified full or partial cPanel backup" + extraction_command="tar -xzf" + EXTRACTED_SIZE=$(($ARCHIVE_SIZE * 2)) + ;; + *.tar.gz) + log "Identified gzipped tar backup" + extraction_command="tar -xzf" + EXTRACTED_SIZE=$(($ARCHIVE_SIZE * 2)) + ;; + *.tgz) + log "Identified tgz backup" + extraction_command="tar -xzf" + EXTRACTED_SIZE=$(($ARCHIVE_SIZE * 3)) + ;; + *.tar) + log "Identified tar backup" + extraction_command="tar -xf" + EXTRACTED_SIZE=$(($ARCHIVE_SIZE * 3)) + ;; + *.zip) + log "Identified zip backup" + extraction_command="unzip" + EXTRACTED_SIZE=$(($ARCHIVE_SIZE * 3)) + ;; + *) + log "FATAL ERROR: Unrecognized backup format: $backup_filename" + exit 1 + ;; + esac +} + +# CHECK DISK USAGE +check_if_disk_available(){ + TMP_DIR="/tmp" + HOME_DIR="/home" + + # Get available space in /tmp and home directories in bytes + AVAILABLE_TMP=$(df --output=avail "$TMP_DIR" | tail -n 1) + AVAILABLE_HOME=$(df --output=avail "$HOME_DIR" | tail -n 1) + + AVAILABLE_TMP=$(($AVAILABLE_TMP * 1024)) + AVAILABLE_HOME=$(($AVAILABLE_HOME * 1024)) + + # Check if there's enough space + if [[ $AVAILABLE_TMP -ge $EXTRACTED_SIZE && $AVAILABLE_HOME -ge $EXTRACTED_SIZE ]]; then + log "There is enough disk space to extract the archive and copy it to the home directory." + else + log "FATAL ERROR: Not enough disk space." + if [[ $AVAILABLE_TMP -lt $EXTRACTED_SIZE ]]; then + log "Insufficient space in the '/tmp' partition." + log "Available: $AVAILABLE_TMP - Needed: $EXTRACTED_SIZE" + fi + if [[ $AVAILABLE_HOME -lt $EXTRACTED_SIZE ]]; then + log "Insufficient space in the '/home' directory." + log "Available: $AVAILABLE_HOME - Needed: $EXTRACTED_SIZE" + fi + exit 1 + fi +} + +# EXTRACT +extract_cpanel_backup() { + backup_location="$1" + backup_dir="$2" + log "Extracting backup from $backup_location to $backup_dir" + mkdir -p "$backup_dir" + + # Extract the backup + if [ "$extraction_command" = "unzip" ]; then + $extraction_command "$backup_location" -d "$backup_dir" + else + $extraction_command "$backup_location" -C "$backup_dir" + fi + if [ $? -eq 0 ]; then + log "Backup extracted successfully." + else + log "FATAL ERROR: Backup extraction failed." + cleanup + exit 1 + fi + + # Handle nested archives (common in some cPanel backups) + for nested_archive in "$backup_dir"/*.tar.gz "$backup_dir"/*.tgz; do + if [ -f "$nested_archive" ]; then + log "Found nested archive: $nested_archive" + tar -xzf "$nested_archive" -C "$backup_dir" + rm "$nested_archive" # Remove the nested archive after extraction + fi + done +} + +# LOCATE FILES IN EXTRACTED BACKUP +locate_backup_directories() { + log "Locating important files in the extracted backup" + + if [ -d "$real_backup_files_path/homedir" ]; then + homedir="$real_backup_files_path/homedir" + log "Home directory: $homedir" + else + log "ERROR: Home directory not found in backup." + exit 1 + fi + + if [ -d "$real_backup_files_path/mysql" ]; then + mysqldir="$real_backup_files_path/mysql" + log "MySQL directory: $mysqldir" + else + log "ERROR: MySQL directory not found in backup." + exit 1 + fi + + if [ -f "$real_backup_files_path/mysql" ]; then + log "MySQL grants: $real_backup_files_path/mysql" + else + log "MySQL grants file not found." + fi + + if [ -f "$real_backup_files_path/cp/$cpanel_username" ]; then + cpconfig="$real_backup_files_path/cp/$cpanel_username" + log "cPanel configuration: $cpconfig" + else + log "ERROR: cPanel configuration file not found." + exit 1 + fi + + log "Backup directories located successfully" +} + +# CPANEL BACKUP METADATA +parse_cpanel_metadata() { + log "Starting to parse cPanel metadata..." + + cp_file="${real_backup_files_path}/cp/${cpanel_username}" + log "DEBUG: Attempting to parse metadata from file: $cp_file" + + if [ ! -f "$cp_file" ]; then + log "WARNING: cp file $cp_file not found. Using default values." + main_domain="" + cpanel_email="" + php_version="inherit" + else + # Function to get value from cp file with default + get_cp_value() { + local key="$1" + local default="$2" + local value + value=$(grep "^$key=" "$cp_file" | cut -d'=' -f2-) + if [ -z "$value" ]; then + echo "$default" + else + echo "$value" + fi + } + + main_domain=$(get_cp_value "DNS" "") + cpanel_email=$(get_cp_value "CONTACTEMAIL" "") + [ -z "$cpanel_email" ] && cpanel_email=$(get_cp_value "CONTACTEMAIL2" "") + [ -z "$cpanel_email" ] && cpanel_email=$(get_cp_value "EMAIL" "") + + # Check for CloudLinux PHP Selector + cfg_file="${real_backup_files_path}/homedir/.cl.selector/defaults.cfg" + if [ -f "$cfg_file" ]; then + php_version=$(grep '^php\s*=' "$cfg_file" | awk -F '=' '{print $2}' | tr -d '[:space:]') + [ -z "$php_version" ] && php_version="inherit" + else + php_version="inherit" + fi + + # Additional metadata + ip_address=$(get_cp_value "IP" "") + plan=$(get_cp_value "PLAN" "default") + max_addon=$(get_cp_value "MAXADDON" "0") + max_ftp=$(get_cp_value "MAXFTP" "unlimited") + max_sql=$(get_cp_value "MAXSQL" "unlimited") + max_pop=$(get_cp_value "MAXPOP" "unlimited") + max_sub=$(get_cp_value "MAXSUB" "unlimited") + + log "Additional metadata parsed:" + log "IP Address: $ip_address" + log "Plan: $plan" + log "Max Addon Domains: $max_addon" + log "Max FTP Accounts: $max_ftp" + log "Max SQL Databases: $max_sql" + log "Max Email Accounts: $max_pop" + log "Max Subdomains: $max_sub" + fi + + # Ensure we have at least an empty string for each variable + main_domain="${main_domain:-}" + cpanel_email="${cpanel_email:-}" + php_version="${php_version:-inherit}" + + log "cPanel metadata parsed:" + log "Main Domain: ${main_domain:-Not found}" + log "Email: ${cpanel_email:-Not found}" + log "PHP Version: $php_version" + log "Finished parsing cPanel metadata." +} + +# CHECK BEFORE EXPORT +check_if_user_exists(){ + backup_filename=$(basename "$backup_location") + cpanel_username="${backup_filename##*_}" + cpanel_username="${cpanel_username%%.*}" + log "Username: $cpanel_username" + + local existing_user="" + if opencli user-list --json > /dev/null 2>&1; then + existing_user=$(opencli user-list --json | jq -r ".[] | select(.username == \"$cpanel_username\") | .id") + fi + if [ -z "$existing_user" ]; then + log "Username $cpanel_username is available, starting import.." + else + log "FATAL ERROR: $cpanel_username already exists." + exit 1 + fi +} + +# CREATE NEW USER +create_new_user() { + local username="$1" + local password="$2" + local email="$3" + local plan_name="$4" + + if [ "$DRY_RUN" = true ]; then + log "DRY RUN: Would create user $username with password $password, email $email, and plan $plan_name" + return + fi + + # Validate the parameters + if [ -z "$username" ] || [ -z "$password" ] || [ -z "$email" ] || [ -z "$plan_name" ]; then + log "ERROR: Missing required parameters. Username, password, email, and plan must be provided." + return + fi + + # Log the creation attempt + log "Attempting to create user $username with email $email, plan $plan_name, and password $password" + + # Construct the correct opencli command + local cli_command="opencli user-add $username $password $email $plan_name" + + # Log the exact command that will be run + log "Running command: $cli_command" + + # Execute the OpenCLI command + create_user_command=$($cli_command 2>&1) + + # Process the output and log it + while IFS= read -r line; do + log "$line" + done <<< "$create_user_command" + + # Check if the user was added successfully + if echo "$create_user_command" | grep -q "Successfully added user"; then + log "User $username was added successfully." + else + log "ERROR: Failed to create user $username. Command output: $create_user_command" + exit 1 + fi +} +# PHP VERSION +restore_php_version() { + local php_version="$1" + + if [ "$DRY_RUN" = true ]; then + log "DRY RUN: Would check/install PHP version $php_version for user $cpanel_username" + return + fi + + # Check if php_version is "inherit" + if [ "$php_version" == "inherit" ]; then + log "PHP version is set to inherit. No changes will be made." + else + log "Checking if current PHP version installed matches the version from backup" + local current_version=$(opencli php-default_php_version "$cpanel_username" | sed 's/Default PHP version for user.*: //') + if [ "$current_version" != "$php_version" ]; then + local installed_versions=$(opencli php-enabled_php_versions "$cpanel_username") + if ! echo "$installed_versions" | grep -q "$php_version"; then + log "Default PHP version $php_version from backup is not present in the container, installing.." + output=$(opencli php-install_php_version "$cpanel_username" "$php_version" 2>&1) + while IFS= read -r line; do + log "$line" + done <<< "$output" + + #SET AS DEFAULT PHP VERSION + log "Setting newly installed PHP $php_version as the default version for all new domains." + output=$(opencli php-default_php_version "$cpanel_username" --update "$php_version" 2>&1) + while IFS= read -r line; do + log "$line" + done <<< "$output" + fi + else + log "Default PHP version in backup file ($php_version) matches the installed PHP version: ($current_version) " + fi + fi +} + +# PHPMYADMIN +grant_phpmyadmin_access() { + local username="$1" + + if [ "$DRY_RUN" = true ]; then + log "DRY RUN: Would grant phpMyAdmin access to all databases for user $username" + return + fi + + log "Granting phpMyAdmin access to all databases for user $username" + # https://github.com/stefanpejcic/OpenPanel/blob/148b5e482f7bde4850868ba5cf85717538770882/docker/apache/phpmyadmin/pma.php#L13C44-L13C54 + phpmyadmin_user="phpmyadmin" + sql_command="GRANT ALL ON *.* TO 'phpmyadmin'@'localhost'; FLUSH PRIVILEGES;" + grant_commands=$(docker exec $username mysql -N -e "$sql_command") + + log "Access granted to phpMyAdmin user for all databases of $username" + +} + +# MYSQL +restore_mysql() { + local mysql_backup_dir="$1" + local mysql_grants_file="$real_backup_files_path/mysql" + + log "Starting MySQL database restoration..." + log "MySQL backup directory: $mysql_backup_dir" + + if [ ! -d "$mysql_backup_dir" ]; then + log "No MySQL backup directory found at $mysql_backup_dir." + return + fi + + # Enable nullglob to handle the case when no .sql files are found + shopt -s nullglob + sql_files=("$mysql_backup_dir"/*.sql) + shopt -u nullglob + + if [ ${#sql_files[@]} -eq 0 ]; then + log "No SQL files found in $mysql_backup_dir." + else + for sql_file in "${sql_files[@]}"; do + db_name=$(basename "$sql_file" .sql) + log "Restoring database: $db_name from $sql_file" + + # Drop the database if it exists + log "Dropping database $db_name if it exists..." + if mysql -e "DROP DATABASE IF EXISTS \`$db_name\`;" 2>&1 | while read -r line; do log "$line"; done; then + log "Database $db_name dropped (if it existed)." + else + log "ERROR: Failed to drop database $db_name." + continue + fi + + # Create the database + log "Creating database $db_name..." + if mysql -e "CREATE DATABASE \`$db_name\`;" 2>&1 | while read -r line; do log "$line"; done; then + log "Database $db_name created successfully." + else + log "ERROR: Failed to create database $db_name." + continue + fi + + # Import the SQL file + log "Importing SQL file $sql_file into database $db_name..." + if mysql "$db_name" < "$sql_file" 2>&1 | while read -r line; do log "$line"; done; then + log "Database $db_name restored successfully." + else + log "ERROR: Failed to import SQL file into database $db_name." + continue + fi + done + fi + + # Restore MySQL users and grants from mysql grants file if available + if [ -f "$mysql_grants_file" ]; then + log "Restoring MySQL users and grants from $mysql_grants_file" + + # Check MySQL version to adjust grant file syntax if necessary + mysql_version=$(mysql -V | awk '{print $5}' | awk -F'.' '{print $1"."$2}') + log "Detected MySQL version: $mysql_version" + + temp_grants_file="/tmp/processed_mysql_grants.sql" + + if (( $(echo "$mysql_version >= 8.0" | bc -l) )); then + log "Modifying grants file for MySQL 8.0 compatibility..." + # Replace 'IDENTIFIED BY PASSWORD' with 'IDENTIFIED WITH mysql_native_password AS' + sed "s/IDENTIFIED BY PASSWORD/IDENTIFIED WITH mysql_native_password AS/g" "$mysql_grants_file" > "$temp_grants_file" + else + log "Using grants file as-is for MySQL version < 8.0" + cp "$mysql_grants_file" "$temp_grants_file" + fi + + # Execute the grants file + if mysql < "$temp_grants_file" 2>&1 | while read -r line; do log "$line"; done; then + log "MySQL users and grants restored successfully." + else + log "ERROR: Failed to restore MySQL users and grants." + fi + + # Remove the temporary grants file + rm -f "$temp_grants_file" + else + log "No MySQL grants file found at $mysql_grants_file." + fi + + log "MySQL database restoration completed." +} +# SSL CACHE +refresh_ssl_file() { + local username="$1" + + if [ "$DRY_RUN" = true ]; then + log "DRY RUN: Would refresh SSL file for user $username" + return + fi + + log "Creating a list of SSL certificates for user interface" + opencli ssl-user "$cpanel_username" + +} + +# SSL CERTIFICATES +restore_ssl() { + local username="$1" + + if [ "$DRY_RUN" = true ]; then + log "DRY RUN: Would restore SSL certificates for user $username" + return + fi + + log "Restoring SSL certificates for user $username" + if [ -d "$real_backup_files_path/ssl" ]; then + for cert_file in "$real_backup_files_path/ssl"/*.crt; do + local domain=$(basename "$cert_file" .crt) + local key_file="$real_backup_files_path/ssl/$domain.key" + if [ -f "$key_file" ]; then + log "Installing SSL certificate for domain: $domain" + opencli ssl install --domain "$domain" --cert "$cert_file" --key "$key_file" + else + log "SSL key file not found for domain: $domain" + fi + done + + # Refresh the SSL file after restoring certificates + refresh_ssl_file "$username" + else + log "No SSL certificates found to restore" + fi + +} + +# SSH KEYS +restore_ssh() { + local username="$1" + + if [ "$DRY_RUN" = true ]; then + log "DRY RUN: Would restore SSH access for user $username" + return + fi + + log "Restoring SSH access for user $username" + local shell_access=$(grep -oP 'shell: \K\S+' "$real_backup_files_path/userdata/main") + if [ "$shell_access" == "/bin/bash" ]; then + opencli user-ssh enable "$username" + if [ -f "$real_backup_files_path/.ssh/id_rsa.pub" ]; then + mkdir -p "/home/$username/.ssh" + cp "$real_backup_files_path/.ssh/id_rsa.pub" "/home/$username/.ssh/authorized_keys" + chown -R "$username:$username" "/home/$username/.ssh" + fi + fi +} + +# DNS ZONES +restore_dns_zones() { + log "Restoring DNS zones for user $cpanel_username" + + + + + #domain_file="$real_backup_files_path/userdata/$domain" + #domain=$(basename "$domain_file") + + + + if [ "$DRY_RUN" = true ]; then + log "DRY RUN: Would restore DNS zones for user $cpanel_username" + return + fi + + if [ -d "$real_backup_files_path/dnszones" ]; then + for zone_file in "$real_backup_files_path/dnszones"/*; do + local zone_name=$(basename "${zone_file%.db}") + + # Check if the destination zone file exists, if not, it was probably a subdomain that had no dns zone and + if [ ! -f "/etc/bind/zones/${zone_name}.zone" ]; then + log "DNS zone file /etc/bind/zones/${zone_name}.zone does not exist. Skipping import for $zone_name." + continue + else + log "Importing DNS zone: $zone_name" + fi + + old_ip=$(grep -oP 'IP=\K[0-9.]+' ${real_backup_files_path}/cp/$cpanel_username) + if [ -z "$old_ip" ]; then + log "WARNING: old server ip address not detected in file ${real_backup_files_path}/cp/$cpanel_username - records will not be automatically updated to new ip address." + else + log "Replacing old server IP: $old_ip with new IP: $new_ip in DNS zone file for domain: $zone_name" + sed -i "s/$old_ip/$new_ip/g" $zone_file + fi + + # Temporary files to store intermediate results + temp_file_of_original_zone=$(mktemp) + temp_file_of_created_zone=$(mktemp) + + # Remove all lines after the last line that starts with '@' + log "Editing original zone for domain $zone_name to temporary file: $temp_file_of_original_zone" + awk '/^@/ { found=1; last_line=NR } { if (found && NR > last_line) exit } { print }' "$zone_file" > "$temp_file_of_original_zone" + + # Remove all lines from the beginning until the line that has 'NS' and including that line + log "Editing created zone for domain $zone_name to temporary file: $temp_file_of_created_zone" + awk '/NS/ { found=1; next } found { print }' "/etc/bind/zones/${zone_name}.zone" > "$temp_file_of_created_zone" + + # Append the processed second file to the first + log "Merging the DNS zone records from $temp_file_of_created_zone with $temp_file_of_original_zone" + cat "$temp_file_of_created_zone" >> "$temp_file_of_original_zone" + + # Move the merged content to the final file + log "Replacing the created zone /etc/bind/zones/${zone_name}.zone with updated records." + mv "$temp_file_of_original_zone" "/etc/bind/zones/${zone_name}.zone" + + # Clean up + rm "$temp_file_of_created_zone" + + log "DNS zone file for $zone_name has been imported." + done + else + log "No DNS zones found to restore" + fi +} + +# HOME DIR +restore_files() { + log "Restoring files ($backup_size) to /home/$cpanel_username/" + log "real_backup_files_path is set to: $real_backup_files_path" + + if [ ! -d "/home/$cpanel_username" ]; then + log "/home/$cpanel_username does not exist. Creating directory." + mkdir -p "/home/$cpanel_username" + log "Successfully created /home/$cpanel_username." + else + log "/home/$cpanel_username exists." + fi + + # Optionally comment out the listing of homedir contents + # log "Contents of $real_backup_files_path/homedir before moving:" + # ls -alh "$real_backup_files_path/homedir" | while IFS= read -r line; do + # log "$line" + # done + + log "Attempting to sync $real_backup_files_path/homedir to /home/$cpanel_username/" + rsync -a "$real_backup_files_path/homedir/" "/home/$cpanel_username/" + if [ $? -eq 0 ]; then + log "Successfully synced homedir to /home/$cpanel_username." + else + log "ERROR: Failed to sync homedir to /home/$cpanel_username." + fi + + # Moving main domain files + log "Moving main domain files from public_html to $main_domain directory using rsync." + if [ ! -d "/home/$cpanel_username/$main_domain" ]; then + mkdir -p "/home/$cpanel_username/$main_domain" + fi + rsync -a "/home/$cpanel_username/public_html/" "/home/$cpanel_username/$main_domain/" + if [ $? -eq 0 ]; then + log "Successfully synced public_html to $main_domain." + else + log "ERROR: Failed to sync public_html to $main_domain." + fi + + # Remove public_html if needed + rm -rf "/home/$cpanel_username/public_html" +} +# PERMISSIONS +fix_perms(){ + log "Changing permissions for all files and folders in user home directory /home/$cpanel_username/" + docker exec $cpanel_username bash -c "chown -R 1000:33 /home/$cpanel_username" +} + + +# WORDPRESS SITES +restore_wordpress() { + local real_backup_files_path="$1" + local username="$2" + + if [ "$DRY_RUN" = true ]; then + log "DRY RUN: Would restore WordPress sites for user $username" + return + fi + + log "Restoring WordPress sites for user $username" + if [ -d "$real_backup_files_path/wptoolkit" ]; then + for wp_file in "$real_backup_files_path/wptoolkit"/*.json; do + log "Importing WordPress site from: $wp_file" + opencli wp-import "$username" "$wp_file" + done + else + log "No WordPress data found to restore" + fi +} + + + + +# DOMAINS +create_domain() { + local domain="$1" + local type="$2" + local username="$3" + + log "DEBUG: domain='$domain', type='$type', username='$username'" + + current_domain_count=$((current_domain_count + 1)) + log "Restoring $type $domain (${current_domain_count}/${domains_total_count})" + + # Log the command being executed + log "Running command: opencli domains-add '$domain' '$username'" + + if [ "$DRY_RUN" = true ]; then + log "DRY RUN: Would restore $type $domain" + else + # Check if the domain already exists + domain_check_output=$(opencli domains-whoowns "$domain" 2>&1) + if echo "$domain_check_output" | grep -q "not found in the database"; then + # Proceed to add the domain + output=$(opencli domains-add "$domain" "$username" 2>&1) + log "opencli domains-add output: $output" + if echo "$output" | grep -q "Successfully added domain"; then + log "Domain $domain added successfully." + else + log "ERROR: Failed to add domain $domain. Command output: $output" + fi + else + log "WARNING: $type $domain already exists and will not be added to this user." + fi + fi +} +restore_domains() { + log "Starting domain restoration process..." + + if [ -f "$real_backup_files_path/userdata/main" ]; then + file_path="$real_backup_files_path/userdata/main" + + # Log the content of the userdata/main file for debugging + log "Contents of userdata/main:" + while IFS= read -r line; do + log "$line" + done < "$file_path" + + # Initialize variables + main_domain="" + parked_domains="" + sub_domains="" + addon_domains="" + + # Read the file line by line + while IFS= read -r line; do + if [[ "$line" =~ ^main_domain: ]]; then + main_domain=$(echo "$line" | awk '{print $2}') + elif [[ "$line" =~ ^parked_domains: ]]; then + parked_domains=$(echo "$line" | awk '{print $2}' | tr -d '[]') + elif [[ "$line" =~ ^sub_domains: ]]; then + sub_domains_section=true + continue + elif [[ "$line" =~ ^addon_domains: ]]; then + addon_domains_section=true + continue + fi + + if [[ "$sub_domains_section" == true ]]; then + if [[ "$line" =~ ^[[:space:]]+- ]]; then + sub_domains+=$(echo "$line" | awk '{print $2}')$'\n' + else + sub_domains_section=false + fi + fi + + if [[ "$addon_domains_section" == true ]]; then + if [[ "$line" =~ ^[[:space:]]*[^:]+:[[:space:]]*[^[:space:]]+$ ]]; then + domain=$(echo "$line" | awk -F: '{print $1}' | tr -d '[:space:]') + # Avoid adding invalid entries and trailing colons + if [[ -n "$domain" && "$domain" != "main_domain" && "$domain" != "parked_domains" ]]; then + addon_domains+="$domain"$'\n' + fi + else + addon_domains_section=false + fi + fi + done < "$file_path" + + # Parse parked_domains + if [[ -z "$parked_domains" ]]; then + parked_domains_array=() + else + IFS=',' read -r -a parked_domains_array <<< "$parked_domains" + fi + + sub_domains_array=() + addon_domains_array=() + + # Parse sub_domains + while IFS= read -r domain; do + if [[ -n "$domain" ]]; then + sub_domains_array+=("$domain") + fi + done <<< "$sub_domains" + + # Parse addon_domains + while IFS= read -r domain; do + if [[ -n "$domain" ]]; then + addon_domains_array+=("$domain") + fi + done <<< "$addon_domains" + + # Filter out subdomains that are essentially addon_domain.$main_domain + filtered_sub_domains=() + for sub_domain in "${sub_domains_array[@]}"; do + trimmed_sub_domain=$(echo "$sub_domain" | xargs) + is_addon=false + for addon in "${addon_domains_array[@]}"; do + if [[ "$trimmed_sub_domain" == "$addon.$main_domain" ]]; then + is_addon=true + break + fi + done + if [ "$is_addon" = false ]; then + filtered_sub_domains+=("$trimmed_sub_domain") + fi + done + + main_domain_count=1 + + addon_domains_count=${#addon_domains_array[@]} + if [ "${#addon_domains_array[@]}" -eq 1 ] && [ -z "${addon_domains_array[0]}" ]; then + addon_domains_count=0 + log "No addon domains detected." + else + log "Addon domains ($addon_domains_count): ${addon_domains_array[@]}" + fi + + parked_domains_count=${#parked_domains_array[@]} + if [ "${#parked_domains_array[@]}" -eq 1 ] && [ -z "${parked_domains_array[0]}" ]; then + parked_domains_count=0 + log "No parked domains detected." + else + log "Parked domains ($parked_domains_count): ${parked_domains_array[@]}" + fi + + filtered_sub_domains_count=${#filtered_sub_domains[@]} + if [ "${#filtered_sub_domains[@]}" -eq 1 ] && [ -z "${filtered_sub_domains[0]}" ]; then + filtered_sub_domains_count=0 + log "No subdomains detected." + else + log "Subdomains ($filtered_sub_domains_count): ${filtered_sub_domains[@]}" + fi + + domains_total_count=$((main_domain_count + addon_domains_count + parked_domains_count + filtered_sub_domains_count)) + + log "Detected a total of $domains_total_count domains for user." + + current_domain_count=0 + + # Process the domains + log "Processing main (primary) domain..." + create_domain "$main_domain" "main domain" "$cpanel_username" + + if [ "$parked_domains_count" -eq 0 ]; then + log "No parked (alias) domains detected." + else + log "Processing parked (alias) domains..." + for parked in "${parked_domains_array[@]}"; do + create_domain "$parked" "alias domain" "$cpanel_username" + done + fi + + if [ "$addon_domains_count" -eq 0 ]; then + log "No addon domains detected." + else + log "Processing addon domains..." + for addon in "${addon_domains_array[@]}"; do + create_domain "$addon" "addon domain" "$cpanel_username" + done + fi + + if [ "$filtered_sub_domains_count" -eq 0 ]; then + log "No subdomains detected." + else + log "Processing subdomains..." + for filtered_sub in "${filtered_sub_domains[@]}"; do + create_domain "$filtered_sub" "subdomain" "$cpanel_username" + # TODO: create record in DNS zone instead of separate domain if only DNS zone and no folder! + done + fi + + log "Finished importing $domains_total_count domains." + + else + log "FATAL ERROR: domains file userdata/main is missing in backup file." + exit 1 + fi +} + +# CRONJOB +restore_cron() { + log "Restoring cron jobs for user $cpanel_username" + + if [ "$DRY_RUN" = true ]; then + log "DRY RUN: Would restore cron jobs for user $cpanel_username" + return + fi + + if [ -f "$real_backup_files_path/cron/$cpanel_username" ]; then + # exclude shell and email variables from file! + sed -i '1,2d' "$real_backup_files_path/cron/$cpanel_username" + + output=$(docker cp $real_backup_files_path/cron/$cpanel_username $cpanel_username:/var/spool/cron/crontabs/$cpanel_username 2>&1) + while IFS= read -r line; do + log "$line" + done <<< "$output" + + output=$(docker exec $cpanel_username bash -c "crontab -u $cpanel_username /var/spool/cron/crontabs/$cpanel_username" 2>&1) + while IFS= read -r line; do + log "$line" + done <<< "$output" + + output=$(docker exec $cpanel_username bash -c "service cron restart" 2>&1) + while IFS= read -r line; do + log "$line" + done <<< "$output" + + docker exec "$cpanel_username" sed -i 's/CRON_STATUS="off"/CRON_STATUS="on"/' /etc/entrypoint.sh >/dev/null 2>&1 + else + log "No cron jobs found to restore" + fi +} + +# Main execution +# Main execution +main() { + local plan_name="$1" + # ... previous steps ... + + parse_cpanel_metadata + + # Now that we have cpanel_username and cpanel_email, create the user + create_new_user "$cpanel_username" "random" "$cpanel_email" "$plan_name" + + # Restore domains (this creates domain directories) + restore_domains + + # Restore files (now that domain directories exist) + restore_files + + # Adjust permissions + fix_perms + + # Restore PHP version + restore_php_version "$php_version" + + # Restore MySQL databases and users + restore_mysql "$mysqldir" + + # ... remaining steps ... + + # Cleanup + cleanup + + end_time=$(date +%s) + elapsed=$(( end_time - start_time )) + hours=$(( elapsed / 3600 )) + minutes=$(( (elapsed % 3600 ) / 60 )) + seconds=$(( elapsed % 60 )) + + log "Elapsed time: ${hours}h ${minutes}m ${seconds}s" + + log "SUCCESS: Import for user $cpanel_username completed successfully." + + # Run post-hook if provided + if [ -n "$post_hook" ]; then + if [ -x "$post_hook" ]; then + log "Executing post-hook script..." + "$post_hook" "$cpanel_username" + else + log "WARNING: Post-hook file '$post_hook' is not executable or not found." + exit 1 + fi + fi +} + +# MAIN FUNCTION +define_data_and_log "$@" \ No newline at end of file diff --git a/integrations/cpanel-import/cp-import.sh b/integrations/cpanel-import/cp-import.sh index d258333a..6ed9acb1 100644 --- a/integrations/cpanel-import/cp-import.sh +++ b/integrations/cpanel-import/cp-import.sh @@ -1,11 +1,37 @@ #!/bin/bash pid=$$ script_dir=$(dirname "$0") -timestamp="$(date +'%Y-%m-%d_%H-%M-%S')" #used by log file name +timestamp="$(date +'%Y-%m-%d_%H-%M-%S')" #used by log file name start_time=$(date +%s) #used to calculate elapsed time at the end set -eo pipefail +DEBUG=true + + + +# wget cp backup +# cd /home && git clone https://github.com/stefanpejcic/cPanel-to-OpenPanel +# bash /home/cPanel-to-OpenPanel/cp-import.sh --backup-location /home/backup-10.23.2024_14-49-42_pejcic.tar.gz --plan-name ubuntu_nginx_mysql + + + + + + + + + + + + + + + + + + + ############################################################### # HELPER FUNCTIONS @@ -16,19 +42,21 @@ usage() { exit 1 } + log() { local message="$1" local timestamp=$(date +'%Y-%m-%d %H:%M:%S') echo "[$timestamp] $message" | tee -a "$log_file" } -DEBUG=true # Set this to true to enable debug logging debug_log() { if [ "$DEBUG" = true ]; then log "DEBUG: $1" fi } + + handle_error() { log "FATAL ERROR: An error occurred in function '$1' on line $2" cleanup @@ -37,11 +65,15 @@ handle_error() { trap 'handle_error "${FUNCNAME[-1]}" "$LINENO"' ERR + cleanup() { log "Cleaning up temporary files and directories" rm -rf "$backup_dir" } + + + define_data_and_log(){ local backup_location="" local plan_name="" @@ -73,7 +105,7 @@ define_data_and_log(){ # Format log file base_name="$(basename "$backup_location")" - base_name_no_ext="${base_name%.*}" + base_name_no_ext="${base_name%.*}" local log_dir="/var/log/openpanel/admin/imports" mkdir -p $log_dir log_file="$log_dir/${base_name_no_ext}_${timestamp}.log" @@ -84,15 +116,19 @@ define_data_and_log(){ main } + + command_exists() { command -v "$1" >/dev/null 2>&1 } + + install_dependencies() { log "Checking and installing dependencies..." - + install_needed=false - + # needed commands declare -A commands=( ["tar"]="tar" @@ -100,11 +136,12 @@ install_dependencies() { ["rsync"]="rsync" ["unzip"]="unzip" ["jq"]="jq" + ["pigz"]="pigz" ["mysql"]="mysql-client" ["wget"]="wget" ["curl"]="curl" ) - + for cmd in "${!commands[@]}"; do if ! command_exists "$cmd"; then install_needed=true @@ -115,39 +152,44 @@ install_dependencies() { # If installation is needed, update package list and install missing packages if [ "$install_needed" = true ]; then log "Updating package manager..." - + # Hold kernel packages to prevent upgrades - sudo apt-mark hold linux-image-generic linux-headers-generic + apt-mark hold linux-image-generic linux-headers-generic >/dev/null 2>&1 # Update package list without upgrading - sudo apt-get update -y >/dev/null 2>&1 + apt-get update -y >/dev/null 2>&1 for cmd in "${!commands[@]}"; do if ! command_exists "$cmd"; then log "Installing ${commands[$cmd]}" # Install package without upgrading or installing recommended packages - sudo apt-get install -y --no-upgrade --no-install-recommends "${commands[$cmd]}" >/dev/null 2>&1 + apt-get install -y --no-upgrade --no-install-recommends "${commands[$cmd]}" >/dev/null 2>&1 fi done # Unhold kernel packages - sudo apt-mark unhold linux-image-generic linux-headers-generic + apt-mark unhold linux-image-generic linux-headers-generic >/dev/null 2>&1 log "Dependencies installed successfully." else log "All required dependencies are already installed." fi } + + + get_server_ipv4(){ # Get server ipv4 from ip.openpanel.co or ifconfig.me new_ip=$(curl --silent --max-time 2 -4 https://ip.openpanel.co || wget --timeout=2 -qO- https://ip.openpanel.co || curl --silent --max-time 2 -4 https://ifconfig.me) - + # if no internet, get the ipv4 from the hostname -I if [ -z "$new_ip" ]; then new_ip=$(ip addr|grep 'inet '|grep global|head -n1|awk '{print $2}'|cut -f1 -d/) fi } + + validate_plan_exists(){ if ! opencli plan-list --json | grep -qw "$plan_name"; then log "FATAL ERROR: Plan name '$plan_name' does not exist." @@ -155,6 +197,12 @@ validate_plan_exists(){ fi } + + + + + + ############################################################### # MAIN FUNCTIONS @@ -239,31 +287,39 @@ check_if_disk_available(){ extract_cpanel_backup() { backup_location="$1" backup_dir="$2" + backup_dir="${backup_dir%.*}" log "Extracting backup from $backup_location to $backup_dir" mkdir -p "$backup_dir" # Extract the backup if [ "$extraction_command" = "unzip" ]; then $extraction_command "$backup_location" -d "$backup_dir" + elif [ "$extraction_command" = "tar -xzf" ]; then + # Get the size of the backup in bytes + backup_size=$(stat -c %s "${backup_location}") + + # Calculate 1% of the backup size (in bytes) + zero_one_percent=$((backup_size / 1000000)) + + # Extract the tar file with progress for every 1% + tar --use-compress-program=pigz \ + --checkpoint="$zero_one_percent" \ + --checkpoint-action=dot \ + -xf "$backup_location" \ + -C "$backup_dir" + else $extraction_command "$backup_location" -C "$backup_dir" fi + if [ $? -eq 0 ]; then log "Backup extracted successfully." + log "Extracted backup folder: $real_backup_files_path" else log "FATAL ERROR: Backup extraction failed." cleanup exit 1 fi - - # Handle nested archives (common in some cPanel backups) - for nested_archive in "$backup_dir"/*.tar.gz "$backup_dir"/*.tgz; do - if [ -f "$nested_archive" ]; then - log "Found nested archive: $nested_archive" - tar -xzf "$nested_archive" -C "$backup_dir" - rm "$nested_archive" # Remove the nested archive after extraction - fi - done } # LOCATE FILES IN EXTRACTED BACKUP @@ -280,43 +336,60 @@ locate_backup_directories() { exit 1 fi - mysqldir=$(find "$backup_dir" -type d -name "mysql" | head -n 1) + + mysqldir="$real_backup_files_path/mysql" if [ -z "$mysqldir" ]; then log "WARNING: Unable to locate MySQL directory in the backup" fi - mysql_conf=$(find "$backup_dir" -type f -name "mysql.sql" | head -n 1) + mysql_conf="$real_backup_files_path/mysql.sql" if [ -z "$mysql_conf" ]; then log "WARNING: Unable to locate MySQL grants file in the backup" fi - cp_file=$(find "$backup_dir" -type f -path "*/cp/*" -name "$cpanel_username" | head -n 1) + + ftp_conf="$real_backup_files_path/proftpdpassword" + if [ -z "$ftp_conf" ]; then + log "WARNING: Unable to locate ProFTPD users file file in the backup" + fi + + domain_logs="$real_backup_files_path/logs/" + if [ -z "$domain_logs" ]; then + log "WARNING: Unable to locate apache domlogs in the backup" + fi + + + + cp_file="$real_backup_files_path/cp/$cpanel_username" if [ -z "$cp_file" ]; then log "FATAL ERROR: Unable to locate cp/$cpanel_username file in the backup" exit 1 fi - log "Backup directories located successfully" - log "Home directory: $homedir" - log "MySQL directory: $mysqldir" - log "MySQL grants: $mysql_conf" - log "cPanel configuration: $cp_file" + log "Backup directories and configuration files located successfully" + log "- Home directory: $homedir" + log "- MySQL directory: $mysqldir" + log "- MySQL grants: $mysql_conf" + log "- PureFTPD users: $ftp_conf" + log "- Domain logs: $domain_logs" + log "- cPanel configuration: $cp_file" } + + # CPANEL BACKUP METADATA parse_cpanel_metadata() { log "Starting to parse cPanel metadata..." - + cp_file="${real_backup_files_path}/cp/${cpanel_username}" - debug_log "Attempting to parse metadata from file: $cp_file" - + if [ ! -f "$cp_file" ]; then log "WARNING: cp file $cp_file not found. Using default values." main_domain="" cpanel_email="" php_version="inherit" else - # Function to get value from cp file with default + get_cp_value() { local key="$1" local default="$2" @@ -351,15 +424,15 @@ parse_cpanel_metadata() { max_sql=$(get_cp_value "MAXSQL" "unlimited") max_pop=$(get_cp_value "MAXPOP" "unlimited") max_sub=$(get_cp_value "MAXSUB" "unlimited") - + log "Additional metadata parsed:" - log "IP Address: $ip_address" - log "Plan: $plan" - log "Max Addon Domains: $max_addon" - log "Max FTP Accounts: $max_ftp" - log "Max SQL Databases: $max_sql" - log "Max Email Accounts: $max_pop" - log "Max Subdomains: $max_sub" + log "IP Address: $ip_address" + log "Plan: $plan" + log "Max Addon Domains: $max_addon" + log "Max FTP Accounts: $max_ftp" + log "Max SQL Databases: $max_sql" + log "Max Email Accounts: $max_pop" + log "Max Subdomains: $max_sub" fi # Ensure we have at least an empty string for each variable @@ -367,32 +440,38 @@ parse_cpanel_metadata() { cpanel_email="${cpanel_email:-}" php_version="${php_version:-inherit}" - log "cPanel metadata parsed:" - log "Main Domain: ${main_domain:-Not found}" - log "Email: ${cpanel_email:-Not found}" - log "PHP Version: $php_version" + log "Main Domain: ${main_domain:-Not found}" + log "Email: ${cpanel_email:-Not found}" + log "PHP Version: $php_version" log "Finished parsing cPanel metadata." } + + # CHECK BEFORE EXPORT -check_if_user_exists(){ +check_if_user_exists(){ backup_filename=$(basename "$backup_location") cpanel_username="${backup_filename##*_}" cpanel_username="${cpanel_username%%.*}" log "Username: $cpanel_username" - + local existing_user="" if opencli user-list --json > /dev/null 2>&1; then existing_user=$(opencli user-list --json | jq -r ".[] | select(.username == \"$cpanel_username\") | .id") fi if [ -z "$existing_user" ]; then - log "Username $cpanel_username is available, starting import.." + log "Username $cpanel_username is available" + if [ "$DRY_RUN" = false ]; then + log "Starting import process.." + fi else log "FATAL ERROR: $cpanel_username already exists." exit 1 fi } + + # CREATE NEW USER create_new_user() { local username="$1" @@ -408,7 +487,7 @@ create_new_user() { while IFS= read -r line; do log "$line" done <<< "$create_user_command" - + if echo "$create_user_command" | grep -q "Successfully added user"; then : else @@ -417,6 +496,8 @@ create_new_user() { fi } + + # PHP VERSION restore_php_version() { local php_version="$1" @@ -431,29 +512,31 @@ restore_php_version() { log "PHP version is set to inherit. No changes will be made." else log "Checking if current PHP version installed matches the version from backup" - local current_version=$(opencli php-default_php_version "$cpanel_username" | sed 's/Default PHP version for user.*: //') + local current_version=$(opencli php-default_version "$cpanel_username" | sed 's/Default PHP version for user.*: //') if [ "$current_version" != "$php_version" ]; then - local installed_versions=$(opencli php-enabled_php_versions "$cpanel_username") + local installed_versions=$(opencli php-installed_versions "$cpanel_username") if ! echo "$installed_versions" | grep -q "$php_version"; then - log "Default PHP version $php_version from backup is not present in the container, installing.." - output=$(opencli php-install_php_version "$cpanel_username" "$php_version" 2>&1) + log "Default PHP version $php_version from backup is not present in the container, installing.." + output=$(opencli php-install_version "$cpanel_username" "$php_version" 2>&1) while IFS= read -r line; do log "$line" done <<< "$output" - - #SET AS DEFAULT PHP VERSION + + # Set as default PHP version log "Setting newly installed PHP $php_version as the default version for all new domains." - output=$(opencli php-default_php_version "$cpanel_username" --update "$php_version" 2>&1) + output=$(opencli php-default_version "$cpanel_username" --update "$php_version" 2>&1) while IFS= read -r line; do log "$line" - done <<< "$output" + done <<< "$output" fi else - log "Default PHP version in backup file ($php_version) matches the installed PHP version: ($current_version) " + log "Default PHP version in backup file ($php_version) matches the installed PHP version: ($current_version)" fi fi } + + # PHPMYADMIN grant_phpmyadmin_access() { local username="$1" @@ -468,18 +551,20 @@ grant_phpmyadmin_access() { phpmyadmin_user="phpmyadmin" sql_command="GRANT ALL ON *.* TO 'phpmyadmin'@'localhost'; FLUSH PRIVILEGES;" grant_commands=$(docker exec $username mysql -N -e "$sql_command") - + log "Access granted to phpMyAdmin user for all databases of $username" } + + # MYSQL restore_mysql() { local mysql_dir="$1" local sandbox_warning_logged=false - + log "Restoring MySQL databases for user $cpanel_username" - + if [ "$DRY_RUN" = true ]; then log "DRY RUN: Would restore MySQL databases for user $cpanel_username" return @@ -490,7 +575,7 @@ restore_mysql() { local db_file="$1" text_to_check='enable the sandbox mode' local first_line - + first_line=$(head -n 1 ${real_backup_files_path}/mysql/$db_file) if echo "$first_line" | grep -q "$text_to_check"; then if [ "$sandbox_warning_logged" = false ]; then @@ -500,16 +585,16 @@ restore_mysql() { # Remove the first line and save the changes to the same file tail -n +2 "${real_backup_files_path}/mysql/$db_file" > "${real_backup_files_path}/mysql/${db_file}.workaround" && mv "${real_backup_files_path}/mysql/${db_file}.workaround" "${real_backup_files_path}/mysql/$db_file" fi - } + } if [ -d "$mysql_dir" ]; then # STEP 1. get old server ip and replace it in the mysql.sql file that has import permissions old_ip=$(grep -oP 'IP=\K[0-9.]+' ${real_backup_files_path}/cp/$cpanel_username) - log "Replacing old server IP: $old_ip with '%' in database grants" + log "Replacing old server IP: $old_ip with '%' in database grants" sed -i "s/$old_ip/%/g" $mysql_conf - + old_hostname=$(cat ${real_backup_files_path}/meta/hostname) - log "Removing old hostname $old_hostname from database grants" + log "Removing old hostname $old_hostname from database grants" sed -i "/$old_hostname/d" "$mysql_conf" @@ -517,7 +602,7 @@ restore_mysql() { log "Initializing MySQL service for user" docker exec $cpanel_username bash -c "service mysql start >/dev/null 2>&1" docker exec "$cpanel_username" sed -i 's/CRON_STATUS="off"/CRON_STATUS="on"/' /etc/entrypoint.sh - + # STEP 3. create and import databases total_databases=$(ls "$mysql_dir"/*.create | wc -l) log "Starting import for $total_databases MySQL databases" @@ -525,15 +610,15 @@ restore_mysql() { current_db=1 for db_file in "$mysql_dir"/*.create; do local db_name=$(basename "$db_file" .create) - - log "Creating database: $db_name (${current_db}/${total_databases})" + + log "Creating database: $db_name (${current_db}/${total_databases})" apply_sandbox_workaround "$db_name.create" # Apply the workaround if it's needed docker cp ${real_backup_files_path}/mysql/$db_name.create $cpanel_username:/tmp/${db_name}.create >/dev/null 2>&1 docker exec $cpanel_username bash -c "mysql < /tmp/${db_name}.create && rm /tmp/${db_name}.create" - + log "Importing tables for database: $db_name" apply_sandbox_workaround "$db_name.sql" # Apply the workaround if it's needed - docker cp ${real_backup_files_path}/mysql/$db_name.sql $cpanel_username:/tmp/$db_name.sql >/dev/null 2>&1 + docker cp ${real_backup_files_path}/mysql/$db_name.sql $cpanel_username:/tmp/$db_name.sql >/dev/null 2>&1 docker exec $cpanel_username bash -c "mysql ${db_name} < /tmp/${db_name}.sql && rm /tmp/${db_name}.sql" current_db=$((current_db + 1)) done @@ -544,7 +629,7 @@ restore_mysql() { # STEP 4. import grants and flush privileges log "Importing database grants" python3 $script_dir/mysql/json_2_sql.py ${real_backup_files_path}/mysql.sql ${real_backup_files_path}/mysql.TEMPORARY.sql >/dev/null 2>&1 - + docker cp ${real_backup_files_path}/mysql.TEMPORARY.sql $cpanel_username:/tmp/mysql.TEMPORARY.sql >/dev/null 2>&1 docker exec $cpanel_username bash -c "mysql < /tmp/mysql.TEMPORARY.sql && mysql -e 'FLUSH PRIVILEGES;' && rm /tmp/mysql.TEMPORARY.sql" @@ -556,20 +641,27 @@ restore_mysql() { fi } + + # SSL CACHE refresh_ssl_file() { local username="$1" - + if [ "$DRY_RUN" = true ]; then log "DRY RUN: Would refresh SSL file for user $username" return fi log "Creating a list of SSL certificates for user interface" - opencli ssl-user "$cpanel_username" - + output=$(opencli ssl-user "$cpanel_username") + while IFS= read -r line; do + log "$line" + done <<< "$output" } + + + # SSL CERTIFICATES restore_ssl() { local username="$1" @@ -579,6 +671,8 @@ restore_ssl() { return fi + + # TODO: edit to cove certs/ keys/ log "Restoring SSL certificates for user $username" if [ -d "$real_backup_files_path/ssl" ]; then for cert_file in "$real_backup_files_path/ssl"/*.crt; do @@ -591,15 +685,51 @@ restore_ssl() { log "SSL key file not found for domain: $domain" fi done - + # Refresh the SSL file after restoring certificates refresh_ssl_file "$username" else log "No SSL certificates found to restore" fi - } + + + + +# SSH PASSWORD + +# openpanel does not use pam for authentication so we can not se the user password to be same as on cp, but we can set ssh password to remain the same! +restore_ssh_password() { + local username="$1" + local shell_file="$real_backup_files_path/shadow" + if [ "$DRY_RUN" = true ]; then + log "DRY RUN: Would set SSH password for user: $username from: $shell_file" + return + fi + + if [ -f "$shell_file" ]; then + log "Restoring SSH password for user $username" + password_hash=$(cat $shell_file) + if [ -z "$password_hash" ]; then + echo "WARNNG: Failed to retrieve password hash for user from $shell_file file." + else + scaped_password_hash=$(echo "$password_hash" | sed 's/\$/\\\$/g') + docker exec "$username" bash -c "sed -i 's|^$username:[^:]*:|$username:$escaped_password_hash:|' /etc/shadow" + if [ $? -eq 0 ]; then + echo "Successfully set the password for ssh user $username in contianer to be the same as in cpanel backup file." + else + echo "Failed to set ssh password for user $username to eb the same as in cpanel backup file." + fi + fi + else + echo "WARNNG: Failed to retrieve password shadow for user from $shell_file file." + fi +} + + + + # SSH KEYS restore_ssh() { local username="$1" @@ -621,6 +751,9 @@ restore_ssh() { fi } + + + # DNS ZONES restore_dns_zones() { log "Restoring DNS zones for user $cpanel_username" @@ -642,45 +775,45 @@ restore_dns_zones() { for zone_file in "$real_backup_files_path/dnszones"/*; do local zone_name=$(basename "${zone_file%.db}") - # Check if the destination zone file exists, if not, it was probably a subdomain that had no dns zone and + # Check if the destination zone file exists, if not, it was probably a subdomain that had no dns zone and if [ ! -f "/etc/bind/zones/${zone_name}.zone" ]; then log "DNS zone file /etc/bind/zones/${zone_name}.zone does not exist. Skipping import for $zone_name." continue else log "Importing DNS zone: $zone_name" fi - + old_ip=$(grep -oP 'IP=\K[0-9.]+' ${real_backup_files_path}/cp/$cpanel_username) if [ -z "$old_ip" ]; then log "WARNING: old server ip address not detected in file ${real_backup_files_path}/cp/$cpanel_username - records will not be automatically updated to new ip address." else - log "Replacing old server IP: $old_ip with new IP: $new_ip in DNS zone file for domain: $zone_name" + log "Replacing old server IP: $old_ip with new IP: $new_ip in DNS zone file for domain: $zone_name" sed -i "s/$old_ip/$new_ip/g" $zone_file fi - + # Temporary files to store intermediate results temp_file_of_original_zone=$(mktemp) temp_file_of_created_zone=$(mktemp) - + # Remove all lines after the last line that starts with '@' log "Editing original zone for domain $zone_name to temporary file: $temp_file_of_original_zone" awk '/^@/ { found=1; last_line=NR } { if (found && NR > last_line) exit } { print }' "$zone_file" > "$temp_file_of_original_zone" - + # Remove all lines from the beginning until the line that has 'NS' and including that line log "Editing created zone for domain $zone_name to temporary file: $temp_file_of_created_zone" awk '/NS/ { found=1; next } found { print }' "/etc/bind/zones/${zone_name}.zone" > "$temp_file_of_created_zone" - + # Append the processed second file to the first log "Merging the DNS zone records from $temp_file_of_created_zone with $temp_file_of_original_zone" cat "$temp_file_of_created_zone" >> "$temp_file_of_original_zone" - + # Move the merged content to the final file log "Replacing the created zone /etc/bind/zones/${zone_name}.zone with updated records." mv "$temp_file_of_original_zone" "/etc/bind/zones/${zone_name}.zone" - + # Clean up rm "$temp_file_of_created_zone" - + log "DNS zone file for $zone_name has been imported." done else @@ -688,27 +821,30 @@ restore_dns_zones() { fi } + + # HOME DIR restore_files() { - du_needed_for_home=$(du -sh "$real_backup_files_path/homedir" | cut -f1) - log "Restoring files ($du_needed_for_home) to /home/$cpanel_username/" - if [ "$DRY_RUN" = true ]; then log "DRY RUN: Would restore files to /home/$cpanel_username/" return fi + du_needed_for_home=$(du -sh "$real_backup_files_path/homedir" | cut -f1) + log "Restoring home directory ($du_needed_for_home) to /home/$cpanel_username/" + mv $real_backup_files_path/homedir /home/$cpanel_username : ' + # LEAVE THIS FOR CLUSTERING FEATURE rsync -Prltvc --info=progress2 "$real_backup_files_path/homedir/" "/home/$cpanel_username/" 2>&1 | while IFS= read -r line; do log "$line" done - + log "Finished transferring files, comparing to source.." original_size=$(du -sb "$real_backup_files_path/homedir" | cut -f1) copied_size=$(du -sb "/home/$cpanel_username/" | cut -f1) - + if [[ "$original_size" -eq "$copied_size" ]]; then log "The original and target directories have the same size." else @@ -717,24 +853,28 @@ restore_files() { log "Target size: $copied_size bytes" fi ' - + # Move all files from public_html to main domain dir log "Moving main domain files from public_html to $main_domain directory." - mv /home/$cpanel_username/public_html /home/$cpanel_username/$main_domain - rm /home/$cpanel_username/www #since www is symlink to public_html - - #shopt -s dotglob - #mv "/home/$cpanel_username/public_html"/* "/home/$cpanel_username/$main_domain"/ - #shopt -u dotglob + mv /home/$cpanel_username/public_html /home/$cpanel_username/$main_domain # openpanel has no concept of 'primary' domain + rm /home/$cpanel_username/www # since www is just a symlink to public_html } + + # PERMISSIONS fix_perms(){ log "Changing permissions for all files and folders in user home directory /home/$cpanel_username/" + if [ "$DRY_RUN" = true ]; then + log 'DRY RUN: Would change permissions with command: docker exec $cpanel_username bash -c "chown -R 1000:33 /home/$cpanel_username"' + return + fi docker exec $cpanel_username bash -c "chown -R 1000:33 /home/$cpanel_username" } + + # WORDPRESS SITES restore_wordpress() { local real_backup_files_path="$1" @@ -745,22 +885,20 @@ restore_wordpress() { return fi - log "Restoring WordPress sites for user $username" - if [ -d "$real_backup_files_path/wptoolkit" ]; then - for wp_file in "$real_backup_files_path/wptoolkit"/*.json; do - log "Importing WordPress site from: $wp_file" - opencli wp-import "$username" "$wp_file" - done - else - log "No WordPress data found to restore" - fi + log "Checking user files for WordPress installations to add to Site Manager interface.." + output=$(opencli websites-scan $cpanel_username) + while IFS= read -r line; do + log "$line" + done <<< "$output" } + + # DOMAINS -restore_domains() { +restore_domains() { if [ -f "$real_backup_files_path/userdata/main" ]; then file_path="$real_backup_files_path/userdata/main" # Initialize variables @@ -768,7 +906,7 @@ restore_domains() { parked_domains="" sub_domains="" addon_domains="" - + # Read the file line by line while IFS= read -r line; do if [[ "$line" =~ ^main_domain: ]]; then @@ -802,25 +940,25 @@ restore_domains() { addon_domains_section=false fi fi - done < "$file_path" - + done < "$file_path" + # Parse parked_domains if [[ -z "$parked_domains" ]]; then parked_domains_array=() else IFS=',' read -r -a parked_domains_array <<< "$parked_domains" fi - + sub_domains_array=() addon_domains_array=() - + # Parse sub_domains while IFS= read -r domain; do if [[ -n "$domain" ]]; then sub_domains_array+=("$domain") fi done <<< "$sub_domains" - + # Parse addon_domains while IFS= read -r domain; do if [[ -n "$domain" ]]; then @@ -851,7 +989,7 @@ restore_domains() { addon_domains_count=0 log "No addon domains detected." else - log "Addon domains ($addon_domains_count): ${addon_domains_array[@]}" + log "Addon domains ($addon_domains_count): ${addon_domains_array[@]}" fi parked_domains_count=${#parked_domains_array[@]} @@ -867,7 +1005,7 @@ restore_domains() { filtered_sub_domains_count=0 log "No subdomains detected." else - log "Subdomains ($filtered_sub_domains_count): ${filtered_sub_domains[@]}" + log "Subdomains ($filtered_sub_domains_count): ${filtered_sub_domains[@]}" fi @@ -882,18 +1020,23 @@ restore_domains() { type="$2" current_domain_count=$((current_domain_count + 1)) - log "Restoring $type $domain (${current_domain_count}/${domains_total_count})" - - if [ "$DRY_RUN" = true ]; then - log "DRY RUN: Would restore $type $domain" - elif opencli domains-whoowns "$domain" | grep -q "not found in the database."; then - output=$(opencli domains-add "$domain" "$cpanel_username" 2>&1) - while IFS= read -r line; do - log "$line" - done <<< "$output" + if [[ $domain == \*.* ]]; then + log "WARNING: Skipping wildcard domain $domain" else - log "WARNING: $type $domain already exists and will not be added to this user." - fi + log "Restoring $type $domain (${current_domain_count}/${domains_total_count})" + + if [ "$DRY_RUN" = true ]; then + log "DRY RUN: Would restore $type $domain" + elif opencli domains-whoowns "$domain" | grep -q "not found in the database."; then + output=$(opencli domains-add "$domain" "$cpanel_username" 2>&1) + while IFS= read -r line; do + log "$line" + done <<< "$output" + else + log "WARNING: $type $domain already exists and will not be added to this user." + fi + fi + } # Process the domains @@ -924,7 +1067,7 @@ restore_domains() { log "Processing sub-domains.." for filtered_sub in "${filtered_sub_domains[@]}"; do create_domain "$filtered_sub" "subdomain" - #TODO: create record in dns zone instead of separate domain if only dns zone and no folder! + # TODO: create record in DNS zone instead of separate domain if only DNS zone and no folder! done fi @@ -939,7 +1082,6 @@ restore_domains() { - # CRONJOB restore_cron() { log "Restoring cron jobs for user $cpanel_username" @@ -974,99 +1116,269 @@ restore_cron() { fi } -# Main execution -main() { + + + +run_custom_post_hook() { + if [ -n "$post_hook" ]; then + if [ -x "$post_hook" ]; then + log "Executing post-hool script.." + "$post_hook" "$cpanel_username" + else + log "WARNING: Post-hook file '$post_hook' is not executable or not found." + exit 1 + fi + fi +} + + + + + + + +create_tmp_dir_and_path() { + backup_filename="${backup_filename%.*}" + backup_dir=$(mktemp -d /tmp/cpanel_import_XXXXXX) + log "Created temporary directory: $backup_dir" + real_backup_files_path="${backup_dir}/${backup_filename%.*}" +} + + +success_message() { + end_time=$(date +%s) + elapsed=$(( end_time - start_time )) + hours=$(( elapsed / 3600 )) + minutes=$(( (elapsed % 3600) / 60 )) + seconds=$(( elapsed % 60 )) + + log "Elapsed time: ${hours}h ${minutes}m ${seconds}s" + + if [ "$DRY_RUN" = true ]; then + log "DRY RUN: import process for user $cpanel_username completed." + else + log "SUCCESS: Import for user $cpanel_username completed successfully." + fi +} + + + +log_paths_are() { + log "Log file: $log_file" + log "PID: $pid" +} + + +start_message() { + + echo -e " ------------------ STARTING CPANEL ACCOUNT IMPORT ------------------ -------------------------------------------------------------------- Currently supported features: -- FILES AND FOLDERS -- DOMAINS: MAIN, ADDONS, ALIASES, SUBDOMAINS -- DNS ZONES -- MYSQL DATABASES, USERS AND THEIR GRANTS -- PHP VERSIONS FROM CLOUDLINUX SELECTOR -- SSH KEYS -- CRONJOBS -- WP SITES FROM WPTOOLKIT OR SOFTACULOUS -emails, nodejs/python apps and postgres are not yet supported! +├─ DOMAINS: +│ ├─ Primary domain, Addons, Aliases and Subdomains +│ ├─ SSL certificates +│ ├─ Domains access logs (Apache domlogs) +│ └─ DNS zones +├─ WEBSITES: +│ └─ WordPress instalations from WPToolkit & Softaculous +├─ DATABASES: +│ ├─ Remote access to MySQL +│ └─ MySQL databases, users and grants +├─ PHP: +│ └─ Installed version from Cloudlinux PHP Selector +├─ FILES +├─ CRONS +├─ SSH +│ ├─ Remote SSH access +│ ├─ SSH password +│ └─ SSH keys +└─ ACCOUNT + ├─ Notification preferences + ├─ cPanel account creation date + └─ locale + +***emails, ftp, nodejs/python, postgres are not yet supported*** -------------------------------------------------------------------- if you experience any errors with this script, please report to https://github.com/stefanpejcic/cPanel-to-OpenPanel/issues -------------------------------------------------------------------- " - - log "Log file: $log_file" - log "PID: $pid" - - # PRE-RUN CHECKS - check_if_valid_cp_backup "$backup_location" - check_if_disk_available - check_if_user_exists - validate_plan_exists - install_dependencies - get_server_ipv4 #used in mysql grants - - # unique - backup_dir=$(mktemp -d /tmp/cpanel_import_XXXXXX) - log "Created temporary directory: $backup_dir" - - # extract - extract_cpanel_backup "$backup_location" "$backup_dir" - real_backup_files_path=$(find "$backup_dir" -type f -name "version" | head -n 1 | xargs dirname) - log "Extracted backup folder: $real_backup_files_path" - - # locate important directories - locate_backup_directories - parse_cpanel_metadata +} - # its faster to restore home dir, then create user - restore_files - create_new_user "$cpanel_username" "random" "$cpanel_email" "$plan_name" - - fix_perms - restore_php_version "$php_version" # php v needs to run before domains - restore_domains - restore_dns_zones - restore_mysql "$mysqldir" - restore_cron - restore_ssl "$cpanel_username" - restore_ssh "$cpanel_username" - restore_wordpress "$real_backup_files_path" "$cpanel_username" - - #todo: - # ftp accounts from proftpdpasswd file - - # Cleanup - cleanup - - end_time=$(date +%s) - elapsed=$(( end_time - start_time )) - hours=$(( elapsed / 3600 )) - minutes=$(( (elapsed % 3600) / 60 )) - seconds=$(( elapsed % 60 )) - - log "Elapsed time: ${hours}h ${minutes}m ${seconds}s" - - log "SUCCESS: Import for user $cpanel_username completed successfully." -# run after install if posthook provided -if [ -n "$post_hook" ]; then - if [ -x "$post_hook" ]; then - log "Executing post-hool script.." - "$post_hook" "$cpanel_username" - else - log "WARNING: Post-hook file '$post_hook' is not executable or not found." - exit 1 +ftp_accounts_import() { + + if [ -f "$ftp_conf" ]; then + log "WARNING: Importing PureFTPD accounts is not yet supported" + : ' + #cat proftpdpasswd + pejcic:$6$cv9wnxSLeD1VEk.U$dm84PcqygxOWqT/uyMjrICKUPFeAQwOimJ8frihDCxjRfa1BKf6bnHIhWrbfmLrLn2YBSMnNatW09ZZMAS7GT/:1030:1034:pejcic:/home/pejcic:/bin/bash + neko@pcx3.com:$6$7GZJXVYlO53hV.M7$750UVg6zKmX.Uj8cmWUxkRnNXxjuZfcm6BxnJceiFD5Zl80sB7jZL0UeHIpw2a3aQRWh.BMH9WuCPdqwj8zxG.:1030:1034:pejcic:/home/pejcic/folder:/bin/ftpsh + whmcsmybekap@openpanel.co:$6$rDNAW7GZEAJ6zHJm$wYqg.H6USldSPCNz4jbgEi55tJ8hgeDzQCAmhSHfAPyzkJeP1u9E.LaLflQ.7kUbuRtBED7I70.QoCNRlxzEy0:1030:1034:pejcic:/home/pejcic/WHMC_MY_OPENPANEL_DB_BEKAP:/bin/ftpsh + pejcic_logs:$6$cv9wnxSLeD1VEk.U$dm84PcqygxOWqT/uyMjrICKUPFeAQwOimJ8frihDCxjRfa1BKf6bnHIhWrbfmLrLn2YBSMnNatW09ZZMAS7GT/:1030:1034:pejcic:/etc/apache2/logs/domlogs/pejcic:/bin/ftpsh + ' fi -fi +} + + +import_domlogs() { + + import_domlogs_for_domain() { + local ssl_log_file="$1" + local domain="$2" + local destination_file="/etc/nginx/domlogs/${domain}.log" + + # Check if the source file exists + if [[ -e "$ssl_log_file" ]]; then + # Move the file to the destination + mv "$ssl_log_file" "$destination_file" + log "Imported logs from file $ssl_log_file to $destination_file" + else + log "WARNING: Error importing ssl logs from file: $ssl_log_file" + fi + } + + if [[ -d "$domain_logs" ]]; then + ALL_DOMAINS_OWNED_BY_USER=$(opencli domains-user "$cpanel_username") + for domain in $ALL_DOMAINS_OWNED_BY_USER; do + ssl_log_file="$domain_logs/$domain-ssl_log" + if [[ -e "$ssl_log_file" ]]; then + log "Importing SSL logs for domain $domain from file: $ssl_log_file" + import_domlogs_for_domain "$ssl_log_file" "$domain" + else + log "SSL logs not available for domain $domain - Skipping" + fi + done + else + log "WARNING: SSL logs not detected for domains and will not be imported." + fi +} + + + + + + +import_email_accounts_and_data() { + log "WARNING: Importing Email accounts is not yet supported" +} + + + + +# timestamp in openadmin/whm +restore_startdate() { + real_backup_files_path="$1" + cpanel_username="$2" + cp_file_path="$real_backup_files_path/cp/$cpanel_username" + STARTDATE=$(grep -oP 'STARTDATE=\K\d+' "$cp_file_path") + + if [ -n "$STARTDATE" ]; then + human_readable_date=$(date -d @"$STARTDATE" +"%Y-%m-%d %H:%M:%S") + log "Updating account creation date to reflect cpanel date: $human_readable_date" + update_timestamp="UPDATE users SET registered_date = '$human_readable_date' WHERE username = '$cpanel_username';" + mysql -e "$update_timestamp" + fi +} + + +# EMAIL NOTIFICATIONS +restore_notifications() { + local real_backup_files_path="$1" + local cpanel_username="$2" + notifications_cp_file="$real_backup_files_path/cp/$cpanel_username" + notifications_op_file="/etc/openpanel/openpanel/core/users/$cpanel_username/notifications.yaml" + + if [ -z "$notifications_cp_file" ]; then + log "WARNING: Unable to access $notifications_cp_file for notification preferences - Skipping" + else + if [ "$DRY_RUN" = true ]; then + log "DRY RUN: Would restore notification preferences from $notifications_cp_file" + check_notifications=$(grep "notify_" $notifications_cp_file) + while IFS= read -r line; do + log "$line" + done <<< "$check_notifications" + return + fi + grep "notify_" $notifications_cp_file > $notifications_op_file + cat_notifications_file=$(cat $notifications_op_file 2>&1) + while IFS= read -r line; do + log "$line" + done <<< "$cat_notifications_file" + fi +} + + + + + + + + + + + +###################################### MAIN SCRIPT EXECUTION ###################################### +################################################################################################### +main() { + + start_message # what will be imported + log_paths_are # where will we store the progress + + # STEP 1. PRE-RUN CHECKS + check_if_valid_cp_backup "$backup_location" # is it? + check_if_disk_available # calculate du needed for extraction + check_if_user_exists # make sure we dont overwrite user! + validate_plan_exists # check if provided plan exists + install_dependencies # install commands we will use for this script + get_server_ipv4 # used in mysql grants + + # STEP 2. EXTRACT + create_tmp_dir_and_path # create /tmp/.. dir and set the path + extract_cpanel_backup "$backup_location" "${backup_dir}" # extract the archive + + # STEP 3. IMPORT + locate_backup_directories # get paths from backup + parse_cpanel_metadata # get data and configurations + restore_files # homedir + create_new_user "$cpanel_username" "random" "$cpanel_email" "$plan_name" # create user data and container + fix_perms # fix permissions for all files + restore_php_version "$php_version" # php v needs to run before domains + restore_domains # add domains + restore_dns_zones # add dns + import_domlogs # import ssl logs for domains + restore_mysql "$mysqldir" # mysql databases, users and grants + restore_cron # cronjob + restore_ssl "$cpanel_username" # ssl certs + restore_ssh "$cpanel_username" # enable remote ssh for user + restore_ssh_password "$cpanel_username" # set ssh password same as in backup + restore_wordpress "$real_backup_files_path" "$cpanel_username" # import wp sites to sitemanager + restore_notifications "$real_backup_files_path" "$cpanel_username" # notification preferences from cp + restore_startdate "$real_backup_files_path" "$cpanel_username" # cp account creation date + + # STEP 4. IMPORT ENTERPRISE FEATURES + import_email_accounts_and_data # import emails, filters, forwarders.. + ftp_accounts_import # import ftp accounts + + # STEP 5. DELETE TMP FILES + cleanup # delete extracter files after import + + # STEP 6. NOTIFY USER + success_message # have a 🍺 + + # STEP 7. RUN ANY CUSTOM SCRIPTS + run_custom_post_hook # any script to run after the import? example: edit dns on cp server, run tests, notify user, etc. + } # MAIN FUNCTION diff --git a/integrations/cpanel-import/cpanel_import.py b/integrations/cpanel-import/cpanel_import.py deleted file mode 100644 index 77d6db94..00000000 --- a/integrations/cpanel-import/cpanel_import.py +++ /dev/null @@ -1,35 +0,0 @@ -import os -import json # will use for get to return data -import socket -from flask import Flask, Response, abort, render_template, request, send_file, g, jsonify, session, url_for, flash, redirect, get_flashed_messages -import subprocess -from app import app, is_license_valid, login_required_route -from modules.helpers import get_all_plans, is_username_unique - -@app.route('/import/cpanel', methods=['GET', 'POST']) -@login_required -def import_cpanel_whm_account(): - if request.method == 'POST': - path = request.form.get('path') - plan_name = request.form.get('plan_name') - - if not path or not plan_name: - flash('Both path to the cPanel backup file (.tar.gz) and plan name are required!', 'error') - return redirect('/import/cpanel') - try: - file_name = os.path.basename(path) - log_file_name = f"cpanel_import_log_{os.path.splitext(file_name)[0]}" - log_file_path = f"/var/log/openpanel/admin/{log_file_name}.log" - - # Run the subprocess command and redirect stdout and stderr to the log file - with open(log_file_path, 'w') as log_file: - subprocess.Popen(['opencli', 'user-import', 'cpanel', path, plan_name], stdout=log_file, stderr=log_file) - - flash(f'Import started! To track the progress open the log file: {log_file_path}', 'success') - except Exception as e: - flash(f'An error occurred: {str(e)}', 'error') - - return redirect('/import/cpanel') - else: - # on GET we will list the sessions in progress.. - return render_template('cpanel-import.html', title='Import cPanel account') diff --git a/integrations/cpanel-import/templates/cpanel-import.html b/integrations/cpanel-import/templates/cpanel-import.html deleted file mode 100644 index c70d901e..00000000 --- a/integrations/cpanel-import/templates/cpanel-import.html +++ /dev/null @@ -1,19 +0,0 @@ -{% extends 'base.html' %} - -{% block content %} - -
- {% with messages = get_flashed_messages() %} - {% if messages %} - {% for message in messages %} - - {% endfor %} - {% endif %} - {% endwith %} -
- - -{% endblock %} diff --git a/integrations/digitalocean/.github/CODEOWNERS b/integrations/digitalocean/.github/CODEOWNERS deleted file mode 100644 index c226b66c..00000000 --- a/integrations/digitalocean/.github/CODEOWNERS +++ /dev/null @@ -1 +0,0 @@ -@marketplace-eng diff --git a/integrations/digitalocean/.github/CONTRIBUTING.md b/integrations/digitalocean/.github/CONTRIBUTING.md deleted file mode 100644 index 1962a365..00000000 --- a/integrations/digitalocean/.github/CONTRIBUTING.md +++ /dev/null @@ -1,27 +0,0 @@ -# Contributing - -We enthusiastically encourage contributions of all sorts to our repository, from correcting typos, to improving checks or adding new ones. - -### Reporting Issues - -This section guides you through submitting an issue for the Marketplace Partners. Following these guidelines helps maintainers and the community understand your report :pencil:, reproduce the behavior :computer: :computer:, and find related reports :mag_right:. - -When you are reporting an issue, please [include as many details as possible](#how-do-i-submit-a-good-bug-report). - -> **Note:** If you find a **Closed** issue that seems like it is the same thing that you're experiencing, open a new issue and include a link to the original issue in the body of your new one. - -#### Before Submitting An Issue -* **Check the [current issues](https://github.com/digitalocean/marketplace-partners/issues)**. - -#### How Do I Submit A (Good) Issue? - -Issues are tracked as [GitHub issues](https://guides.github.com/features/issues/). Create an issue and provide the following information listed below. - -Explain the problem and include additional details to help maintainers reproduce the problem: - -* **Use a clear and descriptive title** for the issue to identify the problem. -* **Describe the exact steps which reproduce the problem** in as many details as possible. When listing steps, **don't just say what you did, but explain how you did it**. -* **Provide specific examples to demonstrate the steps**. Include links to files or GitHub projects, or copy/pasteable snippets, which you use in those examples. If you're providing snippets in the issue, use [Markdown code blocks](https://help.github.com/articles/markdown-basics/#multiple-lines). -* **Describe the behavior you observed after following the steps** and point out what exactly is the problem with that behavior. -* **Explain which behavior you expected to see instead and why.** -* **Include screenshots and animated GIFs** which show you following the described steps and clearly demonstrate the problem. diff --git a/integrations/digitalocean/.gitignore b/integrations/digitalocean/.gitignore deleted file mode 100644 index 6a557f52..00000000 --- a/integrations/digitalocean/.gitignore +++ /dev/null @@ -1,43 +0,0 @@ -# Compiled source # -################### -*.com -*.class -*.dll -*.exe -*.o -*.so - -# Packages # -############ -# it's better to unpack these files and commit the raw source -# git has its own built in compression methods -*.7z -*.dmg -*.gz -*.iso -*.jar -*.rar -*.tar -*.zip - -# Logs and databases # -###################### -*.log -*.sql -*.sqlite - -# OS generated files # -###################### -.DS_Store -.DS_Store? -._* -.Spotlight-V100 -.Trashes -ehthumbs.db -Thumbs.db - -# App generated files # -###################### -.vscode - -.Rproj.user diff --git a/templates/admini/README.md b/templates/admini/README.md deleted file mode 100644 index cf5e34f6..00000000 --- a/templates/admini/README.md +++ /dev/null @@ -1 +0,0 @@ -[admini](https://admini.vercel.app/) is the awesome default theme for OpenPanel ✌️ diff --git a/templates/admini/apache_nginx_conf_editor.html b/templates/admini/apache_nginx_conf_editor.html new file mode 100644 index 00000000..8f99a4d6 --- /dev/null +++ b/templates/admini/apache_nginx_conf_editor.html @@ -0,0 +1,122 @@ +{% extends 'base.html' %} +{% block content %} + + + + + + + + +

{{ _('Here you can edit the main configuration file for your webserver.') }}

+ +
+
+ +
+ + + + + + +
+ +
+ +
+ +
+ +
+
+ + + + + + + + + +{% endblock %} + diff --git a/templates/admini/autoinstaller.html b/templates/admini/autoinstaller.html new file mode 100644 index 00000000..77c90a00 --- /dev/null +++ b/templates/admini/autoinstaller.html @@ -0,0 +1,174 @@ + +{% extends 'base.html' %} + +{% block content %} + + +
+{% if 'wordpress' in enabled_modules %} +
+
+ +
+
+
+ +
+
+
WordPress
+
+
+

Versatile and user-friendly platform for creating and managing websites and blogs.

+
+ +
+
+{% endif %} + +{% if 'pm2' in enabled_modules %} +
+
+ +
+
+
+ PM2 +
+
+
NodeJS & Python
+
+
+

Simplify app setup for scalable NodeJS and Python versatile web development.

+
+ +
+
+{% endif %} + + + +{% if 'mautic' in enabled_modules %} +
+
+ +
+ +
+
+ + +
+
+
Mautic
+
+
+

Powerful and flexible marketing automation software for managing campaigns and customer interactions.

+
+ +
+
+{% endif %} + +{% if 'flarum' in enabled_modules %} +
+
+ +
+
+
+ image/svg+xml +
+
+
Flarum
+
+
+

Fast, lightweight, and customizable forum software for building engaging online communities.

+
+ +
+
+{% endif %} + + + + + + +{% if 'fossbilling' in enabled_modules %} +
+
+ +
+
+
+ + + + + + + +
+
+
FossBilling
+
+
+

The free and open-source solution for efficient billing and client management.

+
+ +
+
+{% endif %} + + + + + + + + + +
+ + +{% endblock %} + diff --git a/templates/admini/base.html b/templates/admini/base.html new file mode 100644 index 00000000..39b7ace9 --- /dev/null +++ b/templates/admini/base.html @@ -0,0 +1,1248 @@ + + + + + + + + + + + + + + + + + + + + + + {{ title }} - {% if brand_name %}{{brand_name}}{% else %}{{brand}}{% endif %} + + + + + + + + + + +{% if current_route == "/server/webserver_conf" or title == "PHP.INI Editor" %} + + + + + + + + + + + +{% endif %} + + + + + + + + + + +{% if current_route.startswith('/usage') %} + + + + + +{% endif %} + + + + + + +{% block custom_header %} + + {% include 'custom_code/in_header.html' %} +{% endblock %} + + + + + + + + + +
+ {% include 'partials/sidebar.html' %} + + + + {% set applications_available_for_install = 0 %} + {% if 'wordpress' in enabled_modules %} + {% set applications_available_for_install = applications_available_for_install + 1 %} + {% endif %} + {% if 'pm2' in enabled_modules %} + {% set applications_available_for_install = applications_available_for_install + 1 %} + {% endif %} + {% if 'mautic' in enabled_modules %} + {% set applications_available_for_install = applications_available_for_install + 1 %} + {% endif %} + {% if 'flarum' in enabled_modules %} + {% set applications_available_for_install = applications_available_for_install + 1 %} + {% endif %} + + + + + + + + + + +
+ + + +{% if current_route.startswith('/website') %} + + + + {% if user_websites %} + + + {% if 'wordpress' in enabled_modules or 'pm2' in enabled_modules or 'mautic' in enabled_modules or 'flarum' in enabled_modules %} + + + + {% endif %} + + + + + + {% endif %} + + +{% endif %} + + + + +
+{% if current_route.startswith('/website') %} + +{% endif %} + + +{% if session.get('impersonate') %} +
+
+

{{ _("You are currently impersonating user") }} '{{current_username}}'

+Return to admin +
+
+ + + + +{% endif %} + +{% if current_route.startswith('/files') %} + + + +
+
+ +
+
+ + +
+
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+
+{% else %} +
+
+ +
+
+ +
+ +
+ + +{% if current_route.startswith('/files') or title == "j" %} + +{% else %} + + +{% endif %} + + + + + + + + + + +
+ +{% if 'favorites' in enabled_modules %} + + + +
+ +
+ + + + + + + + + + + + + + + + +{% endif %} + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ + +{% endif %} + + + +
+
+{% block content %}{% endblock %} +
+
+
+
+
+
+ + + + + + +{% include 'partials/notifications.html' %} + + + +{% include 'partials/_shortcuts.html' %} + + + + + + + + + + + +{% block custom_footer %} + + {% include 'custom_code/in_footer.html' %} +{% endblock %} + +{% if url_for('static', filename='js/custom.js') %} + + +{% endif %} + + diff --git a/templates/admini/cronjobs.html b/templates/admini/cronjobs.html new file mode 100644 index 00000000..e32cc303 --- /dev/null +++ b/templates/admini/cronjobs.html @@ -0,0 +1,1045 @@ +{% extends 'base.html' %} + +{% block content %} + +{% if view_mode == 'table' %} + + + + + +

{{ _('A cron job is a Linux command used to schedule tasks for future execution. It allows you to automate repetitive tasks, such as sending notifications or running scripts at specific intervals.') }}

+ +
+
+
+ + +
+
+

{{ _('Add New Cron Job') }}

+ +
+
+
+ + +
+
+ + +
+
+
+
+ + +
+
+ + +
+ + +
+
+
+ + +
+
+ + + +
+
+
+
+ +
+
+ + + +
+
+
+
+ + +
+
+ + +
+
+
+
+ +
+
+
+ + +
+
+ + +
+
+
+
+ +
+
+ + + + + + + + +{% if cronjobs_with_line_numbers %} + +
+ + + + + + + + + + + + + + {% for item in cronjobs_with_line_numbers %} +{% if item.line.startswith('# ') or item.line.strip() == '' %} + + + +{% else %} + + + + + {% set cron_components = item.line.split(' ') %} + + + + + + + + + + {% endif %} + {% endfor %} + +
{{ _('Minute') }}{{ _('Hour') }}{{ _('Day') }}{{ _('Month') }}{{ _('Weekday') }}{{ _('Command') }}{{ _('Actions') }}
{{item.line}}
+ {% if cron_components[0].startswith('#') %} + {{ cron_components[0][1:] }} + {% else %} + {{ cron_components[0] }} + {% endif %} + {{ cron_components[1] }}{{ cron_components[2] }}{{ cron_components[3] }}{{ cron_components[4] }} +
{{ item.line.split(' ', 5)[5] }}
+
+ + +
+ + + + + {% if item.line.startswith('#') %} + + {% else %} + + {% endif %} + + + + +
+  + + +
+ + + +
+ + + + + + + + + + + +{% else %} +

{{ _('No cronjobs.') }}

+{% endif %} + + + + + + + +{% elif view_mode == 'code' %} + +
+ {{ _('Attention:') }} {{ _('Editing crontab file is intended for advanced users only. If you mistyped the cron entry in the file, you will not be warned as opposed to when saving cronjobs in basic editor.') }} +

+ {{ _("Prepend # before the line to pause cronjob. To create a comment, prepend # followed by space: '# '.") }} +
+ +
+ + + +
+ + + + +{% endif %} + + + + +{% endblock %} diff --git a/templates/admini/.gitkeep b/templates/admini/custom_code/custom.css similarity index 100% rename from templates/admini/.gitkeep rename to templates/admini/custom_code/custom.css diff --git a/templates/admini/custom_code/custom.js b/templates/admini/custom_code/custom.js new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/templates/admini/custom_code/custom.js @@ -0,0 +1 @@ + diff --git a/templates/admini/custom_code/in_footer.html b/templates/admini/custom_code/in_footer.html new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/templates/admini/custom_code/in_footer.html @@ -0,0 +1 @@ + diff --git a/templates/admini/custom_code/in_header.html b/templates/admini/custom_code/in_header.html new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/templates/admini/custom_code/in_header.html @@ -0,0 +1 @@ + diff --git a/templates/admini/dashboard/dashboard.html b/templates/admini/dashboard/dashboard.html new file mode 100644 index 00000000..d23383c4 --- /dev/null +++ b/templates/admini/dashboard/dashboard.html @@ -0,0 +1,1244 @@ + +{% extends 'base.html' %} + +{% block content %} + + + + + + + + +
+ +
+ + +
+ + +{% if custom_message %} +
+
+
+ {{ custom_message|safe }} +
+
+
+{% endif %} + + +{% set domain_count = maindomains|length %} +{% if total_domains_count == 0 or domain_count == 0 %} + +
+ +
+
+

{{ _('👋 Welcome to your new hosting account. OpenPanel is here to help!') }}

+

{{ _('To get started, add a domain name to create a new site and unlock a world of possibilities for your online presence.') }}

+ +{% if dedicated_ip != _("Unknown") %} +

{{ _("To secure your website with a free Let's Encrypt SSL, make sure your domain's A record is pointed to your dedicated IP address:") }} {{ dedicated_ip }} {{ _('Ready to start?') }}

+{% else %} +

{{ _("To secure your website with a free Let's Encrypt SSL, make sure your domain's A record is pointed to the server IP address:") }} {{ server_ip }} {{ _('Ready to start?') }}

+{% endif %} + {{ _('Add a new domain') }} +
+
+
+ +{% endif %} + + + + +
+
{{ _('Files') }}
+
+
+
+ + +{% if 'ftp' in enabled_modules %} + +{% endif %} + +{% if 'disk_usage' in enabled_modules %} + +{% endif %} +{% if 'backups' in enabled_modules %} + +{% endif %} +{% if 'ftp' in enabled_modules %} + +{% endif %} + + +{% if 'inodes' in enabled_modules %} + +{% endif %} +{% if 'malware_scan' in enabled_modules %} + +{% endif %} +{% if 'fix_permissions' in enabled_modules %} + +{% endif %} + + +
+
+
+
+
+
{{ _('Domains') }}
+
+ +
+ + +
+
+
{{ _('Databases') }}
+
+
+
+ +
+ +{% if 'phpmyadmin' in enabled_modules %} + +{% endif %} + + + + +
+
+
+ + + +{% if 'wordpress' in enabled_modules or 'pm2' in enabled_modules or 'mautic' in enabled_modules or 'flarum' in enabled_modules %} + +
+
{{ _('Applications') }}
+
+
+ +
+{% if 'wordpress' in enabled_modules %} + +{% endif %} +{% if 'pm2' in enabled_modules %} + +{% endif %} + +{% if 'mautic' in enabled_modules %} + +{% endif %} + + + +{% if 'flarum' in enabled_modules %} + +{% endif %} + +
+
+
+{% endif %} + + + + + + +{% if 'emails' in enabled_modules %} + +
+
{{ _('Emails') }}
+
+
+ + +
+
+{% endif %} + + + + + + + + + + + + + +{% if 'redis' in enabled_modules or 'memcached' in enabled_modules or 'elasticsearch' in enabled_modules %} + +
+
+
{{ _('Search & Caching') }}
+
+
+
+ +
+{% if 'redis' in enabled_modules %} + +{% endif %} +{% if 'memcached' in enabled_modules %} + +{% endif %} +{% if 'elasticsearch' in enabled_modules %} + +{% endif %} +
+
+
+{% endif %} + + + + + +{% if 'crons' in enabled_modules or 'ssh' in enabled_modules or 'terminal' in enabled_modules or 'usage' in enabled_modules or 'process_manager' in enabled_modules or 'webserver' in enabled_modules%} +
+
+
{{ _('Advanced') }}
+
+
+
+ +
+ +{% if 'crons' in enabled_modules %} + +{% endif %} +{% if 'ssh' in enabled_modules %} + +{% endif %} + + + + +{% if 'terminal' in enabled_modules %} + +{% endif %} +{% if 'usage' in enabled_modules %} + +{% endif %} +{% if 'process_manager' in enabled_modules %} + + +{% endif %} +{% if 'webserver' in enabled_modules %} + + +{% endif %} + + +{% if 'webserver' in enabled_modules %} + +{% endif %} +{% if 'webserver' in enabled_modules %} + +{% endif %} +{% if 'webserver' in enabled_modules %} + +{% endif %} +{% if 'webserver' in enabled_modules %} + +{% endif %} +
+
+
+ + +
+{% endif %} + +
+
+
{{ _('Account') }}
+
+
+
+ +
+ + +{% if 'twofa' in enabled_modules %} + +{% endif %} +{% if 'activity' in enabled_modules %} + +{% endif %} +{% if 'login_history' in enabled_modules %} + +{% endif %} + +
+
+
+
+ + +
+ +
+ +
+ +
+{% if 'twofa' in enabled_modules %} + {% if twofa_nag == "yes" %} + +
+
+
{{ _('Two-Factor Authentication') }}
+ +
+
+ +
+

{{ _('2FA is an added layer of security that significantly reduces the risk of unauthorized access to your account by requiring an additional verification step beyond just a password') }}

+
+ + {% if twofa_enabled %} +

{{ _('2FA is enabled for your account.') }}

+
+ +
+ {% else %} +

{{ _('2FA is disabled for your account.') }}

+
+ + +
+ {% endif %} + + + +
+
+ {% endif %} +{% endif %} +
+
+
+
{{ _('Server Information & Statistics') }}
+ +
+
+ +{% if ns1 and ns2 %} +
+ + +{% endif %} +
+ + + +
+ + + + + + + + + + +
+ +
+ + + + + + + + +{% if 'emails' in enabled_modules %} + +
+{% endif %} + + + + + + + + + + +{% if 'ftp' in enabled_modules %} + +
+{% endif %} + + + + + + + + + + + + + + + + +{% if 'disk_usage' in enabled_modules %} + +{% endif %} + +{% if 'disk_usage' in enabled_modules %} + +{% endif %} +
+ +{% if 'inodes' in enabled_modules %} + +{% endif %} + +{% if 'inodes' in enabled_modules %} + +{% endif %} + + + + + + + + + + + + + + + +
+{% if 'usage' in enabled_modules %} + +{% endif %} + +{% if 'usage' in enabled_modules %} + +{% endif %} + +
+{% if 'usage' in enabled_modules %} + +{% endif %} + +{% if 'usage' in enabled_modules %} + +{% endif %} + + + + + + + + +
+ + + + + +
+
+ + +{% if how_to_guides == "yes" %} +
+
+
+
{{ _('General How-to') }}
+ +
+
+ +
+ +
+
+{% endif %} + +
+ + + + + + + +
+ + + + +
+ + + + + + +{% endblock %} diff --git a/templates/admini/dashboard/knowledge_base_articles.json b/templates/admini/dashboard/knowledge_base_articles.json new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/templates/admini/dashboard/knowledge_base_articles.json @@ -0,0 +1 @@ + diff --git a/templates/admini/dashboard/knowledge_base_articles_default.json b/templates/admini/dashboard/knowledge_base_articles_default.json new file mode 100644 index 00000000..bba6f997 --- /dev/null +++ b/templates/admini/dashboard/knowledge_base_articles_default.json @@ -0,0 +1,11 @@ +{ + "how_to_topics": [ + {"title": "How to install WordPress", "link": "https://openpanel.com/docs/panel/applications/wordpress#install-wordpress"}, + {"title": "Publishing a Python Application", "link": "https://openpanel.com/docs/panel/applications/pm2#python-applications"}, + {"title": "How to edit Nginx / Apache configuration", "link": "https://openpanel.com/docs/panel/advanced/server_settings#nginx--apache-settings"}, + {"title": "How to create a new MySQL database", "link": "https://openpanel.com/docs/panel/databases/#create-a-mysql-database"}, + {"title": "How to add a Cronjob", "link": "https://openpanel.com/docs/panel/advanced/cronjobs#add-a-cronjob"}, + {"title": "How to change server TimeZone", "link": "https://openpanel.com/docs/panel/advanced/server_settings#server-time"} + ], + "knowledge_base_link": "https://openpanel.com/docs/panel/intro/?source=openpanel_server" +} diff --git a/templates/admini/databases/edit_mysql_config.html b/templates/admini/databases/edit_mysql_config.html new file mode 100644 index 00000000..040e73a5 --- /dev/null +++ b/templates/admini/databases/edit_mysql_config.html @@ -0,0 +1,186 @@ + +{% extends 'base.html' %} + +{% block content %} + + + + + + +
+ + + +

{{_('This tool allows you to make changes to your MySQL configuration. Modifications made here will prompt a MySQL service restart.')}}

+ + +
+
+
+
{{_('MySQL Configuration Settings')}}
+ + +
+
+
+ +
+
+
+ {% for key in default_keys %} +
+ + +
+ +
+
+ +
+
+
+ {% endfor %} + +
+
+ + +
+
+ + + + +
+ +
+
+
+
{{_('Recommended values:')}}
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+ + + + + +
+ +
+ {% if mysql_status_display == 'ON' %} {{ _('Enabled') }}{% elif mysql_status_display == 'OFF' %} {{ _('Disabled') }}{% else %} {{ _('Unknown') }}{% endif %} +
+ +
+ +
+
+ + + + + + + + + + + + + +{% endblock %} diff --git a/templates/admini/databases/mysql.html b/templates/admini/databases/mysql.html new file mode 100644 index 00000000..32db386e --- /dev/null +++ b/templates/admini/databases/mysql.html @@ -0,0 +1,743 @@ +{% extends 'base.html' %} + +{% block title %}Databases{% endblock %} + +{% block content %} + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
{{_('Databases')}} ()
+
+ + + + + + +
+ +

{{_("MySQL databases are used to store and manage your website's data, such as content, user information, and product details, making it accessible and organized for your web applications. On this page, you can easily create new databases and efficiently manage existing ones to organize and store your website's data effectively.")}}

+ + + + + + + + + + + + + +
{{_('Database Name')}}{{_('Size')}}{{_('Assigned Users')}}{{_('Action')}}
+ + + +
+ +
+
{{_('Users')}} ()
+
+ + + +
+ + + + + +

{{_("MySQL users are essential for controlling who can access and interact with your databases, ensuring data security and controlled access to your website's information. Here you can create and manage MySQL user accounts with specific permissions, ensuring secure access to your databases.")}}

+ + + + + + + + + +
{{_('User')}}{{_('Action')}}
+ + + + +{% endblock %} + diff --git a/templates/admini/databases/processlist.html b/templates/admini/databases/processlist.html new file mode 100644 index 00000000..340d6246 --- /dev/null +++ b/templates/admini/databases/processlist.html @@ -0,0 +1,37 @@ +{% extends 'base.html' %} + +{% block content %} +
+ +

{{ _('This interface lists all of the processes that currently run on any database on your server.') }}

+ + + + + + + + + + + + + + + + + + {% for row in processlist_output.split('\n')[2:] %} + {% if row %} + + {% for column in row.split('\t') %} + + {% endfor %} + + {% endif %} + {% endfor %} + +
Id{{ _('User') }}{{ _('Host') }}DB{{ _('Command') }}{{ _('Time') }}{{ _('State') }}{{ _('Info') }}
{{ column }}
+ +
+{% endblock %} diff --git a/templates/admini/databases/remote_mysql.html b/templates/admini/databases/remote_mysql.html new file mode 100644 index 00000000..b407a646 --- /dev/null +++ b/templates/admini/databases/remote_mysql.html @@ -0,0 +1,191 @@ + +{% extends 'base.html' %} + +{% block content %} + + + + + + + + + + + +
+ +

{{ _('Remote MySQL access gives you the ability to connect to a MySQL database on this server from a another (remote) device or location over the internet.') }}

+ +
+
+ +
+
+
+ {% if remote_mysql_display == 'ON' %} +

{{ _('Enabled<') }}/h3> + {% elif remote_mysql_display == 'OFF' %} +

{{ _('Disabled') }}

+ {% else %} +

{{ _(' Unknown. Contact Administrator.') }}

+ {% endif %} +
+
+ + {% if remote_mysql_display == 'ON' %} +
+
+
+

{{server_ip}}

+
+
+
+
+
+ + +

{{container_port}}

{{ _('*Port is random generated and unique to your account.') }} +
+
+ {% elif remote_mysql_display == 'OFF' %} + {% else %} + {% endif %} +
+
+
+ + +{% if remote_mysql_display == 'OFF' %} + +
+
+
+
{{ _('Important Security Notice') }}
+ +
+
+
+

{{ _('Allowing remote MySQL access opens your database to connections from the entire internet, which may pose a security risk. Please consider the following:') }}

+
    +
  • {{ _('Security Vulnerabilities') }}: {{ _('Allowing access from the web can expose your database to potential security vulnerabilities, increasing the risk of unauthorized access, data breaches, and data loss.') }}
  • +
  • {{ _('Data Privacy') }}: {{ _('Your sensitive data may be at risk if not properly secured. Make sure to use strong passwords and encryption to protect your information.') }} +
  • {{ _('Firewall and Access Control') }}: {{ _('It is crucial to set up robust firewall rules and access control to restrict connections only to trusted IP addresses.') }} +
  • {{ _('Regular Backups') }}: {{ _('Ensure that you have regular database backups in place to recover data in case of any security incidents.') }} +
+

{{ _("Before enabling remote MySQL access, please review your security settings, and consider the potential risks carefully. If you're unsure about the security implications or need assistance, consult with your system administrator or a security expert.") }}

+ +

{{ _('Your data security is important to us, and we recommend taking the necessary precautions to protect it.') }}

+
+ + +
+
+
+
+{% endif %} + + +
+ +
+ {% if remote_mysql_display == 'ON' %} {{ _('Enabled') }}{% elif remote_mysql_display == 'OFF' %} {{ _('Disabled') }}{% else %} {{ _('Unknown') }}{% endif %} +
+ +
+{% if remote_mysql_display == 'ON' %} +
+ + +
+{% elif remote_mysql_display == 'OFF' %} +
+ + +
+{% else %} +
+ + +
+
+ + +
+{% endif %} +
+
+ + +{% endblock %} + diff --git a/templates/admini/domains/domains.html b/templates/admini/domains/domains.html new file mode 100644 index 00000000..f96c9d71 --- /dev/null +++ b/templates/admini/domains/domains.html @@ -0,0 +1,892 @@ +{% extends 'base.html' %} + +{% block content %} + + + + + + + +
+
+ + +
+ +
+ + + + + +{% if total_pages > 1 %} +
+
+
+

+ {{ _('Showing domains') }} {{ start_line_number }} {{ _('to') }} {{ end_line_number }}, {{ _('from a total of') }} {{ total_domains }}. +

+
+
+ + + +
+
+
+
+{% endif %} + + + + + + + + + + + + + + + + {% for domain in domains %} + + + + + + + +{% else %} + +{% endif %} + + + + + {% endfor %} + +
{{ _('Domain Name') }}{{ _('Document Root') }}{{ _('DNS') }}{{ _(' Zone') }}{{ _('Redirect') }}{{ _('Force ') }}{{ _('HTTPS') }}
+ + {{ domain.domain_url }} + + +
+ /home/{{ current_username }}/{{ domain.domain_url }} +
+
/home/{{ current_username }}/{{ domain.domain_url }} +{{ _('Edit DNS') }} + + {% if domain.redirect_url %} + + +
+ {{ domain.redirect_url }} + + +
+ + + +
+ +
+ {% else %} + + + {% endif %} + + +{% if domain.https != "Unknown" %} +
+ + + +
+ + +
+ +
+ + + + + +
+{% if total_pages > 1 %} +
+
+
+

+ {{ _('Showing domains') }} {{ start_line_number }} {{ _('to') }} {{ end_line_number }}, {{ _('from a total of') }} {{ total_domains }}. +

+
+
+ + + +
+
+
+{% endif %} +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +
+ + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + +{% endblock %} diff --git a/templates/admini/domains/edit_dns_zone.html b/templates/admini/domains/edit_dns_zone.html new file mode 100644 index 00000000..1f9e030b --- /dev/null +++ b/templates/admini/domains/edit_dns_zone.html @@ -0,0 +1,752 @@ +{% extends 'base.html' %} + +{% block content %} +
+ {% if domain %} + + + +

{{ _('The DNS Zone Editor feature allows you to create, edit, and delete Domain Name System (DNS) zone records.') }}

+ + + + + +{% if view_mode == 'table' %} + + + + + + + +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + +{% for item in dnszone_with_line_numbers %} + {% if item.line %} + + + + {% set values = item.line.split(maxsplit=4) %} + + + {% if 'SOA' not in values[3] %} + + + + + + {% endif %} + + {% endif %} +{% endfor %} + + + +
{{ _('Name') }}{{ _('TTL') }}{{ _('Type') }}{{ _('Record') }}{{ _('Actions') }}
+
+ {{ values[0] if values|length > 0 else '' }} + {% if item.comment %} + + + + + + + + + {% endif %} +
+
{{ values[1] if values|length > 1 else '' }}{{ values[3] if values|length > 3 else '' }} + {% if values|length > 4 %} + {% set last_value = values[4] %} + {{ last_value.strip('"') if last_value.startswith('"') and last_value.endswith('"') else values[4:]|join(' ') }} + {% else %} + {{ values[4] if values|length > 4 else '' }} + {% endif %} + + +   + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + +{% elif view_mode == 'code' %} + +
+ Attention: Editing DNS file is intended for advanced users only. + This action can potentially lead to server misconfiguration or downtime if not done correctly. +

+ Please be cautious and make sure you understand the changes you are making. +
+ +
+ + + +
+ + + + + + + + +{% endif %} + {% else %} + + +

{{ _('DNS Zone Editor allows you to manage and edit Domain Name System (DNS) zone files, which contain critical information for mapping domain names to IP addresses and managing various DNS records, such as A, CNAME, MX, and TXT records.') }}

+ + +
+
+ + +
+
+ + + {% endif %} + + + + + + +
+ + + + + {% endblock %} + diff --git a/templates/admini/domains/edit_vhost.html b/templates/admini/domains/edit_vhost.html new file mode 100644 index 00000000..3b45c130 --- /dev/null +++ b/templates/admini/domains/edit_vhost.html @@ -0,0 +1,19 @@ +{% extends 'base.html' %} +{% block content %} +
+
+ Attention: Editing domain file is intended for advanced users only. This action can potentially lead to server misconfiguration or downtime if not done correctly. +

+ Please be cautious and make sure you understand the changes you are making. We use a rollback mechanism to check for errors, and if any issues are detected, we will revert the changes. However, it's important to have a backup of your configurations before proceeding. +
+
+ + +
+ + +
+ +
+
+{% endblock %} diff --git a/templates/admini/domains/logs.html b/templates/admini/domains/logs.html new file mode 100644 index 00000000..dd6d2137 --- /dev/null +++ b/templates/admini/domains/logs.html @@ -0,0 +1,25 @@ +{% extends 'base.html' %} +{% block content %} +
+
+
+ + +
+
+ +
+{% endblock %} diff --git a/templates/admini/domains/logs_single.html b/templates/admini/domains/logs_single.html new file mode 100644 index 00000000..3f478831 --- /dev/null +++ b/templates/admini/domains/logs_single.html @@ -0,0 +1 @@ +{{ html_content|safe }} diff --git a/templates/admini/elasticsearch.html b/templates/admini/elasticsearch.html new file mode 100644 index 00000000..7607f154 --- /dev/null +++ b/templates/admini/elasticsearch.html @@ -0,0 +1,280 @@ + +{% extends 'base.html' %} + +{% block content %} + + + + + +
+ +{% if elastic_status_display == 'ON' %} + +
+
+
+
{{_('Connection Info')}}
+
+ + +
+
+
+

{{_('Active')}}

+ + +
+
+
+
+
+

127.0.0.1

+ + {{_('*or localhost')}} +
+
+
+
+
+ + +

9200

{{_('*Access to the service is NOT available from other servers.')}} +
+
+
+ +
+
+
+
+
+
{{_('Elasticsearch Settings')}}
+ +
+
+
+
+
+ + +
+ + +
+ + + +
+ +{% elif elastic_status_display == 'NOT INSTALLED' %} +
+

{{_('Elasticsearch is not currently installed.')}}

+

{{_('To install Elasticsearch click on the button bellow.')}}

+
+ + +
+
+ + {% elif elastic_status_display == 'OFF' %} +
+

{{_('Elasticsearch is currently disabled.')}}

+

{{_('To enable Elasticsearch click on the button bellow.')}}

+
+ + +
+ + +
+ {% else %} +
+

{{_('Elasticsearch service status is unknown.')}}

+

{{_('Unable to determinate current elasticsearch service status, try Start&Stop actions.')}}
{{_('If the issue persists please contact support.')}}

+
+ + +
+
+ + +
+
+ {% endif %} +
+ + + + + + + + + + + + + + + + +
+ +
+ {% if elastic_status_display == 'ON' %} Enabled{% elif elastic_status_display == 'OFF' %} Disabled{% elif elastic_status_display == 'NOT INSTALLED' %} Not Installed{% else %} Unknown{% endif %} +
+ +
+{% if elastic_status_display == 'ON' %} +
+ + +
+{% elif elastic_status_display == 'OFF' %} +
+ + +
+{% elif elastic_status_display == 'NOT INSTALLED' %} +
+ + +
+{% else %} +
+ + +
+
+ + +
+{% endif %} +
+
+ + + + +{% endblock %} + diff --git a/templates/admini/emails/accounts.html b/templates/admini/emails/accounts.html new file mode 100644 index 00000000..59230a94 --- /dev/null +++ b/templates/admini/emails/accounts.html @@ -0,0 +1,395 @@ +{% extends 'base.html' %} +{% block content %} + + + + + +
+ + + + + + + + + + + + + + + + + + {% for email_entry in current_emails_list %} + {% set parts = email_entry.split(' ') %} + {% set status = parts[0] %} + {% set address = parts[1] %} + {% set quota = ' '.join(parts[2:]) %} + {% set quota_parts = quota.split('[') %} + {% if quota_parts|length > 1 %} + {% set percentage_str = quota_parts[1].split(']')[0] %} + {% else %} + {% set percentage_str = '0' %} + {% endif %} + + + + + + + + {% endfor %} + +
{{ _('Account @ Domain') }}{{ _('Storage') }}{{ _(' Used') }}{{ _('Options') }}
{{ address }} + {{ quota }} +
+
+
+
+
+ +
+ + + + + + + + + + + +
+ +
+ +
+ +
+ + +
+
+ + + + +{% endblock %} + + diff --git a/templates/admini/emails/single_account.html b/templates/admini/emails/single_account.html new file mode 100644 index 00000000..1ad51ef6 --- /dev/null +++ b/templates/admini/emails/single_account.html @@ -0,0 +1,511 @@ +{% extends 'base.html' %} +{% block content %} + + + {% set parts = current_emails_list.split(' ') %} + {% set status = parts[0] %} + {% set address = parts[1] %} + {% set quota = ' '.join(parts[2:]) %} + {% set quota_parts = quota.split('[') %} + {% if quota_parts|length > 1 %} + {% set percentage_str = quota_parts[1].split(']')[0] %} + {% else %} + {% set percentage_str = '0' %} + {% endif %} + + + +
+ + +
+ +
+
+
+

{{ _("Manage an Email Account") }}

+

{{ _("Use this page to manage your email account.") }}

+
+
+ +
+ + + + +
+ +
+ +
+ + + +
+{{ quota }} +
+
+
+
+
+ + +
+
+ + + + + + +
+ +
+
+ + + + +
+ +
+
+ + +
+
+ + +
+
+
+ +
+ +
+
+ + +
+
+ + +
+
+
+ + + + + + + +
+ +
+ +
+ + +
+
+
+ + + + + + +
+ +
+ +
+
+
+
+ + +
+
+

+ + +

+
+
+
+

Sieve {{ _("allows to specify filtering rules for incoming emails that allow for example sorting mails into different folders depending on the title of an email.") }}

+
+
{{ _("Current Filters") }}
+ +{% set domain = address.split('@')[-1] if '@' in address else 'DOMAIN_NAME' %} +{% set user = address.split('@')[0] if '@' in address else 'USERNAME' %} + +/home/{{current_username}}/mail/{{ domain }}/{{user}}/home/.dovecot.sieve +
+ +
+ + + + + +
+ + + +
+ +
{{ _("Examples") }}
+
+
+ + +
+

{{ _("An example of a sieve filter that moves mails to a folder ") }}INBOX/spam {{ _("depending on the sender address:") }}

+ +
+require ["fileinto", "reject"];
+
+if address :contains ["From"] "spam@spam.com" {
+  fileinto "INBOX.spam";
+} else {
+  keep;
+}
+
+
+
+ +
+ +
+

{{ _("Another example of a sieve filter that forward mails to a different address:") }}

+ +
+require ["copy"];
+
+redirect :copy "user2@not-example.com";
+
+ +
+
+ + +
+ +
+

{{ _("Just forward all incoming emails and do not save them locally:") }}

+ +
+redirect "user2@not-example.com";
+
+
+
+ +
+
+

{{ _("It is possible to sort subaddresses such as") }} user+mailing-lists@example.com {{ _("into a corresponding folder") }} (here: INBOX/Mailing-lists) {{ _("automatically.") }}

+ +
+require ["envelope", "fileinto", "mailbox", "subaddress", "variables"];
+
+if envelope :detail :matches "to" "*" {
+  set :lower :upperfirst "tag" "${1}";
+  if mailboxexists "INBOX.${1}" {
+    fileinto "INBOX.${1}";
+  } else {
+    fileinto :create "INBOX.${tag}";
+  }
+}
+
+
+
+ +
+
+ + +
+
+
+
+
+ + + + + + + + + + + + +
+

+ + +

+
+
+
+

{{ _("You can manually configure your mail client using the settings below. We recommend that you use IMAP and SMTP for your email account rather than ActiveSync unless you are on Android and need contacts support or push updates.") }}

+
+
{{ _("Secure SSL/TLS Settings (Recommended)") }}
+
+
+ +
+ +
+
+ +
+ +
+ Use the email account’s password. +
+
+ + +
+ +
+ +
IMAP Port: 993
+ +
+ + +
+ + +
+ +
+ +
SMTP Port: 465
+ +
+
+ + +IMAP and SMTP require authentication. +
+
+ +
{{ _("Non-SSL Settings (NOT Recommended) +") }}
+
+
+ +
+ +
+
+ +
+ +
+ Use the email account’s password. +
+
+ + +
+ +
+ +
IMAP Port: 143
+ +
+ + +
+ + +
+ +
+ +
SMTP Port: 587
+ +
+
+ + +IMAP and SMTP require authentication. +
+
+ + +
+
+
+
+
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + +
+ + + + + +
+ + + + +
+ + +
+ +{% endblock %} + + diff --git a/templates/admini/error_pages/404.html b/templates/admini/error_pages/404.html new file mode 100644 index 00000000..f5e9c541 --- /dev/null +++ b/templates/admini/error_pages/404.html @@ -0,0 +1 @@ +OpenPanel

404

{{ _('That page does not exist') }}

diff --git a/templates/admini/error_pages/500.html b/templates/admini/error_pages/500.html new file mode 100644 index 00000000..6dee91f6 --- /dev/null +++ b/templates/admini/error_pages/500.html @@ -0,0 +1 @@ +{{ _('500 Error Page') }}

500

{{ _('Server') }}{{ _('Error') }}

{{ _('Click on the button bellow to reload. If the issue persists please contact support.') }}

{{ _('Refresh page') }}
diff --git a/templates/admini/files/backup.html b/templates/admini/files/backup.html new file mode 100644 index 00000000..ae69480b --- /dev/null +++ b/templates/admini/files/backup.html @@ -0,0 +1,540 @@ +{% extends 'base.html' %} +{% block content %} + + + + +
+ + + +
+
+
+
{{ _('Backup Storage') }}
+ +
+
+
+ +
+ +
+
+ +
+
+
{{ _('Queue') }}
+
+
0
+
+
+
+
+ +
+ +
+
+ +
+
+
{{ _('Total Backups') }}
+
+
{{ num_backups if num_backups else '0' }}
+
+
+
+
+ + +
+ +
+
+ +
+
+
{{ _('Total Account usage (GB)') }}
+
+
14 GB
+
+
+
+
+ +
+
+
+
+ + + + + + + + + +
+
+
+
{{ _('Backups') }}
+ +
+
+
+ + + + + + + + + + + + + + +
CreatedEnd TimeDurationStatusContainsActions
+
+
+
+ + + + + +
+ + + + + + + + + + +
+
+
+
{{ _('Backup Logs') }}
+ +
+
+
    + +
+
+ +
+
+ + +
+
+
+
{{ _('Restore History') }}
+ +
+
+
    + +
+
+ +
+
+ + +
+ + + + + + + + +{% endblock %} diff --git a/templates/admini/files/disk_usage.html b/templates/admini/files/disk_usage.html new file mode 100644 index 00000000..8aa013a3 --- /dev/null +++ b/templates/admini/files/disk_usage.html @@ -0,0 +1,255 @@ +{% extends 'base.html' %} + +{% block content %} + + +
+ +

{{_('Disk usage is the amount of space that is used by the content of your sites, this includes databases, files, videos, images, emails and pages.')}}

+ +
+
+
+
{{_('Disk usage per directory')}}
+ +
+
+ + + + +
+
+
+
+
+
+
{{_('Browse Directories')}}
+ +
+
+ + + + + + + + + + {% if request.path != '/disk-usage/' %} + + + + + {% endif %} + {% for line in total_du_output.split('\n') %} + {% if line.strip() %} + + {% set parts = line.split() %} + {% set count = parts[0] %} + {% set directory = parts[1:]|join(' ') %} + + + + {% endif %} + {% endfor %} + +
DirectorySize
{{_('Up One Level')}}
{{ directory }} +{{ count }}
+
+
+
+
+ + + + + + + + + + + +{% endblock %} diff --git a/templates/admini/files/edit_file.html b/templates/admini/files/edit_file.html new file mode 100644 index 00000000..53f4124d --- /dev/null +++ b/templates/admini/files/edit_file.html @@ -0,0 +1,179 @@ +{% extends 'base.html' %} + +{% block content %} + +{% if file_content == '404_file_not_exsist_error' %} + +
+ +
+ {{_('The specified file does not exist.')}} +
+
/home/{{ current_username }}/{{ file_path }}
+
+ +{% else %} + + + + + + + +
+ + +
+
+
/home/{{ current_username }}/{{ file_path }}
+
+ + +
+
+ +
+
+
+ + + +{% endif %} + +{% endblock %} diff --git a/templates/admini/files/filemanager.html b/templates/admini/files/filemanager.html new file mode 100644 index 00000000..52943b45 --- /dev/null +++ b/templates/admini/files/filemanager.html @@ -0,0 +1,2385 @@ + +{% extends 'base.html' %} + +{% block content %} + + + + + + + + + + + + + + +{% set directories = [] %} +{% set files = [] %} + +{% for info in files_info %} +{% if info['type'] == 'Directory' %} {% set _ = directories.append(info) %} +{% else %}{% set _ = files.append(info) %} +{% endif %} +{% endfor %} + + + + +{% if directories|length + files|length == 0 %} +
+ + + {% with messages = get_flashed_messages(with_categories=true) %} + {% for category, message in messages %} + {% if category == 'error' %} +
+ {{ message }} +
+
/home/{{ current_username }}/{{path_param}}
+ {% endif %} + {% endfor %} + + {% if not messages %} +
{{ _('No items found.') }}
+
{{ _('Start creating new folders or uploading a new file!') }}
+ {% endif %} + {% endwith %} +
+ +{% else %} + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+ + + + + + + + + + +{% for info in directories + files %} + + + + + + + + {% if info['type'] == 'Directory' %} + + + {% else %} + + + + + + + + + + + + + + + + + + + + + +{% endfor %} + +
{{ _('Name') }}{{ _('Size') }}{{ _('Last Modified') }}{{ _('Date') }}{{ _('Permissions') }}
{% if path_param %}
{{ info['file'] }}
+ {% else %} +
{{ info['file'] }}
+ {% endif %}
{{ info['file'] }}
+ {% endif %} +
+ {% if info['type'] == 'Directory' %} + {{ _('Calculate') }} + {% else %} + {{ info['size'] }} + {% endif %} + {{ info['date'] }}{{ info['permissions'] }} +
+{% endif %} +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +{% endblock %} diff --git a/templates/admini/files/fix_permissions.html b/templates/admini/files/fix_permissions.html new file mode 100644 index 00000000..2c7f33b6 --- /dev/null +++ b/templates/admini/files/fix_permissions.html @@ -0,0 +1,101 @@ +{% extends 'base.html' %} + +{% block content %} +

{{ _('Fix and reset permissions for files and folders.') }}

+ +
+
+
+
+ + + {% for directory in directories %} + + + + + + + +
+
+ + + + +
+ + + +{% endblock %} diff --git a/templates/admini/files/ftp.html b/templates/admini/files/ftp.html new file mode 100644 index 00000000..e54b8c80 --- /dev/null +++ b/templates/admini/files/ftp.html @@ -0,0 +1,530 @@ +{% extends 'base.html' %} + +{% block content %} + + + + + + + + + + + +

{{ _('Use your FTP account with an FTP client such as ') }}FileZilla {{ _('to transfer files to and from your website.') }}

+ +
+ + + + + + + + + + + + +
{{ _('Username (Login)') }}{{ _('Path') }}{{ _('Actions') }}
+
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ + +{{ _('FTP server') }}:  {% if dedicated_ip != _("Unknown") %}{{ dedicated_ip }}{% else %}{{ server_ip }}{% endif %} +
+
+{{ _('FTP port') }}: 21 + +
+ +
+ + + + +
+
+ + + + + + + +{% endblock %} diff --git a/templates/admini/files/inodes.html b/templates/admini/files/inodes.html new file mode 100644 index 00000000..ebe17ee8 --- /dev/null +++ b/templates/admini/files/inodes.html @@ -0,0 +1,228 @@ +{% extends 'base.html' %} + +{% block content %} + + +
+ +

{{_('An inode is a data structure that keeps the information about a file on your hosting account. The number of inodes indicates the number of files and folders you have. This includes everything on your account, emails, files, folders, and anything you store on the server.')}}

+ + +
+
+
+
{{_('Inodes usage per directory')}}
+ +
+
+ + + + +
+
+
+
+
+
+
{{_('Browse Directories')}}
+ +
+
+ + + + + + + + + + {% if request.path != '/inodes-explorer/' %} + + + + + {% endif %} + {% for line in total_inodes_output.split('\n') %} + {% if line.strip() %} + + {% set parts = line.split() %} + {% set count = parts[0] %} + {% set directory = parts[1:]|join(' ') %} + + + + {% endif %} + {% endfor %} + +
{{_('Directory')}}{{_('Inodes')}}
{{_('Up One Level')}}
{{ directory }} +{{ count }}
+
+
+
+
+ + + + + + + + + + + + +{% endblock %} diff --git a/templates/admini/flarum.html b/templates/admini/flarum.html new file mode 100644 index 00000000..cbbbc600 --- /dev/null +++ b/templates/admini/flarum.html @@ -0,0 +1,708 @@ + +{% extends 'base.html' %} + +{% block content %} + +{% if domains %} + + + +{% with messages = get_flashed_messages() %} +{% if messages %} +{% for message in messages %} +{% if "Error" in message %} + +{% else %} + +{% endif %} +{% endfor %} +{% endif %} +{% endwith %} + + +
+ +
+
+ +
+ + +
+
+

{{ _("Install Flarum") }}

+

{{ _("Install Flarum on an existing domain.") }}

+
+
+
+ + +
+
+
+ +
+ + +
+ +
+
+ + +
+
+ + +
+ + + + + +
+
+ + +
+
+ +
+ +
+ + +
+
+
+
+ + + + + + +
+ +
+ +
+
+ + + + + + + +
+ +
+ + + + +
+
+
+ +
+
+{% if data %} +{% if view_mode == 'table' %} + + + + + + + + + + + + {% for row in data %} + + + + +{% set domain_url = row[0] %} + + + + + + + + {% endfor %} + + +
{{ _("Domain") }}{{ _("Flarum Version") }}{{ _("Admin Email") }}{{ _("Created on") }}{{ _("Actions") }}
{{ row[0] }} Favicon + {{ row[0] }} {{ row[3] }}{{ row[2] }}{{ row[4] }} +{{ _("Manage") }} + + +
+{% endif %} +{% if view_mode == 'cards' %} + + + +
+
+ {% for row in data %} + + +
+
+ + +
+
+
image/svg+xml
+
+
{{ row[0] }}
{{ _("Flarum") }} {{ row[3] }} +
+
+
+
+ +
+ +
+ +
+ {% endfor %} + +
+
+ + + + +{% endif %} + + + + + + + +
+ + +{% else %} + + +
+

{{ _("No Flarum Installations") }}

+

{{ _("There are no existing Flarum installations. You can install a new instance below.") }}

+ + +
+{% endif %} + + + + + + +{% else %} + +
+

{{ _("No Domains") }}

+

{{ _("Add a domain name first in order to install Flarum.") }}

+ + {{ _("Add a Domain Name") }} + +
+{% endif %} + + + + + + + + +
+ +
+
+ +
+ + + + + + +{% if view_mode == 'cards' %} + +{% endif %} +{% if view_mode == 'table' %} + +{% endif %} + + + +
+
+ + + +{% endblock %} diff --git a/templates/admini/ip_blocker.html b/templates/admini/ip_blocker.html new file mode 100644 index 00000000..42afb799 --- /dev/null +++ b/templates/admini/ip_blocker.html @@ -0,0 +1,153 @@ + +{% extends 'base.html' %} + +{% block content %} + +{% if domains %} + + + + +
+ +
+ +
+ + + + + + + + + + + + + + +{% for domain in domains %} + + + + +{% endfor %} + + +
{{ _('Domain') }}{{ _('Blocked IPs') }}
{{ domain.domain_url }} +
+ +
+
+ +
+ + +
+
+
+
+ + + + +{% else %} + + +
+

{{ _('No Domains') }}

+ + {{ _('Add a Domain Name') }} + +
+ + +{% endif %} + + + + + + + +{% endblock %} diff --git a/templates/admini/malware_scanner.html b/templates/admini/malware_scanner.html new file mode 100644 index 00000000..7560036c --- /dev/null +++ b/templates/admini/malware_scanner.html @@ -0,0 +1,163 @@ +{% extends 'base.html' %} + +{% block content %} + + +

{{ _('The Clam AntiVirus Scanner (ClamAV) antivirus software searches your files for malicious programs. If the scanner identifies a potential security threat, it flags the file to allow you to take the appropriate action.') }}

+ +
+ + +
+
+
+ + + {% for directory in directories %} + + + + + + + + + +
+
+ + + + + + + + +
+ + + + + + + + + + +{% endblock %} diff --git a/templates/admini/manager/.gitkeep b/templates/admini/manager/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/templates/admini/manager/flarum.html b/templates/admini/manager/flarum.html new file mode 100644 index 00000000..7c8f76c9 --- /dev/null +++ b/templates/admini/manager/flarum.html @@ -0,0 +1,1017 @@ + +{% extends 'base.html' %} + + +{% block content %} + + + + + + +{% if current_domain %} + + +
+
+ +
+ {% include 'partials/screenshot.html' %} +
+ +
+ + + + + +
+
+
+   +

+ + + {{ _('Purge Cache') }} + + + + + + + + + + +

+ + +
+
+
+
+ {{ _('Type') }} +

+ +

+ + +
+
+
+ + + +
+
+
+ {{ _('Files') }} ({{ _('Calculating size...') }}) +

{{ domain_directory }}

+
+
+
+ +
+ {{ _('Domain:') }} +

+ + {{ current_domain }} + +

+ +
+
+
+ + + +
+ + +
+
+ + + +

+

+
    +
  • {{ _('Database:') }}
  • +
  • {{ _('Table prefix:') }}
  • +
  • {{ _('Username:') }}
  • + +
  • {{ _('Password:') }} + +
  • +
+
+ +

+
+
+ + + + +
+
+ {{ _('Created') }} + +

+ {{ container.created_date }} +

+ + +
+
+
+ + + + +
+
+
+ {{ _('Flarum version:') }} +

+
+
+ + +
+ {{ _('PHP version:') }} +

+
+
+
+
+ {{ _('MySQL version:') }} +

+
+
+
+
+
+
+ + + +
+
+{% if 'temporary_links' in enabled_modules %} + + + +{% endif %} + + + +{% if backup_files_available %} +{% endif %} + + + + + + +
+ +
+ +

{{ _("Preview website with a temporary domain,") }} {{ _("valid for 15 minutes only!") }} {{ _("Helpful if your domain hasn't been pointed to the server's IP address yet and lacks an SSL certificate.") }}

+

{{ _("Create a manual backup of the ") }} {{container.type}} {{ _("website's files and database for data protection.") }}

+

{{ _('Restore the website to a previous state using a previously created backup.') }}

+

{{ _('Remove the {{container.type}} website from this manager without actually deleting any files or database.') }}

+

{{ _('Completely remove the {{container.type}} website, including its files, database, and records from this manager.') }}

+
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +{% endif %} + + + +{% endblock %} + + + diff --git a/templates/admini/manager/nodejs.html b/templates/admini/manager/nodejs.html new file mode 100644 index 00000000..a35f694a --- /dev/null +++ b/templates/admini/manager/nodejs.html @@ -0,0 +1,865 @@ + +{% extends 'base.html' %} + +{% block content %} + + + + + + + + + + + + + + + + +{% if current_domain %} + + + + +
+
+ +
+ {% include 'partials/screenshot.html' %} +
+ +
+ + + + + +
+
+
+ Status + +

● {{ pm2_data[8] }}

+ + +
+
+
+
+ {{ _('Type') }} +

{{ container.type }}

+
+
+ +
+ + + + +
+
+
+ {{ _('Files') }} ({{ _('Calculating size...') }}) +

{{ domain_directory }}

+ +
+
+
+ +
+ {{ _('Domain:') }} +

+ + {{ current_domain }} + +

+ +
+
+
+ + + +
+ + +
+
+ + + +

+

+
    +
  • {{ _('Uptime:') }} {{ pm2_data[6] }}
  • +
  • {{ _('Restarts:') }} {{ pm2_data[7] }}
  • +
  • {{ _('Watching:') }} {{ pm2_data[12] }}
  • +
+
+
+
+ + +
+
+ {{ _('Created') }} + +

+ {{ container.created_date }} +

+ + + + + + +
+
+
+ + + + + + + +
+
+
+ {{ _('NodeJS version:') }} +

+
+
+
+ {{ _('CPU usage:') }} +

{{ pm2_data[9] }}

+
+
+
+
+ {{ _('Memory usage:') }} +

{{ pm2_data[10] }}

+
+
+
+ + + +
+
+
+ + +
+
+{% if 'temporary_links' in enabled_modules %} + + + +{% endif %} + + + + +{% if pm2_data[8] == 'stopped' %} + + + + +{% else %} + + + + + + +{% endif %} + + + + + + + + + + + + + +
+ + +
+ +

 

+

{{ _("Preview website with a temporary domain,") }} {{ _("valid for 15 minutes only!") }} {{ _("Helpful if your domain hasn't been pointed to the server's IP address yet and lacks an SSL certificate.") }}

+

{{ _("View application error log file.") }}

+

{{ _("Start the application process and make app available again on the domain.") }}

+

{{ _('Stop the application process and make app temporary unavailable.') }}

+

{{ _('Restart the nodejs application (executes pm2 stop and pm2 start commands).') }}

+

{{ _('Completely remove the nodejs application, including the domain proxy, and records from this manager.') }}

+
+
+ + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + +{% endif %} + + + +{% endblock %} + diff --git a/templates/admini/manager/python.html b/templates/admini/manager/python.html new file mode 100644 index 00000000..b621732c --- /dev/null +++ b/templates/admini/manager/python.html @@ -0,0 +1,863 @@ + +{% extends 'base.html' %} + +{% block content %} + + + + + + + + + + + + + + + + +{% if current_domain %} + + + + +
+
+ +
+ {% include 'partials/screenshot.html' %} +
+ +
+ + + + + +
+
+
+ Status + +

● {{ pm2_data[8] }}

+ + +
+
+
+
+ {{ _('Type') }} +

{{ container.type }}

+
+
+ +
+ + + + +
+
+
+ {{ _('Files') }} ({{ _('Calculating size...') }}) +

{{ domain_directory }}

+ +
+
+
+ +
+ {{ _('Domain:') }} +

+ + {{ current_domain }} + +

+ +
+
+
+ + + +
+ + +
+
+ + + +

+

+
    +
  • {{ _('Uptime:') }} {{ pm2_data[6] }}
  • +
  • {{ _('Restarts:') }} {{ pm2_data[7] }}
  • +
  • {{ _('Watching:') }} {{ pm2_data[12] }}
  • +
+
+
+
+ + +
+
+ {{ _('Created') }} + +

+ {{ container.created_date }} +

+ + + + + + +
+
+
+ + + + + + + +
+
+
+ {{ _('Python version:') }} +

+
+
+
+ {{ _('CPU usage:') }} +

{{ pm2_data[9] }}

+
+
+
+
+ {{ _('Memory usage:') }} +

{{ pm2_data[10] }}

+
+
+
+ + + +
+
+
+ + +
+
+{% if 'temporary_links' in enabled_modules %} + + + +{% endif %} + + + + +{% if pm2_data[8] == 'stopped' %} + + + + +{% else %} + + + + + + +{% endif %} + + + + + + + + + + + + + +
+ + +
+ +

 

+

{{ _("Preview website with a temporary domain,") }} {{ _("valid for 15 minutes only!") }} {{ _("Helpful if your domain hasn't been pointed to the server's IP address yet and lacks an SSL certificate.") }}

+

{{ _("View application error log file.") }}

+

{{ _("Start the application process and make app available again on the domain.") }}

+

{{ _('Stop the application process and make app temporary unavailable.') }}

+

{{ _('Restart the python application (executes pm2 stop and pm2 start commands).') }}

+

{{ _('Completely remove the python application, including the domain proxy, and records from this manager.') }}

+
+
+ + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + +{% endif %} + + + +{% endblock %} + diff --git a/templates/admini/manager/wordpress.html b/templates/admini/manager/wordpress.html new file mode 100644 index 00000000..96822c69 --- /dev/null +++ b/templates/admini/manager/wordpress.html @@ -0,0 +1,2229 @@ + +{% extends 'base.html' %} + + +{% block content %} + + + + + + +{% if current_domain %} + + + +
+
+

{{ current_domain }}

+

+ +
+
+ + + + + + + +
+
+ +
+ + +
+
+
+ + +
+
+ + +
+
+
+
+
+ + +
+
+ + +
+
+
+ +
+ +
+ +
+
+
+
+ + +
+
+ +
+ +
+ +
+
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+ +
+ +
+ +
{{ _('WordPress version:') }}
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ + +
+ + +
+ + +
+
+ + {{ _('Recommended') }} + +
+
+ + +
+
+
+ +
+ +
+ + +
+
+ + +
+
+
+ +
+ +
+ + +
+
+ + +
+
+
+ +
+ + + + + + + + + +
+ +
+ + + + +

{{ _('The options below allow you to manage the native WordPress debugging tools, enabling and disabling these tools in the wp-config.php file. It is not recommended to use these options on production websites since they are meant for development and test installations. Refer to') }} {{ _('Debugging in WordPress') }} {{ _('article for more information on these options.') }}

+
+
+ + + +
+ + + + +
+
+ + +
+
+
+ +
+ +
+
+ + +
+
+
+ +
+ +
+
+ + +
+
+
+ +
+ +
+
+ + +
+
+
+ +
+ +
+
+ + +
+
+
+ + + +
+ + + + + + + + + + +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
{{ _('Security Measures') }} +
{{ _('Status') }}
+
+
+ +
+
+ {{ _('Restrict access to files and directories') }} + + + + + {{ _('STATUS') }} + + + +
+
+ +
+
+ {{ _('Configure security keys') }} + + + + + {{ _('STATUS') }} + + + +
+
+ +
+
+ {{ _('Block access to') }} xmlrpc.php + ({{ _('can be reverted') }}) + + + + + {{ _('STATUS') }} + + + +
+
+ +
+
+ {{ _('Block directory browsing') }} + ({{ _('can be reverted') }}) + + + + + {{ _('STATUS') }} + + + +
+
+ +
+
+ {{ _('Forbid execution of PHP scripts in the wp-includes directory') }} + ({{ _('can be reverted') }}) + + + + + {{ _('STATUS') }} + + + +
+
+ +
+
+ {{ _('Forbid execution of PHP scripts in the wp-content/uploads directory') }} + ({{ _('can be reverted') }}) + + + + + {{ _('STATUS') }} + + + +
+
+ +
+
+ {{ _('Block access to wp-config.php') }} + ({{ _('can be reverted') }}) + + + + + {{ _('STATUS') }} + + + +
+
+ +
+
+ {{ _('Disable scripts concatenation for WordPress admin panel') }} + ({{ _('can be reverted') }}) + + + + + {{ _('STATUS') }} + + + +
+
+ +
+
+ {{ _('Turn off pingbacks') }} + ({{ _('can be reverted') }}) + + + + + {{ _('STATUS') }} + + + +
+
+ +
+
+ {{ _('Disable PHP execution in cache directories') }} + ({{ _('can be reverted') }}) + + + + + {{ _('STATUS') }} + + + +
+
+ +
+
+ {{ _('Disable file editing in WordPress Dashboard') }} + ({{ _('can be reverted') }}) + + + + + {{ _('STATUS') }} + + + +
+
+ +
+
+ {{ _('Change default database table prefix') }} + + + + + {{ _('STATUS') }} + + + +
+
+ +
+
+ {{ _('Enable bot protection') }} + ({{ _('can be reverted') }}) + + + + + {{ _('STATUS') }} + + + +
+
+ +
+
+ {{ _('Block access to sensitive files') }} + ({{ _('can be reverted') }}) + + + + + {{ _('STATUS') }} + + + +
+
+ +
+
+ {{ _('Block access to potentially sensitive files') }} + ({{ _('can be reverted') }}) + + + + + {{ _('STATUS') }} + + + +
+
+ +
+
+ {{ _('Block access to .htaccess and .htpasswd') }} + ({{ _('can be reverted') }}) + + + + + {{ _('STATUS') }} + + + +
+
+ +
+
+ {{ _('Block author scans') }} + ({{ _('can be reverted') }}) + + + + + {{ _('STATUS') }} + + + +
+
+ +
+
+ {{ _("Change default administrator's username") }} + + + + + {{ _('STATUS') }} + + + +
+ +
+
+
+
+ + + +
+
+ + + +
+ {% include 'partials/screenshot.html' %} +
+ +
+ + + + + +
+
+
+   + + + + +

+ + + {{ _('Login as Admin') }} + + + + + + + +

+ + +
+
+
+
+ {{ _('Type') }} +

+ {{ container.type }} +

+ + +
+
+
+ + + +
+
+
+ {{ _('Files') }} ({{ _('Calculating size...') }}) +

{{ domain_directory }}

+
+
+
+ +
+ {{ _('Domain:') }} +

+ + {{ current_domain }} + +

+ +
+
+
+ + + +
+ + +
+
+ + + +

+

+
    +
  • {{ _('Database:') }}
  • +
  • {{ _('Table prefix:') }}
  • +
  • {{ _('Username:') }}
  • + +
  • {{ _('Password:') }} + +
  • +
+
+ +

+
+
+ + + + +
+
+ {{ _('Created') }} + +

+ {{ container.created_date }} +

+ + + + + +
+
+
+ + + + +
+
+
+ {{ _('WP version:') }} +

+
+
+ + +
+ {{ _('PHP version:') }} +

+
+
+
+
+ {{ _('MySQL version:') }} +

+
+
+
+
+
+
+ + + + + +
+
+{% if 'temporary_links' in enabled_modules %} + + + +{% endif %} + + + +{% if backup_files_available %} +{% endif %} + + + + + +
+ +
+ +

{{ _("Preview website with a temporary domain,") }} {{ _("valid for 15 minutes only!") }} {{ _("Helpful if your domain hasn't been pointed to the server's IP address yet and lacks an SSL certificate.") }}

+

{{ _("Create a manual backup of the ") }} {{container.type}} {{ _("website's files and database for data protection.") }}

+

{{ _('Restore the website to a previous state using a previously created backup.') }}

+

{{ _('Remove the {{container.type}} website from this manager without actually deleting any files or database.') }}

+

{{ _('Completely remove the {{container.type}} website, including its files, database, and records from this manager.') }}

+
+
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +{% endif %} + + + +{% endblock %} + + + diff --git a/templates/admini/mautic.html b/templates/admini/mautic.html new file mode 100644 index 00000000..11988285 --- /dev/null +++ b/templates/admini/mautic.html @@ -0,0 +1,710 @@ + +{% extends 'base.html' %} + +{% block content %} + +{% if domains %} + + + +{% with messages = get_flashed_messages() %} +{% if messages %} +{% for message in messages %} +{% if "Error" in message %} + +{% else %} + +{% endif %} +{% endfor %} +{% endif %} +{% endwith %} + + +
+ +
+
+ +
+ + +
+
+

{{ _("Install Mautic") }}

+

{{ _("Install Mautic on an existing domain.") }}

+
+
+
+ + +
+
+
+ +
+ + +
+ + +
+
+ + +
+ + + + + +
+
+ + +
+
+ +
+ +
+ + +
+
+
+
+ + + + + + +
+ +
+ +
+
+ + + + + + + +
+ +
+ + + + +
+
+
+ +
+
+{% if data %} +{% if view_mode == 'table' %} + + + + + + + + + + + + {% for row in data %} + + + + +{% set domain_url = row[0] %} + + + + + + + + {% endfor %} + + +
{{ _("Domain") }}{{ _("Mautic Version") }}{{ _("Admin Email") }}{{ _("Created on") }}{{ _("Actions") }}
{{ row[0] }} Favicon + {{ row[0] }} {{ row[3] }}{{ row[2] }}{{ row[4] }} +{{ _("Manage") }} + + +
+{% endif %} +{% if view_mode == 'cards' %} + + + +
+
+ {% for row in data %} + + +
+
+ + +
+
+
+
+
{{ row[0] }}
{{ _("Mautic") }} {{ row[3] }} +
+
+
+
+ +
+ +
+ +
+ {% endfor %} + +
+
+ + + + +{% endif %} + + + + + + + +
+ + +{% else %} + + +
+

{{ _("No Mautic Installations") }}

+

{{ _("There are no existing Mautic installations. You can install a new instance below.") }}

+ + +
+{% endif %} + + + + + + +{% else %} + +
+

{{ _("No Domains") }}

+

{{ _("Add a domain name first in order to install Mautic.") }}

+ + {{ _("Add a Domain Name") }} + +
+{% endif %} + + + + + + + + +
+ +
+
+ +
+ + + + + + +{% if view_mode == 'cards' %} + +{% endif %} +{% if view_mode == 'table' %} + +{% endif %} + + + +
+
+ + + +{% endblock %} diff --git a/templates/admini/memcached.html b/templates/admini/memcached.html new file mode 100644 index 00000000..5a171f27 --- /dev/null +++ b/templates/admini/memcached.html @@ -0,0 +1,320 @@ + +{% extends 'base.html' %} + +{% block content %} + + + +
+ +{% if memcached_status_display == 'NOT INSTALLED' %} +
+

{{_('Memcached is not currently installed.')}}

+

{{_('To install Memcached click on the button bellow.')}}

+
+ + +
+
+ + +{% elif memcached_status_display == 'ON' %} + + + + + + +
+
+
+
{{ _('Connection Info') }}
+
+ + +
+
+
+

{{ _('Active') }}

+ + +
+
+
+
+
+

127.0.0.1

+ + {{ _('*or localhost') }} +
+
+
+
+
+ + +

11211

{{ _('*Access to the service is NOT available from other servers.') }} +
+
+
+ +
+
+
+
+
+
{{ _('Memcached Memory Allocation') }}
+ +
+
+ +

{{ _('You can allocate RAM to Memcached service.') }}

+
+
+
+
+

{{ _('Current Memory limit for Memcached service') }}

+

+ {% if maxmemory_value == 0 %} + + {% else %} + {{ maxmemory_value | int }} MB + {% endif %} +

+ + +
+
+ + {{ maxmemory_value | int }} MB
+ +
+
+ +
+
+
+ + +
+ +
+
+ + + +
+ +{% endif %} + + + + {% if memcached_status_display == 'ON' %} + {% elif memcached_status_display == 'NOT INSTALLED' %} + {% elif memcached_status_display == 'OFF' %} +
+

{{ _('Memcached is currently disabled.') }}

+

{{ _('To enable Memcached SERVER click on the button bellow.') }}

+
+ + +
+
+ {% else %} +
+

{{ _('Memcached service status is unknown.') }}

+

{{ _('Unable to determinate current Memcached service status, try Start&Stop actions.') }}
{{ _('If the issue persists please contact support.') }}

+
+ + +
+
+ + +
+
+ {% endif %} +
+ + + + + + + + + + + + + + +
+ +
+ {% if memcached_status_display == 'ON' %} Enabled{% elif memcached_status_display == 'OFF' %} Disabled{% elif memcached_status_display == 'NOT INSTALLED' %} Not Installed{% else %} Unknown{% endif %} +
+ +
+{% if memcached_status_display == 'ON' %} +
+ + +
+{% elif memcached_status_display == 'OFF' %} +
+ + +
+{% elif memcached_status_display == 'NOT INSTALLED' %} +
+ + +
+ +{% else %} +
+ + +
+
+ + +
+{% endif %} +
+
+ + +{% endblock %} + diff --git a/templates/admini/partials/_shortcuts.html b/templates/admini/partials/_shortcuts.html new file mode 100644 index 00000000..ff7b6881 --- /dev/null +++ b/templates/admini/partials/_shortcuts.html @@ -0,0 +1,259 @@ + + diff --git a/templates/admini/partials/notifications.html b/templates/admini/partials/notifications.html new file mode 100644 index 00000000..fe7af7e6 --- /dev/null +++ b/templates/admini/partials/notifications.html @@ -0,0 +1,42 @@ + +{% with messages = get_flashed_messages() %} +{% if messages %} +
+
+ {% for message in messages %} + {% if 'success' in message.lower() %} + {% set toast_class = 'bg-success text-white' %} + {% set toast_icon = 'success' %} + {% set title = 'success' %} + {% elif 'error' in message.lower() %} + {% set toast_class = 'bg-danger text-white' %} + {% set toast_icon = 'error' %} + {% set title = 'Error' %} + {% elif 'warning' in message.lower() %} + {% set toast_class = 'bg-warning text-white' %} + {% set toast_icon = 'warning' %} + {% set title = 'Warning' %} + {% else %} + {% set toast_class = 'bg-primary text-white' %} + {% set toast_icon = 'info' %} + {% set title = 'Notification' %} + {% endif %} + + + {% endfor %} +
+
+{% endif %} +{% endwith %} + diff --git a/templates/admini/partials/pagespeed.html b/templates/admini/partials/pagespeed.html new file mode 100644 index 00000000..0cd10a53 --- /dev/null +++ b/templates/admini/partials/pagespeed.html @@ -0,0 +1,200 @@ +
+
+ +
+ + Loading data... +
+
+ + +
+ + + + +
+
+ + +
+
Desktop
+ + + + +
+
+ + +
+
Mobile
+ + + + +
+
+
+
+ +
+
+ First Contentful Paint +
+   /   +
+
+
+ Speed Index +
+  /  +
+
+
+ Time to Interactive +
+  /  +
+
+
+ Measured at Loading... +
+
+ View complete results on Google PageSpeed Insights. +
+
+ + + +
+
+
diff --git a/templates/admini/partials/phpmyadmin_link.html b/templates/admini/partials/phpmyadmin_link.html new file mode 100644 index 00000000..b743e955 --- /dev/null +++ b/templates/admini/partials/phpmyadmin_link.html @@ -0,0 +1,89 @@ +{% if 'phpmyadmin' in enabled_modules %} + + + +{% endif %} diff --git a/templates/admini/partials/screenshot.html b/templates/admini/partials/screenshot.html new file mode 100644 index 00000000..ef1b3a62 --- /dev/null +++ b/templates/admini/partials/screenshot.html @@ -0,0 +1,18 @@ + + + diff --git a/templates/admini/partials/sidebar.html b/templates/admini/partials/sidebar.html new file mode 100644 index 00000000..c97bcc1c --- /dev/null +++ b/templates/admini/partials/sidebar.html @@ -0,0 +1,936 @@ + + + + + diff --git a/templates/admini/php/ini_editor.html b/templates/admini/php/ini_editor.html new file mode 100644 index 00000000..71909858 --- /dev/null +++ b/templates/admini/php/ini_editor.html @@ -0,0 +1,71 @@ +{% extends 'base.html' %} + +{% block content %} + + + + {% if version %} +
+
+ +
+ + + + +
+ +
+
+ +
+ +
+
+
+ + + + + + + + {% else %} + +

{{ _('PHP.INI Editor allows you to modify PHP settings stored in the php.ini configuration file, such as memory limits, error reporting, and extension settings.') }}

+ +
+
+ + +
+
+ + + + {% endif %} + + +{% endblock %} + diff --git a/templates/admini/php/settings.html b/templates/admini/php/settings.html new file mode 100644 index 00000000..e6f5cc1a --- /dev/null +++ b/templates/admini/php/settings.html @@ -0,0 +1,516 @@ + +{% extends 'base.html' %} + +{% block content %} + +
+
+ + + +
+ + +
+ +

{{ _('Changing the PHP version will stop all the processes on your site. It takes 1-2 seconds to complete. Be sure to check your script and plugin requirements to know which PHP version works best for your website.') }}

+ + + + + + + + + + + {% for domain in domains %} + + + + + + + + + + {% endfor %} + +
{{ _('Domain') }}{{ _('Current') }} {{ _('PHP Version') }}{{ _('Change') }} PHP version for domain') }}
{{ domain.domain_url }} + = 8 %} + green; + {% elif php_version_integer >= 7 %} + orange; + {% else %} + red; + {% endif %} + {% endif %} + "> + {{ php_version_numeric | string }} + + +
+ + +
+
+
+ +
+
+ +
+
+ +
+
+
+
+ +
+
+ +
+
+
+
{{ _('Default PHP version:') }}
+
+
+
+

{{ _('The PHP version that is used by default for newly added domains is the one that you choose here.') }}

+ +

{{ _('Current default PHP version:') }} {{ php_default_version|replace('php', '') }}

+ +
+
+ +
+
+
+ +
+
+ +
+
+
+ + + +
+ +
+ + +
+
+ +
+
+ +
+
+
+
{{ _('Install a new version') }}
+
+
+
+

{{ _('For best performance we recommend to only install PHP versions that you will be activelly using.') }}

+ +

{{ _("Currently installed PHP versions") }}: +{% for version in available_php_versions %} + {{ version|replace('php', '') }}{% if not loop.last %}, {% endif %} +{% endfor %} +

+ + + + +
+
+
+
+
+ +
+ +
+
+ + + + + + + + + + + + + +
+
+
+ +
+
+
+
+ + + + + + + + + + + +
+
+ +
+
+
+
+ + + + +
+
+
+ + + +{% endblock %} diff --git a/templates/admini/pm2.html b/templates/admini/pm2.html new file mode 100644 index 00000000..38b0b7c6 --- /dev/null +++ b/templates/admini/pm2.html @@ -0,0 +1,535 @@ +{% extends 'base.html' %} + +{% block content %} + +{% if domains %} + + + + + + + + + + +
+
+ +
+ + +
+
+

{{ _('Create a new Application') }}

+

{{ _("Run a NodeJS or Python application.") }}

+
+ +
+ +
+ +
+ +
+
+
+
+ +
+ +
+
+ /home/{{ current_username }}/ +
+ +
+
 
+
+
+ +
+ +
+ +
+
+ + +
+
+ + +
+ + +
+ + +
 
+
+ +
+ + +
+
+ +
+ + +
+
+
+ +
+ + +
+
+
+ + + +
+ +
+
+ + + + + +
+
+
+
+{% if pm2_data %} +
+ + + + + + + + + + + + + + + + + + + + + + + + {% if pm2_data %} + {% for row in pm2_data %} + + + + + + + + + + + + + + + + {% for site in all_sites %} + {% if row[1] == site.site_name %} + + + + + + {% endif %} + {% endfor %} + + + {% endfor %} + {% else %} + + + + {% endif %} + +
{{ _('Application') }}{{ _('Uptime') }}{{ _('Restarts') }}{{ _('Status') }}{{ _('CPU') }}{{ _('Memory') }}{{ _('Watching') }}Actions{{ _('Type') }}Port {{ _('Startup file') }}
{{ row[1] }}{{ row[6] }}{{ row[7] }} + {{ row[8] }} +{{ row[9] }}{{ row[10] }}{{ row[12] }} + {% if row[8] == 'stopped' %} +
+ +
+ {% else %} +
+ +
+ {% endif %} + +
+ +
+ +
+ +
+ + + +
+ {% if site.type == "NodeJS" %} + + {% elif site.type == "Python" %} + + {% else %} + {{ site.type }} + {% endif %} +{{ site.ports }}{{ site.path }}
{{ _('No PM2 data available.') }}
+
+ + +{% else %} + +
+

{{ _('No existing Applications') }}

+

{{ _('There are no existing applications. You can start a new NodeJS or Python app below.') }}

+ +
+{% endif %} + + + + + + + + + + +
+ +
+
+ +
+ + +
+
+ + + + + + + + + + + +{% else %} + +
+

{{ _("No Domains") }}

+

{{ _("Add a domain name first in order to install Python adn NodeJS applications.") }}

+ + {{ _("Add a Domain Name") }} + +
+{% endif %} + + + + +{% endblock %} diff --git a/templates/admini/process_manager.html b/templates/admini/process_manager.html new file mode 100644 index 00000000..5eda0ef6 --- /dev/null +++ b/templates/admini/process_manager.html @@ -0,0 +1,114 @@ +{% extends 'base.html' %} + +{% block content %} +
+ {% if error_message %} + + {% else %} + + + + + + + + + + + + {% for process in process_data %} + {% if '/etc/entrypoint.sh' not in process['CMD'] and 'ps -eo pid,%cpu,time,cmd' not in process['CMD'] and '/dev/null' not in process['CMD'] %} + {# Display the current process #} + + + + + + + + {% endif %} + {% endfor %} + +
PID{{ _('TIME') }}CPUCMD{{ _('ACTION') }}
{{ process['PID'] }}{{ process['TIME'] }}{{ process['%CPU'] }} + {% if process['CMD']|length > 255 %} + + + {{ process['CMD'][:255] }}... + {{ _('View full command') }} + + + {% else %} + + {{ process['CMD'] }} + {% endif %} +
+ {% endif %} +
+ + + + + + + + + + +{% endblock %} diff --git a/templates/admini/redis.html b/templates/admini/redis.html new file mode 100644 index 00000000..bebbdac0 --- /dev/null +++ b/templates/admini/redis.html @@ -0,0 +1,321 @@ + +{% extends 'base.html' %} + +{% block content %} + + + +
+ + +{% if redis_status_display == 'NOT INSTALLED' %} +
+

{{_('REDIS is not currently installed.')}}

+

{{_('To install REDIS click on the button bellow.')}}

+
+ + +
+
+ + +{% elif redis_status_display == 'ON' %} + + +{% set maxmemory_value_int = maxmemory_value | int %} +{% set maxmemory_value_in_MB = maxmemory_value_int / (1000 * 1000) %} + + + +
+
+
+
{{ _('Connection Info') }}
+
+ + +
+
+
+

{{ _('Active') }}

+ + +
+
+
+
+
+

127.0.0.1

+ + {{ _('*or localhost') }} +
+
+
+
+
+ + +

6379

{{ _('*Access to the service is NOT available from other servers.') }} +
+
+
+ +
+
+
+
+
+
{{ _('REDIS Memory Allocation') }}
+ +
+
+ +

{{ _('You can allocate RAM to REDIS service.') }}

+
+
+
+
+

{{ _('Current Memory limit for REDIS service') }}

+

+ {% if maxmemory_value_int == 0 %} + + {% else %} + {{ maxmemory_value_in_MB | int }} MB + {% endif %} +

+ + +
+
+ + {{ maxmemory_value_in_MB | int }} MB
+ +
+
+ +
+
+
+ + +
+ +
+
+ + + +
+ +{% endif %} + + + + {% if redis_status_display == 'ON' %} + {% elif redis_status_display == 'NOT INSTALLED' %} + {% elif redis_status_display == 'OFF' %} +
+

{{ _('REDIS is currently disabled.') }}

+

{{ _('To enable REDIS SERVER click on the button bellow.') }}

+
+ + +
+
+ + {% else %} +
+

{{ _('REDIS service status is unknown.') }}

+

{{ _('Unable to determinate current REDIS service status, try Start&Stop actions.') }}
{{ _('If the issue persists please contact support.') }}

+
+ + +
+
+ + +
+
+ {% endif %} +
+ + + + + + + + + + + + + + +
+ +
+ {% if redis_status_display == 'ON' %} Enabled{% elif redis_status_display == 'OFF' %} Disabled{% elif redis_status_display == 'NOT INSTALLED' %} Not Installed{% else %} Unknown{% endif %} +
+ +
+{% if redis_status_display == 'ON' %} +
+ + +
+{% elif redis_status_display == 'OFF' %} +
+ + +
+{% elif redis_status_display == 'NOT INSTALLED' %} +
+ + +
+{% else %} +
+ + +
+
+ + +
+{% endif %} +
+
+ + +{% endblock %} + diff --git a/templates/admini/sites.html b/templates/admini/sites.html new file mode 100644 index 00000000..0c2c5055 --- /dev/null +++ b/templates/admini/sites.html @@ -0,0 +1,68 @@ +{% extends 'base.html' %} + +{% block content %} + + + + + + + + + + + + + + + {% for site in data %} + + + + + + + + + {% endfor %} + +
{{ _('Site Name') }}{{ _('Admin Email') }}{{ _('Created on') }}{{ _('Type') }}{{ _('Version') }}{{ _('Actions') }}
{{ site[0] }} Favicon{{ site[0] }}{{ site[2] }}{{ site[4] }}{{ site[5] }}{{ site[3] }} + {% if 'Static' in site[5] %} + Manage + {% elif 'WordPress' in site[5] or 'Node' in site[5] or 'Mautic' in site[5] %} + Manage + {% else %} + Manage + {% endif %} +
+ + + + + + + + +
+ +
+
+ +
+ + + +
+
+ + + + + + +{% endblock %} diff --git a/templates/admini/ssh.html b/templates/admini/ssh.html new file mode 100644 index 00000000..bc84a9ff --- /dev/null +++ b/templates/admini/ssh.html @@ -0,0 +1,214 @@ + +{% extends 'base.html' %} + +{% block content %} + + + + + + +
+ {% if ssh_status_display == 'ON' %} + {% elif ssh_status_display == 'OFF' %} +

{{ _('SSH access is currently disabled.') }}

+ {% else %} + + {% endif %} + + + + +
+ + + + +{% if ssh_status_display == 'ON' %} +
+
+
+
+
{{ _('SSH Connection Information') }}
+
+
+ +
+
+ +

{{ server_ip }}

+
+
+ +

{% if host_port_mapping %} {{ host_port_mapping }} {% else %} {{ _("CONTAINER NOT RUNNING") }} {% endif %}

+
+
+ +

{{ current_username }}

+
+
+ +

**********

+
+
+
+ +
+
+
+ + + + + + + + + + + + + + + +{% endif %} + +
+ +
+ {% if ssh_status_display == 'ON' %} {{ _('Enabled') }}{% elif ssh_status_display == 'OFF' %} {{ _('Disabled') }}{% else %} {{ _('Unknown') }}{% endif %} +
+ +
+{% if ssh_status_display == 'ON' %} +
+ + +
+{% elif ssh_status_display == 'OFF' %} +
+ + +
+{% else %} +
+ + +
+
+ + +
+{% endif %} +
+
+{% endblock %} + diff --git a/templates/admini/ssl.html b/templates/admini/ssl.html new file mode 100644 index 00000000..b431e642 --- /dev/null +++ b/templates/admini/ssl.html @@ -0,0 +1,384 @@ + +{% extends 'base.html' %} + +{% block content %} + +{% if domains %} + + + + + + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + {% for domain in domains %} + + + + + + + {% endfor %} + +
{{ _('Domain') }}{{ _('SSL Status') }}{{ _('Actions') }}
{{ domain.domain_url }} + {% if domain.ssl_expiry_date %} + {% if domain.ssl_expiry_date == 'None' %} +
{{ _('No SSL installed') }}
+ {% else %} +
{{ _('AutoSSL Domain Validated') }}
+ {{ _('Expires on') }}: {{ domain.ssl_expiry_date }}
| + {% endif %} + {% else %} +
{{ _('SSL check is in progress.. please click here to refresh.') }}
+ + + + + + + {% endif %} +
+
+ +{% if domain.ssl_expiry_date != 'None' %} + + + + + + +
+ + + +
+ {% else %} + + +
+ + + +
+ + + + {% endif %} + + +
+
+
+ + + + + + + + + + + +
+ +
+
+ +
+ +
+ +
+ + + + +{% else %} + + +
+

{{ _('No Domains') }}

+

{{ _("When you create a domain, the system will attempt to secure that domain with a free Let\'s Encrypt certificate.") }}

+ + {{ _('Add a Domain Name') }} + +
+ + +{% endif %} + + + + + + + + +{% endblock %} diff --git a/templates/admini/system/general.html b/templates/admini/system/general.html new file mode 100644 index 00000000..8d4097f7 --- /dev/null +++ b/templates/admini/system/general.html @@ -0,0 +1,139 @@ +{% extends 'base.html' %} + +{% block content %} + + + +
+ +
+
+
+
+ +
+
+

{{ _('Server Time') }}

+

{{ _('Set your server’s time zone and synchronize its time with your network’s time server.') }}

+ + {{ _('Change TimeZone') }} + +
+
+
+
+ + +
+
+
+
+ +
+
+

{{ _('Service Status') }}

+

{{ _('Display a list of OpenPanel’s monitored services, their current version and statuses.') }}

+ + {{ _('Monitor Services') }} + +
+
+
+
+ + +
+
+
+
+ +
+
+

{{service_name}} {{ _('Settings') }}

+

{{ _('Configure') }} {{service_name}} {{ _('web server software that handles HTTP requests') }}.

+ + {{service_name}} {{ _('Configuration') }} + +
+
+
+
+ + +
+
+
+
+ +
+
+

{{ _('MySQL Settings') }}

+

{{ _('Make changes to your MySQL® or MariaDB® configuration.') }}

+ + {{ _('MySQL Configuration') }} + +
+
+
+
+ + +
+
+
+
+ +
+
+

{{ _('PHP Settings') }}

+

{{ _('Make changes to your PHP configuration.') }}

+ + {{ _('PHP Configuration') }} + +
+
+
+
+ + +
+
+
+
+ +
+
+

{{ _('ModSecurity® Settings') }}

+

{{ _('Enable or disable ModSecurity for your domains.') }}

+ + {{ _(' ModSecurity Settings') }} + +
+
+
+
+ + +
+
+
+
+ +
+
+

{{ _('Server Information') }}

+

{{ _('Displays information about your account and the server.') }}

+ + {{ _('Server Information') }} + +
+
+
+
+ + +
+ + + +{% endblock %} diff --git a/templates/admini/system/modsecurity.html b/templates/admini/system/modsecurity.html new file mode 100644 index 00000000..46718ffc --- /dev/null +++ b/templates/admini/system/modsecurity.html @@ -0,0 +1,208 @@ + +{% extends 'base.html' %} + +{% block content %} + +{% if domains %} + + + + +
+ +
+ +
+ + + + + + + + + + + + + + +{% for domain in domains %} + + + + +{% endfor %} + + +
{{ _('Domain') }}{{ _('Status') }}
{{ domain.domain_url }} +
+ +
+
+ +
+ +
+
+
+
+ + + + + + +
+ +
+
+ +
+ +
+ + +
+ + + +{% else %} + + +
+

{{ _('No Domains') }}

+ + {{ _('Add a Domain Name') }} + +
+ + +{% endif %} + + + + + + + +{% endblock %} diff --git a/templates/admini/system/server_info.html b/templates/admini/system/server_info.html new file mode 100644 index 00000000..464ebe17 --- /dev/null +++ b/templates/admini/system/server_info.html @@ -0,0 +1,129 @@ +{% extends 'base.html' %} + +{% block content %} +
+ +
+
+
+
{{ _('Server Information') }}
+
+
+
+
+
{{ _('Hostname') }} +
{{ _('Loading...') }}
+
+
+
+
+ +
+
+
{{ _('Average Load') }} +
{{ _('Loading...') }}
+
+
+
+
+
+
+
{{ _('Uptime') }} +
{{ _('Loading...') }}
+
+
+
+
+ + +
+
+
+ {{ _('IP Address') }} +
{{ _('Loading...') }}
+
+
+
+
+ +
+
+
+ {{ _('Panel Version') }} + {{ panel_version }} +
+
+
+
+ + +
+
+
+ {{ _('OS') }} +
{{ _('Loading...') }}
+
+
+
+
+ +
+
+
+ {{ _('Release') }} +
{{ _('Loading...') }}
+
+
+
+
+
+
+
+ {{ _('Version') }} +
{{ _('Loading...') }}
+
+
+
+
+
+
+
+ {{ _('Processor') }} +
{{ _('Loading...') }}
+
+
+ + + +
+
+
+
+ + + + +{% endblock %} diff --git a/templates/admini/system/services_status.html b/templates/admini/system/services_status.html new file mode 100644 index 00000000..e84d8449 --- /dev/null +++ b/templates/admini/system/services_status.html @@ -0,0 +1,311 @@ +{% extends 'base.html' %} + +{% block content %} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +{% if 'phpmyadmin' in enabled_modules %} + +{% else %} + +{% endif %} + + + + + +{% if 'pm2' in enabled_modules %} + +{% else %} + +{% endif %} + + + + + +{% if 'pm2' in enabled_modules %} + +{% else %} + +{% endif %} + + + + + +{% if 'redis' in enabled_modules %} + +{% else %} + +{% endif %} + + + + + + +{% if 'memcached' in enabled_modules %} + +{% else %} + +{% endif %} + + + + + + +{% if 'elasticsearch' in enabled_modules %} + +{% else %} + +{% endif %} + + + + + + +
{{ _('Service') }}{{ _('Version') }}{{ _('Status') }}
{{ web_server|capitalize }}  + +
{{ _('PHP') }} +
{% if mysql_type == 'mysql' %} + {{ _('MySQL') }} + {% elif mysql_type == 'mariadb' %} + {{ _('MariaDB') }} + {% endif %}  + + +
{{ _('phpMyAdmin') }}
{{ _('NodeJS') }} +
{{ _('Python') }} +
{{ _('REDIS') }} +
{{ _('Memcached') }} +
{{ _('Elasticsearch') }} +
+ + + +{% endblock %} diff --git a/templates/admini/system/timezone.html b/templates/admini/system/timezone.html new file mode 100644 index 00000000..620663a9 --- /dev/null +++ b/templates/admini/system/timezone.html @@ -0,0 +1,78 @@ +{% extends 'base.html' %} + +{% block content %} + + + + + +Current timezone: {{ current_timezone_in_docker_container }} + +
+
+ + +
+ +
+ + + +{% endblock %} diff --git a/templates/admini/terminal/landing.html b/templates/admini/terminal/landing.html new file mode 100644 index 00000000..10aa88eb --- /dev/null +++ b/templates/admini/terminal/landing.html @@ -0,0 +1,15 @@ +{% extends 'base.html' %} +{% block content %} + +

{{ _('This interface provides command line access to your account on the server.') }}

+

{{ _('You can open a web terminal for yourself or create a temporary account with a one-time login to share with a third party.') }}

+ +
+
+ {{ _('Access Web Terminal') }} or + +
+
+ +{% endblock %} + diff --git a/templates/admini/terminal/running.html b/templates/admini/terminal/running.html new file mode 100644 index 00000000..292e259f --- /dev/null +++ b/templates/admini/terminal/running.html @@ -0,0 +1,55 @@ +{% extends 'base.html' %} +{% block content %} + + +{% if random_username %} + +

{{ _('External Terminal Session created') }}

+ +

{{ _('Temporary session has been created for the web terminal. Login information:') }}

+ +
+
+ +
+
+
+
+ username: + +
+
+
+
+ username: + +
+
+
+
+
+ +
+ +
+ +
+
+ +
+ + +{% elif 'exists' in ttyd_url %} + +

{{ _('Terminal Session is Already Running') }}

+

Currently only one active web terminal session is supported. You need to either wait for the existing user to exit their web terminal session or terminate their session by killing the ttyd process from the Process Manager.

+ +{% else %} + +

{{ _('This interface provides command line access to your account on the server.') }}

+ + +{% endif %} + +{% endblock %} + diff --git a/templates/admini/user/account.html b/templates/admini/user/account.html new file mode 100644 index 00000000..aeefed2d --- /dev/null +++ b/templates/admini/user/account.html @@ -0,0 +1,279 @@ +{% extends 'base.html' %} + +{% block content %} + +
+ + + +
+
+ +
+
{{ _('Profile Picture') }}
+
+ + {% if avatar_type == 'gravatar' %} + + +
{{ email }}
+ {{ _('Change image on Gravatar') }} + {% elif avatar_type == 'letter' %} + {{ current_username[0] }} + {% else %} + +
{{ email }}
+ {% endif %} +
+
+
+
+ +
+
{{ _('Account Details') }}
+
+
+ +
+ + +
+
+ + +
+
+ +
+ +
+ + +
+
+
+
+ + +
+
+ +
+
+
+
+
+ +
+
{{ _('Language') }}
+
+ + + + + +
+
+
+
{{ _('Theme') }}
+
+ +
+
+ +
+
+
+ + + + + + +{% endblock %} diff --git a/templates/admini/user/activity.html b/templates/admini/user/activity.html new file mode 100644 index 00000000..199e98a2 --- /dev/null +++ b/templates/admini/user/activity.html @@ -0,0 +1,372 @@ + +{% extends 'base.html' %} +{% block content %} + + + +
+ + + +

{{ _('Activity Log records all important actions performed by user on the panel, such as editing or modifying files, deleting websites, enabling SSH access, etc.') }}

+ + + + + +
+
+ {% if search_term %} + Showing {{ log_content|length }} of {{ total_lines }} items + {% else %} + Showing {{ items_per_page * (current_page - 1) + 1 }} - {% if items_per_page * current_page > total_lines %}{{ total_lines }}{% else %}{{ items_per_page * current_page }}{% endif %} out of {{ total_lines }} items + {% endif %} +
+ {% if search_term %} + {% else %} +
+ + + + +
+ {% endif %} +
+ + + + + + +
    + + {% for log_entry in log_content %} + {% set parts = log_entry.split(' ') %} + {% if parts|length >= 6 %} + {% set timestamp = parts[0] ~ ' ' ~ parts[1] ~ ' ' ~ parts[2] %} + {% set ip = parts[3] %} + {% set admin = parts[4] %} + {% if "Administrator" in admin %} + {% set action_parts = parts[5:] %} + {% set action = action_parts|join(' ') %} + {% else %} + {% set user = parts[5] %} + {% set action_parts = parts[6:] %} + {% set action = action_parts|join(' ') %} + {% endif %} + {% set action_classes = "activity-item" %} + {% if "accessed" in action %} + {% set action_classes = action_classes ~ " search" %} + {% elif "deleted" in action or "edited MySQL configuration" in action %} + {% set action_classes = action_classes ~ " comment" %} + {% elif "File Manager" in action %} + {% set action_classes = action_classes ~ " folder" %} + {% elif "enabled" in action %} + {% set action_classes = action_classes ~ " like" %} + {% elif "disabled" in action %} + {% set action_classes = action_classes ~ " disabled" %} + {% elif "logged in" in action %} + {% set action_classes = action_classes ~ " logged" %} + {% elif "logged out" in action %} + {% set action_classes = action_classes ~ " loggedout" %} + {% elif "wordpress" in action %} + {% set action_classes = action_classes ~ " wordpress" %} + {% else %} + {% set action_classes = action_classes ~ " post" %} + {% endif %} + + {% set show_div = "/home/" ~ user in action or "created a" in action or "changed" in action or "edited MySQL configuration" in action %} +
  • {{ timestamp }}
  • +
  • + {% if "Administrator" in admin %} +

    +

    +
    {% if "Administrator" in admin %}{{admin}}{% else%}{{ user }}{% endif %} {{ action }}
    +
    +

    + + {% else %} + {% if show_div %} +

    + {% if gravatar_image_url is not none %} + + {% endif %} + {{ user }} + {{ ip }} +

    +
    +
    {% if "Administrator" in admin %}{{admin}}{% else%}{{ user }}{% endif %} {{ action }}
    +
    + {% else %} +

    + {% if gravatar_image_url is not none %} + + {% endif %} + + + {% if "Administrator" in admin %}{{admin}}{% else%}{{ user }}{% endif %} {{ action }} + + + {{ ip }} +

    + {% endif %} + {% endif %} +
  • + {% endif %} + {% endfor %} + + +
+ + + + + + + + + + + + + + + + + + + + +
+{% endblock %} + diff --git a/templates/admini/user/forgot_password.html_TODO b/templates/admini/user/forgot_password.html_TODO new file mode 100644 index 00000000..9f5e4c20 --- /dev/null +++ b/templates/admini/user/forgot_password.html_TODO @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + {% if brand_name %}{{brand_name}}{% else %}{{brand}}{% endif %} + + + + + +
+
+ + + +{% if email_sent %} + +

Email Sent

+

A password reset email has been sent to your inbox, and it will remain valid for the next 30 minutes. Kindly review your email to proceed with the password reset.

+
+ + + +
+ + +{% elif not email_sent %} + {% if not twofa_enabled %} +

Reset Password

+

Please provide the email address associated with your username, and a link to reset your password will be emailed to you.

+ {% elif twofa_enabled %} +

Verification code (2FA)

+

TwoFactor Authentification is enabled, please enter the 2FA code from your device.

+ {% endif %} + +
+
+ {% if not twofa_enabled %} + +
+ + +
+ {% endif %} + + {% if twofa_enabled %} + + +
+ + +
+ {% endif %} + + + {% if error_message %} +
+ {{ error_message }} +
+ {% endif %} + + + + +
+
+ +{% endif %} + + + + + + diff --git a/templates/admini/user/history_usage.html b/templates/admini/user/history_usage.html new file mode 100644 index 00000000..1b7a5584 --- /dev/null +++ b/templates/admini/user/history_usage.html @@ -0,0 +1,250 @@ + +{% extends 'base.html' %} + +{% block content %} + + + + + +
+{% if charts_mode == 'one' %} +
+
+
+
{{ _('Historical CPU and Memory Usage:') }}
+
+ +
+
+
+
+{% elif charts_mode == 'two' %} +
+
+
+
{{ _('Historical CPU Usage:') }}
+
+ +
+
+
+
+
+
{{ _('Historical Memory Usage:') }}
+
+ +
+
+
+
+{% else %} + +{% endif %} + +
+
+ {% if show_all %} + Showing 1 - {{ total_lines }} of {{ total_lines }} items + {% else %} + Showing {{ items_per_page * (current_page - 1) + 1 }} - {% if items_per_page * current_page > total_lines %}{{ total_lines }}{% else %}{{ items_per_page * current_page }}{% endif %} out of {{ total_lines }} items + {% endif %} +
+
+ + + + +
+ +
+ + +
+ + + + + + + + + + + + {% for entry in usage_data %} + + + + + + + + {% endfor %} + +
{{ _("Date") }} {{ _("CPU %") }} {{ _("Memory %") }} {{ _("Net I/O") }} {{ _("Block I/O") }}
{{ entry.timestamp }}{{ entry.cpu_percent | round(2) }}{{ entry.mem_percent | round(2) }}{{ entry.net_io }}{{ entry.block_io }}
+
+ + + + + + + +{% if charts_mode == 'one' %} + +{% elif charts_mode == 'two' %} + +{% endif %} + + +
+{% endblock %} diff --git a/templates/admini/user/login.html b/templates/admini/user/login.html new file mode 100644 index 00000000..705dbf1d --- /dev/null +++ b/templates/admini/user/login.html @@ -0,0 +1,189 @@ + + + + + + + + + + {% if brand_name %}{{brand_name}}{% else %}OpenPanel{% endif %} + + + + + + + +
+
+

{{ _('Sign In') }}

+

{{ _('Welcome back! Please sign in to continue.') }}

+
+
+
+ {% if not twofa_enabled %} + +
+ +
+ + + + + + +
+
+
+ +
+ + + + + + +
+ + +
+
+
+ {% endif %} + + {% if twofa_enabled %} + + +
+ +
+ + + + + + + +
+ + + +
+ {% endif %} + + +
+ + + +
+ + + + {% if error_message %} + + {% endif %} + + +
+ + + + + + + + + + + + + + diff --git a/templates/admini/user/loginlog.html b/templates/admini/user/loginlog.html new file mode 100644 index 00000000..23aa23fa --- /dev/null +++ b/templates/admini/user/loginlog.html @@ -0,0 +1,105 @@ + +{% extends 'base.html' %} + +{% block content %} +
+ + + + +
+
+ Successfull logins +
+
+ + {% for login_record in last_login_data %} +
+
+ {% with country_code_lower=login_record.country_code|lower %} + {{ login_record.country_code }} +   {{ login_record.country_code }} + {% endwith %} +
+
{{ login_record.ip }} +
+
{{ _('Copied!') }}
+
+
+
+
{{ login_record.login_time }}
+
+
+
+ {% endfor %} + +
+
+ + + + + + +{% endblock %} diff --git a/templates/admini/user/notifications.html b/templates/admini/user/notifications.html new file mode 100644 index 00000000..2cf43907 --- /dev/null +++ b/templates/admini/user/notifications.html @@ -0,0 +1,28 @@ +{% extends 'base.html' %} + +{% block content %} + +
+
+ +
+

{{ title }}

+
+

Receive email notifications for:

+ + {% for key, value in notifications.items() %} +
+
+ + +
+
+ {% endfor %} +
+ +
+ +
+
+ +{% endblock %} diff --git a/templates/admini/user/stats.html b/templates/admini/user/stats.html new file mode 100644 index 00000000..a04a3878 --- /dev/null +++ b/templates/admini/user/stats.html @@ -0,0 +1,184 @@ +{% extends 'base.html' %} + +{% block content %} +
+
+
+
{{ _("CPU") }}
+
+ +
+

{{ _('Current CPU usage:') }} {{ container_stats['CPU %'] }}
 

+ + {{ _("View past usage") }} +
+
+
+ + + + +
+
+
+
{{ _("RAM") }}
+
+
+

{{ _('Current Memory usage:') }} {{ container_stats['Memory %'] }}
({{ container_stats['Memory Usage'] }} / {{ container_stats['Memory Limit'] }})

+ + {{ _("View past usage") }} +
+
+
+ + +
+
+
+ + + + + + + + + +
+ + + + + + + +
+
+
+
{{ _('Network I/O') }}
+
{{ container_stats['Network I/O'] }}
+
+
+
+
+
{{ _('Block I/O') }}
+
{{ container_stats['Block I/O'] }}
+
+
+
+
+
{{ _("PIDs") }}
+
{{ container_stats['PIDs'] }}
+
+
+
+ + +{% endblock %} diff --git a/templates/admini/user/twofa_settings.html b/templates/admini/user/twofa_settings.html new file mode 100644 index 00000000..d1f6be18 --- /dev/null +++ b/templates/admini/user/twofa_settings.html @@ -0,0 +1,187 @@ +{% extends 'base.html' %} + +{% block content %} +
+ + + +
+ {% if success_message %} + + {% endif %} + +
+ +
+
{{ _('Two-Factor Authentication') }}
+
+ +

T{{ _('wo-factor authentication') }} ({{ _('also known as') }} 2FA, {{ _('2-step verification') }}, or {{ _('2-phase authentication') }}) {{ _('is a way of adding additional security to your account. 2FA requires you to enter an extra code when you log in or perform some account-sensitive action. The code is generated from an application on your computer or mobile phone.') }}

+ +

{{ _('To enable 2FA for your account you will need an application that manages 2FA codes, such as') }}{{ _('Google Authenticator') }}. {{ _('You can install it here:') }}

+

    +

+ +
+{% if twofa_enabled %} +
{{ _('2FA is currently') }} {{ _('enabled') }} {{ _('for your account.') }}
+ +
+ +
+ + {% else %} +
{{ _('2FA is currently') }} {{ _('disabled') }} {{ _('for your account.') }}
+ +
+ + +
+ {% endif %} + +
+
+
+{% if otp_secret %} +
+
+
{{ _('QR code') }}
+
+ + + + +

+ + + + +{{ _('Display OTP code') }} +
+ + +
+ +{{ _('After configuring the OTP code in the 2FA application, kindly confirm by clicking the button below to permanently delete the OTP secret.') }} + +
+ +
+
+
+ {% endif %} +
+
+ + + + + + +{% endblock %} diff --git a/templates/admini/websites.html b/templates/admini/websites.html new file mode 100644 index 00000000..613c2d85 --- /dev/null +++ b/templates/admini/websites.html @@ -0,0 +1,3164 @@ + +{% extends 'base.html' %} + +{% block content %} + + + + + + + +{% if current_domain %} + + +
+
+

{{ current_domain }}

+

+ +
+
+ + + + + +
+
+ +
+ + +
+
+
+ + +
+
+ + +
+
+
+
+
+ + +
+
+ + +
+
+
+ +
+ +
+ +
+
+
+
+ + +
+
+ +
+ +
+ +
+
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+ +
+ +
+ +
{{ _('WordPress version:') }}
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ + +
+ + +
+ + +
+
+ + {{ _('Recommended') }} + +
+
+ + +
+
+
+ +
+ +
+ + +
+
+ + +
+
+
+ +
+ +
+ + +
+
+ + +
+
+
+ +
+ + + + + + + + + +
+ +
+ + + + +

{{ _('The options below allow you to manage the native WordPress debugging tools, enabling and disabling these tools in the wp-config.php file. It is not recommended to use these options on production websites since they are meant for development and test installations. Refer to') }} {{ _('Debugging in WordPress') }} {{ _('article for more information on these options.') }}

+
+
+ + + +
+ + + + +
+
+ + +
+
+
+ +
+ +
+
+ + +
+
+
+ +
+ +
+
+ + +
+
+
+ +
+ +
+
+ + +
+
+
+ +
+ +
+
+ + +
+
+
+ + + +
+ + + + + + + + + + +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
{{ _('Security Measures') }} +
{{ _('Status') }}
+
+
+ +
+
+ {{ _('Restrict access to files and directories') }} + + + + + {{ _('STATUS') }} + + + +
+
+ +
+
+ {{ _('Configure security keys') }} + + + + + {{ _('STATUS') }} + + + +
+
+ +
+
+ {{ _('Block access to') }} xmlrpc.php + ({{ _('can be reverted') }}) + + + + + {{ _('STATUS') }} + + + +
+
+ +
+
+ {{ _('Block directory browsing') }} + ({{ _('can be reverted') }}) + + + + + {{ _('STATUS') }} + + + +
+
+ +
+
+ {{ _('Forbid execution of PHP scripts in the wp-includes directory') }} + ({{ _('can be reverted') }}) + + + + + {{ _('STATUS') }} + + + +
+
+ +
+
+ {{ _('Forbid execution of PHP scripts in the wp-content/uploads directory') }} + ({{ _('can be reverted') }}) + + + + + {{ _('STATUS') }} + + + +
+
+ +
+
+ {{ _('Block access to wp-config.php') }} + ({{ _('can be reverted') }}) + + + + + {{ _('STATUS') }} + + + +
+
+ +
+
+ {{ _('Disable scripts concatenation for WordPress admin panel') }} + ({{ _('can be reverted') }}) + + + + + {{ _('STATUS') }} + + + +
+
+ +
+
+ {{ _('Turn off pingbacks') }} + ({{ _('can be reverted') }}) + + + + + {{ _('STATUS') }} + + + +
+
+ +
+
+ {{ _('Disable PHP execution in cache directories') }} + ({{ _('can be reverted') }}) + + + + + {{ _('STATUS') }} + + + +
+
+ +
+
+ {{ _('Disable file editing in WordPress Dashboard') }} + ({{ _('can be reverted') }}) + + + + + {{ _('STATUS') }} + + + +
+
+ +
+
+ {{ _('Change default database table prefix') }} + + + + + {{ _('STATUS') }} + + + +
+
+ +
+
+ {{ _('Enable bot protection') }} + ({{ _('can be reverted') }}) + + + + + {{ _('STATUS') }} + + + +
+
+ +
+
+ {{ _('Block access to sensitive files') }} + ({{ _('can be reverted') }}) + + + + + {{ _('STATUS') }} + + + +
+
+ +
+
+ {{ _('Block access to potentially sensitive files') }} + ({{ _('can be reverted') }}) + + + + + {{ _('STATUS') }} + + + +
+
+ +
+
+ {{ _('Block access to .htaccess and .htpasswd') }} + ({{ _('can be reverted') }}) + + + + + {{ _('STATUS') }} + + + +
+
+ +
+
+ {{ _('Block author scans') }} + ({{ _('can be reverted') }}) + + + + + {{ _('STATUS') }} + + + +
+
+ +
+
+ {{ _("Change default administrator's username") }} + + + + + {{ _('STATUS') }} + + + +
+ +
+
+
+
+ + + + + +
+
+ +
+ + + + + +
+ +
+ + + + + +
+
+
+   + {% if container.type|lower == "wordpress" %} + + + +

+ + + {{ _('Login as Admin') }} + + + + + + + +

+ {% else %} +

+ {% endif %} + + + + +
+
+
+
+ {{ _('Type') }} +

+ {% if container.type|lower == "wordpress" %} + {{ container.type }} + {% elif container.type|lower == "mautic" %} + + {% elif container.type|lower == "flarum" %} + + {% elif container.type|lower == "nodejs" %} + + {% else %} + {{ container.type }} + {% endif %} +

+ +
+
+
+ + + +
+
+
+ {{ _('Files') }} ({{ _('Calculating size...') }}) +

{{ domain_directory }}

+
+
+
+ +
+ {{ _('Domain:') }} +

+ + {{ current_domain }} + +

+ +
+
+
+ + + +
+ + {% if container.type|lower == "wordpress" or container.type|lower == "mautic" %} +
+
+ + + +

+

+
    +
  • {{ _('Database:') }}
  • +
  • {{ _('Table prefix:') }}
  • +
  • {{ _('Username:') }}
  • + +
  • {{ _('Password:') }} + +
  • +
+
+ +

+
+
+ + {% elif container.type|lower == "nodejs" %} +
+ {% else %} +
+ {% endif %} + + + + + + + + + +
+
+ {{ _('Created') }} + +

+ {{ container.created_date }} +

+{% if container.type|lower == "wordpress" %} + + +{% elif container.type|lower == "mautic" %} + + +{% endif %} + + +
+
+
+ + + + + + + + + + +
+
+
+ {% if container.type|lower == "wordpress" %} + {{ _('WP version:') }} +

+ {% elif container.type|lower == "mautic" %} + {{ _('Mautic version:') }} +

+ {% elif container.type|lower == "nodejs" %} + {{ _('NodeJS version:') }} +

+ {% endif %} +
+
+
+ {% if container.type|lower == "wordpress" or container.type|lower == "mautic" %} + {{ _('PHP version:') }} +

+ {% endif %} +
+
+
+
+ {% if container.type|lower == "wordpress" or container.type|lower == "mautic" %} + {{ _('MySQL version:') }} +

+ {% endif %} +
+
+
+ + + + + + + + + + +
+
+
+ + +
+
+{% if 'temporary_links' in enabled_modules %} + + + +{% endif %} + + + + +{% if backup_files_available %} +{% endif %} + + + + + +
+ + {% if container.type|lower == "wordpress" or container.type|lower == "mautic" %} +
+ +

{{ _("Preview website with a temporary domain,") }} {{ _("valid for 15 minutes only!") }} {{ _("Helpful if your domain hasn't been pointed to the server's IP address yet and lacks an SSL certificate.") }}

+

{{ _("Create a manual backup of the ") }} {{container.type}} {{ _("website's files and database for data protection.") }}

+

{{ _('Restore the website to a previous state using a previously created backup.') }}

+

{{ _('Remove the {{container.type}} website from this manager without actually deleting any files or database.') }}

+

{{ _('Completely remove the {{container.type}} website, including its files, database, and records from this manager.') }}

+
+ {% endif %} +
+ + + +{% if container.type|lower == "wordpress" %} + + + + + + + + + +{% elif container.type|lower == "mautic" %} + + + + +{% elif container.type|lower == "nodejs" %} + + + +{% endif %} + + +
+ +
+ +
+
+
+ + Loading data... +
+ + +
+ + + + +
+
+ + +
+
Desktop
+ + + + +
+
+ + +
+
Mobile
+ + + + +
+
+
+
+ +
+
+ First Contentful Paint +
+   /   +
+
+
+ Speed Index +
+  /  +
+
+
+ Time to Interactive +
+  /  +
+
+
+ Measured at Loading... +
+
+ View complete results on Google PageSpeed Insights. +
+
+ + + + + + + + + + + + + + + + + + + + +
+
+
+ +
+
+ + + + + + +
+ + {% if container.type|lower == "wordpress" or container.type|lower == "mautic" %} + + + +
+
+ + + + + + + + + + + + + + + +
{{ _('phpMyAdmin') }}
+
+
+ {% elif container.type|lower == "nodejs" %} + + +
+
+ + + + + + + + + + + + + + + +
{{ _('PM2') }}
+
+
+ {% endif %} +
+ + + + + + +{% if container.type|lower == "wordpress" %} +
+
+
+ + + + + + + + + + + +
{{ _('Login as admin') }}
+
+
+
+{% elif container.type|lower == "nodejs" %} + +{% endif %} + + +{% if container.type|lower == "wordpress" or container.type|lower == "mautic" %} + +{% elif container.type|lower == "nodejs" %} + +{% endif %} + + + + + + +{% if container.type|lower != "nodejs" or container.type|lower != "python" %} + + + + + +{% endif %} + + + +{% if 'malware_scan' in enabled_modules %} + +{% endif %} + + + +
+
+
+ + + + + + + + +{% if container.type|lower == "wordpress" %} + + + + + + + + + + + + + + +{% elif container.type|lower == "mautic" %} + + + + + + + + + + + + + +{% endif %} + + + + + + + + + + + + + + + +{% endif %} + + + +{% endblock %} diff --git a/templates/admini/wordpress.html b/templates/admini/wordpress.html new file mode 100644 index 00000000..8828fc0c --- /dev/null +++ b/templates/admini/wordpress.html @@ -0,0 +1,984 @@ + +{% extends 'base.html' %} + +{% block content %} + +{% if domains %} + + + +{% with messages = get_flashed_messages() %} +{% if messages %} +{% for message in messages %} +{% if "Error" in message %} + +{% else %} + +{% endif %} +{% endfor %} +{% endif %} +{% endwith %} + + +
+ + + + + + + + + + + +
+
+ +
+ + +
+
+

{{ _("Install WordPress") }}

+

{{ _("Install WordPress on an existing domain.") }}

+
+
+
+ + +
+
+ + +
+
+
+ +
+ + +
+ +
+
+ + +
+
+ + +
+ + + + + +
+
+ + +
+
+ +
+ +
+ + +
+
+
+
+ + + + + + +
+ +
+ +
+
+ + +
+ +
+
+ + + + + + +
+
+
+ +
+
+{% if data %} +{% if view_mode == 'table' %} + + + + + + + + + + + + {% for row in data %} + + + + +{% set domain_url = row[0] %} + + + + + + + + {% endfor %} + + +
{{ _("Domain") }}{{ _("WordPress Version") }}{{ _("Admin Email") }}{{ _("Created on") }}{{ _("Actions") }}
{{ row[0] }} Favicon + {{ row[0] }} {{ row[3] }}{{ row[2] }}{{ row[4] }} + {{ _("Login as Admin") }} +{{ _("Manage") }} + + +
+{% endif %} +{% if view_mode == 'cards' %} + + + +
+
+ {% for row in data %} + + +
+
+ + +
+
+
+
+
{{ row[0] }}
{{ _("WordPress") }} {{ row[3] }} +
+
+
+ +
+ +
+ +
+ {% endfor %} + +
+
+ + + + +{% endif %} + + + + + + + + + +
+ + +{% else %} + + +
+

{{ _("No WordPress Installations") }}

+

{{ _("You don't have WordPress sites connected yet. Install a new WordPress site or scan to find existing ones.") }}

+ +

{{ _("or") }}

+ + +
+{% endif %} + + + + + + +{% else %} + +
+

{{ _("No Domains") }}

+

{{ _("Add a domain name first in order to install WordPress.") }}

+ + {{ _("Add a Domain Name") }} + +
+{% endif %} + + + + + + + + + + +
+ +
+
+ +
+ + + + + + + +{% if view_mode == 'cards' %} + +{% endif %} +{% if view_mode == 'table' %} + +{% endif %} + + + +
+
+ + + +{% endblock %} diff --git a/templates/tabler/README.md b/templates/tabler/README.md deleted file mode 100644 index 13f50134..00000000 --- a/templates/tabler/README.md +++ /dev/null @@ -1 +0,0 @@ -[tabler](https://tabler.io/admin-template) is the awesome default theme for OpenAdmin ✌️ diff --git a/templates/tabler/backups.html b/templates/tabler/backups.html new file mode 100644 index 00000000..54a20f1b --- /dev/null +++ b/templates/tabler/backups.html @@ -0,0 +1,2962 @@ +{% extends 'base.html' %} + +{% block content %} + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+
+
+

Configuration

+ + + + + + + + + + + +
+
+
+
+
+
+
+

+ Backup Jobs +

+

+ Backup Jobs allows you to configure how OpenPanel generates and manages your backups according to your backup job configuration. +

+
+
+
+ + + + New Backup Job + + + + + + + + + + + + + +
+
+
+ + + + {% if error %} +

{{ error }}

+ {% else %} + + + + + + + + + + + + + + + + {% for job in backup_jobs %} + + + + + + + + + + {% endfor %} +
NameDestinationTypeScheduleStatusFilters
{{ job.name }}{% if "wasabi" in job.destination %} {% elif "local" in job.destination %} {% else %} {% endif %} {{ job.destination }} +
+ {% for type in job.type %} +{% if "accounts" in type %} + +{% elif "partial" in type %} + +{% elif "config" in type %} + +{% endif %} + {{ type.capitalize() }} + {% endfor %} +
+
+ +{% if "hour" in job.schedule %} +{% elif "daily" in job.schedule %} +{% elif "week" in job.schedule %} +{% elif "month" in job.schedule %} +{% else %} +{% endif%} {{ job.schedule }}
Retain {{ job.retention }} Backups
+
{{ job.status.capitalize() }} +
+{% for filter_value in job.filters %} + {% if filter_value == 'mysql' %} + MySQL + {% elif filter_value == 'php' %} + PHP + {% elif filter_value == 'ssh' %} + SSH + {% else %} + {{ filter_value|capitalize }} + {% endif %} +{% endfor %} + + + +
+
+ + + + +
+ + + + + + {% endif %} + + + +
+
+
+
+

+ Destinations +

+

+ A Backup destination serves as the storage location for your backup files (backup destinations can be remote or local) +

+
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
DestinationTypeSSH UserSSH PortSSH KeyStorage Limit
+ + + + + + + + + + + + +
+
+
+
+

+ Restore & Download +

+

+ In this section, you can view, restore or download Account Backups and Configuration Backups generated from your Backup Jobs. +

+
+
+
+
+
+
+ +
+
+
+ + +
+ + + + + + + + + + + + + +
+ + + + + + + +
+
+
+

+ Logs +

+

+ View and download all logs for Backup-related processes and check their corresponding status. +

+
+
+
+
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + +
+
+
+
+

+ Settings +

+

+ Configure and finetune your server backups settings. +

+
+
+
+ +
+
+
+ + + + +
+
+
+ + +
+
+ + +
Directory does not exist.
+ + + The workspace directory that the system will use to store all the temporary files.
+To prevent issues with the system performance, move the original folder to the new destination instead of creating new directory +
+
+ + + + + + + + +
+ + +
Directory does not exist.
+ + + OpenPanel will use this directory to store all system downloads, include accounts backup downloads. + +
+
+ +
+ + days +
+ + Orphan backups are account backup files that are not associated with any ACTIVE account.
+OpenPanel will automatically remove these backups if the date these backups were CREATED is older than the number of days specified in this field. +
+
+
+ +
+ + days +
+ + The time to keep logs. + +
+
+ + +
+
+
+ +
+ + + +
+ +
+ OpenPanel checks average system load when starting a backup job. If system load is above this value then the backup job will not run.
Recommended value: 2 x Number of CPU cores.
+
+ + +
+ + + Set the maximum number of concurrent backup/restore tasks that may run simultaneously.
NOTE: Higher value doesn't necessarily mean higher performance, we recommend 1 task per server CPU core, but no more than 5. You also need to consider limiting CPU usage (200% is a reasonable limit).
+
+
+ +
+ + minutes +
+ Set the maximum time a backup/restore process can run for a user account. It will automatically abort once it reaches the set TTL. +
+
+ +
+ + % +
+ limit CPU usage in percentage; 100% is one core.
Recommended values: 100% for a single/dual CPU server, anything above we recommend values between 200% - 400%
+
+
+ +
+ + MB/s +
+ limit IO read usage in MB per second +
+
+ + + limit IO write usage in MB per second +
+
+ +
+ + + + + +
+If encryption is enabled, this key is needed to restore backups. +
+
+
+
+ + +
+
+ + + + Set the email address to send Emails from the system. + +
+ + +
+ + + + +
+
+
+ + + + + + + + + + + + + + + + + +
+ + + + + + + +
+ +
+
+
+
+
+ + + + + + +{% endblock %} diff --git a/templates/tabler/base.html b/templates/tabler/base.html new file mode 100644 index 00000000..5c1d389c --- /dev/null +++ b/templates/tabler/base.html @@ -0,0 +1,1123 @@ + + + + + + + + + OpenAdmin [{% if force_domain_value %}{{ force_domain_value }}{% elif server_hostname %}{{ server_hostname }}{% else %}{{public_ip}}{% endif %}] {% if title %}{{title}}{%endif%} + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + +
+ +
+
+ + + + +{% with messages = get_flashed_messages() %} +{% if messages %} + {% for message in messages %} + {% if 'success' in message.lower() %} + {% set alert_class = 'alert-success' %} + {% set alert_icon = '' %} + {% elif 'error' in message.lower() %} + {% set alert_class = 'alert-danger' %} + {% set alert_icon = '' %} + {% else %} + {% set alert_class = 'alert-primary' %} + {% set alert_icon = '' %} + {% endif %} + + {% endfor %} +{% endif %} +{% endwith %} + + + + + {% block content %}{% endblock %} + +
+
+ +
+
+ + + + + + + + + + + + + + + + + + diff --git a/templates/tabler/cluster.html b/templates/tabler/cluster.html new file mode 100644 index 00000000..b435f418 --- /dev/null +++ b/templates/tabler/cluster.html @@ -0,0 +1,61 @@ +{% extends 'base.html' %} + +{% block content %} + + + + + +
+ +
+ + + + + + + + + + + + + +
ServerDocker EndpointDefault
+
+ + + + + +
+ + + + + + + + +{% endblock %} diff --git a/templates/tabler/dashboard/cpu_per_core_usage.html b/templates/tabler/dashboard/cpu_per_core_usage.html new file mode 100644 index 00000000..b7c5e64b --- /dev/null +++ b/templates/tabler/dashboard/cpu_per_core_usage.html @@ -0,0 +1,156 @@ + + + + + + + + + + +
+
+
+
+
+
CPU
+

Real-time usage per cpu core.

+
+
+
+
+
+

The data being displayed is the usage percentage of each CPU core, with one hexagon per CPU core, and background colors indicating usage levels (default for 0-79%, orange for 80-89%, and red for 90-100%).

+

The CPU usage percentage represents the amount of the CPU's processing power that is currently being utilized. It indicates how much of the CPU's capacity is in use at a specific moment. For example, a CPU usage of 50% means that + the CPU is operating at half of its maximum processing capacity, while 100% usage indicates that the CPU is fully utilized, and there may be resource constraints or performance issues.

+

The data is auto-refreshed every 1 second to provide real-time updates.

+
+ + +
+ + +
+ + + + + + +
diff --git a/templates/tabler/dashboard/dashboard.html b/templates/tabler/dashboard/dashboard.html new file mode 100644 index 00000000..4736404f --- /dev/null +++ b/templates/tabler/dashboard/dashboard.html @@ -0,0 +1,687 @@ +{% extends 'base.html' %} {% block content %} + + + +
+ + + + + + + +
+ +
+
+
+ + + +
+ + +
+
+
 ... ... ...
+
+ +
+
+ +
+
+ +
+ + + + + + + + + + + + + +
+
+
+
+
+
+
+
+
User Activity
+

Real-time user activity log.

+
+
+
+
Users activity log will appear here.
+
+
+
+
+ + + {% if history_usage_graphs %} + + {% include 'dashboard/usage_graphs.html' %} + {% endif %} + + + {% if get_started %} + + {% include 'dashboard/get_started.html' %} + {% endif %} + +
+
+
+
+
Services Status
+

The Service Status table only reports monitored services.

+
+ +
+
+
+

Display current status of all monitored system services and docker containers. To add custom services to the list, edit the /etc/openpanel/openadmin/config/services.json file. +

+ +

+

    +
  • - is currently active and running.
  • +
  • - not currently active, either failed or stopped.
  • +
  • - not yet started, will auto-start when user/domains are created.
  • +
  • - there was a problem getting service status.
  • +
+

+ + + +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ServiceStatusActions
Loading;Checking + +
LoadingChecking + +
LoadingChecking + +
LoadingChecking + +
LoadingChecking + +
LoadingChecking + +
+
+
+
+
+ + + + + + + + +
+
+
+
+
System Information
+

Information about your server configuration.

+
+ + +
+
+
+

Server hardware and OS information

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Hostname +
+
OS +
+
OpenPanel version +
+
Server Time +
+
Kernel +
+
CPU +
+
Uptime +
+
Running Processes +
+
Package Updates +
+
+
+
+
+
+ + + + {% if license_type == "Community" %} + {% if try_enterprise %} + + {% include 'dashboard/try_enterprise.html' %} + {% endif %} + {% endif %} + + + + {% if openpanel_news %} + + {% include 'dashboard/openpanel_news.html' %} + {% endif %} + + + + {% if cpu_per_core_usage %} + + {% include 'dashboard/cpu_per_core_usage.html' %} + {% endif %} + +
+ + + +
+
+
+
+
Disk Usage
+

Current partition and hard disk usage.

+
+ +
+
+
+

This section provides an overview of your system's disk usage. It displays information about each mounted disk partition, including details such as the device, mount point, filesystem type, and the amount of space used and available + in a human-readable format (in gigabytes, GB or terabytes, TB). The 'Usage Percentage' column indicates the percentage of disk space currently in use.

+

Partitions located within the/home/directory contain data inside users containers.

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DeviceTypeMountpointUsed SpaceTotal SpaceFree Space%
+
+
+
+
+
+
+
15.2% Complete
+
+
/
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
15.2% Complete
+
+
/
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
15.2% Complete
+
+
/
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
15.2% Complete
+
+
/
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
15.2% Complete
+
+
/
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + +
+ + + + + + + +{% endblock %} diff --git a/templates/tabler/dashboard/get_started.html b/templates/tabler/dashboard/get_started.html new file mode 100644 index 00000000..7e9c6050 --- /dev/null +++ b/templates/tabler/dashboard/get_started.html @@ -0,0 +1,70 @@ + + + + + +
{% if force_domain and ns1 and ns2 and user_count > 0 and plan_count > 0 and is_modsec_installed == 'YES' and backup_jobs|int > 0 %} {% else %} +
+
+
+
+
Quick start guide
+

Recommended steps for new installations.

+
+
+
recommended
+
+
{% if force_domain %} + {% else %} + + + {% endif %} {% if ns1 and ns2 %} + {% else %} + + + {% endif %} {% if user_count|int == 0 and plan_count|int == 0 %} + + + {% elif user_count|int > 0 and plan_count|int > 0 %} + {% elif plan_count|int > 0 and user_count|int == 0 %} + + + {% elif plan_count|int == 0 and user_count|int > 0 %} + + + {% endif %}{% if backup_jobs|int > 0 and backup_jobs|int == 0 %} + {% else %} + + + {% endif %}
+ + +
{% endif %} +
diff --git a/templates/tabler/dashboard/openpanel_news.html b/templates/tabler/dashboard/openpanel_news.html new file mode 100644 index 00000000..363cb156 --- /dev/null +++ b/templates/tabler/dashboard/openpanel_news.html @@ -0,0 +1,131 @@ + + + + + + + +
+
+
+
+
+
Latest News
+

from the openpanel.co blog

+
+
+
news
+
+
+
+
+
+
+
+ + diff --git a/templates/tabler/dashboard/try_enterprise.html b/templates/tabler/dashboard/try_enterprise.html new file mode 100644 index 00000000..afda2636 --- /dev/null +++ b/templates/tabler/dashboard/try_enterprise.html @@ -0,0 +1,92 @@ + + + + + + + +
+
+
+
+
+
Try Enterprise
+

+
+
+ +
+
+ +

OpenPanel Enterprise edition offers advanced features for user isolation and management, suitable for web hosting providers.

+ +
+
+ + + + +
+
+ diff --git a/templates/tabler/dashboard/usage_graphs.html b/templates/tabler/dashboard/usage_graphs.html new file mode 100644 index 00000000..fbc312fe --- /dev/null +++ b/templates/tabler/dashboard/usage_graphs.html @@ -0,0 +1,170 @@ + + + + + + +
+
+ +
+
+
+
Usage
+

Historical resource usage.

+
+
+ +
+ +
+
+

Daily usage reports

+
+ +
+
+
+
+
+
+
+
+ Websites +
+
...
+
+
+
+ Domains +
+
...
+
+
+
+ Users +
+
{{ user_count }}
+
+
+
+
+
+
+
+ + + + + + diff --git a/templates/tabler/domains/domains.html b/templates/tabler/domains/domains.html new file mode 100644 index 00000000..29cda09c --- /dev/null +++ b/templates/tabler/domains/domains.html @@ -0,0 +1,271 @@ +{% extends 'base.html' %} + +{% block content %} + + + + + + + + +
+{% if domains %} +
+
+
+
+
+ + + + + + + + + + + + + + {% for domain in domains %} + + + + + + + + + + {% endfor %} + +
EditorsAnalyticsAdvanced
{{ domain.domain_id }}{{ domain.domain_url }}{{ domain.username.split('_')[-1] }} {% if "SUSPENDED_" in domain.username %}SUSPENDED{% endif %} + + DNS Zone + VirtualHosts Access Log | Visitors Report Transfer Remove
+
+
+
+
+
+ + +
+
+
Edit DNS
+ +
+
+ +
+
+ +
+
+
View log
+
+
+

+    
+
+ +
+
+
Edit DNS
+ +
+
+ +
+
+ + + + + + + + + +{% else %} +
+
+
+
No Domains
+

No domains yet.

+
+
+
+{% endif %} +
+ + + + + + +{% endblock %} diff --git a/templates/tabler/domains/logs.html b/templates/tabler/domains/logs.html new file mode 100644 index 00000000..dd6d2137 --- /dev/null +++ b/templates/tabler/domains/logs.html @@ -0,0 +1,25 @@ +{% extends 'base.html' %} +{% block content %} +
+
+
+ + +
+
+ +
+{% endblock %} diff --git a/templates/tabler/domains/logs_single.html b/templates/tabler/domains/logs_single.html new file mode 100644 index 00000000..3f478831 --- /dev/null +++ b/templates/tabler/domains/logs_single.html @@ -0,0 +1 @@ +{{ html_content|safe }} diff --git a/templates/tabler/emails/accounts.html b/templates/tabler/emails/accounts.html new file mode 100644 index 00000000..e7b86fb5 --- /dev/null +++ b/templates/tabler/emails/accounts.html @@ -0,0 +1,94 @@ +{% extends 'base.html' %} + +{% block content %} + + + + + + +{% if mailserver_status == 'running' %} + + +
+
+
+
+
+
+ + + + + + + + + + + + {% for email, quota in emails %} + + + + + + + {% endfor %} + +
WebmailAdvanced
{{ email }}{{ quota }} Login to WebmailAdvanced
+
+
+
+
+
+
+ + + + +{% elif mailserver_status == 'not_installed' %} + +{% include 'emails/mailserver_is_not_installed.html' %} + +{% elif mailserver_status == 'stopped' %} + +{% include 'emails/mailserver_is_stopped.html' %} + + +{% else %} + +Mailserver status not detected! + +{% endif %} + + +{% endblock %} + diff --git a/templates/tabler/emails/data/.gitkeep b/templates/tabler/emails/data/.gitkeep new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/templates/tabler/emails/data/.gitkeep @@ -0,0 +1 @@ + diff --git a/templates/tabler/emails/mailserver_is_not_installed.html b/templates/tabler/emails/mailserver_is_not_installed.html new file mode 100644 index 00000000..0ed11430 --- /dev/null +++ b/templates/tabler/emails/mailserver_is_not_installed.html @@ -0,0 +1,13 @@ +
+
+
+
MailServer is not installed
+

Mailserver is not yet installed, please install it from terminal with the folowing command:

+

+

+
+
opencli email-server install
+
+
+
+
diff --git a/templates/tabler/emails/mailserver_is_stopped.html b/templates/tabler/emails/mailserver_is_stopped.html new file mode 100644 index 00000000..8f06734e --- /dev/null +++ b/templates/tabler/emails/mailserver_is_stopped.html @@ -0,0 +1,43 @@ +
+
+
+
MailServer is not running
+

Mailserver is currently stopped.

+

+

+ +
+
+
+ + diff --git a/templates/tabler/emails/queue.html b/templates/tabler/emails/queue.html new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/templates/tabler/emails/queue.html @@ -0,0 +1 @@ + diff --git a/templates/tabler/emails/reports.html b/templates/tabler/emails/reports.html new file mode 100644 index 00000000..8a7d9df4 --- /dev/null +++ b/templates/tabler/emails/reports.html @@ -0,0 +1,4 @@ +{% extends 'base.html' %} +{% block content %} + +{% endblock %} diff --git a/templates/tabler/emails/settings.html b/templates/tabler/emails/settings.html new file mode 100644 index 00000000..ca2602a6 --- /dev/null +++ b/templates/tabler/emails/settings.html @@ -0,0 +1,1176 @@ +{% extends 'base.html' %} + +{% block content %} + + + + + + + + + + +
+ + + + + + +{% endblock %} diff --git a/templates/tabler/emails/webmail.html b/templates/tabler/emails/webmail.html new file mode 100644 index 00000000..ec239eee --- /dev/null +++ b/templates/tabler/emails/webmail.html @@ -0,0 +1,31 @@ +{% extends 'base.html' %} + +{% block content %} + + + + + + + +{% endblock %} + diff --git a/templates/tabler/license.html b/templates/tabler/license.html new file mode 100644 index 00000000..5b6e3f42 --- /dev/null +++ b/templates/tabler/license.html @@ -0,0 +1,287 @@ +{% extends 'base.html' %} + +{% block content %} + + + +
+ + +
+
+ + +
+ + +
+ + + +
+
+
+

License key

+

Enter your OpenPanel Enterprise license key to unlock premium features.

+
+
+ + + + +
+
+ +
+
+ + + + + + +
+
+
+

License Info

+

+
+ + + + + +
+
+
+ + +
+
+
+
+
+ + + + + + + + + +{% endblock %} diff --git a/templates/tabler/license_error.html b/templates/tabler/license_error.html new file mode 100644 index 00000000..7eaea80f --- /dev/null +++ b/templates/tabler/license_error.html @@ -0,0 +1,77 @@ + + + + + + + +Openpanel - Enterprise License verification failed + + + + + +
+
+ +
+
+

Your OpenPanel Enterprise license key is invalid!

+

+If you want to continue using OpenPanel Enterprise features, it's time to extend your license. +

+
    +
  • + + + + +Unlimited Users +Create and manage unlimited users + +
  • +
  • + + + + +Access to new features +Access to beta releases with new features. + +
  • +
  • + + + + +Regular updates +Regular updates and improvements. + +
  • +
+ +

+License check runs every 6 hours, if you just extended the license please run the command opencli license verify to re-check the license immediatelly. +

+
+
+
+
+ + diff --git a/templates/tabler/login.html b/templates/tabler/login.html new file mode 100644 index 00000000..a6a70680 --- /dev/null +++ b/templates/tabler/login.html @@ -0,0 +1,216 @@ + + + + + + + + {% if force_domain_value %}{{ force_domain_value }}{% elif server_hostname %}{{ server_hostname }}{% else %}{{public_ip}}{% endif %} - Sign in to OpenAdmin + + + + + + + + + + + + + +
+
+
+ +
+ +
+ + + +
+

+ OpenPanel

+{% if license_type == "Enterprise" %} +
Enterprise edition
+{% elif license_type == "Community" %} +
Community edition
+{% else %} +
UNLICENSED - NO UPDATES
+{% endif %} + +
+ + +
+
+version {{ panel_version }} +
+
+
+ +
+ +

Login

+ +

Server: {% if force_domain_value %}{{ force_domain_value }}{% elif server_hostname %}{{ server_hostname }}{% else %}{{public_ip}}{% endif %}

+ +

Type the Username and Password and click Signin.

+ +
+ +
+ +
+ +
+ + + + + + +
+
+ + +
+ +
+ + + + + + + +
+
+ + +
+ + +
+ +
+ + +
+ + +
+ +
+ + +
+ +
+ +
+ {% with messages = get_flashed_messages() %} + {% if messages %} + {% for message in messages %} +

{{ message }}

+ {% endfor %} + {% else %} + {% endif %} + {% endwith %} +
+
or
+ +
+
+ +
+{% if license_type == "Enterprise" %} +Support +{% else %} +Support +{% endif %} + Privacy Policy About +
+
+ + + +
+ +
+ + + + + + + diff --git a/templates/tabler/notifications.html b/templates/tabler/notifications.html new file mode 100644 index 00000000..93223460 --- /dev/null +++ b/templates/tabler/notifications.html @@ -0,0 +1,674 @@ + +{% extends 'base.html' %} {% block content %} + + + + + + + + +
+
+
+
+ +{% if notifications %} +
    + {% for notification in notifications %} + + {% set parts = notification.split(' MESSAGE: ', 1) %} + {% set time_and_status_and_title = parts[0].split(' ', 4) %} + {% set time = time_and_status_and_title[0] ~ ' ' ~ time_and_status_and_title[1] %} + {% set status = time_and_status_and_title[2] %} + {% set title = time_and_status_and_title[3:]|join(' ') %} + {% set message = parts[1] if parts|length > 1 else '' %} + + +
  • +{% if status == "UNREAD" %} +
    +
    + +
    + + +{% elif status == "READ" %} +
    +{% endif %} +
    +
    +
    +
    {{time}}
    + {% if "REBOOT" not in title and "accessed from new IP address" not in title and "SSH login" not in title %}

    {{ title }}

    {% endif %} + +{% if "Backup Job" in title %} +
    +
    +{% set message_parts = message.split("-") %} +{% set accounts_count = message_parts[0]|trim|replace('Accounts:', '')|trim %} +{% set execute_seconds = message_parts[1]|trim|replace('Total execution time:', '')|trim %} + +{% set seconds = execute_seconds|float %} +{% set minutes = seconds // 60 %} +{% set hours = minutes // 60 %} +{% set days = hours // 24 %} + +
    +
      +
    • Total accounts: {{ accounts_count }}
    • +
    • Total execution time: + +{% if days >= 1 %} + {{ days|int }} days, {{ hours|round|int % 24 }} hours +{% elif hours >= 1 %} + {{ hours|int }} hours, {{ minutes|round|int % 60 }} minutes +{% elif minutes >= 1 %} + {{ minutes|int }} minutes, {{ seconds|round|int % 60 }} seconds +{% else %} + {{ seconds|round|int }} seconds +{% endif %} + + +
    • +
    • View Backup Logs
    • +
    +
    +
    + +
    + + +{% elif "SSH login" in title %} + + + {% set ip_addresses_start_index = message.find("IP addresses:") %} + + {% if ip_addresses_start_index != -1 %} + {% set message_text = message[:ip_addresses_start_index].strip() %} + {% set ip_addresses_str = message[ip_addresses_start_index + 13:].strip() %} + + {% set ip_addresses_list = ip_addresses_str.split() %} + {% else %} + {% set message_text = message %} + {% set ip_addresses_list = [] %} + {% endif %} + + +
    +
    +

    + {{ title }} +

    +
    +
      +
    • + {{ message_text }}
      + {% for ip_address in ip_addresses_list %} +
      {{ ip_address }}
      + {% endfor %} +
      +
    • +
    +
    +
    +
    + + + +{% elif "accessed from new IP address" in title %} + +{% set message_parts = message.split("Admin account") %} +{% set username_and_ip = message_parts[1]|trim %} +{% set username_parts = username_and_ip.split("was accessed from a new IP address:") %} +{% set username = username_parts[0]|trim %} +{% set ip = username_parts[1]|trim %} + +
    +
    +

    + {{ title }} +

    +
    +
      +
    • + Admin account {{ username }} was accessed from a new IP address: {{ ip }} +
    • +
    +
    +
    +
    + + + + +{% elif "REBOOT" in title %} + +{% set message_parts = message.split("System was rebooted.") %} +{% set uptime = message_parts[1]|trim %} + +
    +
    + + + + + +
    +
    +

    + {{title}} +

    +
    +
      +
    • Server reboot detected!
    • +
    • Time: {{uptime}}
    • +
    +
    +
    + +
    + + + +{% elif "Disk Space" in title %} + + + + +{% set message_parts = message.split("| Partitions:") %} +{% set before_disk = message_parts[0]|trim %} +{% set after_disks = message_parts[1]|trim %} + +
    + +
    +
    Disk:
    +
    + + {{ before_disk.split(':')[1].strip() }} + + +
    +
    +
    +
    + {{ before_disk.split(':')[1].strip() }} Complete +
    +
    + + + +

    Disk usage per partitions:

    +
    +{{ after_disks|replace('\\n', '
    ')|safe }} +
    +
    + + + + +{% elif "RAM" in message %} + {% set ram_info = message.split(', ') %} + {% set used_ram = ram_info[0]|replace("Used RAM: ", "")|replace(" MB", "") %} + {% set total_ram = ram_info[1]|replace("Total RAM: ", "")|replace(" MB", "") %} + {% set usage_percentage = ram_info[2]|replace("Usage: ", "")|replace("%", "")|trim ~ "%" %} + + +
    +
    + + Used + {{ used_ram }} MB ({{ usage_percentage }}) +
    +
    + + Total + {{ total_ram }} MB +
    +
    + + Free + {{ (total_ram|int - used_ram|int) }} MB +
    +
    + +
    +
    +
    + +{% elif "service is not active" in title %} + +{% if "Deactivated successfully" in message or "Processing signal" in message %} +
  • + + {% endfor %} + + + + + + +
+ +{% else %} +

No notifications available.

+{% endif %} + + + +
+ + +
+
+ +
+
+
+
+ +

Settings

+ +
+ ? +
+
+ + +
+
+
+
Notification Preferences:
+ + + + + + +
+ +
+
Email for notifications:
+
+ + +
+
+ +
+
+ +
+ + + {% for service in ['panel', 'admin', 'nginx', 'mysql', 'docker', 'named', 'csf', 'ufw', 'certbot'] %} + + {% set display_name = service %} + + {% if service == 'panel' %} + {% set display_name = 'OpenPanel' %} + {% elif service == 'admin' %} + {% set display_name = 'OpenAdmin' %} + {% elif service == 'nginx' %} + {% set display_name = 'Nginx' %} + {% elif service == 'mysql' %} + {% set display_name = 'MySQL' %} + {% elif service == 'docker' %} + {% set display_name = 'Docker' %} + {% elif service == 'named' %} + {% set display_name = 'BIND9' %} + {% elif service == 'csf' %} + {% set display_name = 'ConfigServer Firewall' %} + {% elif service == 'ufw' %} + {% set display_name = 'UFW' %} + {% elif service == 'certbot' %} + {% set display_name = 'Certbot' %} + {% endif %} + + + + {% endfor %} + +
+ + + + + +
+ +
+ + + +
+ +
+ +
+
+ + % +
+
+
+ +
+ +
+
+ + % +
+
+
+ +
+ +
+
+ + % +
+
+
+ +
+ +
+
+ + % +
+
+
+ +
+ +
+
+ + % +
+
+
+ + +
+ + +
+
+
+
+
+
+ + + + +
+
+
+ + +
+ + + + + + + + + + + + + + + + +{% endblock %} diff --git a/templates/tabler/plans.html b/templates/tabler/plans.html new file mode 100644 index 00000000..bc393b3b --- /dev/null +++ b/templates/tabler/plans.html @@ -0,0 +1,1897 @@ + +{% extends 'base.html' %} {% block content %} + + + + + + + + +
+ + +{% if plans %} + +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + {% for plan in plans %} + + + + + + + + + + + + + + + + + + {% endfor %} + +
 
{{ plan.id }} +
+
+
{{ plan.name }}
+ {{ plan.description }} +
+
+
+ + +
+ +{% if 'openpanel' in plan.docker_image %} +
+ + +
+ + +Ubuntu 24.04 + + + + + + + + + +PHP 8.2 + + + + + + + + + {% if 'nginx' in plan.docker_image %} + +Nginx 1.24 + {% elif 'apache' in plan.docker_image %} + +Apache 2.4 + {% elif 'litespeed' in plan.docker_image %} + LiteSpeed + {% endif %} + + + + + {% if 'mysql' in plan.docker_image %} + +MySQL 8 + {% elif 'mariadb' in plan.docker_image %} + +MariaDB 10 + + + + + + + + + + + + + {% else %} + +MySQL 8 + {% endif %} + + + + + + + + + +
+
+
+ +{% else %} + + + + +
+ + +
+custom image +
+
+ + + + +{% endif %} + + + + +
{% if plan.disk_limit == 0 %}∞{% else %}{{ plan.disk_limit }}{% endif %}{% if plan.storage_file == "0 GB" or plan.storage_file is none %}∞{% else %}{{ plan.storage_file }}{% endif %}{% if plan.inodes_limit == "0" or plan.inodes_limit is none %}∞{% else %}{{ plan.inodes_limit }}{% endif %}{% if plan.domains_limit == 0 %}∞{% else %}{{ plan.domains_limit }}{% endif %}{% if plan.websites_limit == 0 %}∞{% else %}{{ plan.websites_limit }}{% endif %}{% if plan.email_limit == 0 %}∞{% else %}{{ plan.email_limit }}{% endif %}{% if plan.ftp_limit == 0 %}∞{% else %}{{ plan.ftp_limit }}{% endif %}{% if plan.db_limit == 0 %}∞{% else %}{{ plan.db_limit }}{% endif %}{% if plan.cpu == 0 %}∞{% else %}{{ plan.cpu }}{% endif %}{% if plan.ram == '0 g' %}∞{% else %}{{ plan.ram.rstrip('g') }}{% endif %}{% if plan.bandwidth == 0 %}∞{% else %}{{ plan.bandwidth }} mbits{% endif %} +
+ + + Edit + + + + + + + + + + + Delete + + + + + + + +
+
+
+
+
+
+{% else %} +
+
+
+
No Plans
+

No plans or the MySQL service is not running.

+

+

+
+ + + + + + + + + +
+
+
+
+{% endif %} + +
+ + + + + + + + + + + +