Merge pull request #1703 from master3395/v2.5.5-dev

V2.5.5 dev
This commit is contained in:
Master3395
2026-02-16 00:13:07 +01:00
committed by GitHub
68 changed files with 9995 additions and 9264 deletions

View File

@@ -0,0 +1,89 @@
#!/bin/bash
# Migrate RainLoop to SnappyMail on live server: rename public folder and/or install SnappyMail if missing, migrate data, fix paths, restart, test.
# Run as root: bash /usr/local/CyberCP/CPScripts/migrate_rainloop_to_snappymail.sh
set -e
LOG="/var/log/cyberpanel_upgrade_debug.log"
log() { echo -e "[$(date +"%Y-%m-%d %H:%M:%S")] $*" | tee -a "$LOG"; }
SNAPPY_VERSION="${SNAPPY_VERSION:-2.38.2}"
log "=== RainLoop -> SnappyMail migration ==="
# 1) Ensure public/snappymail exists: rename rainloop -> snappymail OR download and install SnappyMail
if [ -d "/usr/local/CyberCP/public/rainloop" ] && [ ! -d "/usr/local/CyberCP/public/snappymail" ]; then
log "Renaming public/rainloop to public/snappymail..."
mv /usr/local/CyberCP/public/rainloop /usr/local/CyberCP/public/snappymail
log "Renamed public/rainloop -> public/snappymail"
if [ -f "/usr/local/CyberCP/public/snappymail/include.php" ]; then
sed -i 's|/usr/local/lscp/cyberpanel/rainloop/data|/usr/local/lscp/cyberpanel/snappymail/data|g' /usr/local/CyberCP/public/snappymail/include.php
log "Updated include.php data path"
fi
for inc in /usr/local/CyberCP/public/snappymail/snappymail/v/*/include.php /usr/local/CyberCP/public/snappymail/rainloop/v/*/include.php; do
[ -f "$inc" ] && sed -i 's|/usr/local/lscp/cyberpanel/rainloop/data|/usr/local/lscp/cyberpanel/snappymail/data|g' "$inc" && log "Updated $inc" && break
done 2>/dev/null || true
elif [ ! -d "/usr/local/CyberCP/public/snappymail" ]; then
log "public/snappymail missing - installing SnappyMail v${SNAPPY_VERSION}..."
cd /usr/local/CyberCP/public || exit 1
if ! wget -q "https://github.com/the-djmaze/snappymail/releases/download/v${SNAPPY_VERSION}/snappymail-${SNAPPY_VERSION}.zip" -O "snappymail-${SNAPPY_VERSION}.zip"; then
log "ERROR: wget SnappyMail failed"
exit 1
fi
unzip -q "snappymail-${SNAPPY_VERSION}.zip" -d /usr/local/CyberCP/public/snappymail
rm -f "snappymail-${SNAPPY_VERSION}.zip"
find /usr/local/CyberCP/public/snappymail -type d -exec chmod 755 {} \;
find /usr/local/CyberCP/public/snappymail -type f -exec chmod 644 {} \;
log "SnappyMail installed"
# Configure data path and run CyberPanel integration
wget -q -O /usr/local/CyberCP/snappymail_cyberpanel.php "https://raw.githubusercontent.com/the-djmaze/snappymail/master/integrations/cyberpanel/install.php" 2>/dev/null || true
if [ -f /usr/local/CyberCP/snappymail_cyberpanel.php ]; then
for php in /usr/local/lsws/lsphp83/bin/php /usr/local/lsws/lsphp82/bin/php /usr/local/lsws/lsphp81/bin/php /usr/local/lsws/lsphp80/bin/php; do
[ -x "$php" ] && $php /usr/local/CyberCP/snappymail_cyberpanel.php 2>/dev/null && break
done
fi
else
log "public/snappymail already exists"
fi
# 2) Data migration: lscp/cyberpanel/rainloop/data -> snappymail/data
mkdir -p /usr/local/lscp/cyberpanel/snappymail/data/_data_/_default_/configs/
mkdir -p /usr/local/lscp/cyberpanel/snappymail/data/_data_/_default_/domains/
mkdir -p /usr/local/lscp/cyberpanel/snappymail/data/_data_/_default_/storage/
mkdir -p /usr/local/lscp/cyberpanel/snappymail/data/_data_/_default_/temp/
mkdir -p /usr/local/lscp/cyberpanel/snappymail/data/_data_/_default_/cache/
if [ -d "/usr/local/lscp/cyberpanel/rainloop/data" ] && [ "$(ls -A /usr/local/lscp/cyberpanel/rainloop/data 2>/dev/null)" ]; then
log "Migrating rainloop data to snappymail..."
rsync -av --ignore-existing /usr/local/lscp/cyberpanel/rainloop/data/ /usr/local/lscp/cyberpanel/snappymail/data/ 2>&1 | tee -a "$LOG"
if [ -f "/usr/local/CyberCP/public/snappymail/include.php" ]; then
sed -i 's|/usr/local/lscp/cyberpanel/rainloop/data|/usr/local/lscp/cyberpanel/snappymail/data|g' /usr/local/CyberCP/public/snappymail/include.php
fi
find /usr/local/lscp/cyberpanel/snappymail/data -type f \( -name "*.ini" -o -name "*.json" -o -name "*.php" -o -name "*.cfg" \) -exec grep -l "rainloop" {} \; 2>/dev/null | while read -r f; do
sed -i 's|/usr/local/lscp/cyberpanel/rainloop/data|/usr/local/lscp/cyberpanel/snappymail/data|g; s|/rainloop/|/snappymail/|g; s|rainloop/data|snappymail/data|g' "$f"
done
log "Data migration done"
fi
# 3) Ownership and permissions
if id -u lscpd >/dev/null 2>&1; then
chown -R lscpd:lscpd /usr/local/lscp/cyberpanel/snappymail/
chown -R lscpd:lscpd /usr/local/CyberCP/public/snappymail/ 2>/dev/null || true
log "Set ownership lscpd:lscpd"
fi
chmod -R 775 /usr/local/lscp/cyberpanel/snappymail/data/ 2>/dev/null || true
# 4) Restart panel
log "Restarting lscpd..."
systemctl restart lscpd
sleep 2
# 5) Test
PORT=$(cat /usr/local/lscp/conf/bind.conf 2>/dev/null | grep -oE '[0-9]+' | head -1)
PORT=${PORT:-8090}
log "Testing https://127.0.0.1:${PORT}/snappymail/index.php ..."
CODE=$(curl -sk -o /dev/null -w "%{http_code}" "https://127.0.0.1:${PORT}/snappymail/index.php" 2>/dev/null || echo "000")
if [ "$CODE" = "200" ] || [ "$CODE" = "302" ]; then
log "OK: SnappyMail URL returned HTTP $CODE"
else
log "WARNING: SnappyMail URL returned HTTP $CODE (expected 200 or 302)"
fi
log "=== Migration script finished ==="

View File

@@ -13,11 +13,13 @@ Including another URLconf
1. Import the include() function: from django.urls import path, include
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
import os
from django.urls import path, re_path, include
from django.contrib import admin
from django.conf import settings
from django.conf.urls.static import static
from django.views.static import serve
from django.views.generic import RedirectView
from firewall import views as firewall_views
# Plugin routes are no longer hardcoded here; pluginHolder.urls dynamically
@@ -34,6 +36,11 @@ except ModuleNotFoundError:
urlpatterns = [
# Serve static files first (before catch-all routes)
re_path(r'^static/(?P<path>.*)$', serve, {'document_root': settings.STATIC_ROOT}),
# Serve SnappyMail and phpMyAdmin from public directory (fixes 404 when panel is served by Django/lscpd on :2087/:8090)
re_path(r'^snappymail/?$', RedirectView.as_view(url='/snappymail/index.php', permanent=False)),
re_path(r'^snappymail/(?P<path>.*)$', serve, {'document_root': os.path.join(settings.PUBLIC_ROOT, 'snappymail')}),
re_path(r'^phpmyadmin/?$', RedirectView.as_view(url='/phpmyadmin/index.php', permanent=False)),
re_path(r'^phpmyadmin/(?P<path>.*)$', serve, {'document_root': os.path.join(settings.PUBLIC_ROOT, 'phpmyadmin')}),
path('base/', include('baseTemplate.urls')),
path('imunifyav/', firewall_views.imunifyAV, name='imunifyav_root'),
path('ImunifyAV/', firewall_views.imunifyAV, name='imunifyav_root_legacy'),

View File

@@ -282,11 +282,11 @@ app.controller('adminController', function ($scope, $http, $timeout) {
}
if (!Boolean(response.data.deleteZone)) {
$('.addDeleteRecords').hide();
$('.deleteZone').hide();
}
if (!Boolean(response.data.addDeleteRecords)) {
$('.deleteDatabase').hide();
$('.addDeleteRecords').hide();
}
// Email Management

View File

@@ -1696,22 +1696,22 @@
</a>
{% endif %}
{% if admin or deleteZone %}
<a href="{% url 'deleteDNSZone' %}" class="menu-item">
<a href="{% url 'deleteDNSZone' %}" class="menu-item deleteZone">
<span>Delete Zone</span>
</a>
{% endif %}
{% if admin or addDeleteRecords %}
<a href="{% url 'addDeleteDNSRecords' %}" class="menu-item">
<a href="{% url 'addDeleteDNSRecords' %}" class="menu-item addDeleteRecords">
<span>Add/Delete Records</span>
</a>
{% endif %}
{% if admin or addDeleteRecords %}
<a href="{% url 'addDeleteDNSRecordsCloudFlare' %}" class="menu-item">
<a href="{% url 'addDeleteDNSRecordsCloudFlare' %}" class="menu-item addDeleteRecords">
<span>CloudFlare</span>
</a>
{% endif %}
{% if admin or addDeleteRecords %}
<a href="{% url 'ResetDNSConfigurations' %}" class="menu-item">
<a href="{% url 'ResetDNSConfigurations' %}" class="menu-item addDeleteRecords">
<span>Reset DNS Configurations</span>
</a>
{% endif %}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1945,6 +1945,19 @@ fi
# Fix SnappyMail directory permissions for Ubuntu 24.04 and other systems
echo -e "[$(date +"%Y-%m-%d %H:%M:%S")] Checking SnappyMail directories..." | tee -a /var/log/cyberpanel_upgrade_debug.log
# If public web app is still named rainloop, rename to snappymail so /snappymail/ URL works
if [ -d "/usr/local/CyberCP/public/rainloop" ] && [ ! -d "/usr/local/CyberCP/public/snappymail" ]; then
echo -e "[$(date +"%Y-%m-%d %H:%M:%S")] Renaming public/rainloop to public/snappymail..." | tee -a /var/log/cyberpanel_upgrade_debug.log
mv /usr/local/CyberCP/public/rainloop /usr/local/CyberCP/public/snappymail
echo -e "[$(date +"%Y-%m-%d %H:%M:%S")] Renamed public/rainloop -> public/snappymail" | tee -a /var/log/cyberpanel_upgrade_debug.log
if [ -f "/usr/local/CyberCP/public/snappymail/include.php" ]; then
sed -i 's|/usr/local/lscp/cyberpanel/rainloop/data|/usr/local/lscp/cyberpanel/snappymail/data|g' /usr/local/CyberCP/public/snappymail/include.php
fi
for inc in /usr/local/CyberCP/public/snappymail/snappymail/v/*/include.php /usr/local/CyberCP/public/snappymail/rainloop/v/*/include.php; do
[ -f "$inc" ] && sed -i 's|/usr/local/lscp/cyberpanel/rainloop/data|/usr/local/lscp/cyberpanel/snappymail/data|g' "$inc" && break
done 2>/dev/null
fi
# Migrate data from old rainloop folder to new snappymail folder (2.4.4 -> 2.5.5 upgrade)
if [ -d "/usr/local/lscp/cyberpanel/rainloop/data" ] && [ "$(ls -A /usr/local/lscp/cyberpanel/rainloop/data 2>/dev/null)" ]; then
echo -e "[$(date +"%Y-%m-%d %H:%M:%S")] Migrating rainloop data to snappymail..." | tee -a /var/log/cyberpanel_upgrade_debug.log
@@ -1971,6 +1984,14 @@ if [ -d "/usr/local/lscp/cyberpanel/rainloop/data" ] && [ "$(ls -A /usr/local/ls
sed -i 's|/usr/local/lscp/cyberpanel/rainloop/data|/usr/local/lscp/cyberpanel/snappymail/data|g' /usr/local/CyberCP/public/snappymail/include.php
echo -e "[$(date +"%Y-%m-%d %H:%M:%S")] Updated include.php to use snappymail data path" | tee -a /var/log/cyberpanel_upgrade_debug.log
fi
# Replace ALL rainloop path/URL references in migrated SnappyMail data (configs, domains, plugins)
if [ -d "/usr/local/lscp/cyberpanel/snappymail/data" ]; then
find /usr/local/lscp/cyberpanel/snappymail/data -type f \( -name "*.ini" -o -name "*.json" -o -name "*.php" -o -name "*.cfg" \) -exec grep -l "rainloop" {} \; 2>/dev/null | while read -r f; do
sed -i 's|/usr/local/lscp/cyberpanel/rainloop/data|/usr/local/lscp/cyberpanel/snappymail/data|g; s|/rainloop/|/snappymail/|g; s|rainloop/data|snappymail/data|g' "$f"
done
echo -e "[$(date +"%Y-%m-%d %H:%M:%S")] Replaced rainloop→snappymail links in SnappyMail data files" | tee -a /var/log/cyberpanel_upgrade_debug.log
fi
else
echo -e "[$(date +"%Y-%m-%d %H:%M:%S")] WARNING: Data migration completed with errors" | tee -a /var/log/cyberpanel_upgrade_debug.log
fi
@@ -1994,6 +2015,20 @@ else
echo -e "[$(date +"%Y-%m-%d %H:%M:%S")] WARNING: lscpd user not found, skipping ownership change" | tee -a /var/log/cyberpanel_upgrade_debug.log
fi
# Ensure /rainloop→/snappymail redirect exists (even when no migration ran)
HTACCESS="/usr/local/CyberCP/public/.htaccess"
if [ -d "/usr/local/CyberCP/public" ] && { [ ! -f "$HTACCESS" ] || ! grep -q "Redirect old RainLoop URL to SnappyMail" "$HTACCESS" 2>/dev/null; }; then
{
echo ""
echo "# Redirect old RainLoop URL to SnappyMail (2.5.5 upgrade)"
echo "<IfModule mod_rewrite.c>"
echo "RewriteEngine On"
echo "RewriteRule ^rainloop/?(.*)\$ /snappymail/\$1 [R=301,L]"
echo "</IfModule>"
} >> "$HTACCESS"
echo -e "[$(date +"%Y-%m-%d %H:%M:%S")] Added /rainloop→/snappymail redirect to .htaccess" | tee -a /var/log/cyberpanel_upgrade_debug.log
fi
# Set proper permissions for SnappyMail data directories (group writable)
chmod -R 775 /usr/local/lscp/cyberpanel/snappymail/data/
echo -e "[$(date +"%Y-%m-%d %H:%M:%S")] Set SnappyMail data directory permissions to 775 (group writable)" | tee -a /var/log/cyberpanel_upgrade_debug.log

View File

@@ -31,6 +31,8 @@ app.controller('firewallController', function ($scope, $http, $timeout) {
$scope.couldNotConnect = true;
$scope.rulesDetails = false;
// Initialize rules array - prevents "Cannot read 'length' of undefined" when template evaluates rules.length before API loads
$scope.rules = [];
// Banned IPs variables tab from hash so we stay on /firewall/ (avoids 404 on servers without /firewall/firewall-rules/)
function tabFromHash() {
var h = (window.location.hash || '').replace(/^#/, '');

View File

@@ -1293,7 +1293,7 @@
<!-- Rules Table -->
<div ng-hide="rulesDetails" class="rules-table-section">
<div class="table-responsive">
<table class="rules-table" ng-if="rules.length > 0">
<table class="rules-table" ng-if="rules && rules.length > 0">
<thead>
<tr>
<th>{% trans "ID" %}</th>
@@ -1361,7 +1361,7 @@
</div>
<!-- Empty State -->
<div ng-if="rules.length == 0" class="empty-state">
<div ng-if="!rules || rules.length == 0" class="empty-state">
<i class="fas fa-shield-alt empty-icon"></i>
<h3 class="empty-title">{% trans "No Firewall Rules" %}</h3>
<p class="empty-text">{% trans "Add your first firewall rule to control network access to your server." %}</p>

View File

@@ -99,6 +99,14 @@ fi
# Check disk space
check_disk_space
# If running from repo with modular installer, use it
INSTALL_SCRIPT_DIR="$(cd "$(dirname "$0")" 2>/dev/null && pwd)"
if [ -n "$INSTALL_SCRIPT_DIR" ] && [ -f "$INSTALL_SCRIPT_DIR/cyberpanel.sh" ] && [ -d "$INSTALL_SCRIPT_DIR/install_modules" ]; then
echo "Using local CyberPanel installer (modular)"
cd "$INSTALL_SCRIPT_DIR" || exit 1
exec bash ./cyberpanel.sh -b "${BRANCH_NAME}" "$@"
fi
# Download and execute cyberpanel.sh for the specified branch
echo "Downloading CyberPanel installer for branch: $BRANCH_NAME"

View File

@@ -1,476 +0,0 @@
# ACCESS(5) ACCESS(5)
#
# NAME
# access - Postfix SMTP server access table
#
# SYNOPSIS
# postmap /etc/postfix/access
#
# postmap -q "string" /etc/postfix/access
#
# postmap -q - /etc/postfix/access <inputfile
#
# DESCRIPTION
# This document describes access control on remote SMTP
# client information: host names, network addresses, and
# envelope sender or recipient addresses; it is implemented
# by the Postfix SMTP server. See header_checks(5) or
# body_checks(5) for access control on the content of email
# messages.
#
# Normally, the access(5) table is specified as a text file
# that serves as input to the postmap(1) command. The
# result, an indexed file in dbm or db format, is used for
# fast searching by the mail system. Execute the command
# "postmap /etc/postfix/access" to rebuild an indexed file
# after changing the corresponding text file.
#
# When the table is provided via other means such as NIS,
# LDAP or SQL, the same lookups are done as for ordinary
# indexed files.
#
# Alternatively, the table can be provided as a regular-
# expression map where patterns are given as regular expres-
# sions, or lookups can be directed to TCP-based server. In
# those cases, the lookups are done in a slightly different
# way as described below under "REGULAR EXPRESSION TABLES"
# or "TCP-BASED TABLES".
#
# CASE FOLDING
# The search string is folded to lowercase before database
# lookup. As of Postfix 2.3, the search string is not case
# folded with database types such as regexp: or pcre: whose
# lookup fields can match both upper and lower case.
#
# TABLE FORMAT
# The input format for the postmap(1) command is as follows:
#
# pattern action
# When pattern matches a mail address, domain or host
# address, perform the corresponding action.
#
# blank lines and comments
# Empty lines and whitespace-only lines are ignored,
# as are lines whose first non-whitespace character
# is a `#'.
#
# multi-line text
# A logical line starts with non-whitespace text. A
# line that starts with whitespace continues a logi-
# cal line.
#
# EMAIL ADDRESS PATTERNS
# With lookups from indexed files such as DB or DBM, or from
# networked tables such as NIS, LDAP or SQL, patterns are
# tried in the order as listed below:
#
# user@domain
# Matches the specified mail address.
#
# domain.tld
# Matches domain.tld as the domain part of an email
# address.
#
# The pattern domain.tld also matches subdomains, but
# only when the string smtpd_access_maps is listed in
# the Postfix parent_domain_matches_subdomains con-
# figuration setting.
#
# .domain.tld
# Matches subdomains of domain.tld, but only when the
# string smtpd_access_maps is not listed in the Post-
# fix parent_domain_matches_subdomains configuration
# setting.
#
# user@ Matches all mail addresses with the specified user
# part.
#
# Note: lookup of the null sender address is not possible
# with some types of lookup table. By default, Postfix uses
# <> as the lookup key for such addresses. The value is
# specified with the smtpd_null_access_lookup_key parameter
# in the Postfix main.cf file.
#
# EMAIL ADDRESS EXTENSION
# When a mail address localpart contains the optional recip-
# ient delimiter (e.g., user+foo@domain), the lookup order
# becomes: user+foo@domain, user@domain, domain, user+foo@,
# and user@.
#
# HOST NAME/ADDRESS PATTERNS
# With lookups from indexed files such as DB or DBM, or from
# networked tables such as NIS, LDAP or SQL, the following
# lookup patterns are examined in the order as listed:
#
# domain.tld
# Matches domain.tld.
#
# The pattern domain.tld also matches subdomains, but
# only when the string smtpd_access_maps is listed in
# the Postfix parent_domain_matches_subdomains con-
# figuration setting.
#
# .domain.tld
# Matches subdomains of domain.tld, but only when the
# string smtpd_access_maps is not listed in the Post-
# fix parent_domain_matches_subdomains configuration
# setting.
#
# net.work.addr.ess
#
# net.work.addr
#
# net.work
#
# net Matches the specified IPv4 host address or subnet-
# work. An IPv4 host address is a sequence of four
# decimal octets separated by ".".
#
# Subnetworks are matched by repeatedly truncating
# the last ".octet" from the remote IPv4 host address
# string until a match is found in the access table,
# or until further truncation is not possible.
#
# NOTE 1: The access map lookup key must be in canon-
# ical form: do not specify unnecessary null charac-
# ters, and do not enclose network address informa-
# tion with "[]" characters.
#
# NOTE 2: use the cidr lookup table type to specify
# network/netmask patterns. See cidr_table(5) for
# details.
#
# net:work:addr:ess
#
# net:work:addr
#
# net:work
#
# net Matches the specified IPv6 host address or subnet-
# work. An IPv6 host address is a sequence of three
# to eight hexadecimal octet pairs separated by ":".
#
# Subnetworks are matched by repeatedly truncating
# the last ":octetpair" from the remote IPv6 host
# address string until a match is found in the access
# table, or until further truncation is not possible.
#
# NOTE 1: the truncation and comparison are done with
# the string representation of the IPv6 host address.
# Thus, not all the ":" subnetworks will be tried.
#
# NOTE 2: The access map lookup key must be in canon-
# ical form: do not specify unnecessary null charac-
# ters, and do not enclose network address informa-
# tion with "[]" characters.
#
# NOTE 3: use the cidr lookup table type to specify
# network/netmask patterns. See cidr_table(5) for
# details.
#
# IPv6 support is available in Postfix 2.2 and later.
#
# ACCEPT ACTIONS
# OK Accept the address etc. that matches the pattern.
#
# all-numerical
# An all-numerical result is treated as OK. This for-
# mat is generated by address-based relay authoriza-
# tion schemes such as pop-before-smtp.
#
# REJECT ACTIONS
# Postfix version 2.3 and later support enhanced status
# codes as defined in RFC 3463. When no code is specified
# at the beginning of the text below, Postfix inserts a
# default enhanced status code of "5.7.1" in the case of
# reject actions, and "4.7.1" in the case of defer actions.
# See "ENHANCED STATUS CODES" below.
#
# 4NN text
#
# 5NN text
# Reject the address etc. that matches the pattern,
# and respond with the numerical three-digit code and
# text. 4NN means "try again later", while 5NN means
# "do not try again".
#
# The following responses have special meaning for
# the Postfix SMTP server:
#
# 421 text (Postfix 2.3 and later)
#
# 521 text (Postfix 2.6 and later)
# After responding with the numerical three-
# digit code and text, disconnect immediately
# from the SMTP client. This frees up SMTP
# server resources so that they can be made
# available to another SMTP client.
#
# Note: The "521" response should be used only
# with botnets and other malware where inter-
# operability is of no concern. The "send 521
# and disconnect" behavior is NOT defined in
# the SMTP standard.
#
# REJECT optional text...
# Reject the address etc. that matches the pattern.
# Reply with "$access_map_reject_code optional
# text..." when the optional text is specified, oth-
# erwise reply with a generic error response message.
#
# DEFER optional text...
# Reject the address etc. that matches the pattern.
# Reply with "$access_map_defer_code optional
# text..." when the optional text is specified, oth-
# erwise reply with a generic error response message.
#
# This feature is available in Postfix 2.6 and later.
#
# DEFER_IF_REJECT optional text...
# Defer the request if some later restriction would
# result in a REJECT action. Reply with
# "$access_map_defer_code 4.7.1 optional text..."
# when the optional text is specified, otherwise
# reply with a generic error response message.
#
# Prior to Postfix 2.6, the SMTP reply code is 450.
#
# This feature is available in Postfix 2.1 and later.
#
# DEFER_IF_PERMIT optional text...
# Defer the request if some later restriction would
# result in a an explicit or implicit PERMIT action.
# Reply with "$access_map_defer_code 4.7.1 optional
# text..." when the optional text is specified, oth-
# erwise reply with a generic error response message.
#
# Prior to Postfix 2.6, the SMTP reply code is 450.
#
# This feature is available in Postfix 2.1 and later.
#
# OTHER ACTIONS
# restriction...
# Apply the named UCE restriction(s) (permit, reject,
# reject_unauth_destination, and so on).
#
# BCC user@domain
# Send one copy of the message to the specified
# recipient.
#
# If multiple BCC actions are specified within the
# same SMTP MAIL transaction, only the last action
# will be used.
#
# This feature is not part of the stable Postfix
# release.
#
# DISCARD optional text...
# Claim successful delivery and silently discard the
# message. Log the optional text if specified, oth-
# erwise log a generic message.
#
# Note: this action currently affects all recipients
# of the message. To discard only one recipient
# without discarding the entire message, use the
# transport(5) table to direct mail to the discard(8)
# service.
#
# This feature is available in Postfix 2.0 and later.
#
# DUNNO Pretend that the lookup key was not found. This
# prevents Postfix from trying substrings of the
# lookup key (such as a subdomain name, or a network
# address subnetwork).
#
# This feature is available in Postfix 2.0 and later.
#
# FILTER transport:destination
# After the message is queued, send the entire mes-
# sage through the specified external content filter.
# The transport name specifies the first field of a
# mail delivery agent definition in master.cf; the
# syntax of the next-hop destination is described in
# the manual page of the corresponding delivery
# agent. More information about external content
# filters is in the Postfix FILTER_README file.
#
# Note 1: do not use $number regular expression sub-
# stitutions for transport or destination unless you
# know that the information has a trusted origin.
#
# Note 2: this action overrides the main.cf con-
# tent_filter setting, and affects all recipients of
# the message. In the case that multiple FILTER
# actions fire, only the last one is executed.
#
# Note 3: the purpose of the FILTER command is to
# override message routing. To override the recipi-
# ent's transport but not the next-hop destination,
# specify an empty filter destination (Postfix 2.7
# and later), or specify a transport:destination that
# delivers through a different Postfix instance
# (Postfix 2.6 and earlier). Other options are using
# the recipient-dependent transport_maps or the sen-
# der-dependent sender_dependent_default_transport-
# _maps features.
#
# This feature is available in Postfix 2.0 and later.
#
# HOLD optional text...
# Place the message on the hold queue, where it will
# sit until someone either deletes it or releases it
# for delivery. Log the optional text if specified,
# otherwise log a generic message.
#
# Mail that is placed on hold can be examined with
# the postcat(1) command, and can be destroyed or
# released with the postsuper(1) command.
#
# Note: use "postsuper -r" to release mail that was
# kept on hold for a significant fraction of $maxi-
# mal_queue_lifetime or $bounce_queue_lifetime, or
# longer. Use "postsuper -H" only for mail that will
# not expire within a few delivery attempts.
#
# Note: this action currently affects all recipients
# of the message.
#
# This feature is available in Postfix 2.0 and later.
#
# PREPEND headername: headervalue
# Prepend the specified message header to the mes-
# sage. When more than one PREPEND action executes,
# the first prepended header appears before the sec-
# ond etc. prepended header.
#
# Note: this action must execute before the message
# content is received; it cannot execute in the con-
# text of smtpd_end_of_data_restrictions.
#
# This feature is available in Postfix 2.1 and later.
#
# REDIRECT user@domain
# After the message is queued, send the message to
# the specified address instead of the intended
# recipient(s).
#
# Note: this action overrides the FILTER action, and
# currently affects all recipients of the message.
#
# This feature is available in Postfix 2.1 and later.
#
# WARN optional text...
# Log a warning with the optional text, together with
# client information and if available, with helo,
# sender, recipient and protocol information.
#
# This feature is available in Postfix 2.1 and later.
#
# ENHANCED STATUS CODES
# Postfix version 2.3 and later support enhanced status
# codes as defined in RFC 3463. When an enhanced status
# code is specified in an access table, it is subject to
# modification. The following transformations are needed
# when the same access table is used for client, helo,
# sender, or recipient access restrictions; they happen
# regardless of whether Postfix replies to a MAIL FROM, RCPT
# TO or other SMTP command.
#
# o When a sender address matches a REJECT action, the
# Postfix SMTP server will transform a recipient DSN
# status (e.g., 4.1.1-4.1.6) into the corresponding
# sender DSN status, and vice versa.
#
# o When non-address information matches a REJECT
# action (such as the HELO command argument or the
# client hostname/address), the Postfix SMTP server
# will transform a sender or recipient DSN status
# into a generic non-address DSN status (e.g.,
# 4.0.0).
#
# REGULAR EXPRESSION TABLES
# This section describes how the table lookups change when
# the table is given in the form of regular expressions. For
# a description of regular expression lookup table syntax,
# see regexp_table(5) or pcre_table(5).
#
# Each pattern is a regular expression that is applied to
# the entire string being looked up. Depending on the appli-
# cation, that string is an entire client hostname, an
# entire client IP address, or an entire mail address. Thus,
# no parent domain or parent network search is done,
# user@domain mail addresses are not broken up into their
# user@ and domain constituent parts, nor is user+foo broken
# up into user and foo.
#
# Patterns are applied in the order as specified in the ta-
# ble, until a pattern is found that matches the search
# string.
#
# Actions are the same as with indexed file lookups, with
# the additional feature that parenthesized substrings from
# the pattern can be interpolated as $1, $2 and so on.
#
# TCP-BASED TABLES
# This section describes how the table lookups change when
# lookups are directed to a TCP-based server. For a descrip-
# tion of the TCP client/server lookup protocol, see tcp_ta-
# ble(5). This feature is not available up to and including
# Postfix version 2.4.
#
# Each lookup operation uses the entire query string once.
# Depending on the application, that string is an entire
# client hostname, an entire client IP address, or an entire
# mail address. Thus, no parent domain or parent network
# search is done, user@domain mail addresses are not broken
# up into their user@ and domain constituent parts, nor is
# user+foo broken up into user and foo.
#
# Actions are the same as with indexed file lookups.
#
# EXAMPLE
# The following example uses an indexed file, so that the
# order of table entries does not matter. The example per-
# mits access by the client at address 1.2.3.4 but rejects
# all other clients in 1.2.3.0/24. Instead of hash lookup
# tables, some systems use dbm. Use the command "postconf
# -m" to find out what lookup tables Postfix supports on
# your system.
#
# /etc/postfix/main.cf:
# smtpd_client_restrictions =
# check_client_access hash:/etc/postfix/access
#
# /etc/postfix/access:
# 1.2.3 REJECT
# 1.2.3.4 OK
#
# Execute the command "postmap /etc/postfix/access" after
# editing the file.
#
# BUGS
# The table format does not understand quoting conventions.
#
# SEE ALSO
# postmap(1), Postfix lookup table manager
# smtpd(8), SMTP server
# postconf(5), configuration parameters
# transport(5), transport:nexthop syntax
#
# README FILES
# Use "postconf readme_directory" or "postconf html_direc-
# tory" to locate this information.
# SMTPD_ACCESS_README, built-in SMTP server access control
# DATABASE_README, Postfix lookup table overview
#
# LICENSE
# The Secure Mailer license must be distributed with this
# software.
#
# AUTHOR(S)
# Wietse Venema
# IBM T.J. Watson Research
# P.O. Box 704
# Yorktown Heights, NY 10598, USA
#
# ACCESS(5)

View File

@@ -1,278 +0,0 @@
# CANONICAL(5) CANONICAL(5)
#
# NAME
# canonical - Postfix canonical table format
#
# SYNOPSIS
# postmap /etc/postfix/canonical
#
# postmap -q "string" /etc/postfix/canonical
#
# postmap -q - /etc/postfix/canonical <inputfile
#
# DESCRIPTION
# The optional canonical(5) table specifies an address map-
# ping for local and non-local addresses. The mapping is
# used by the cleanup(8) daemon, before mail is stored into
# the queue. The address mapping is recursive.
#
# Normally, the canonical(5) table is specified as a text
# file that serves as input to the postmap(1) command. The
# result, an indexed file in dbm or db format, is used for
# fast searching by the mail system. Execute the command
# "postmap /etc/postfix/canonical" to rebuild an indexed
# file after changing the corresponding text file.
#
# When the table is provided via other means such as NIS,
# LDAP or SQL, the same lookups are done as for ordinary
# indexed files.
#
# Alternatively, the table can be provided as a regular-
# expression map where patterns are given as regular expres-
# sions, or lookups can be directed to TCP-based server. In
# those cases, the lookups are done in a slightly different
# way as described below under "REGULAR EXPRESSION TABLES"
# or "TCP-BASED TABLES".
#
# By default the canonical(5) mapping affects both message
# header addresses (i.e. addresses that appear inside mes-
# sages) and message envelope addresses (for example, the
# addresses that are used in SMTP protocol commands). This
# is controlled with the canonical_classes parameter.
#
# NOTE: Postfix versions 2.2 and later rewrite message head-
# ers from remote SMTP clients only if the client matches
# the local_header_rewrite_clients parameter, or if the
# remote_header_rewrite_domain configuration parameter spec-
# ifies a non-empty value. To get the behavior before Post-
# fix 2.2, specify "local_header_rewrite_clients =
# static:all".
#
# Typically, one would use the canonical(5) table to replace
# login names by Firstname.Lastname, or to clean up
# addresses produced by legacy mail systems.
#
# The canonical(5) mapping is not to be confused with vir-
# tual alias support or with local aliasing. To change the
# destination but not the headers, use the virtual(5) or
# aliases(5) map instead.
#
# CASE FOLDING
# The search string is folded to lowercase before database
# lookup. As of Postfix 2.3, the search string is not case
# folded with database types such as regexp: or pcre: whose
# lookup fields can match both upper and lower case.
#
# TABLE FORMAT
# The input format for the postmap(1) command is as follows:
#
# pattern result
# When pattern matches a mail address, replace it by
# the corresponding result.
#
# blank lines and comments
# Empty lines and whitespace-only lines are ignored,
# as are lines whose first non-whitespace character
# is a `#'.
#
# multi-line text
# A logical line starts with non-whitespace text. A
# line that starts with whitespace continues a logi-
# cal line.
#
# TABLE SEARCH ORDER
# With lookups from indexed files such as DB or DBM, or from
# networked tables such as NIS, LDAP or SQL, patterns are
# tried in the order as listed below:
#
# user@domain address
# Replace user@domain by address. This form has the
# highest precedence.
#
# This is useful to clean up addresses produced by
# legacy mail systems. It can also be used to pro-
# duce Firstname.Lastname style addresses, but see
# below for a simpler solution.
#
# user address
# Replace user@site by address when site is equal to
# $myorigin, when site is listed in $mydestination,
# or when it is listed in $inet_interfaces or
# $proxy_interfaces.
#
# This form is useful for replacing login names by
# Firstname.Lastname.
#
# @domain address
# Replace other addresses in domain by address. This
# form has the lowest precedence.
#
# Note: @domain is a wild-card. When this form is
# applied to recipient addresses, the Postfix SMTP
# server accepts mail for any recipient in domain,
# regardless of whether that recipient exists. This
# may turn your mail system into a backscatter
# source: Postfix first accepts mail for non-existent
# recipients and then tries to return that mail as
# "undeliverable" to the often forged sender address.
#
# RESULT ADDRESS REWRITING
# The lookup result is subject to address rewriting:
#
# o When the result has the form @otherdomain, the
# result becomes the same user in otherdomain.
#
# o When "append_at_myorigin=yes", append "@$myorigin"
# to addresses without "@domain".
#
# o When "append_dot_mydomain=yes", append ".$mydomain"
# to addresses without ".domain".
#
# ADDRESS EXTENSION
# When a mail address localpart contains the optional recip-
# ient delimiter (e.g., user+foo@domain), the lookup order
# becomes: user+foo@domain, user@domain, user+foo, user, and
# @domain.
#
# The propagate_unmatched_extensions parameter controls
# whether an unmatched address extension (+foo) is propa-
# gated to the result of table lookup.
#
# REGULAR EXPRESSION TABLES
# This section describes how the table lookups change when
# the table is given in the form of regular expressions. For
# a description of regular expression lookup table syntax,
# see regexp_table(5) or pcre_table(5).
#
# Each pattern is a regular expression that is applied to
# the entire address being looked up. Thus, user@domain mail
# addresses are not broken up into their user and @domain
# constituent parts, nor is user+foo broken up into user and
# foo.
#
# Patterns are applied in the order as specified in the ta-
# ble, until a pattern is found that matches the search
# string.
#
# Results are the same as with indexed file lookups, with
# the additional feature that parenthesized substrings from
# the pattern can be interpolated as $1, $2 and so on.
#
# TCP-BASED TABLES
# This section describes how the table lookups change when
# lookups are directed to a TCP-based server. For a descrip-
# tion of the TCP client/server lookup protocol, see tcp_ta-
# ble(5). This feature is not available up to and including
# Postfix version 2.4.
#
# Each lookup operation uses the entire address once. Thus,
# user@domain mail addresses are not broken up into their
# user and @domain constituent parts, nor is user+foo broken
# up into user and foo.
#
# Results are the same as with indexed file lookups.
#
# BUGS
# The table format does not understand quoting conventions.
#
# CONFIGURATION PARAMETERS
# The following main.cf parameters are especially relevant.
# The text below provides only a parameter summary. See
# postconf(5) for more details including examples.
#
# canonical_classes
# What addresses are subject to canonical address
# mapping.
#
# canonical_maps
# List of canonical mapping tables.
#
# recipient_canonical_maps
# Address mapping lookup table for envelope and
# header recipient addresses.
#
# sender_canonical_maps
# Address mapping lookup table for envelope and
# header sender addresses.
#
# propagate_unmatched_extensions
# A list of address rewriting or forwarding mecha-
# nisms that propagate an address extension from the
# original address to the result. Specify zero or
# more of canonical, virtual, alias, forward,
# include, or generic.
#
# Other parameters of interest:
#
# inet_interfaces
# The network interface addresses that this system
# receives mail on. You need to stop and start Post-
# fix when this parameter changes.
#
# local_header_rewrite_clients
# Rewrite message header addresses in mail from these
# clients and update incomplete addresses with the
# domain name in $myorigin or $mydomain; either don't
# rewrite message headers from other clients at all,
# or rewrite message headers and update incomplete
# addresses with the domain specified in the
# remote_header_rewrite_domain parameter.
#
# proxy_interfaces
# Other interfaces that this machine receives mail on
# by way of a proxy agent or network address transla-
# tor.
#
# masquerade_classes
# List of address classes subject to masquerading:
# zero or more of envelope_sender, envelope_recipi-
# ent, header_sender, header_recipient.
#
# masquerade_domains
# List of domains that hide their subdomain struc-
# ture.
#
# masquerade_exceptions
# List of user names that are not subject to address
# masquerading.
#
# mydestination
# List of domains that this mail system considers
# local.
#
# myorigin
# The domain that is appended to locally-posted mail.
#
# owner_request_special
# Give special treatment to owner-xxx and xxx-request
# addresses.
#
# remote_header_rewrite_domain
# Don't rewrite message headers from remote clients
# at all when this parameter is empty; otherwise, re-
# write message headers and append the specified
# domain name to incomplete addresses.
#
# SEE ALSO
# cleanup(8), canonicalize and enqueue mail
# postmap(1), Postfix lookup table manager
# postconf(5), configuration parameters
# virtual(5), virtual aliasing
#
# README FILES
# Use "postconf readme_directory" or "postconf html_direc-
# tory" to locate this information.
# DATABASE_README, Postfix lookup table overview
# ADDRESS_REWRITING_README, address rewriting guide
#
# LICENSE
# The Secure Mailer license must be distributed with this
# software.
#
# AUTHOR(S)
# Wietse Venema
# IBM T.J. Watson Research
# P.O. Box 704
# Yorktown Heights, NY 10598, USA
#
# CANONICAL(5)

View File

@@ -1,21 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIDizCCAnOgAwIBAgIJAIJuX7vycgv0MA0GCSqGSIb3DQEBCwUAMFwxCzAJBgNV
BAYTAlVTMQ8wDQYDVQQIDAZEZW5pYWwxFDASBgNVBAcMC1NwcmluZ2ZpZWxkMQww
CgYDVQQKDANEaXMxGDAWBgNVBAMMD3d3dy5leGFtcGxlLmNvbTAeFw0xNzEwMTEw
ODU3MzVaFw0yNzEwMDkwODU3MzVaMFwxCzAJBgNVBAYTAlVTMQ8wDQYDVQQIDAZE
ZW5pYWwxFDASBgNVBAcMC1NwcmluZ2ZpZWxkMQwwCgYDVQQKDANEaXMxGDAWBgNV
BAMMD3d3dy5leGFtcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
ggEBANokcgV4eK3soeeLSuBP2Qi55RO/RSS53TQV7NpxgiKkKRYoMoUz7Hh1Vdc8
nV7LfKYWxECzvBUWbRFrgYE768WI3HUcFGdtxm62Nskg+IL5Ik403dQ5QOZFKykX
X9vEpBmGTgsOaP1fnaeV7qa69w666Wp1HrAul7MPi/uUklBDfjubGiZUD52pYEPD
C/3N/+fH6rd6O7HzZMWpNSd4Yic3XBQjPmFRO33gmJDM5NEAIt026XI4n8AzQYI2
VmgeGRax5vrs8hMPjM8QkAeUrWcmMkwa2hcVPrxKFu/kgvduP9RtoD0/n5M6Bhpc
n1Jma6T1XmiKtbNqK5ToaAebS4MCAwEAAaNQME4wHQYDVR0OBBYEFAMyeCibjAJR
cp3wpZhTwWwXWsnoMB8GA1UdIwQYMBaAFAMyeCibjAJRcp3wpZhTwWwXWsnoMAwG
A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAKE+Dgv4hwhX0HGQ8oi1a5VN
ij0uIn/hDmWPXVH5TxtPSR/GcjWH6csRl1VuSrXAxhppopD2NpvyUgOhvH7ZaY2C
8BUs+KrQ4dB2ipW5MPgl7CfzAGip7/LzCFKdn26YBViNwAn8pwIJd79XcuhmbxzL
N3zUQXv2uDSo6i7jkxlTglnsqP9N9/GdaVaNmcGGblAfXbiZGGa8/uboz3WdDO3c
sIGf9J7RNrn0Q9Xq6K7Xk9qV8QOVVxp/ClwsG1Tq6ZR362wG44YBYc0H7/3AuySu
p73fSvjg7cOzcG1z66Tiafpiqtfu6fWmDkZAVctH8NSf8wCfzwL+jgygo7NSLB8=
-----END CERTIFICATE-----

View File

@@ -1,4 +0,0 @@
driver = mysql
connect = host=127.0.0.1 dbname=cyberpanel user=cyberpanel password=1qaz@9xvps
password_query = SELECT email as user, password FROM e_users WHERE email='%u';
user_query = SELECT '5000' as uid, '5000' as gid, mail FROM e_users WHERE email='%u';

View File

@@ -1,85 +0,0 @@
protocols = imap pop3
log_timestamp = "%Y-%m-%d %H:%M:%S "
#mail_location = maildir:/home/vmail/%d/%n/Maildir
#mail_location = mdbox:/home/vmail/%d/%n/Mdbox
ssl_cert = <cert.pem
ssl_key = <key.pem
mail_plugins = zlib
mdbox_rotate_size = 2M
namespace {
type = private
separator = .
prefix = INBOX.
inbox = yes
}
service auth {
unix_listener auth-master {
mode = 0600
user = vmail
}
unix_listener /var/spool/postfix/private/auth {
mode = 0666
user = postfix
group = postfix
}
user = root
}
service auth-worker {
user = root
}
protocol lda {
log_path = /home/vmail/dovecot-deliver.log
auth_socket_path = /var/run/dovecot/auth-master
postmaster_address = postmaster@example.com
mail_plugins = zlib
}
protocol pop3 {
pop3_uidl_format = %08Xu%08Xv
mail_plugins = $mail_plugins zlib
}
protocol imap {
mail_plugins = $mail_plugins zlib imap_zlib
}
passdb {
driver = sql
args = /etc/dovecot/dovecot-sql.conf.ext
}
userdb {
driver = sql
args = /etc/dovecot/dovecot-sql.conf.ext
}
plugin {
zlib_save = gz
zlib_save_level = 6
}
service stats {
unix_listener stats-reader {
user = vmail
group = vmail
mode = 0660
}
unix_listener stats-writer {
user = vmail
group = vmail
mode = 0660
}
}

View File

@@ -1,240 +0,0 @@
# GENERIC(5) GENERIC(5)
#
# NAME
# generic - Postfix generic table format
#
# SYNOPSIS
# postmap /etc/postfix/generic
#
# postmap -q "string" /etc/postfix/generic
#
# postmap -q - /etc/postfix/generic <inputfile
#
# DESCRIPTION
# The optional generic(5) table specifies an address mapping
# that applies when mail is delivered. This is the opposite
# of canonical(5) mapping, which applies when mail is
# received.
#
# Typically, one would use the generic(5) table on a system
# that does not have a valid Internet domain name and that
# uses something like localdomain.local instead. The
# generic(5) table is then used by the smtp(8) client to
# transform local mail addresses into valid Internet mail
# addresses when mail has to be sent across the Internet.
# See the EXAMPLE section at the end of this document.
#
# The generic(5) mapping affects both message header
# addresses (i.e. addresses that appear inside messages) and
# message envelope addresses (for example, the addresses
# that are used in SMTP protocol commands).
#
# Normally, the generic(5) table is specified as a text file
# that serves as input to the postmap(1) command. The
# result, an indexed file in dbm or db format, is used for
# fast searching by the mail system. Execute the command
# "postmap /etc/postfix/generic" to rebuild an indexed file
# after changing the corresponding text file.
#
# When the table is provided via other means such as NIS,
# LDAP or SQL, the same lookups are done as for ordinary
# indexed files.
#
# Alternatively, the table can be provided as a regular-
# expression map where patterns are given as regular expres-
# sions, or lookups can be directed to TCP-based server. In
# those case, the lookups are done in a slightly different
# way as described below under "REGULAR EXPRESSION TABLES"
# or "TCP-BASED TABLES".
#
# CASE FOLDING
# The search string is folded to lowercase before database
# lookup. As of Postfix 2.3, the search string is not case
# folded with database types such as regexp: or pcre: whose
# lookup fields can match both upper and lower case.
#
# TABLE FORMAT
# The input format for the postmap(1) command is as follows:
#
# pattern result
# When pattern matches a mail address, replace it by
# the corresponding result.
#
# blank lines and comments
# Empty lines and whitespace-only lines are ignored,
# as are lines whose first non-whitespace character
# is a `#'.
#
# multi-line text
# A logical line starts with non-whitespace text. A
# line that starts with whitespace continues a logi-
# cal line.
#
# TABLE SEARCH ORDER
# With lookups from indexed files such as DB or DBM, or from
# networked tables such as NIS, LDAP or SQL, patterns are
# tried in the order as listed below:
#
# user@domain address
# Replace user@domain by address. This form has the
# highest precedence.
#
# user address
# Replace user@site by address when site is equal to
# $myorigin, when site is listed in $mydestination,
# or when it is listed in $inet_interfaces or
# $proxy_interfaces.
#
# @domain address
# Replace other addresses in domain by address. This
# form has the lowest precedence.
#
# RESULT ADDRESS REWRITING
# The lookup result is subject to address rewriting:
#
# o When the result has the form @otherdomain, the
# result becomes the same user in otherdomain.
#
# o When "append_at_myorigin=yes", append "@$myorigin"
# to addresses without "@domain".
#
# o When "append_dot_mydomain=yes", append ".$mydomain"
# to addresses without ".domain".
#
# ADDRESS EXTENSION
# When a mail address localpart contains the optional recip-
# ient delimiter (e.g., user+foo@domain), the lookup order
# becomes: user+foo@domain, user@domain, user+foo, user, and
# @domain.
#
# The propagate_unmatched_extensions parameter controls
# whether an unmatched address extension (+foo) is propa-
# gated to the result of table lookup.
#
# REGULAR EXPRESSION TABLES
# This section describes how the table lookups change when
# the table is given in the form of regular expressions. For
# a description of regular expression lookup table syntax,
# see regexp_table(5) or pcre_table(5).
#
# Each pattern is a regular expression that is applied to
# the entire address being looked up. Thus, user@domain mail
# addresses are not broken up into their user and @domain
# constituent parts, nor is user+foo broken up into user and
# foo.
#
# Patterns are applied in the order as specified in the ta-
# ble, until a pattern is found that matches the search
# string.
#
# Results are the same as with indexed file lookups, with
# the additional feature that parenthesized substrings from
# the pattern can be interpolated as $1, $2 and so on.
#
# TCP-BASED TABLES
# This section describes how the table lookups change when
# lookups are directed to a TCP-based server. For a descrip-
# tion of the TCP client/server lookup protocol, see tcp_ta-
# ble(5). This feature is not available up to and including
# Postfix version 2.4.
#
# Each lookup operation uses the entire address once. Thus,
# user@domain mail addresses are not broken up into their
# user and @domain constituent parts, nor is user+foo broken
# up into user and foo.
#
# Results are the same as with indexed file lookups.
#
# EXAMPLE
# The following shows a generic mapping with an indexed
# file. When mail is sent to a remote host via SMTP, this
# replaces his@localdomain.local by his ISP mail address,
# replaces her@localdomain.local by her ISP mail address,
# and replaces other local addresses by his ISP account,
# with an address extension of +local (this example assumes
# that the ISP supports "+" style address extensions).
#
# /etc/postfix/main.cf:
# smtp_generic_maps = hash:/etc/postfix/generic
#
# /etc/postfix/generic:
# his@localdomain.local hisaccount@hisisp.example
# her@localdomain.local heraccount@herisp.example
# @localdomain.local hisaccount+local@hisisp.example
#
# Execute the command "postmap /etc/postfix/generic" when-
# ever the table is changed. Instead of hash, some systems
# use dbm database files. To find out what tables your sys-
# tem supports use the command "postconf -m".
#
# BUGS
# The table format does not understand quoting conventions.
#
# CONFIGURATION PARAMETERS
# The following main.cf parameters are especially relevant.
# The text below provides only a parameter summary. See
# postconf(5) for more details including examples.
#
# smtp_generic_maps
# Address mapping lookup table for envelope and
# header sender and recipient addresses while deliv-
# ering mail via SMTP.
#
# propagate_unmatched_extensions
# A list of address rewriting or forwarding mecha-
# nisms that propagate an address extension from the
# original address to the result. Specify zero or
# more of canonical, virtual, alias, forward,
# include, or generic.
#
# Other parameters of interest:
#
# inet_interfaces
# The network interface addresses that this system
# receives mail on. You need to stop and start Post-
# fix when this parameter changes.
#
# proxy_interfaces
# Other interfaces that this machine receives mail on
# by way of a proxy agent or network address transla-
# tor.
#
# mydestination
# List of domains that this mail system considers
# local.
#
# myorigin
# The domain that is appended to locally-posted mail.
#
# owner_request_special
# Give special treatment to owner-xxx and xxx-request
# addresses.
#
# SEE ALSO
# postmap(1), Postfix lookup table manager
# postconf(5), configuration parameters
# smtp(8), Postfix SMTP client
#
# README FILES
# Use "postconf readme_directory" or "postconf html_direc-
# tory" to locate this information.
# ADDRESS_REWRITING_README, address rewriting guide
# DATABASE_README, Postfix lookup table overview
# STANDARD_CONFIGURATION_README, configuration examples
#
# LICENSE
# The Secure Mailer license must be distributed with this
# software.
#
# HISTORY
# A genericstable feature appears in the Sendmail MTA.
#
# This feature is available in Postfix 2.2 and later.
#
# AUTHOR(S)
# Wietse Venema
# IBM T.J. Watson Research
# P.O. Box 704
# Yorktown Heights, NY 10598, USA
#
# GENERIC(5)

View File

@@ -1,496 +0,0 @@
# HEADER_CHECKS(5) HEADER_CHECKS(5)
#
# NAME
# header_checks - Postfix built-in content inspection
#
# SYNOPSIS
# header_checks = pcre:/etc/postfix/header_checks
# mime_header_checks = pcre:/etc/postfix/mime_header_checks
# nested_header_checks = pcre:/etc/postfix/nested_header_checks
# body_checks = pcre:/etc/postfix/body_checks
#
# milter_header_checks = pcre:/etc/postfix/milter_header_checks
#
# smtp_header_checks = pcre:/etc/postfix/smtp_header_checks
# smtp_mime_header_checks = pcre:/etc/postfix/smtp_mime_header_checks
# smtp_nested_header_checks = pcre:/etc/postfix/smtp_nested_header_checks
# smtp_body_checks = pcre:/etc/postfix/smtp_body_checks
#
# postmap -q "string" pcre:/etc/postfix/filename
# postmap -q - pcre:/etc/postfix/filename <inputfile
#
# DESCRIPTION
# This document describes access control on the content of
# message headers and message body lines; it is implemented
# by the Postfix cleanup(8) server before mail is queued.
# See access(5) for access control on remote SMTP client
# information.
#
# Each message header or message body line is compared
# against a list of patterns. When a match is found the
# corresponding action is executed, and the matching process
# is repeated for the next message header or message body
# line.
#
# Note: message headers are examined one logical header at a
# time, even when a message header spans multiple lines.
# Body lines are always examined one line at a time.
#
# For examples, see the EXAMPLES section at the end of this
# manual page.
#
# Postfix header or body_checks are designed to stop a flood
# of mail from worms or viruses; they do not decode attach-
# ments, and they do not unzip archives. See the documents
# referenced below in the README FILES section if you need
# more sophisticated content analysis.
#
# FILTERS WHILE RECEIVING MAIL
# Postfix implements the following four built-in content
# inspection classes while receiving mail:
#
# header_checks (default: empty)
# These are applied to initial message headers
# (except for the headers that are processed with
# mime_header_checks).
#
# mime_header_checks (default: $header_checks)
# These are applied to MIME related message headers
# only.
#
# This feature is available in Postfix 2.0 and later.
#
# nested_header_checks (default: $header_checks)
# These are applied to message headers of attached
# email messages (except for the headers that are
# processed with mime_header_checks).
#
# This feature is available in Postfix 2.0 and later.
#
# body_checks
# These are applied to all other content, including
# multi-part message boundaries.
#
# With Postfix versions before 2.0, all content after
# the initial message headers is treated as body con-
# tent.
#
# FILTERS AFTER RECEIVING MAIL
# Postfix supports a subset of the built-in content inspec-
# tion classes after the message is received:
#
# milter_header_checks (default: empty)
# These are applied to headers that are added with
# Milter applications.
#
# This feature is available in Postfix 2.7 and later.
#
# FILTERS WHILE DELIVERING MAIL
# Postfix supports all four content inspection classes while
# delivering mail via SMTP.
#
# smtp_header_checks (default: empty)
#
# smtp_mime_header_checks (default: empty)
#
# smtp_nested_header_checks (default: empty)
#
# smtp_body_checks (default: empty)
# These features are available in Postfix 2.5 and
# later.
#
# COMPATIBILITY
# With Postfix version 2.2 and earlier specify "postmap -fq"
# to query a table that contains case sensitive patterns. By
# default, regexp: and pcre: patterns are case insensitive.
#
# TABLE FORMAT
# This document assumes that header and body_checks rules
# are specified in the form of Postfix regular expression
# lookup tables. Usually the best performance is obtained
# with pcre (Perl Compatible Regular Expression) tables. The
# regexp (POSIX regular expressions) tables are usually
# slower, but more widely available. Use the command "post-
# conf -m" to find out what lookup table types your Postfix
# system supports.
#
# The general format of Postfix regular expression tables is
# given below. For a discussion of specific pattern or
# flags syntax, see pcre_table(5) or regexp_table(5),
# respectively.
#
# /pattern/flags action
# When /pattern/ matches the input string, execute
# the corresponding action. See below for a list of
# possible actions.
#
# !/pattern/flags action
# When /pattern/ does not match the input string,
# execute the corresponding action.
#
# if /pattern/flags
#
# endif Match the input string against the patterns between
# if and endif, if and only if the same input string
# also matches /pattern/. The if..endif can nest.
#
# Note: do not prepend whitespace to patterns inside
# if..endif.
#
# if !/pattern/flags
#
# endif Match the input string against the patterns between
# if and endif, if and only if the same input string
# does not match /pattern/. The if..endif can nest.
#
# blank lines and comments
# Empty lines and whitespace-only lines are ignored,
# as are lines whose first non-whitespace character
# is a `#'.
#
# multi-line text
# A pattern/action line starts with non-whitespace
# text. A line that starts with whitespace continues
# a logical line.
#
# TABLE SEARCH ORDER
# For each line of message input, the patterns are applied
# in the order as specified in the table. When a pattern is
# found that matches the input line, the corresponding
# action is executed and then the next input line is
# inspected.
#
# TEXT SUBSTITUTION
# Substitution of substrings from the matched expression
# into the action string is possible using the conventional
# Perl syntax ($1, $2, etc.). The macros in the result
# string may need to be written as ${n} or $(n) if they
# aren't followed by whitespace.
#
# Note: since negated patterns (those preceded by !) return
# a result when the expression does not match, substitutions
# are not available for negated patterns.
#
# ACTIONS
# Action names are case insensitive. They are shown in upper
# case for consistency with other Postfix documentation.
#
# DISCARD optional text...
# Claim successful delivery and silently discard the
# message. Log the optional text if specified, oth-
# erwise log a generic message.
#
# Note: this action disables further header or
# body_checks inspection of the current message and
# affects all recipients. To discard only one recip-
# ient without discarding the entire message, use the
# transport(5) table to direct mail to the discard(8)
# service.
#
# This feature is available in Postfix 2.0 and later.
#
# This feature is not supported with smtp header/body
# checks.
#
# DUNNO Pretend that the input line did not match any pat-
# tern, and inspect the next input line. This action
# can be used to shorten the table search.
#
# For backwards compatibility reasons, Postfix also
# accepts OK but it is (and always has been) treated
# as DUNNO.
#
# This feature is available in Postfix 2.1 and later.
#
# FILTER transport:destination
# After the message is queued, send the entire mes-
# sage through the specified external content filter.
# The transport name specifies the first field of a
# mail delivery agent definition in master.cf; the
# syntax of the next-hop destination is described in
# the manual page of the corresponding delivery
# agent. More information about external content
# filters is in the Postfix FILTER_README file.
#
# Note 1: do not use $number regular expression sub-
# stitutions for transport or destination unless you
# know that the information has a trusted origin.
#
# Note 2: this action overrides the main.cf con-
# tent_filter setting, and affects all recipients of
# the message. In the case that multiple FILTER
# actions fire, only the last one is executed.
#
# Note 3: the purpose of the FILTER command is to
# override message routing. To override the recipi-
# ent's transport but not the next-hop destination,
# specify an empty filter destination (Postfix 2.7
# and later), or specify a transport:destination that
# delivers through a different Postfix instance
# (Postfix 2.6 and earlier). Other options are using
# the recipient-dependent transport_maps or the sen-
# der-dependent sender_dependent_default_transport-
# _maps features.
#
# This feature is available in Postfix 2.0 and later.
#
# This feature is not supported with smtp header/body
# checks.
#
# HOLD optional text...
# Arrange for the message to be placed on the hold
# queue, and inspect the next input line. The mes-
# sage remains on hold until someone either deletes
# it or releases it for delivery. Log the optional
# text if specified, otherwise log a generic message.
#
# Mail that is placed on hold can be examined with
# the postcat(1) command, and can be destroyed or
# released with the postsuper(1) command.
#
# Note: use "postsuper -r" to release mail that was
# kept on hold for a significant fraction of $maxi-
# mal_queue_lifetime or $bounce_queue_lifetime, or
# longer. Use "postsuper -H" only for mail that will
# not expire within a few delivery attempts.
#
# Note: this action affects all recipients of the
# message.
#
# This feature is available in Postfix 2.0 and later.
#
# This feature is not supported with smtp header/body
# checks.
#
# IGNORE Delete the current line from the input, and inspect
# the next input line.
#
# INFO optional text...
# Log an "info:" record with the optional text... (or
# log a generic text), and inspect the next input
# line. This action is useful for routine logging or
# for debugging.
#
# This feature is available in Postfix 2.8 and later.
#
# PREPEND text...
# Prepend one line with the specified text, and
# inspect the next input line.
#
# Notes:
#
# o The prepended text is output on a separate
# line, immediately before the input that
# triggered the PREPEND action.
#
# o The prepended text is not considered part of
# the input stream: it is not subject to
# header/body checks or address rewriting, and
# it does not affect the way that Postfix adds
# missing message headers.
#
# o When prepending text before a message header
# line, the prepended text must begin with a
# valid message header label.
#
# o This action cannot be used to prepend multi-
# line text.
#
# This feature is available in Postfix 2.1 and later.
#
# This feature is not supported with mil-
# ter_header_checks.
#
# REDIRECT user@domain
# Write a message redirection request to the queue
# file, and inspect the next input line. After the
# message is queued, it will be sent to the specified
# address instead of the intended recipient(s).
#
# Note: this action overrides the FILTER action, and
# affects all recipients of the message. If multiple
# REDIRECT actions fire, only the last one is exe-
# cuted.
#
# This feature is available in Postfix 2.1 and later.
#
# This feature is not supported with smtp header/body
# checks.
#
# REPLACE text...
# Replace the current line with the specified text,
# and inspect the next input line.
#
# This feature is available in Postfix 2.2 and later.
# The description below applies to Postfix 2.2.2 and
# later.
#
# Notes:
#
# o When replacing a message header line, the
# replacement text must begin with a valid
# header label.
#
# o The replaced text remains part of the input
# stream. Unlike the result from the PREPEND
# action, a replaced message header may be
# subject to address rewriting and may affect
# the way that Postfix adds missing message
# headers.
#
# REJECT optional text...
# Reject the entire message. Reply with optional
# text... when the optional text is specified, other-
# wise reply with a generic error message.
#
# Note: this action disables further header or
# body_checks inspection of the current message and
# affects all recipients.
#
# Postfix version 2.3 and later support enhanced sta-
# tus codes. When no code is specified at the begin-
# ning of optional text..., Postfix inserts a default
# enhanced status code of "5.7.1".
#
# This feature is not supported with smtp header/body
# checks.
#
# WARN optional text...
# Log a "warning:" record with the optional text...
# (or log a generic text), and inspect the next input
# line. This action is useful for debugging and for
# testing a pattern before applying more drastic
# actions.
#
# BUGS
# Empty lines never match, because some map types mis-behave
# when given a zero-length search string. This limitation
# may be removed for regular expression tables in a future
# release.
#
# Many people overlook the main limitations of header and
# body_checks rules.
#
# o These rules operate on one logical message header
# or one body line at a time. A decision made for one
# line is not carried over to the next line.
#
# o If text in the message body is encoded (RFC 2045)
# then the rules need to be specified for the encoded
# form.
#
# o Likewise, when message headers are encoded (RFC
# 2047) then the rules need to be specified for the
# encoded form.
#
# Message headers added by the cleanup(8) daemon itself are
# excluded from inspection. Examples of such message headers
# are From:, To:, Message-ID:, Date:.
#
# Message headers deleted by the cleanup(8) daemon will be
# examined before they are deleted. Examples are: Bcc:, Con-
# tent-Length:, Return-Path:.
#
# CONFIGURATION PARAMETERS
# body_checks
# Lookup tables with content filter rules for message
# body lines. These filters see one physical line at
# a time, in chunks of at most $line_length_limit
# bytes.
#
# body_checks_size_limit
# The amount of content per message body segment
# (attachment) that is subjected to $body_checks fil-
# tering.
#
# header_checks
#
# mime_header_checks (default: $header_checks)
#
# nested_header_checks (default: $header_checks)
# Lookup tables with content filter rules for message
# header lines: respectively, these are applied to
# the initial message headers (not including MIME
# headers), to the MIME headers anywhere in the mes-
# sage, and to the initial headers of attached mes-
# sages.
#
# Note: these filters see one logical message header
# at a time, even when a message header spans multi-
# ple lines. Message headers that are longer than
# $header_size_limit characters are truncated.
#
# disable_mime_input_processing
# While receiving mail, give no special treatment to
# MIME related message headers; all text after the
# initial message headers is considered to be part of
# the message body. This means that header_checks is
# applied to all the initial message headers, and
# that body_checks is applied to the remainder of the
# message.
#
# Note: when used in this manner, body_checks will
# process a multi-line message header one line at a
# time.
#
# EXAMPLES
# Header pattern to block attachments with bad file name
# extensions. For convenience, the PCRE /x flag is speci-
# fied, so that there is no need to collapse the pattern
# into a single line of text. The purpose of the
# [[:xdigit:]] sub-expressions is to recognize Windows CLSID
# strings.
#
# /etc/postfix/main.cf:
# header_checks = pcre:/etc/postfix/header_checks.pcre
#
# /etc/postfix/header_checks.pcre:
# /^Content-(Disposition|Type).*name\s*=\s*"?(.*(\.|=2E)(
# ade|adp|asp|bas|bat|chm|cmd|com|cpl|crt|dll|exe|
# hlp|ht[at]|
# inf|ins|isp|jse?|lnk|md[betw]|ms[cipt]|nws|
# \{[[:xdigit:]]{8}(?:-[[:xdigit:]]{4}){3}-[[:xdigit:]]{12}\}|
# ops|pcd|pif|prf|reg|sc[frt]|sh[bsm]|swf|
# vb[esx]?|vxd|ws[cfh]))(\?=)?"?\s*(;|$)/x
# REJECT Attachment name "$2" may not end with ".$4"
#
# Body pattern to stop a specific HTML browser vulnerability
# exploit.
#
# /etc/postfix/main.cf:
# body_checks = regexp:/etc/postfix/body_checks
#
# /etc/postfix/body_checks:
# /^<iframe src=(3D)?cid:.* height=(3D)?0 width=(3D)?0>$/
# REJECT IFRAME vulnerability exploit
#
# SEE ALSO
# cleanup(8), canonicalize and enqueue Postfix message
# pcre_table(5), format of PCRE lookup tables
# regexp_table(5), format of POSIX regular expression tables
# postconf(1), Postfix configuration utility
# postmap(1), Postfix lookup table management
# postsuper(1), Postfix janitor
# postcat(1), show Postfix queue file contents
# RFC 2045, base64 and quoted-printable encoding rules
# RFC 2047, message header encoding for non-ASCII text
#
# README FILES
# Use "postconf readme_directory" or "postconf html_direc-
# tory" to locate this information.
# DATABASE_README, Postfix lookup table overview
# CONTENT_INSPECTION_README, Postfix content inspection overview
# BUILTIN_FILTER_README, Postfix built-in content inspection
# BACKSCATTER_README, blocking returned forged mail
#
# LICENSE
# The Secure Mailer license must be distributed with this
# software.
#
# AUTHOR(S)
# Wietse Venema
# IBM T.J. Watson Research
# P.O. Box 704
# Yorktown Heights, NY 10598, USA
#
# HEADER_CHECKS(5)

View File

@@ -1,28 +0,0 @@
-----BEGIN PRIVATE KEY-----
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDaJHIFeHit7KHn
i0rgT9kIueUTv0Ukud00FezacYIipCkWKDKFM+x4dVXXPJ1ey3ymFsRAs7wVFm0R
a4GBO+vFiNx1HBRnbcZutjbJIPiC+SJONN3UOUDmRSspF1/bxKQZhk4LDmj9X52n
le6muvcOuulqdR6wLpezD4v7lJJQQ347mxomVA+dqWBDwwv9zf/nx+q3ejux82TF
qTUneGInN1wUIz5hUTt94JiQzOTRACLdNulyOJ/AM0GCNlZoHhkWseb67PITD4zP
EJAHlK1nJjJMGtoXFT68Shbv5IL3bj/UbaA9P5+TOgYaXJ9SZmuk9V5oirWzaiuU
6GgHm0uDAgMBAAECggEBANN6h6u0ClKa2K8vw+xInKCwD1wgjvi207M+Gjv/1Oie
e1KGr8ug9fwlzI14rxwKbBJcefA8DvfmoOBFd+yA2ebL8uX5zfIjYz9LmTtNon7e
5hopeHDY/IkAv4H7rivRrEEuihR/6NrSSnYAjbfIA+Gc5NMXLiQhV2H5jXzdoSb7
LLbsi294f2F91anUspecM/Hk5/W4JOSllY8RtLWKTxqLN22ujnvZKFqMNB/RH3d1
HrFc6jbn8Nb6C5B5VnSBw64RNbpZbCYntbDmb4DCp/+Z2llFNrFM1XxjaJBsrHnJ
ZTGoVIPCo1DClP/YUEUP0RTIoM/LUJwfma2hq9MrQ3ECgYEA+pCyx+MnZPog7yLD
paR4h4Eb37majfhILO1wJRXGnmCzkp63MOLxSEZIc/JvePlS6FYRdy/F1N6NnST2
Z2PO6JaDWxDJOhcc8QSswQsTNkUKjdygbqw4adraltriheCy/9pI131MoMLBYPdg
Rvnw2CrPNGwwdm3Wq64fGnL0m8sCgYEA3t+20ft4QqjMYgdNL/HHPiMpgdEIEdNN
F+wMxhxcHKI2uR/ZMGGq7AauQcxtNfoPZbQkjKwUSnkJEf6lk5Gr6hb9bz1yviu6
NycnxlWvXiqz+Sql2e8xqSdtsw2Vuv+vPBSiUdAz4vRO3MmL8KBfmY8WG+XP78bF
HvXSetqwCCkCgYEA0GAhrgYErv8tAHKizlA3RElkyuvp0oNWUraresvfP7sf26FO
q8Mv8XExs+s8NRjzj/Bz2fDKzzq9/p/MozLn0ZnKZ6NQFZU/JllC6c+yDIHiQxPl
/+QNjkrJWodxtvClLA12Ym77mP4eH+vaD2ywlLUVWH1Y2ESEMIY/q5lKP30CgYEA
kFO/SGvYjRJSiIjB63Je3FZY4sBCwYhcPEmYXBKxc7l4RpnhQ/t7fC03W1TOxE2S
+wGVSaOF4FRRE14cS1viQE1zAT6Bt7UJef3ZPA7w6cItmgWMMX08Y5Ys6+64L8iz
6exS0ThK4YXkLAY4oTK5te97GcXQyi2mKU53ZyeHJ0ECgYAtqdndLIkiirXplJ10
9VkrDKZG/Zsqm7vQjl//ZPIDzWcwo3ehBvyt4U+mnjUt+WQ4+YpmZ8mxIv486ZsI
2GqNZVrtKE+p2llmXYIw87/NofMB+D5AfodYzjJElO+X4YQSkCQIcZOVyL2BDBs5
D5SV7kNMb2fRDwK1/mmYBscfEw==
-----END PRIVATE KEY-----

View File

@@ -1,66 +0,0 @@
# Global Postfix configuration file. This file lists only a subset
# of all parameters. For the syntax, and for a complete parameter
# list, see the postconf(5) manual page (command: "man 5 postconf").
#
# For common configuration examples, see BASIC_CONFIGURATION_README
# and STANDARD_CONFIGURATION_README. To find these documents, use
# the command "postconf html_directory readme_directory", or go to
# http://www.postfix.org/.
#
# For best results, change no more than 2-3 parameters at a time,
# and test if Postfix still works after every change.
queue_directory = /var/spool/postfix
command_directory = /usr/sbin
daemon_directory = /usr/libexec/postfix
data_directory = /var/lib/postfix
mail_owner = postfix
inet_protocols = all
mydestination = localhost, localhost.localdomain, [::1]
unknown_local_recipient_reject_code = 550
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
debug_peer_level = 2
debugger_command =
PATH=/bin:/usr/bin:/usr/local/bin:/usr/X11R6/bin
ddd $daemon_directory/$process_name $process_id & sleep 5
sendmail_path = /usr/sbin/sendmail.postfix
newaliases_path = /usr/bin/newaliases.postfix
mailq_path = /usr/bin/mailq.postfix
setgid_group = postdrop
html_directory = no
manpage_directory = /usr/share/man
sample_directory = /usr/share/doc/postfix-2.10.1/samples
readme_directory = /usr/share/doc/postfix-2.10.1/README_FILES
myhostname = server.example.com
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
message_size_limit = 30720000
virtual_alias_domains =
virtual_alias_maps = proxy:mysql:/etc/postfix/mysql-virtual_forwardings.cf, mysql:/etc/postfix/mysql-virtual_email2email.cf
virtual_mailbox_domains = proxy:mysql:/etc/postfix/mysql-virtual_domains.cf
virtual_mailbox_maps = proxy:mysql:/etc/postfix/mysql-virtual_mailboxes.cf
virtual_mailbox_base = /home/vmail
virtual_uid_maps = static:5000
virtual_gid_maps = static:5000
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_auth_enable = yes
broken_sasl_auth_clients = yes
smtpd_sasl_authenticated_header = yes
smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination
smtpd_use_tls = yes
smtpd_tls_cert_file = /etc/pki/dovecot/certs/dovecot.pem
smtpd_tls_key_file = /etc/pki/dovecot/private/dovecot.pem
virtual_create_maildirsize = yes
virtual_maildir_extended = yes
proxy_read_maps = $local_recipient_maps $mydestination $virtual_alias_maps $virtual_alias_domains $virtual_mailbox_maps $virtual_mailbox_domains $relay_recipient_maps $relay_domains $canonical_maps $sender_canonical_maps $recipient_canonical_maps $relocated_maps $transport_maps $mynetworks $virtual_mailbox_limit_maps
virtual_transport = dovecot
dovecot_destination_recipient_limit = 1
inet_interfaces = all
smtp_tls_security_level = may
disable_vrfy_command = yes

View File

@@ -1,129 +0,0 @@
#
# Postfix master process configuration file. For details on the format
# of the file, see the master(5) manual page (command: "man 5 master").
#
# Do not forget to execute "postfix reload" after editing this file.
#
# ==========================================================================
# service type private unpriv chroot wakeup maxproc command + args
# (yes) (yes) (yes) (never) (100)
# ==========================================================================
smtp inet n - n - - smtpd
#smtp inet n - n - 1 postscreen
#smtpd pass - - n - - smtpd
#dnsblog unix - - n - 0 dnsblog
#tlsproxy unix - - n - 0 tlsproxy
submission inet n - n - - smtpd
-o syslog_name=postfix/submission
-o smtpd_tls_security_level=encrypt
-o smtpd_sasl_auth_enable=yes
-o smtpd_reject_unlisted_recipient=no
-o smtpd_client_restrictions=$mua_client_restrictions
-o smtpd_helo_restrictions=$mua_helo_restrictions
-o smtpd_sender_restrictions=$mua_sender_restrictions
-o smtpd_recipient_restrictions=permit_sasl_authenticated,reject
-o milter_macro_daemon_name=ORIGINATING
smtps inet n - n - - smtpd
-o syslog_name=postfix/smtps
-o smtpd_tls_wrappermode=yes
-o smtpd_sasl_auth_enable=yes
-o smtpd_reject_unlisted_recipient=no
-o smtpd_client_restrictions=$mua_client_restrictions
-o smtpd_helo_restrictions=$mua_helo_restrictions
-o smtpd_sender_restrictions=$mua_sender_restrictions
-o smtpd_recipient_restrictions=permit_sasl_authenticated,reject
-o milter_macro_daemon_name=ORIGINATING
#628 inet n - n - - qmqpd
pickup unix n - n 60 1 pickup
cleanup unix n - n - 0 cleanup
qmgr unix n - n 300 1 qmgr
#qmgr unix n - n 300 1 oqmgr
tlsmgr unix - - n 1000? 1 tlsmgr
rewrite unix - - n - - trivial-rewrite
bounce unix - - n - 0 bounce
defer unix - - n - 0 bounce
trace unix - - n - 0 bounce
verify unix - - n - 1 verify
flush unix n - n 1000? 0 flush
proxymap unix - - n - - proxymap
proxywrite unix - - n - 1 proxymap
smtp unix - - n - - smtp
relay unix - - n - - smtp
# -o smtp_helo_timeout=5 -o smtp_connect_timeout=5
showq unix n - n - - showq
error unix - - n - - error
retry unix - - n - - error
discard unix - - n - - discard
local unix - n n - - local
virtual unix - n n - - virtual
lmtp unix - - n - - lmtp
anvil unix - - n - 1 anvil
scache unix - - n - 1 scache
#
# ====================================================================
# Interfaces to non-Postfix software. Be sure to examine the manual
# pages of the non-Postfix software to find out what options it wants.
#
# Many of the following services use the Postfix pipe(8) delivery
# agent. See the pipe(8) man page for information about ${recipient}
# and other message envelope options.
# ====================================================================
#
# maildrop. See the Postfix MAILDROP_README file for details.
# Also specify in main.cf: maildrop_destination_recipient_limit=1
#
#maildrop unix - n n - - pipe
# flags=DRhu user=vmail argv=/usr/local/bin/maildrop -d ${recipient}
#
# ====================================================================
#
# Recent Cyrus versions can use the existing "lmtp" master.cf entry.
#
# Specify in cyrus.conf:
# lmtp cmd="lmtpd -a" listen="localhost:lmtp" proto=tcp4
#
# Specify in main.cf one or more of the following:
# mailbox_transport = lmtp:inet:localhost
# virtual_transport = lmtp:inet:localhost
#
# ====================================================================
#
# Cyrus 2.1.5 (Amos Gouaux)
# Also specify in main.cf: cyrus_destination_recipient_limit=1
#
#cyrus unix - n n - - pipe
# user=cyrus argv=/usr/lib/cyrus-imapd/deliver -e -r ${sender} -m ${extension} ${user}
#
# ====================================================================
#
# Old example of delivery via Cyrus.
#
#old-cyrus unix - n n - - pipe
# flags=R user=cyrus argv=/usr/lib/cyrus-imapd/deliver -e -m ${extension} ${user}
#
# ====================================================================
#
# See the Postfix UUCP_README file for configuration details.
#
#uucp unix - n n - - pipe
# flags=Fqhu user=uucp argv=uux -r -n -z -a$sender - $nexthop!rmail ($recipient)
#
# ====================================================================
#
# Other external delivery methods.
#
#ifmail unix - n n - - pipe
# flags=F user=ftn argv=/usr/lib/ifmail/ifmail -r $nexthop ($recipient)
#
#bsmtp unix - n n - - pipe
# flags=Fq. user=bsmtp argv=/usr/local/sbin/bsmtp -f $sender $nexthop $recipient
#
#scalemail-backend unix - n n - 2 pipe
# flags=R user=scalemail argv=/usr/lib/scalemail/bin/scalemail-store
# ${nexthop} ${user} ${extension}
#
#mailman unix - n n - - pipe
# flags=FR user=list argv=/usr/lib/mailman/bin/postfix-to-mailman.py
# ${nexthop} ${user}
dovecot unix - n n - - pipe
flags=DRhu user=vmail:vmail argv=/usr/libexec/dovecot/deliver -f ${sender} -d ${recipient}

View File

@@ -1,5 +0,0 @@
user = cyberpanel
password = 1qaz@9xvps
dbname = cyberpanel
query = SELECT domain AS virtual FROM e_domains WHERE domain='%s'
hosts = 127.0.0.1:3307

View File

@@ -1,5 +0,0 @@
user = cyberpanel
password = 1qaz@9xvps
dbname = cyberpanel
query = SELECT email FROM e_users WHERE email='%s'
hosts = 127.0.0.1:3307

View File

@@ -1,5 +0,0 @@
user = cyberpanel
password = 1qaz@9xvps
dbname = cyberpanel
query = SELECT destination FROM e_forwardings WHERE source='%s'
hosts = 127.0.0.1:3307

View File

@@ -1,5 +0,0 @@
user = cyberpanel
password = 1qaz@9xvps
dbname = cyberpanel
query = SELECT CONCAT(SUBSTRING_INDEX(email,'@',-1),'/',SUBSTRING_INDEX(email,'@',1),'/') FROM e_users WHERE email='%s'
hosts = 127.0.0.1:3307

View File

@@ -1,171 +0,0 @@
# RELOCATED(5) RELOCATED(5)
#
# NAME
# relocated - Postfix relocated table format
#
# SYNOPSIS
# postmap /etc/postfix/relocated
#
# DESCRIPTION
# The optional relocated(5) table provides the information
# that is used in "user has moved to new_location" bounce
# messages.
#
# Normally, the relocated(5) table is specified as a text
# file that serves as input to the postmap(1) command. The
# result, an indexed file in dbm or db format, is used for
# fast searching by the mail system. Execute the command
# "postmap /etc/postfix/relocated" to rebuild an indexed
# file after changing the corresponding relocated table.
#
# When the table is provided via other means such as NIS,
# LDAP or SQL, the same lookups are done as for ordinary
# indexed files.
#
# Alternatively, the table can be provided as a regular-
# expression map where patterns are given as regular expres-
# sions, or lookups can be directed to TCP-based server. In
# those case, the lookups are done in a slightly different
# way as described below under "REGULAR EXPRESSION TABLES"
# or "TCP-BASED TABLES".
#
# Table lookups are case insensitive.
#
# CASE FOLDING
# The search string is folded to lowercase before database
# lookup. As of Postfix 2.3, the search string is not case
# folded with database types such as regexp: or pcre: whose
# lookup fields can match both upper and lower case.
#
# TABLE FORMAT
# The input format for the postmap(1) command is as follows:
#
# o An entry has one of the following form:
#
# pattern new_location
#
# Where new_location specifies contact information
# such as an email address, or perhaps a street
# address or telephone number.
#
# o Empty lines and whitespace-only lines are ignored,
# as are lines whose first non-whitespace character
# is a `#'.
#
# o A logical line starts with non-whitespace text. A
# line that starts with whitespace continues a logi-
# cal line.
#
# TABLE SEARCH ORDER
# With lookups from indexed files such as DB or DBM, or from
# networked tables such as NIS, LDAP or SQL, patterns are
# tried in the order as listed below:
#
# user@domain
# Matches user@domain. This form has precedence over
# all other forms.
#
# user Matches user@site when site is $myorigin, when site
# is listed in $mydestination, or when site is listed
# in $inet_interfaces or $proxy_interfaces.
#
# @domain
# Matches other addresses in domain. This form has
# the lowest precedence.
#
# ADDRESS EXTENSION
# When a mail address localpart contains the optional recip-
# ient delimiter (e.g., user+foo@domain), the lookup order
# becomes: user+foo@domain, user@domain, user+foo, user, and
# @domain.
#
# REGULAR EXPRESSION TABLES
# This section describes how the table lookups change when
# the table is given in the form of regular expressions or
# when lookups are directed to a TCP-based server. For a
# description of regular expression lookup table syntax, see
# regexp_table(5) or pcre_table(5). For a description of the
# TCP client/server table lookup protocol, see tcp_table(5).
# This feature is not available up to and including Postfix
# version 2.4.
#
# Each pattern is a regular expression that is applied to
# the entire address being looked up. Thus, user@domain mail
# addresses are not broken up into their user and @domain
# constituent parts, nor is user+foo broken up into user and
# foo.
#
# Patterns are applied in the order as specified in the ta-
# ble, until a pattern is found that matches the search
# string.
#
# Results are the same as with indexed file lookups, with
# the additional feature that parenthesized substrings from
# the pattern can be interpolated as $1, $2 and so on.
#
# TCP-BASED TABLES
# This section describes how the table lookups change when
# lookups are directed to a TCP-based server. For a descrip-
# tion of the TCP client/server lookup protocol, see tcp_ta-
# ble(5). This feature is not available up to and including
# Postfix version 2.4.
#
# Each lookup operation uses the entire address once. Thus,
# user@domain mail addresses are not broken up into their
# user and @domain constituent parts, nor is user+foo broken
# up into user and foo.
#
# Results are the same as with indexed file lookups.
#
# BUGS
# The table format does not understand quoting conventions.
#
# CONFIGURATION PARAMETERS
# The following main.cf parameters are especially relevant.
# The text below provides only a parameter summary. See
# postconf(5) for more details including examples.
#
# relocated_maps
# List of lookup tables for relocated users or sites.
#
# Other parameters of interest:
#
# inet_interfaces
# The network interface addresses that this system
# receives mail on. You need to stop and start Post-
# fix when this parameter changes.
#
# mydestination
# List of domains that this mail system considers
# local.
#
# myorigin
# The domain that is appended to locally-posted mail.
#
# proxy_interfaces
# Other interfaces that this machine receives mail on
# by way of a proxy agent or network address transla-
# tor.
#
# SEE ALSO
# trivial-rewrite(8), address resolver
# postmap(1), Postfix lookup table manager
# postconf(5), configuration parameters
#
# README FILES
# Use "postconf readme_directory" or "postconf html_direc-
# tory" to locate this information.
# DATABASE_README, Postfix lookup table overview
# ADDRESS_REWRITING_README, address rewriting guide
#
# LICENSE
# The Secure Mailer license must be distributed with this
# software.
#
# AUTHOR(S)
# Wietse Venema
# IBM T.J. Watson Research
# P.O. Box 704
# Yorktown Heights, NY 10598, USA
#
# RELOCATED(5)

View File

@@ -1,294 +0,0 @@
# TRANSPORT(5) TRANSPORT(5)
#
# NAME
# transport - Postfix transport table format
#
# SYNOPSIS
# postmap /etc/postfix/transport
#
# postmap -q "string" /etc/postfix/transport
#
# postmap -q - /etc/postfix/transport <inputfile
#
# DESCRIPTION
# The optional transport(5) table specifies a mapping from
# email addresses to message delivery transports and next-
# hop destinations. Message delivery transports such as
# local or smtp are defined in the master.cf file, and next-
# hop destinations are typically hosts or domain names. The
# table is searched by the trivial-rewrite(8) daemon.
#
# This mapping overrides the default transport:nexthop
# selection that is built into Postfix:
#
# local_transport (default: local:$myhostname)
# This is the default for final delivery to domains
# listed with mydestination, and for [ipaddress] des-
# tinations that match $inet_interfaces or
# $proxy_interfaces. The default nexthop destination
# is the MTA hostname.
#
# virtual_transport (default: virtual:)
# This is the default for final delivery to domains
# listed with virtual_mailbox_domains. The default
# nexthop destination is the recipient domain.
#
# relay_transport (default: relay:)
# This is the default for remote delivery to domains
# listed with relay_domains. In order of decreasing
# precedence, the nexthop destination is taken from
# relay_transport, sender_dependent_relayhost_maps,
# relayhost, or from the recipient domain.
#
# default_transport (default: smtp:)
# This is the default for remote delivery to other
# destinations. In order of decreasing precedence,
# the nexthop destination is taken from sender_depen-
# dent_default_transport_maps, default_transport,
# sender_dependent_relayhost_maps, relayhost, or from
# the recipient domain.
#
# Normally, the transport(5) table is specified as a text
# file that serves as input to the postmap(1) command. The
# result, an indexed file in dbm or db format, is used for
# fast searching by the mail system. Execute the command
# "postmap /etc/postfix/transport" to rebuild an indexed
# file after changing the corresponding transport table.
#
# When the table is provided via other means such as NIS,
# LDAP or SQL, the same lookups are done as for ordinary
# indexed files.
#
# Alternatively, the table can be provided as a regular-
# expression map where patterns are given as regular expres-
# sions, or lookups can be directed to TCP-based server. In
# those case, the lookups are done in a slightly different
# way as described below under "REGULAR EXPRESSION TABLES"
# or "TCP-BASED TABLES".
#
# CASE FOLDING
# The search string is folded to lowercase before database
# lookup. As of Postfix 2.3, the search string is not case
# folded with database types such as regexp: or pcre: whose
# lookup fields can match both upper and lower case.
#
# TABLE FORMAT
# The input format for the postmap(1) command is as follows:
#
# pattern result
# When pattern matches the recipient address or
# domain, use the corresponding result.
#
# blank lines and comments
# Empty lines and whitespace-only lines are ignored,
# as are lines whose first non-whitespace character
# is a `#'.
#
# multi-line text
# A logical line starts with non-whitespace text. A
# line that starts with whitespace continues a logi-
# cal line.
#
# The pattern specifies an email address, a domain name, or
# a domain name hierarchy, as described in section "TABLE
# LOOKUP".
#
# The result is of the form transport:nexthop and specifies
# how or where to deliver mail. This is described in section
# "RESULT FORMAT".
#
# TABLE SEARCH ORDER
# With lookups from indexed files such as DB or DBM, or from
# networked tables such as NIS, LDAP or SQL, patterns are
# tried in the order as listed below:
#
# user+extension@domain transport:nexthop
# Deliver mail for user+extension@domain through
# transport to nexthop.
#
# user@domain transport:nexthop
# Deliver mail for user@domain through transport to
# nexthop.
#
# domain transport:nexthop
# Deliver mail for domain through transport to nex-
# thop.
#
# .domain transport:nexthop
# Deliver mail for any subdomain of domain through
# transport to nexthop. This applies only when the
# string transport_maps is not listed in the par-
# ent_domain_matches_subdomains configuration set-
# ting. Otherwise, a domain name matches itself and
# its subdomains.
#
# * transport:nexthop
# The special pattern * represents any address (i.e.
# it functions as the wild-card pattern, and is
# unique to Postfix transport tables).
#
# Note 1: the null recipient address is looked up as
# $empty_address_recipient@$myhostname (default: mailer-dae-
# mon@hostname).
#
# Note 2: user@domain or user+extension@domain lookup is
# available in Postfix 2.0 and later.
#
# RESULT FORMAT
# The lookup result is of the form transport:nexthop. The
# transport field specifies a mail delivery transport such
# as smtp or local. The nexthop field specifies where and
# how to deliver mail.
#
# The transport field specifies the name of a mail delivery
# transport (the first name of a mail delivery service entry
# in the Postfix master.cf file).
#
# The interpretation of the nexthop field is transport
# dependent. In the case of SMTP, specify a service on a
# non-default port as host:service, and disable MX (mail
# exchanger) DNS lookups with [host] or [host]:port. The []
# form is required when you specify an IP address instead of
# a hostname.
#
# A null transport and null nexthop result means "do not
# change": use the delivery transport and nexthop informa-
# tion that would be used when the entire transport table
# did not exist.
#
# A non-null transport field with a null nexthop field
# resets the nexthop information to the recipient domain.
#
# A null transport field with non-null nexthop field does
# not modify the transport information.
#
# EXAMPLES
# In order to deliver internal mail directly, while using a
# mail relay for all other mail, specify a null entry for
# internal destinations (do not change the delivery trans-
# port or the nexthop information) and specify a wildcard
# for all other destinations.
#
# my.domain :
# .my.domain :
# * smtp:outbound-relay.my.domain
#
# In order to send mail for example.com and its subdomains
# via the uucp transport to the UUCP host named example:
#
# example.com uucp:example
# .example.com uucp:example
#
# When no nexthop host name is specified, the destination
# domain name is used instead. For example, the following
# directs mail for user@example.com via the slow transport
# to a mail exchanger for example.com. The slow transport
# could be configured to run at most one delivery process at
# a time:
#
# example.com slow:
#
# When no transport is specified, Postfix uses the transport
# that matches the address domain class (see DESCRIPTION
# above). The following sends all mail for example.com and
# its subdomains to host gateway.example.com:
#
# example.com :[gateway.example.com]
# .example.com :[gateway.example.com]
#
# In the above example, the [] suppress MX lookups. This
# prevents mail routing loops when your machine is primary
# MX host for example.com.
#
# In the case of delivery via SMTP, one may specify host-
# name:service instead of just a host:
#
# example.com smtp:bar.example:2025
#
# This directs mail for user@example.com to host bar.example
# port 2025. Instead of a numerical port a symbolic name may
# be used. Specify [] around the hostname if MX lookups must
# be disabled.
#
# The error mailer can be used to bounce mail:
#
# .example.com error:mail for *.example.com is not deliverable
#
# This causes all mail for user@anything.example.com to be
# bounced.
#
# REGULAR EXPRESSION TABLES
# This section describes how the table lookups change when
# the table is given in the form of regular expressions. For
# a description of regular expression lookup table syntax,
# see regexp_table(5) or pcre_table(5).
#
# Each pattern is a regular expression that is applied to
# the entire address being looked up. Thus,
# some.domain.hierarchy is not looked up via its parent
# domains, nor is user+foo@domain looked up as user@domain.
#
# Patterns are applied in the order as specified in the ta-
# ble, until a pattern is found that matches the search
# string.
#
# The trivial-rewrite(8) server disallows regular expression
# substitution of $1 etc. in regular expression lookup
# tables, because that could open a security hole (Postfix
# version 2.3 and later).
#
# TCP-BASED TABLES
# This section describes how the table lookups change when
# lookups are directed to a TCP-based server. For a descrip-
# tion of the TCP client/server lookup protocol, see tcp_ta-
# ble(5). This feature is not available up to and including
# Postfix version 2.4.
#
# Each lookup operation uses the entire recipient address
# once. Thus, some.domain.hierarchy is not looked up via
# its parent domains, nor is user+foo@domain looked up as
# user@domain.
#
# Results are the same as with indexed file lookups.
#
# CONFIGURATION PARAMETERS
# The following main.cf parameters are especially relevant.
# The text below provides only a parameter summary. See
# postconf(5) for more details including examples.
#
# empty_address_recipient
# The address that is looked up instead of the null
# sender address.
#
# parent_domain_matches_subdomains
# List of Postfix features that use domain.tld pat-
# terns to match sub.domain.tld (as opposed to
# requiring .domain.tld patterns).
#
# transport_maps
# List of transport lookup tables.
#
# SEE ALSO
# trivial-rewrite(8), rewrite and resolve addresses
# master(5), master.cf file format
# postconf(5), configuration parameters
# postmap(1), Postfix lookup table manager
#
# README FILES
# Use "postconf readme_directory" or "postconf html_direc-
# tory" to locate this information.
# ADDRESS_REWRITING_README, address rewriting guide
# DATABASE_README, Postfix lookup table overview
# FILTER_README, external content filter
#
# LICENSE
# The Secure Mailer license must be distributed with this
# software.
#
# AUTHOR(S)
# Wietse Venema
# IBM T.J. Watson Research
# P.O. Box 704
# Yorktown Heights, NY 10598, USA
#
# TRANSPORT(5)

View File

@@ -1,294 +0,0 @@
# VIRTUAL(5) VIRTUAL(5)
#
# NAME
# virtual - Postfix virtual alias table format
#
# SYNOPSIS
# postmap /etc/postfix/virtual
#
# postmap -q "string" /etc/postfix/virtual
#
# postmap -q - /etc/postfix/virtual <inputfile
#
# DESCRIPTION
# The optional virtual(5) alias table rewrites recipient
# addresses for all local, all virtual, and all remote mail
# destinations. This is unlike the aliases(5) table which
# is used only for local(8) delivery. Virtual aliasing is
# recursive, and is implemented by the Postfix cleanup(8)
# daemon before mail is queued.
#
# The main applications of virtual aliasing are:
#
# o To redirect mail for one address to one or more
# addresses.
#
# o To implement virtual alias domains where all
# addresses are aliased to addresses in other
# domains.
#
# Virtual alias domains are not to be confused with
# the virtual mailbox domains that are implemented
# with the Postfix virtual(8) mail delivery agent.
# With virtual mailbox domains, each recipient
# address can have its own mailbox.
#
# Virtual aliasing is applied only to recipient envelope
# addresses, and does not affect message headers. Use
# canonical(5) mapping to rewrite header and envelope
# addresses in general.
#
# Normally, the virtual(5) alias table is specified as a
# text file that serves as input to the postmap(1) command.
# The result, an indexed file in dbm or db format, is used
# for fast searching by the mail system. Execute the command
# "postmap /etc/postfix/virtual" to rebuild an indexed file
# after changing the corresponding text file.
#
# When the table is provided via other means such as NIS,
# LDAP or SQL, the same lookups are done as for ordinary
# indexed files.
#
# Alternatively, the table can be provided as a regular-
# expression map where patterns are given as regular expres-
# sions, or lookups can be directed to TCP-based server. In
# those case, the lookups are done in a slightly different
# way as described below under "REGULAR EXPRESSION TABLES"
# or "TCP-BASED TABLES".
#
# CASE FOLDING
# The search string is folded to lowercase before database
# lookup. As of Postfix 2.3, the search string is not case
# folded with database types such as regexp: or pcre: whose
# lookup fields can match both upper and lower case.
#
# TABLE FORMAT
# The input format for the postmap(1) command is as follows:
#
# pattern result
# When pattern matches a mail address, replace it by
# the corresponding result.
#
# blank lines and comments
# Empty lines and whitespace-only lines are ignored,
# as are lines whose first non-whitespace character
# is a `#'.
#
# multi-line text
# A logical line starts with non-whitespace text. A
# line that starts with whitespace continues a logi-
# cal line.
#
# TABLE SEARCH ORDER
# With lookups from indexed files such as DB or DBM, or from
# networked tables such as NIS, LDAP or SQL, patterns are
# tried in the order as listed below:
#
# user@domain address, address, ...
# Redirect mail for user@domain to address. This
# form has the highest precedence.
#
# user address, address, ...
# Redirect mail for user@site to address when site is
# equal to $myorigin, when site is listed in $mydes-
# tination, or when it is listed in $inet_interfaces
# or $proxy_interfaces.
#
# This functionality overlaps with functionality of
# the local aliases(5) database. The difference is
# that virtual(5) mapping can be applied to non-local
# addresses.
#
# @domain address, address, ...
# Redirect mail for other users in domain to address.
# This form has the lowest precedence.
#
# Note: @domain is a wild-card. With this form, the
# Postfix SMTP server accepts mail for any recipient
# in domain, regardless of whether that recipient
# exists. This may turn your mail system into a
# backscatter source: Postfix first accepts mail for
# non-existent recipients and then tries to return
# that mail as "undeliverable" to the often forged
# sender address.
#
# RESULT ADDRESS REWRITING
# The lookup result is subject to address rewriting:
#
# o When the result has the form @otherdomain, the
# result becomes the same user in otherdomain. This
# works only for the first address in a multi-address
# lookup result.
#
# o When "append_at_myorigin=yes", append "@$myorigin"
# to addresses without "@domain".
#
# o When "append_dot_mydomain=yes", append ".$mydomain"
# to addresses without ".domain".
#
# ADDRESS EXTENSION
# When a mail address localpart contains the optional recip-
# ient delimiter (e.g., user+foo@domain), the lookup order
# becomes: user+foo@domain, user@domain, user+foo, user, and
# @domain.
#
# The propagate_unmatched_extensions parameter controls
# whether an unmatched address extension (+foo) is propa-
# gated to the result of table lookup.
#
# VIRTUAL ALIAS DOMAINS
# Besides virtual aliases, the virtual alias table can also
# be used to implement virtual alias domains. With a virtual
# alias domain, all recipient addresses are aliased to
# addresses in other domains.
#
# Virtual alias domains are not to be confused with the vir-
# tual mailbox domains that are implemented with the Postfix
# virtual(8) mail delivery agent. With virtual mailbox
# domains, each recipient address can have its own mailbox.
#
# With a virtual alias domain, the virtual domain has its
# own user name space. Local (i.e. non-virtual) usernames
# are not visible in a virtual alias domain. In particular,
# local aliases(5) and local mailing lists are not visible
# as localname@virtual-alias.domain.
#
# Support for a virtual alias domain looks like:
#
# /etc/postfix/main.cf:
# virtual_alias_maps = hash:/etc/postfix/virtual
#
# Note: some systems use dbm databases instead of hash. See
# the output from "postconf -m" for available database
# types.
#
# /etc/postfix/virtual:
# virtual-alias.domain anything (right-hand content does not matter)
# postmaster@virtual-alias.domain postmaster
# user1@virtual-alias.domain address1
# user2@virtual-alias.domain address2, address3
#
# The virtual-alias.domain anything entry is required for a
# virtual alias domain. Without this entry, mail is rejected
# with "relay access denied", or bounces with "mail loops
# back to myself".
#
# Do not specify virtual alias domain names in the main.cf
# mydestination or relay_domains configuration parameters.
#
# With a virtual alias domain, the Postfix SMTP server
# accepts mail for known-user@virtual-alias.domain, and
# rejects mail for unknown-user@virtual-alias.domain as
# undeliverable.
#
# Instead of specifying the virtual alias domain name via
# the virtual_alias_maps table, you may also specify it via
# the main.cf virtual_alias_domains configuration parameter.
# This latter parameter uses the same syntax as the main.cf
# mydestination configuration parameter.
#
# REGULAR EXPRESSION TABLES
# This section describes how the table lookups change when
# the table is given in the form of regular expressions. For
# a description of regular expression lookup table syntax,
# see regexp_table(5) or pcre_table(5).
#
# Each pattern is a regular expression that is applied to
# the entire address being looked up. Thus, user@domain mail
# addresses are not broken up into their user and @domain
# constituent parts, nor is user+foo broken up into user and
# foo.
#
# Patterns are applied in the order as specified in the ta-
# ble, until a pattern is found that matches the search
# string.
#
# Results are the same as with indexed file lookups, with
# the additional feature that parenthesized substrings from
# the pattern can be interpolated as $1, $2 and so on.
#
# TCP-BASED TABLES
# This section describes how the table lookups change when
# lookups are directed to a TCP-based server. For a descrip-
# tion of the TCP client/server lookup protocol, see tcp_ta-
# ble(5). This feature is not available up to and including
# Postfix version 2.4.
#
# Each lookup operation uses the entire address once. Thus,
# user@domain mail addresses are not broken up into their
# user and @domain constituent parts, nor is user+foo broken
# up into user and foo.
#
# Results are the same as with indexed file lookups.
#
# BUGS
# The table format does not understand quoting conventions.
#
# CONFIGURATION PARAMETERS
# The following main.cf parameters are especially relevant
# to this topic. See the Postfix main.cf file for syntax
# details and for default values. Use the "postfix reload"
# command after a configuration change.
#
# virtual_alias_maps
# List of virtual aliasing tables.
#
# virtual_alias_domains
# List of virtual alias domains. This uses the same
# syntax as the mydestination parameter.
#
# propagate_unmatched_extensions
# A list of address rewriting or forwarding mecha-
# nisms that propagate an address extension from the
# original address to the result. Specify zero or
# more of canonical, virtual, alias, forward,
# include, or generic.
#
# Other parameters of interest:
#
# inet_interfaces
# The network interface addresses that this system
# receives mail on. You need to stop and start Post-
# fix when this parameter changes.
#
# mydestination
# List of domains that this mail system considers
# local.
#
# myorigin
# The domain that is appended to any address that
# does not have a domain.
#
# owner_request_special
# Give special treatment to owner-xxx and xxx-request
# addresses.
#
# proxy_interfaces
# Other interfaces that this machine receives mail on
# by way of a proxy agent or network address transla-
# tor.
#
# SEE ALSO
# cleanup(8), canonicalize and enqueue mail
# postmap(1), Postfix lookup table manager
# postconf(5), configuration parameters
# canonical(5), canonical address mapping
#
# README FILES
# Use "postconf readme_directory" or "postconf html_direc-
# tory" to locate this information.
# ADDRESS_REWRITING_README, address rewriting guide
# DATABASE_README, Postfix lookup table overview
# VIRTUAL_README, domain hosting guide
#
# LICENSE
# The Secure Mailer license must be distributed with this
# software.
#
# AUTHOR(S)
# Wietse Venema
# IBM T.J. Watson Research
# P.O. Box 704
# Yorktown Heights, NY 10598, USA
#
# VIRTUAL(5)

View File

@@ -3595,7 +3595,7 @@ class Migration(migrations.Migration):
command = "chown -R root:root /usr/local/lscp"
preFlightsChecks.call(command, self.distro, command, command, 1, 0, os.EX_OSERR)
command = "chown -R lscpd:lscpd /usr/local/lscp/cyberpanel/rainloop"
command = "chown -R lscpd:lscpd /usr/local/lscp/cyberpanel/snappymail"
preFlightsChecks.call(command, self.distro, command, command, 1, 0, os.EX_OSERR)
command = "chmod 700 /usr/local/CyberCP/cli/cyberPanel.py"
@@ -4583,15 +4583,15 @@ user_query = SELECT email as user, password, 'vmail' as uid, 'vmail' as gid, '/h
command = "chown -R lscpd:lscpd /usr/local/CyberCP/public/snappymail/data || true"
preFlightsChecks.call(command, self.distro, command, command, 1, 0, os.EX_OSERR)
command = "mkdir -p /usr/local/lscp/cyberpanel/rainloop/data"
command = "mkdir -p /usr/local/lscp/cyberpanel/snappymail/data"
preFlightsChecks.call(command, self.distro, command, command, 1, 0, os.EX_OSERR)
### Enable sub-folders
command = "mkdir -p /usr/local/lscp/cyberpanel/rainloop/data/_data_/_default_/configs/"
command = "mkdir -p /usr/local/lscp/cyberpanel/snappymail/data/_data_/_default_/configs/"
preFlightsChecks.call(command, self.distro, command, command, 1, 0, os.EX_OSERR)
# labsPath = '/usr/local/lscp/cyberpanel/rainloop/data/_data_/_default_/configs/application.ini'
# labsPath = '/usr/local/lscp/cyberpanel/snappymail/data/_data_/_default_/configs/application.ini'
#
# labsData = """[labs]
# imap_folder_list_limit = 0
@@ -4612,7 +4612,7 @@ user_query = SELECT email as user, password, 'vmail' as uid, 'vmail' as gid, '/h
# for items in data:
# if items.find("$sCustomDataPath = '';") > -1:
# writeToFile.writelines(
# " $sCustomDataPath = '/usr/local/lscp/cyberpanel/rainloop/data';\n")
# " $sCustomDataPath = '/usr/local/lscp/cyberpanel/snappymail/data';\n")
# else:
# writeToFile.writelines(items)
#
@@ -4623,7 +4623,7 @@ user_query = SELECT email as user, password, 'vmail' as uid, 'vmail' as gid, '/h
#
# if os.path.exists(includeFileOldPath):
# writeToFile = open(includeFileOldPath, 'a')
# writeToFile.write("\ndefine('APP_DATA_FOLDER_PATH', '/usr/local/lscp/cyberpanel/rainloop/data/');\n")
# writeToFile.write("\ndefine('APP_DATA_FOLDER_PATH', '/usr/local/lscp/cyberpanel/snappymail/data/');\n")
# writeToFile.close()
#
# command = 'mv %s %s' % (includeFileOldPath, includeFileNewPath)
@@ -4635,22 +4635,22 @@ user_query = SELECT email as user, password, 'vmail' as uid, 'vmail' as gid, '/h
#
# ### now download and install actual plugin
#
# command = f'mkdir /usr/local/lscp/cyberpanel/rainloop/data/_data_/_default_/plugins/mailbox-detect'
# command = f'mkdir /usr/local/lscp/cyberpanel/snappymail/data/_data_/_default_/plugins/mailbox-detect'
# preFlightsChecks.call(command, self.distro, command, command, 1, 0, os.EX_OSERR)
#
# command = f'chmod 700 /usr/local/lscp/cyberpanel/rainloop/data/_data_/_default_/plugins/mailbox-detect'
# command = f'chmod 700 /usr/local/lscp/cyberpanel/snappymail/data/_data_/_default_/plugins/mailbox-detect'
# preFlightsChecks.call(command, self.distro, command, command, 1, 0, os.EX_OSERR)
#
# command = f'chmod 700 /usr/local/lscp/cyberpanel/rainloop/data/_data_/_default_/plugins/mailbox-detect'
# command = f'chmod 700 /usr/local/lscp/cyberpanel/snappymail/data/_data_/_default_/plugins/mailbox-detect'
# preFlightsChecks.call(command, self.distro, command, command, 1, 0, os.EX_OSERR)
#
# command = f'wget -O /usr/local/lscp/cyberpanel/rainloop/data/_data_/_default_/plugins/mailbox-detect/index.php https://raw.githubusercontent.com/the-djmaze/snappymail/master/plugins/mailbox-detect/index.php'
# command = f'wget -O /usr/local/lscp/cyberpanel/snappymail/data/_data_/_default_/plugins/mailbox-detect/index.php https://raw.githubusercontent.com/the-djmaze/snappymail/master/plugins/mailbox-detect/index.php'
# preFlightsChecks.call(command, self.distro, command, command, 1, 0, os.EX_OSERR)
#
# command = f'chmod 644 /usr/local/lscp/cyberpanel/rainloop/data/_data_/_default_/plugins/mailbox-detect/index.php'
# command = f'chmod 644 /usr/local/lscp/cyberpanel/snappymail/data/_data_/_default_/plugins/mailbox-detect/index.php'
# preFlightsChecks.call(command, self.distro, command, command, 1, 0, os.EX_OSERR)
#
# command = f'chown lscpd:lscpd /usr/local/lscp/cyberpanel/rainloop/data/_data_/_default_/plugins/mailbox-detect/index.php'
# command = f'chown lscpd:lscpd /usr/local/lscp/cyberpanel/snappymail/data/_data_/_default_/plugins/mailbox-detect/index.php'
# preFlightsChecks.call(command, self.distro, command, command, 1, 0, os.EX_OSERR)
#
# ### Enable plugins and enable mailbox creation plugin
@@ -4674,7 +4674,7 @@ user_query = SELECT email as user, password, 'vmail' as uid, 'vmail' as gid, '/h
# WriteToFile.close()
#
# ## enable auto create in the enabled plugin
# PluginsFilePath = '/usr/local/lscp/cyberpanel/rainloop/data/_data_/_default_/configs/plugin-mailbox-detect.json'
# PluginsFilePath = '/usr/local/lscp/cyberpanel/snappymail/data/_data_/_default_/configs/plugin-mailbox-detect.json'
#
# WriteToFile = open(PluginsFilePath, 'w')
# WriteToFile.write("""{

File diff suppressed because it is too large Load Diff

View File

@@ -1,424 +0,0 @@
; Start a new pool named 'www'.
; the variable $pool can we used in any directive and will be replaced by the
; pool name ('www' here)
[www]
; Per pool prefix
; It only applies on the following directives:
; - 'access.log'
; - 'slowlog'
; - 'listen' (unixsocket)
; - 'chroot'
; - 'chdir'
; - 'php_values'
; - 'php_admin_values'
; When not set, the global prefix (or @php_fpm_prefix@) applies instead.
; Note: This directive can also be relative to the global prefix.
; Default Value: none
;prefix = /path/to/pools/$pool
; Unix user/group of processes
; Note: The user is mandatory. If the group is not set, the default user's group
; will be used.
user = nginx
group = nginx
; The address on which to accept FastCGI requests.
; Valid syntaxes are:
; 'ip.add.re.ss:port' - to listen on a TCP socket to a specific IPv4 address on
; a specific port;
; '[ip:6:addr:ess]:port' - to listen on a TCP socket to a specific IPv6 address on
; a specific port;
; 'port' - to listen on a TCP socket to all IPv4 addresses on a
; specific port;
; '[::]:port' - to listen on a TCP socket to all addresses
; (IPv6 and IPv4-mapped) on a specific port;
; '/path/to/unix/socket' - to listen on a unix socket.
; Note: This value is mandatory.
listen = 127.0.0.1:9000
; WARNING: If you switch to a unix socket, you have to grant your webserver user
; access to that socket by setting listen.acl_users to the webserver user.
;
listen = /run/php-fpm/www.sock
; Set listen(2) backlog.
; Default Value: 65535 (-1 on FreeBSD and OpenBSD)
;listen.backlog = 65535
; Set permissions for unix socket, if one is used. In Linux, read/write
; permissions must be set in order to allow connections from a web server. Many
; BSD-derived systems allow connections regardless of permissions.
; Default Values: user and group are set as the running user
; mode is set to 0660
listen.owner = root
listen.group = root
;listen.mode = 0660
; When POSIX Access Control Lists are supported you can set them using
; these options, value is a comma separated list of user/group names.
; When set, listen.owner and listen.group are ignored
;listen.acl_users = apache,nginx
;listen.acl_users = apache
;listen.acl_users = nginx
;listen.acl_groups =
; List of addresses (IPv4/IPv6) of FastCGI clients which are allowed to connect.
; Equivalent to the FCGI_WEB_SERVER_ADDRS environment variable in the original
; PHP FCGI (5.2.2+). Makes sense only with a tcp listening socket. Each address
; must be separated by a comma. If this value is left blank, connections will be
; accepted from any ip address.
; Default Value: any
listen.allowed_clients = 127.0.0.1
; Specify the nice(2) priority to apply to the pool processes (only if set)
; The value can vary from -19 (highest priority) to 20 (lower priority)
; Note: - It will only work if the FPM master process is launched as root
; - The pool processes will inherit the master process priority
; unless it specified otherwise
; Default Value: no set
; process.priority = -19
; Choose how the process manager will control the number of child processes.
; Possible Values:
; static - a fixed number (pm.max_children) of child processes;
; dynamic - the number of child processes are set dynamically based on the
; following directives. With this process management, there will be
; always at least 1 children.
; pm.max_children - the maximum number of children that can
; be alive at the same time.
; pm.start_servers - the number of children created on startup.
; pm.min_spare_servers - the minimum number of children in 'idle'
; state (waiting to process). If the number
; of 'idle' processes is less than this
; number then some children will be created.
; pm.max_spare_servers - the maximum number of children in 'idle'
; state (waiting to process). If the number
; of 'idle' processes is greater than this
; number then some children will be killed.
; ondemand - no children are created at startup. Children will be forked when
; new requests will connect. The following parameter are used:
; pm.max_children - the maximum number of children that
; can be alive at the same time.
; pm.process_idle_timeout - The number of seconds after which
; an idle process will be killed.
; Note: This value is mandatory.
pm = dynamic
; The number of child processes to be created when pm is set to 'static' and the
; maximum number of child processes when pm is set to 'dynamic' or 'ondemand'.
; This value sets the limit on the number of simultaneous requests that will be
; served. Equivalent to the ApacheMaxClients directive with mpm_prefork.
; Equivalent to the PHP_FCGI_CHILDREN environment variable in the original PHP
; CGI. The below defaults are based on a server without much resources. Don't
; forget to tweak pm.* to fit your needs.
; Note: Used when pm is set to 'static', 'dynamic' or 'ondemand'
; Note: This value is mandatory.
pm.max_children = 50
; The number of child processes created on startup.
; Note: Used only when pm is set to 'dynamic'
; Default Value: min_spare_servers + (max_spare_servers - min_spare_servers) / 2
pm.start_servers = 5
; The desired minimum number of idle server processes.
; Note: Used only when pm is set to 'dynamic'
; Note: Mandatory when pm is set to 'dynamic'
pm.min_spare_servers = 5
; The desired maximum number of idle server processes.
; Note: Used only when pm is set to 'dynamic'
; Note: Mandatory when pm is set to 'dynamic'
pm.max_spare_servers = 35
; The number of seconds after which an idle process will be killed.
; Note: Used only when pm is set to 'ondemand'
; Default Value: 10s
;pm.process_idle_timeout = 10s;
; The number of requests each child process should execute before respawning.
; This can be useful to work around memory leaks in 3rd party libraries. For
; endless request processing specify '0'. Equivalent to PHP_FCGI_MAX_REQUESTS.
; Default Value: 0
;pm.max_requests = 500
; The URI to view the FPM status page. If this value is not set, no URI will be
; recognized as a status page. It shows the following informations:
; pool - the name of the pool;
; process manager - static, dynamic or ondemand;
; start time - the date and time FPM has started;
; start since - number of seconds since FPM has started;
; accepted conn - the number of request accepted by the pool;
; listen queue - the number of request in the queue of pending
; connections (see backlog in listen(2));
; max listen queue - the maximum number of requests in the queue
; of pending connections since FPM has started;
; listen queue len - the size of the socket queue of pending connections;
; idle processes - the number of idle processes;
; active processes - the number of active processes;
; total processes - the number of idle + active processes;
; max active processes - the maximum number of active processes since FPM
; has started;
; max children reached - number of times, the process limit has been reached,
; when pm tries to start more children (works only for
; pm 'dynamic' and 'ondemand');
; Value are updated in real time.
; Example output:
; pool: www
; process manager: static
; start time: 01/Jul/2011:17:53:49 +0200
; start since: 62636
; accepted conn: 190460
; listen queue: 0
; max listen queue: 1
; listen queue len: 42
; idle processes: 4
; active processes: 11
; total processes: 15
; max active processes: 12
; max children reached: 0
;
; By default the status page output is formatted as text/plain. Passing either
; 'html', 'xml' or 'json' in the query string will return the corresponding
; output syntax. Example:
; http://www.foo.bar/status
; http://www.foo.bar/status?json
; http://www.foo.bar/status?html
; http://www.foo.bar/status?xml
;
; By default the status page only outputs short status. Passing 'full' in the
; query string will also return status for each pool process.
; Example:
; http://www.foo.bar/status?full
; http://www.foo.bar/status?json&full
; http://www.foo.bar/status?html&full
; http://www.foo.bar/status?xml&full
; The Full status returns for each process:
; pid - the PID of the process;
; state - the state of the process (Idle, Running, ...);
; start time - the date and time the process has started;
; start since - the number of seconds since the process has started;
; requests - the number of requests the process has served;
; request duration - the duration in µs of the requests;
; request method - the request method (GET, POST, ...);
; request URI - the request URI with the query string;
; content length - the content length of the request (only with POST);
; user - the user (PHP_AUTH_USER) (or '-' if not set);
; script - the main script called (or '-' if not set);
; last request cpu - the %cpu the last request consumed
; it's always 0 if the process is not in Idle state
; because CPU calculation is done when the request
; processing has terminated;
; last request memory - the max amount of memory the last request consumed
; it's always 0 if the process is not in Idle state
; because memory calculation is done when the request
; processing has terminated;
; If the process is in Idle state, then informations are related to the
; last request the process has served. Otherwise informations are related to
; the current request being served.
; Example output:
; ************************
; pid: 31330
; state: Running
; start time: 01/Jul/2011:17:53:49 +0200
; start since: 63087
; requests: 12808
; request duration: 1250261
; request method: GET
; request URI: /test_mem.php?N=10000
; content length: 0
; user: -
; script: /home/fat/web/docs/php/test_mem.php
; last request cpu: 0.00
; last request memory: 0
;
; Note: There is a real-time FPM status monitoring sample web page available
; It's available in: @EXPANDED_DATADIR@/fpm/status.html
;
; Note: The value must start with a leading slash (/). The value can be
; anything, but it may not be a good idea to use the .php extension or it
; may conflict with a real PHP file.
; Default Value: not set
;pm.status_path = /status
; The ping URI to call the monitoring page of FPM. If this value is not set, no
; URI will be recognized as a ping page. This could be used to test from outside
; that FPM is alive and responding, or to
; - create a graph of FPM availability (rrd or such);
; - remove a server from a group if it is not responding (load balancing);
; - trigger alerts for the operating team (24/7).
; Note: The value must start with a leading slash (/). The value can be
; anything, but it may not be a good idea to use the .php extension or it
; may conflict with a real PHP file.
; Default Value: not set
;ping.path = /ping
; This directive may be used to customize the response of a ping request. The
; response is formatted as text/plain with a 200 response code.
; Default Value: pong
;ping.response = pong
; The access log file
; Default: not set
;access.log = log/$pool.access.log
; The access log format.
; The following syntax is allowed
; %%: the '%' character
; %C: %CPU used by the request
; it can accept the following format:
; - %{user}C for user CPU only
; - %{system}C for system CPU only
; - %{total}C for user + system CPU (default)
; %d: time taken to serve the request
; it can accept the following format:
; - %{seconds}d (default)
; - %{miliseconds}d
; - %{mili}d
; - %{microseconds}d
; - %{micro}d
; %e: an environment variable (same as $_ENV or $_SERVER)
; it must be associated with embraces to specify the name of the env
; variable. Some exemples:
; - server specifics like: %{REQUEST_METHOD}e or %{SERVER_PROTOCOL}e
; - HTTP headers like: %{HTTP_HOST}e or %{HTTP_USER_AGENT}e
; %f: script filename
; %l: content-length of the request (for POST request only)
; %m: request method
; %M: peak of memory allocated by PHP
; it can accept the following format:
; - %{bytes}M (default)
; - %{kilobytes}M
; - %{kilo}M
; - %{megabytes}M
; - %{mega}M
; %n: pool name
; %o: output header
; it must be associated with embraces to specify the name of the header:
; - %{Content-Type}o
; - %{X-Powered-By}o
; - %{Transfert-Encoding}o
; - ....
; %p: PID of the child that serviced the request
; %P: PID of the parent of the child that serviced the request
; %q: the query string
; %Q: the '?' character if query string exists
; %r: the request URI (without the query string, see %q and %Q)
; %R: remote IP address
; %s: status (response code)
; %t: server time the request was received
; it can accept a strftime(3) format:
; %d/%b/%Y:%H:%M:%S %z (default)
; %T: time the log has been written (the request has finished)
; it can accept a strftime(3) format:
; %d/%b/%Y:%H:%M:%S %z (default)
; %u: remote user
;
; Default: "%R - %u %t \"%m %r\" %s"
;access.format = "%R - %u %t \"%m %r%Q%q\" %s %f %{mili}d %{kilo}M %C%%"
; The log file for slow requests
; Default Value: not set
; Note: slowlog is mandatory if request_slowlog_timeout is set
slowlog = /var/log/php-fpm/www-slow.log
; The timeout for serving a single request after which a PHP backtrace will be
; dumped to the 'slowlog' file. A value of '0s' means 'off'.
; Available units: s(econds)(default), m(inutes), h(ours), or d(ays)
; Default Value: 0
;request_slowlog_timeout = 0
; The timeout for serving a single request after which the worker process will
; be killed. This option should be used when the 'max_execution_time' ini option
; does not stop script execution for some reason. A value of '0' means 'off'.
; Available units: s(econds)(default), m(inutes), h(ours), or d(ays)
; Default Value: 0
;request_terminate_timeout = 0
; Set open file descriptor rlimit.
; Default Value: system defined value
;rlimit_files = 1024
; Set max core size rlimit.
; Possible Values: 'unlimited' or an integer greater or equal to 0
; Default Value: system defined value
;rlimit_core = 0
; Chroot to this directory at the start. This value must be defined as an
; absolute path. When this value is not set, chroot is not used.
; Note: you can prefix with '$prefix' to chroot to the pool prefix or one
; of its subdirectories. If the pool prefix is not set, the global prefix
; will be used instead.
; Note: chrooting is a great security feature and should be used whenever
; possible. However, all PHP paths will be relative to the chroot
; (error_log, sessions.save_path, ...).
; Default Value: not set
;chroot =
; Chdir to this directory at the start.
; Note: relative path can be used.
; Default Value: current directory or / when chroot
;chdir = /var/www
; Redirect worker stdout and stderr into main error log. If not set, stdout and
; stderr will be redirected to /dev/null according to FastCGI specs.
; Note: on highloaded environement, this can cause some delay in the page
; process time (several ms).
; Default Value: no
;catch_workers_output = yes
; Clear environment in FPM workers
; Prevents arbitrary environment variables from reaching FPM worker processes
; by clearing the environment in workers before env vars specified in this
; pool configuration are added.
; Setting to "no" will make all environment variables available to PHP code
; via getenv(), $_ENV and $_SERVER.
; Default Value: yes
;clear_env = no
; Limits the extensions of the main script FPM will allow to parse. This can
; prevent configuration mistakes on the web server side. You should only limit
; FPM to .php extensions to prevent malicious users to use other extensions to
; exectute php code.
; Note: set an empty value to allow all extensions.
; Default Value: .php
;security.limit_extensions = .php .php3 .php4 .php5
; Pass environment variables like LD_LIBRARY_PATH. All $VARIABLEs are taken from
; the current environment.
; Default Value: clean env
;env[HOSTNAME] = $HOSTNAME
;env[PATH] = /usr/local/bin:/usr/bin:/bin
;env[TMP] = /tmp
;env[TMPDIR] = /tmp
;env[TEMP] = /tmp
; Additional php.ini defines, specific to this pool of workers. These settings
; overwrite the values previously defined in the php.ini. The directives are the
; same as the PHP SAPI:
; php_value/php_flag - you can set classic ini defines which can
; be overwritten from PHP call 'ini_set'.
; php_admin_value/php_admin_flag - these directives won't be overwritten by
; PHP call 'ini_set'
; For php_*flag, valid values are on, off, 1, 0, true, false, yes or no.
; Defining 'extension' will load the corresponding shared extension from
; extension_dir. Defining 'disable_functions' or 'disable_classes' will not
; overwrite previously defined php.ini values, but will append the new value
; instead.
; Note: path INI options can be relative and will be expanded with the prefix
; (pool, global or @prefix@)
; Default Value: nothing is defined by default except the values in php.ini and
; specified at startup with the -d argument
;php_admin_value[sendmail_path] = /usr/sbin/sendmail -t -i -f www@my.domain.com
;php_flag[display_errors] = off
php_admin_value[error_log] = /var/log/php-fpm/www-error.log
php_admin_flag[log_errors] = on
;php_admin_value[memory_limit] = 128M
; Set session path to a directory owned by process user
php_value[session.save_handler] = files
php_value[session.save_path] = /var/www/html
php_value[soap.wsdl_cache_dir] = /var/lib/php-fpm/wsdlcache

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,423 @@
#!/usr/bin/env bash
# install/venvsetup part 1
#!/bin/bash
#CyberPanel installer script for Ubuntu 18.04 and CentOS 7.X
DEV="OFF"
BRANCH="stable"
POSTFIX_VARIABLE="ON"
POWERDNS_VARIABLE="ON"
PUREFTPD_VARIABLE="ON"
PROVIDER="undefined"
SERIAL_NO=""
DIR=$(pwd)
TEMP=$(curl --silent https://cyberpanel.net/version.txt)
CP_VER1=${TEMP:12:3}
CP_VER2=${TEMP:25:1}
SERVER_OS="CentOS"
VERSION="OLS"
LICENSE_KEY=""
KEY_SIZE=""
ADMIN_PASS="1234567"
MEMCACHED="ON"
REDIS="ON"
MARIADB_VER="11.8"
TOTAL_RAM=$(free -m | awk '/Mem\:/ { print $2 }')
# Robust pip install function to handle broken pipe errors
safe_pip_install() {
local pip_cmd="$1"
local requirements_file="$2"
local install_args="$3"
echo "Installing Python packages..."
# Method 1: Install with full error suppression and broken pipe handling
if timeout 300 $pip_cmd $install_args -r "$requirements_file" --quiet --no-warn-script-location --disable-pip-version-check 2>/dev/null || true; then
echo "✅ Package installation completed successfully"
return 0
fi
# Method 2: Install with even more aggressive error suppression
echo "⚠️ Trying fallback installation method..."
if timeout 300 $pip_cmd $install_args -r "$requirements_file" --quiet --no-warn-script-location --disable-pip-version-check --no-color --no-cache-dir 2>/dev/null || true; then
echo "✅ Package installation completed with fallback method"
return 0
fi
# Method 3: Install packages individually to avoid broken pipes
echo "⚠️ Trying individual package installation..."
while IFS= read -r line; do
# Skip empty lines and comments
[[ -z "$line" || "$line" =~ ^#.*$ ]] && continue
# Extract package name and version
package=$(echo "$line" | cut -d'=' -f1 | cut -d'>' -f1 | cut -d'<' -f1 | tr -d ' ')
if [[ -n "$package" ]]; then
echo "Installing $package..."
timeout 60 $pip_cmd install $install_args "$package" --quiet --no-warn-script-location --disable-pip-version-check 2>/dev/null || true
fi
done < "$requirements_file"
echo "✅ Package installation completed with individual method"
return 0
}
license_validation() {
CURRENT_DIR=$(pwd)
if [ -f /root/cyberpanel-tmp ] ; then
rm -rf /root/cyberpanel-tmp
fi
mkdir /root/cyberpanel-tmp
cd /root/cyberpanel-tmp
wget -q https://$DOWNLOAD_SERVER/litespeed/lsws-$LSWS_STABLE_VER-ent-x86_64-linux.tar.gz
tar xzvf lsws-$LSWS_STABLE_VER-ent-x86_64-linux.tar.gz > /dev/null
cd /root/cyberpanel-tmp/lsws-$LSWS_STABLE_VER/conf
if [[ $LICENSE_KEY == "TRIAL" ]] ; then
wget -q http://license.litespeedtech.com/reseller/trial.key
sed -i "s|writeSerial = open('lsws-5.4.2/serial.no', 'w')|command = 'wget -q --output-document=./lsws-$LSWS_STABLE_VER/trial.key http://license.litespeedtech.com/reseller/trial.key'|g" $CURRENT_DIR/installCyberPanel.py
sed -i 's|writeSerial.writelines(self.serial)|subprocess.call(command, shell=True)|g' $CURRENT_DIR/installCyberPanel.py
sed -i 's|writeSerial.close()||g' $CURRENT_DIR/installCyberPanel.py
else
echo $LICENSE_KEY > serial.no
fi
cd /root/cyberpanel-tmp/lsws-$LSWS_STABLE_VER/bin
if [[ $LICENSE_KEY == "TRIAL" ]] ; then
if ./lshttpd -V |& grep "ERROR" ; then
echo -e "\n\nIt apeears to have some issue with license , please check above result..."
exit
fi
LICENSE_KEY="1111-2222-3333-4444"
else
if ./lshttpd -r |& grep "ERROR" ; then
./lshttpd -r
echo -e "\n\nIt apeears to have some issue with license , please check above result..."
exit
fi
fi
echo -e "License seems valid..."
cd /root/cyberpanel-tmp
rm -rf lsws-$LSWS_STABLE_VER*
cd $CURRENT_DIR
rm -rf /root/cyberpanel-tmp
}
special_change(){
sed -i 's|cyberpanel.sh|'$DOWNLOAD_SERVER'|g' install.py
sed -i 's|mirror.cyberpanel.net|'$DOWNLOAD_SERVER'|g' install.py
sed -i 's|git clone https://github.com/usmannasir/cyberpanel|echo downloaded|g' install.py
#change to CDN first, regardless country
sed -i 's|http://|https://|g' install.py
LATEST_URL="https://update.litespeedtech.com/ws/latest.php"
#LATEST_URL="https://cyberpanel.sh/latest.php"
curl --silent -o /tmp/lsws_latest $LATEST_URL 2>/dev/null
LSWS_STABLE_LINE=`cat /tmp/lsws_latest | grep LSWS_STABLE`
LSWS_STABLE_VER=`expr "$LSWS_STABLE_LINE" : '.*LSWS_STABLE=\(.*\) BUILD .*'`
# Fallback to LSWS 6.3.4 (Stable) if fetch failed or empty
if [ -z "$LSWS_STABLE_VER" ]; then
LSWS_STABLE_VER="6.3.4"
fi
if [[ $SERVER_COUNTRY == "CN" ]] ; then
#line1="$(grep -n "github.com/usmannasir/cyberpanel" install.py | head -n 1 | cut -d: -f1)"
#line2=$((line1 - 1))
#sed -i "${line2}i\ \ \ \ \ \ \ \ subprocess.call(command, shell=True)" install.py
#sed -i "${line2}i\ \ \ \ \ \ \ \ command = 'tar xzvf cyberpanel-git.tar.gz'" install.py
#sed -i "${line2}i\ \ \ \ \ \ \ \ subprocess.call(command, shell=True)" install.py
#sed -i "${line2}i\ \ \ \ \ \ \ \ command = 'wget cyberpanel.sh/cyberpanel-git.tar.gz'" install.py
sed -i 's|wget https://rpms.litespeedtech.com/debian/|wget --no-check-certificate https://rpms.litespeedtech.com/debian/|g' install.py
sed -i 's|https://repo.powerdns.com/repo-files/centos-auth-42.repo|https://'$DOWNLOAD_SERVER'/powerdns/powerdns.repo|g' installCyberPanel.py
sed -i 's|https://snappymail.eu/repository/latest.tar.gz|https://'$DOWNLOAD_SERVER'/repository/latest.tar.gz|g' install.py
sed -i 's|rpm -ivh https://rpms.litespeedtech.com/centos/litespeed-repo-1.1-1.el7.noarch.rpm|curl -o /etc/yum.repos.d/litespeed.repo https://'$DOWNLOAD_SERVER'/litespeed/litespeed.repo|g' install.py
sed -i 's|https://copr.fedorainfracloud.org/coprs/copart/restic/repo/epel-7/copart-restic-epel-7.repo|https://'$DOWNLOAD_SERVER'/restic/restic.repo|g' install.py
sed -i 's|yum -y install https://cyberpanel.sh/gf-release-latest.gf.el7.noarch.rpm|wget -O /etc/yum.repos.d/gf.repo https://'$DOWNLOAD_SERVER'/gf-plus/gf.repo|g' install.py
sed -i 's|dovecot-2.3-latest|dovecot-2.3-latest-mirror|g' install.py
sed -i 's|git clone https://github.com/usmannasir/cyberpanel|wget https://cyberpanel.sh/cyberpanel-git.tar.gz \&\& tar xzvf cyberpanel-git.tar.gz|g' install.py
sed -i 's|https://repo.dovecot.org/ce-2.3-latest/centos/$releasever/RPMS/$basearch|https://'$DOWNLOAD_SERVER'/dovecot/|g' install.py
sed -i 's|'$DOWNLOAD_SERVER'|cyberpanel.sh|g' install.py
sed -i 's|https://www.litespeedtech.com/packages/5.0/lsws-5.4.2-ent-x86_64-linux.tar.gz|https://'$DOWNLOAD_SERVER'/litespeed/lsws-'$LSWS_STABLE_VER'-ent-x86_64-linux.tar.gz|g' installCyberPanel.py
# global change for CN , regardless provider and system
if [[ $SERVER_OS == "CentOS" ]] ; then
DIR=$(pwd)
cd $DIR/mysql
echo "[mariadb-tsinghua]
name = MariaDB
baseurl = https://mirrors.tuna.tsinghua.edu.cn/mariadb/yum/10.1/centos7-amd64
gpgkey = https://mirrors.tuna.tsinghua.edu.cn/mariadb/yum//RPM-GPG-KEY-MariaDB
gpgcheck = 1" > MariaDB.repo
#above to set mariadb db to Tsinghua repo
cd $DIR
sed -i 's|https://www.litespeedtech.com/packages/5.0/lsws-5.3.5-ent-x86_64-linux.tar.gz|https://cyberpanel.sh/packages/5.0/lsws-5.3.5-ent-x86_64-linux.tar.gz|g' installCyberPanel.py
mkdir /root/.pip
cat << EOF > /root/.pip/pip.conf
[global]
index-url = https://mirrors.aliyun.com/pypi/simple/
EOF
echo -e "\nSet to Aliyun pip repo..."
cat << EOF > composer.sh
#!/usr/bin/env bash
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php composer-setup.php
php -r "unlink('composer-setup.php');"
mv composer.phar /usr/bin/composer
if [ ! -d /root/.config ]; then
mkdir /root/.config
fi
if [ ! -d /root/.config/composer ]; then
mkdir /root/.config/composer
fi
echo '{
"bitbucket-oauth": {},
"github-oauth": {},
"gitlab-oauth": {},
"gitlab-token": {},
"http-basic": {}
}
' > /root/.config/composer/auth.json
echo '{
"config": {},
"repositories": {
"packagist": {
"type": "composer",
"url": "https://mirrors.aliyun.com/composer/"
}
}
}
' > /root/.config/composer/config.json
composer clear-cache
EOF
fi
if [[ $SERVER_OS == "Ubuntu" ]] ; then
echo $'\n89.208.248.38 rpms.litespeedtech.com\n' >> /etc/hosts
echo -e "Mirror server set..."
pip config set global.index-url https://mirrors.aliyun.com/pypi/simple/
cat << EOF > /root/.pip/pip.conf
[global]
index-url = https://mirrors.aliyun.com/pypi/simple/
EOF
echo -e "\nSet to Aliyun pip repo..."
if [[ $PROVIDER == "Tencent Cloud" ]] ; then
#tencent cloud and ubuntu system
echo -e "\n Tencent Cloud detected ... bypass default repository"
cp /etc/apt/sources.list /etc/apt/sources.list-backup
#backup original sources list
cat << 'EOF' > /etc/apt/sources.list
deb http://mirrors.aliyun.com/ubuntu/ bionic main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ bionic-security main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ bionic-updates main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ bionic-proposed main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ bionic-backports main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-security main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-updates main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-proposed main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-backports main restricted universe multiverse
EOF
DEBIAN_FRONTEND=noninteractive apt update -y
pip config set global.index-url https://mirrors.aliyun.com/pypi/simple/
cat << EOF > composer.sh
#!/usr/bin/env bash
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php composer-setup.php
php -r "unlink('composer-setup.php');"
mv composer.phar /usr/bin/composer
if [ ! -d /root/.config ]; then
mkdir /root/.config
fi
if [ ! -d /root/.config/composer ]; then
mkdir /root/.config/composer
fi
echo '{
"bitbucket-oauth": {},
"github-oauth": {},
"gitlab-oauth": {},
"gitlab-token": {},
"http-basic": {}
}
' > /root/.config/composer/auth.json
echo '{
"config": {},
"repositories": {
"packagist": {
"type": "composer",
"url": "https://mirrors.cloud.tencent.com/composer/"
}
}
}
' > /root/.config/composer/config.json
composer clear-cache
EOF
else
cat << EOF > composer.sh
#!/usr/bin/env bash
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php composer-setup.php
php -r "unlink('composer-setup.php');"
mv composer.phar /usr/bin/composer
if [ ! -d /root/.config ]; then
mkdir /root/.config
fi
if [ ! -d /root/.config/composer ]; then
mkdir /root/.config/composer
fi
echo '{
"bitbucket-oauth": {},
"github-oauth": {},
"gitlab-oauth": {},
"gitlab-token": {},
"http-basic": {}
}
' > /root/.config/composer/auth.json
echo '{
"config": {},
"repositories": {
"packagist": {
"type": "composer",
"url": "https://packagist.phpcomposer.com"
}
}
}
' > /root/.config/composer/config.json
composer clear-cache
EOF
fi
fi
fi
}
system_tweak() {
if [[ $SERVER_OS == "CentOS" ]] ; then
setenforce 0
sed -i 's/SELINUX=enforcing/SELINUX=permissive/g' /etc/selinux/config
fi
if ! grep -q "pid_max" /etc/rc.local; then
if [[ $SERVER_OS == "CentOS" ]] ; then
echo "echo 1000000 > /proc/sys/kernel/pid_max
echo 1 > /sys/kernel/mm/ksm/run" >> /etc/rc.d/rc.local
chmod +x /etc/rc.d/rc.local
else
echo "echo 1000000 > /proc/sys/kernel/pid_max
echo 1 > /sys/kernel/mm/ksm/run" >> /etc/rc.local
chmod +x /etc/rc.local
fi
echo "fs.file-max = 65535" >> /etc/sysctl.conf
sysctl -p > /dev/null
echo "* soft nofile 65535
* hard nofile 65535
root soft nofile 65535
root hard nofile 65535
* soft nproc 65535
* hard nproc 65535
root soft nproc 65535
root hard nproc 65535" >> /etc/security/limits.conf
fi
#sed -i 's|#DefaultLimitNOFILE=|DefaultLimitNOFILE=65535|g' /etc/systemd/system.conf
TOTAL_SWAP=$(free -m | awk '/^Swap:/ { print $2 }')
SET_SWAP=$((TOTAL_RAM - TOTAL_SWAP))
SWAP_FILE=/cyberpanel.swap
if [ ! -f $SWAP_FILE ] ; then
if [[ $TOTAL_SWAP -gt $TOTAL_RAM ]] || [[ $TOTAL_SWAP -eq $TOTAL_RAM ]] ; then
echo "SWAP check..."
else
if [[ $SET_SWAP -gt "2049" ]] ; then
SET_SWAP="2048"
else
echo "Checking SWAP..."
fi
fallocate --length ${SET_SWAP}MiB $SWAP_FILE
chmod 600 $SWAP_FILE
mkswap $SWAP_FILE
swapon $SWAP_FILE
echo "${SWAP_FILE} swap swap sw 0 0" | sudo tee -a /etc/fstab
sysctl vm.swappiness=10
echo "vm.swappiness = 10" >> /etc/sysctl.conf
echo "SWAP set..."
fi
fi
}
install_required() {
echo -e "\nInstalling necessary components..."
if [[ $SERVER_OS == "CentOS" ]] ; then
rpm --import https://$DOWNLOAD_SERVER/mariadb/RPM-GPG-KEY-MariaDB
rpm --import https://$DOWNLOAD_SERVER/litespeed/RPM-GPG-KEY-litespeed
rpm --import https://$DOWNLOAD_SERVER/powerdns/FD380FBB-pub.asc
rpm --import http://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-7
rpm --import https://$DOWNLOAD_SERVER/gf-plus/RPM-GPG-KEY-gf.el7
rpm --import https://repo.dovecot.org/DOVECOT-REPO-GPG
rpm --import https://copr-be.cloud.fedoraproject.org/results/copart/restic/pubkey.gpg
yum autoremove epel-release -y
rm -f /etc/yum.repos.d/epel.repo
rm -f /etc/yum.repos.d/epel.repo.rpmsave
yum clean all
yum update -y
yum install epel-release -y
yum install -y wget strace htop net-tools telnet curl which bc telnet htop libevent-devel gcc python-devel libattr-devel xz-devel gpgme-devel mariadb-devel curl-devel python-pip git
if [[ $DEV == "ON" ]] ; then
yum -y install yum-utils
yum -y groupinstall development
yum -y install https://centos7.iuscommunity.org/ius-release.rpm
yum -y install python36u python36u-pip python36u-devel
fi
fi
if [[ $SERVER_OS == "Ubuntu" ]] ; then
apt update -y
DEBIAN_FRONTEND=noninteractive apt upgrade -y
# Check if this is Debian (no lsb-release) and version >= 13
if [[ ! -f /etc/lsb-release ]] && [[ -f /etc/debian_version ]]; then
DEBIAN_VERSION=$(cat /etc/debian_version | cut -d'.' -f1)
if [[ $DEBIAN_VERSION -ge 13 ]]; then
# Debian 13 (Trixie) package mappings
DEBIAN_FRONTEND=noninteractive apt install -y htop telnet python3-mysqldb python3-dev libcurl4-gnutls-dev libgnutls28-dev libgcrypt20-dev libattr1 libattr1-dev liblzma-dev libgpgme-dev libmariadb-dev-compat libmariadb-dev libcurl4-gnutls-dev libssl-dev nghttp2 libnghttp2-dev idn2 libidn2-dev librtmp-dev libpsl-dev nettle-dev libgnutls28-dev libldap2-dev libgssapi-krb5-2 libk5crypto3 libkrb5-dev libcom-err2 libldap2-dev python3-gpg python3 python3-setuptools virtualenv python3-dev python3-pip git
elif [[ $DEBIAN_VERSION -ge 12 ]]; then
# Debian 12 (Bookworm) package mappings
DEBIAN_FRONTEND=noninteractive apt install -y htop telnet python3-mysqldb python3-dev libcurl4-gnutls-dev libgnutls28-dev libgcrypt20-dev libattr1 libattr1-dev liblzma-dev libgpgme-dev libmariadb-dev libcurl4-gnutls-dev libssl-dev nghttp2 libnghttp2-dev idn2 libidn2-dev librtmp-dev libpsl-dev nettle-dev libgnutls28-dev libldap2-dev libgssapi-krb5-2 libk5crypto3 libkrb5-dev libcom-err2 libldap2-dev python3-gpg python3 python3-setuptools virtualenv python3-dev python3-pip git
else
# Older Debian versions
DEBIAN_FRONTEND=noninteractive apt install -y htop telnet python-mysqldb python-dev libcurl4-gnutls-dev libgnutls28-dev libgcrypt20-dev libattr1 libattr1-dev liblzma-dev libgpgme-dev libmariadb-dev-compat libmariadb-dev libcurl4-gnutls-dev libssl-dev nghttp2 libnghttp2-dev idn2 libidn2-dev librtmp-dev libpsl-dev nettle-dev libgnutls28-dev libldap2-dev libgssapi-krb5-2 libk5crypto3 libkrb5-dev libcom-err2 libldap2-dev python-gpg python python-minimal python-setuptools virtualenv python-dev python-pip git
fi
else
# Ubuntu or older Debian with compatible package names
DEBIAN_FRONTEND=noninteractive apt install -y htop telnet python-mysqldb python-dev libcurl4-gnutls-dev libgnutls28-dev libgcrypt20-dev libattr1 libattr1-dev liblzma-dev libgpgme-dev libmariadb-dev-compat libmariadb-dev libcurl4-gnutls-dev libssl-dev nghttp2 libnghttp2-dev idn2 libidn2-dev librtmp-dev libpsl-dev nettle-dev libgnutls28-dev libldap2-dev libgssapi-krb5-2 libk5crypto3 libkrb5-dev libcom-err2 libldap2-dev python-gpg python python-minimal python-setuptools virtualenv python-dev python-pip git
fi
if [[ $DEV == "ON" ]] ; then
DEBIAN_FRONTEND=noninteractive apt install -y python3-pip
DEBIAN_FRONTEND=noninteractive apt install -y build-essential libssl-dev libffi-dev python3-dev
DEBIAN_FRONTEND=noninteractive apt install -y python3-venv
fi
fi
}

View File

@@ -0,0 +1,499 @@
#!/usr/bin/env bash
# install/venvsetup part 2 memcached through main_install
memcached_installation() {
if [[ $SERVER_OS == "CentOS" ]] ; then
yum install -y lsphp73-memcached lsphp72-memcached lsphp71-memcached lsphp70-memcached lsphp56-pecl-memcached lsphp55-pecl-memcached lsphp54-pecl-memcached
if [[ $TOTAL_RAM -eq "2048" ]] || [[ $TOTAL_RAM -gt "2048" ]] ; then
yum groupinstall "Development Tools" -y
yum install autoconf automake zlib-devel openssl-devel expat-devel pcre-devel libmemcached-devel cyrus-sasl* -y
wget https://$DOWNLOAD_SERVER/litespeed/lsmcd.tar.gz
tar xzvf lsmcd.tar.gz
DIR=$(pwd)
cd $DIR/lsmcd
./fixtimestamp.sh
./configure CFLAGS=" -O3" CXXFLAGS=" -O3"
make
make install
systemctl enable lsmcd
systemctl start lsmcd
cd $DIR
else
yum install -y memcached
sed -i 's|OPTIONS=""|OPTIONS="-l 127.0.0.1 -U 0"|g' /etc/sysconfig/memcached
systemctl enable memcached
systemctl start memcached
fi
fi
if [[ $SERVER_OS == "Ubuntu" ]] ; then
DEBIAN_FRONTEND=noninteractive apt install -y lsphp73-memcached lsphp72-memcached lsphp71-memcached lsphp70-memcached
if [[ $TOTAL_RAM -eq "2048" ]] || [[ $TOTAL_RAM -gt "2048" ]] ; then
DEBIAN_FRONTEND=noninteractive apt install build-essential zlib1g-dev libexpat1-dev openssl libssl-dev libsasl2-dev libpcre3-dev git -y
wget https://$DOWNLOAD/litespeed/lsmcd.tar.gz
tar xzvf lsmcd.tar.gz
DIR=$(pwd)
cd $DIR/lsmcd
./fixtimestamp.sh
./configure CFLAGS=" -O3" CXXFLAGS=" -O3"
make
make install
cd $DIR
systemctl enable lsmcd
systemctl start lsmcd
else
DEBIAN_FRONTEND=noninteractive apt install -y memcached
systemctl enable memcached
systemctl start memcached
fi
fi
if ps -aux | grep "lsmcd" | grep -v grep ; then
echo -e "\n\nLiteSpeed Memcached installed and running..."
fi
if ps -aux | grep "memcached" | grep -v grep ; then
echo -e "\n\nMemcached installed and running..."
fi
}
redis_installation() {
if [[ $SERVER_OS == "CentOS" ]] ; then
yum install -y lsphp73-redis lsphp72-redis lsphp71-redis lsphp70-redis lsphp56-redis lsphp55-redis lsphp54-redis redis
fi
if [[ $SERVER_OS == "Ubuntu" ]] ; then
DEBIAN_FRONTEND=noninteractive apt install -y lsphp73-redis lsphp72-redis lsphp71-redis lsphp70-redis redis
fi
if ifconfig -a | grep inet6 ; then
echo -e "\n IPv6 detected..."
else
sed -i 's|bind 127.0.0.1 ::1|bind 127.0.0.1|g' /etc/redis/redis.conf
echo -e "\n no IPv6 detected..."
fi
if [[ $SERVER_OS == "CentOS" ]] ; then
systemctl enable redis
systemctl start redis
fi
if [[ $SERVER_OS == "Ubuntu" ]] ; then
systemctl enable redis-server
systemctl start redis-server
fi
if ps -aux | grep "redis" | grep -v grep ; then
echo -e "\n\nRedis installed and running..."
fi
}
check_provider() {
if hash dmidecode > /dev/null 2>&1 ; then
if [ "$(dmidecode -s bios-vendor)" = 'Google' ] ; then
PROVIDER='Google Cloud Platform'
elif [ "$(dmidecode -s bios-vendor)" = 'DigitalOcean' ] ; then
PROVIDER='Digital Ocean'
elif [ "$(dmidecode -s system-product-name | cut -c 1-7)" = 'Alibaba' ] ; then
PROVIDER='Alibaba Cloud'
elif [ "$(dmidecode -s system-manufacturer)" = 'Microsoft Corporation' ] ; then
PROVIDER='Microsoft Azure'
elif [ -d /usr/local/qcloud ] ; then
PROVIDER='Tencent Cloud'
else
PROVIDER='undefined'
fi
else
PROVIDER='undefined'
fi
if [ "$(cat /sys/devices/virtual/dmi/id/product_uuid | cut -c 1-3)" = 'EC2' ] && [ -d /home/ubuntu ]; then
PROVIDER='Amazon Web Service'
fi
}
check_OS() {
echo -e "\nChecking OS..."
OUTPUT=$(cat /etc/*release)
if echo $OUTPUT | grep -q "CentOS Linux 7" ; then
echo -e "\nDetecting CentOS 7.X...\n"
SERVER_OS="CentOS"
elif echo $OUTPUT | grep -q "CloudLinux 7" ; then
echo -e "\nDetecting CloudLinux 7.X...\n"
SERVER_OS="CentOS"
elif echo $OUTPUT | grep -q "Ubuntu 18.04" ; then
echo -e "\nDetecting Ubuntu 18.04...\n"
SERVER_OS="Ubuntu"
else
cat /etc/*release
echo -e "\nUnable to detect your OS...\n"
echo -e "\nCyberPanel is supported on Ubuntu 18.04, CentOS 7.x and CloudLinux 7.x...\n"
exit 1
fi
}
check_root() {
echo -e "Checking root privileges...\n"
if [[ $(id -u) != 0 ]] > /dev/null; then
echo -e "You must use root account to do this"
echo -e "or run following command: (do NOT miss the quotes)"
echo -e "\e[31msudo su -c \"sh <(curl https://cyberpanel.sh || wget -O - https://cyberpanel.sh)\"\e[39m"
exit 1
else
echo -e "You are runing as root...\n"
fi
}
check_panel() {
if [ -d /usr/local/cpanel ]; then
echo -e "\ncPanel detected...exit...\n"
exit 1
fi
if [ -d /opt/plesk ]; then
echo -e "\nPlesk detected...exit...\n"
exit 1
fi
}
check_process() {
if systemctl is-active --quiet httpd; then
systemctl disable httpd
systemctl stop httpd
echo -e "\nhttpd process detected, disabling...\n"
fi
if systemctl is-active --quiet apache2; then
systemctl disable apache2
systemctl stop apache2
echo -e "\napache2 process detected, disabling...\n"
fi
if systemctl is-active --quiet named; then
systemctl stop named
systemctl disable named
echo -e "\nnamed process detected, disabling...\n"
fi
if systemctl is-active --quiet exim; then
systemctl stop exim
systemctl disable exim
echo -e "\nexim process detected, disabling...\n"
fi
}
show_help() {
echo -e "\nCyberPanel Installer Script Help\n"
echo -e "\nUsage: wget https://cyberpanel.sh/cyberpanel.sh"
echo -e "\nchmod +x cyberpanel.sh"
echo -e "\n./cyberpanel.sh -v ols/SERIAL_NUMBER -c 1 -a 1"
echo -e "\n -v or --version: choose to install CyberPanel OpenLiteSpeed or CyberPanel Enterprise, available options are \e[31mols\e[39m and \e[31mSERIAL_NUMBER\e[39m, default ols"
echo -e "\n Please be aware, this serial number must be obtained from LiteSpeed Store."
echo -e "\n And if this serial number has been used before, it must be released/migrated in Store first, otherwise it will fail to start."
echo -e "\n -a or --addons: install addons: memcached, redis, PHP extension for memcached and redis, 1 for install addons, 0 for not to install, default 0, only applicable for CentOS system."
echo -e "\n -p or --password: set password of new installation, empty for default 1234567, [r] or [random] for randomly generated 16 digital password, any other value besdies [d] and [r(andom)] will be accept as password, default use 1234567."
#echo -e "\n -m: set to minimal mode which will not install PowerDNS, Pure-FTPd and Postfix"
echo -e "\n Example:"
echo -e "\n ./cyberpanel.sh -v ols -p r or ./cyberpanel.sh --version ols --password random"
echo -e "\n This will install CyberPanel OpenLiteSpeed and randomly generate the password."
echo -e "\n ./cyberpanel.sh default"
echo -e "\n This will install everything default , which is OpenLiteSpeed and nothing more.\n"
}
license_input() {
VERSION="ENT"
echo -e "\nPlease note that your server has \e[31m$TOTAL_RAM\e[39m RAM"
echo -e "If you are using \e[31mFree Start\e[39m license, It will not start due to \e[31m2GB RAM limit\e[39m.\n"
echo -e "If you do not have any license, you can also use trial license (if server has not used trial license before), type \e[31mTRIAL\e[39m\n"
printf "%s" "Please input your serial number for LiteSpeed WebServer Enterprise:"
read LICENSE_KEY
if [ -z "$LICENSE_KEY" ] ; then
echo -e "\nPlease provide license key\n"
exit
fi
echo -e "The serial number you input is: \e[31m$LICENSE_KEY\e[39m"
printf "%s" "Please verify it is correct. [y/N]"
read TMP_YN
if [ -z "$TMP_YN" ] ; then
echo -e "\nPlease type \e[31my\e[39m\n"
exit
fi
KEY_SIZE=${#LICENSE_KEY}
TMP=$(echo $LICENSE_KEY | cut -c5)
TMP2=$(echo $LICENSE_KEY | cut -c10)
TMP3=$(echo $LICENSE_KEY | cut -c15)
if [[ $TMP == "-" ]] && [[ $TMP2 == "-" ]] && [[ $TMP3 == "-" ]] && [[ $KEY_SIZE == "19" ]] ; then
echo -e "\nLicense key set..."
elif [[ $LICENSE_KEY == "trial" ]] || [[ $LICENSE_KEY == "TRIAL" ]] || [[ $LICENSE_KEY == "Trial" ]] ; then
echo -e "\nTrial license set..."
LICENSE_KEY="TRIAL"
else
echo -e "\nLicense key seems incorrect, please verify\n"
echo -e "\nIf you are copying/pasting, please make sure you didn't paste blank space...\n"
exit
fi
}
interactive_mode() {
echo -e " CyberPanel Installer v$CP_VER1$CP_VER2
1. Install CyberPanel.
2. Addons and Miscellaneous
3. Exit.
"
read -p " Please enter the number[1-3]: " num
echo ""
case "$num" in
1)
interactive_install
;;
2)
interactive_others
;;
3)
exit
;;
*)
echo -e " Please enter the right number [1-3]\n"
exit
;;
esac
}
interactive_others() {
if [ ! -e "/etc/cyberpanel/machineIP" ]; then
echo -e "\nYou don't have CyberPanel installed...\n"
exit
fi
echo -e " CyberPanel Addons v$CP_VER1$CP_VER2
1. Install Memcached extension and backend
2. Install Redis extension and backend
3. Return to main page.
4. Exit
"
echo && read -p "Please enter the number[1-4]: " num
case "$num" in
1)
memcached_installation
exit
;;
2)
redis_installation
exit
;;
3)
interactive_mode
;;
4)
exit
;;
*)
echo -e "${Error} please enter the right number [1-4]"
;;
esac
}
interactive_install() {
RAM=$(free -m | awk 'NR==2{printf "%s/%sMB (%.2f%%)\n", $3,$2,$3*100/$2 }')
DISK=$(df -h | awk '$NF=="/"{printf "%d/%dGB (%s)\n", $3,$2,$5}')
#clear
echo -e " CyberPanel Installer v$CP_VER1$CP_VER2
RAM check : $RAM
Disk check : $DISK (Minimal \e[31m10GB\e[39m free space)
1. Install CyberPanel with \e[31mOpenLiteSpeed\e[39m.
2. Install Cyberpanel with \e[31mLiteSpeed Enterprise\e[39m.
3. Exit.
"
read -p " Please enter the number[1-3]: " num
echo ""
case "$num" in
1)
VERSION="OLS"
;;
2)
license_input
;;
3)
exit
;;
*)
echo -e " Please enter the right number [1-3]\n"
exit
;;
esac
<<COMMENT
echo -e "\nInstall minimal service for CyberPanel? This will skip PowerDNS, Postfix and Pure-FTPd."
printf "%s" "Minimal installation [y/N]: "
read TMP_YN
if [ `expr "x$TMP_YN" : 'x[Yy]'` -gt 1 ]; then
echo -e "\nMinimal installation selected..."
POSTFIX_VARIABLE="OFF"
POWERDNS_VARIABLE="OFF"
PUREFTPD_VARIABLE="OFF"
else
printf "%s" "Install Postfix? [Y/n]: "
read TMP_YN
if [[ $TMP_YN =~ ^(no|n|N) ]] ; then
POSTFIX_VARIABLE="OFF"
else
POSTFIX_VARIABLE="ON"
fi
printf "%s" "Install PowerDNS? [Y/n]: "
read TMP_YN
if [[ $TMP_YN =~ ^(no|n|N) ]] ; then
POWERDNS_VARIABLE="OFF"
else
POWERDNS_VARIABLE="ON"
fi
printf "%s" "Install PureFTPd? [Y/n]: "
read TMP_YN
if [[ $TMP_YN =~ ^(no|n|N) ]] ; then
PUREFTPD_VARIABLE="OFF"
else
PUREFTPD_VARIABLE="ON"
fi
fi
COMMENT
#above comment for future use
if [[ $DEV_ARG == "ON" ]] ; then
echo -e "\nDo you want to specify which branch you want to install?"
echo -e "\nNOTE: this feature is only for developers "
echo -e "\nonly use this feature if you are a \e[31mdeveloper\e[39m"
#echo -e "\nPlease press Enter key or n to proceed as normal user"
#echo -e "\nPlease enter \e[31mdeveloper\e[39m to confirm you want to use this feature"
#printf "%s" ""
#read TMP_YN
#if [[ $TMP_YN == "developer" ]] ; then
DEV="ON"
echo -e "\nPlease specify branch name"
printf "%s" ""
read TMP_YN
BRANCH_NAME=$TMP_YN
echo -e "Branch name set to $BRANCH_NAME"
#else
# DEV="OFF"
#fi
fi
echo -e "\nPlease choose to use default admin password \e[31m1234567\e[39m, randomly generate one \e[31m(recommended)\e[39m or specify the admin password?"
printf "%s" "Choose [d]fault, [r]andom or [s]et password: [d/r/s] "
read TMP_YN
if [[ $TMP_YN =~ ^(d|D| ) ]] || [[ -z $TMP_YN ]]; then
ADMIN_PASS="1234567"
echo -e "\nAdmin password will be set to $ADMIN_PASS\n"
elif [[ $TMP_YN =~ ^(r|R) ]] ; then
ADMIN_PASS=$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 16 ; echo '')
echo -e "\nAdmin password will be provided once installation is completed...\n"
elif [[ $TMP_YN =~ ^(s|S) ]] ; then
echo -e "\nPlease enter your password:"
printf "%s" ""
read TMP_YN
if [ -z "$TMP_YN" ] ; then
echo -e "\nPlease do not use empty string...\n"
exit
fi
if [ ${#TMP_YN} -lt 8 ] ; then
echo -e "\nPassword lenth less than 8 digital, please choose a more complicated password.\n"
exit
fi
TMP_YN1=$TMP_YN
echo -e "\nPlease confirm your password:\n"
printf "%s" ""
read TMP_YN
if [ -z "$TMP_YN" ] ; then
echo -e "\nPlease do not use empty string...\n"
exit
fi
TMP_YN2=$TMP_YN
if [ $TMP_YN1 = $TMP_YN2 ] ; then
ADMIN_PASS=$TMP_YN1
else
echo -e "\nRepeated password didn't match , please check...\n"
exit
fi
else
ADMIN_PASS="1234567"
echo -e "\nAdmin password will be set to $ADMIN_PASS\n"
fi
echo -e "\nDo you wish to install Memcached extension and backend?"
printf "%s" "Please select [Y/n]: "
read TMP_YN
if [[ $TMP_YN =~ ^(no|n|N) ]] ; then
MEMCACHED="OFF"
else
MEMCACHED="ON"
fi
echo -e "\nDo you wish to install Redis extension and backend?"
printf "%s" "Please select [Y/n]: "
read TMP_YN
if [[ $TMP_YN =~ ^(no|n|N) ]] ; then
REDIS="OFF"
else
REDIS="ON"
fi
echo -e "\nWhich MariaDB version do you want to install? \e[31m11.8\e[39m (LTS, default) or \e[31m12.1\e[39m?"
printf "%s" "Choose [1] for 11.8 LTS (recommended), [2] for 12.1, or press Enter for default [1]: "
read TMP_YN
if [[ $TMP_YN =~ ^(2|12\.1) ]] ; then
MARIADB_VER="12.1"
echo -e "\nMariaDB 12.1 will be installed.\n"
else
MARIADB_VER="11.8"
echo -e "\nMariaDB 11.8 LTS will be installed (default).\n"
fi
}
main_install() {
if [[ -e /usr/local/CyberCP ]] ; then
echo -e "\n CyberPanel already installed, exiting..."
#exit
fi
special_change
if [[ $VERSION == "ENT" ]] ; then
echo -e "\nValidating the license..."
echo -e "\nThis may take a minute..."
echo -e "\nplease be patient...\n\n"
license_validation
SERIAL_NO="--ent ent --serial "
fi
sed -i 's|lsws-5.4.2|lsws-'$LSWS_STABLE_VER'|g' installCyberPanel.py
sed -i 's|lsws-5.3.5|lsws-'$LSWS_STABLE_VER'|g' installCyberPanel.py
sed -i 's|lsws-6.0|lsws-'$LSWS_STABLE_VER'|g' installCyberPanel.py
sed -i 's|lsws-6.3.4|lsws-'$LSWS_STABLE_VER'|g' installCyberPanel.py
#this sed must be done after license validation
echo -e "Preparing..."
echo -e "Installation will start in 10 seconds, if you wish to stop please press CTRL + C"
sleep 10
main_install_run
}

View File

@@ -0,0 +1,125 @@
#!/usr/bin/env bash
# install/venvsetup part 3 main_install_run, pip_virtualenv
main_install_run() {
debug="1"
if [[ $debug == "0" ]] ; then
echo "/usr/local/CyberPanel/bin/python2 install.py $SERVER_IP $SERIAL_NO $LICENSE_KEY"
exit
fi
if [[ $debug == "1" ]] ; then
if [[ $DEV == "ON" ]] ; then
/usr/local/CyberPanel/bin/python install.py $SERVER_IP $SERIAL_NO $LICENSE_KEY --mariadb-version "${MARIADB_VER:-11.8}"
else
/usr/local/CyberPanel/bin/python2 install.py $SERVER_IP $SERIAL_NO $LICENSE_KEY --mariadb-version "${MARIADB_VER:-11.8}"
fi
if grep "CyberPanel installation successfully completed" /var/log/installLogs.txt > /dev/null; then
echo -e "\nCyberPanel installation sucessfully completed..."
else
echo -e "Oops, something went wrong..."
exit
fi
if [[ $MEMCACHED == "ON" ]] ; then
memcached_installation
fi
if [[ $REDIS == "ON" ]] ; then
redis_installation
fi
after_install
fi
}
pip_virtualenv() {
if [[ $DEV == "OFF" ]] ; then
if [[ $SERVER_COUNTRY == "CN" ]] ; then
mkdir /root/.pip
cat << EOF > /root/.pip/pip.conf
[global]
index-url = https://mirrors.aliyun.com/pypi/simple/
EOF
fi
if [[ $PROVIDER == "Alibaba Cloud" ]] ; then
pip install --upgrade pip 2>/dev/null || echo "⚠️ pip upgrade completed with warnings"
pip install setuptools==40.8.0 2>/dev/null || echo "⚠️ setuptools installation completed with warnings"
fi
pip install virtualenv 2>/dev/null || echo "⚠️ virtualenv installation completed with warnings"
# Create virtual environment with fallback for Ubuntu 22.04 compatibility
echo "Creating CyberPanel virtual environment..."
if python3 -m venv --system-site-packages /usr/local/CyberPanel 2>&1 | grep -q "unrecognized option"; then
# Fallback to virtualenv if python3 -m venv doesn't support --system-site-packages
virtualenv --system-site-packages /usr/local/CyberPanel
elif python3 -m venv --system-site-packages /usr/local/CyberPanel 2>/dev/null; then
echo "Virtual environment created successfully using python3 -m venv"
else
# Final fallback to virtualenv
virtualenv --system-site-packages /usr/local/CyberPanel
fi
source /usr/local/CyberPanel/bin/activate
rm -rf requirements.txt
wget -O requirements.txt https://raw.githubusercontent.com/usmannasir/cyberpanel/1.8.0/requirments.txt
# Install packages with robust error handling to prevent broken pipe errors
safe_pip_install "pip" "requirements.txt" "--ignore-installed"
fi
if [[ $DEV == "ON" ]] ; then
#install dev branch
#wget https://raw.githubusercontent.com/usmannasir/cyberpanel/$BRANCH_NAME/requirments.txt
cd /usr/local/
python3.6 -m venv CyberPanel
source /usr/local/CyberPanel/bin/activate
# Try to download requirements file with fallback options
echo "Attempting to download requirements for branch/commit: $BRANCH_NAME"
# First try the specified branch/commit
if wget -O requirements.txt https://raw.githubusercontent.com/usmannasir/cyberpanel/$BRANCH_NAME/requirments.txt 2>/dev/null; then
echo "Successfully downloaded requirements from $BRANCH_NAME"
elif wget -O requirements.txt https://raw.githubusercontent.com/usmannasir/cyberpanel/$BRANCH_NAME/requirments-old.txt 2>/dev/null; then
echo "Successfully downloaded requirements-old.txt from $BRANCH_NAME"
elif wget -O requirements.txt https://raw.githubusercontent.com/usmannasir/cyberpanel/stable/requirments.txt 2>/dev/null; then
echo "Fallback: Downloaded requirements from stable branch"
else
echo "Warning: Could not download requirements file, using minimal default requirements"
cat > requirements.txt << 'EOF'
# Minimal CyberPanel requirements - fallback when requirements file is not available
Django==3.2.25
PyMySQL==1.1.0
requests==2.31.0
cryptography==41.0.7
psutil==5.9.6
EOF
fi
safe_pip_install "pip3.6" "requirements.txt" "--ignore-installed"
fi
if [ -f requirements.txt ] && [ -d cyberpanel ] ; then
rm -rf cyberpanel
rm -f requirements.txt
fi
if [[ $SERVER_COUNTRY == "CN" ]] ; then
wget https://cyberpanel.sh/cyberpanel-git.tar.gz
tar xzvf cyberpanel-git.tar.gz > /dev/null
cp -r cyberpanel /usr/local/cyberpanel
cd cyberpanel/install
else
if [[ $DEV == "ON" ]] ; then
git clone https://github.com/usmannasir/cyberpanel
cd cyberpanel
git checkout $BRANCH_NAME
cd -
cd cyberpanel/install
else
git clone https://github.com/usmannasir/cyberpanel
cd cyberpanel/install
fi
fi
curl https://cyberpanel.sh/?version
}

View File

@@ -0,0 +1,239 @@
#!/usr/bin/env bash
# install/venvsetup part 4 after_install
after_install() {
if [ ! -d "/var/lib/php" ]; then
mkdir /var/lib/php
fi
if [ ! -d "/var/lib/php/session" ]; then
mkdir /var/lib/php/session
fi
chmod 1733 /var/lib/php/session
if grep "\[ERROR\] We are not able to run ./install.sh return code: 1. Fatal error, see /var/log/installLogs.txt for full details" /var/log/installLogs.txt > /dev/null; then
cd ${DIR}/cyberpanel/install/lsws-*
./install.sh
echo -e "\n\n\nIt seems LiteSpeed Enterprise has failed to install, please check your license key is valid"
echo -e "\nIf this license key has been used before, you may need to go to store to release it first."
exit
fi
if grep "CyberPanel installation successfully completed" /var/log/installLogs.txt > /dev/null; then
if [[ $DEV == "ON" ]] ; then
python3.6 -m venv /usr/local/CyberCP
source /usr/local/CyberCP/bin/activate
# Try to download requirements file with fallback options
echo "Attempting to download requirements for branch/commit: $BRANCH_NAME"
# First try the specified branch/commit
if wget -O requirements.txt https://raw.githubusercontent.com/usmannasir/cyberpanel/$BRANCH_NAME/requirments.txt 2>/dev/null; then
echo "Successfully downloaded requirements from $BRANCH_NAME"
elif wget -O requirements.txt https://raw.githubusercontent.com/usmannasir/cyberpanel/$BRANCH_NAME/requirments-old.txt 2>/dev/null; then
echo "Successfully downloaded requirements-old.txt from $BRANCH_NAME"
elif wget -O requirements.txt https://raw.githubusercontent.com/usmannasir/cyberpanel/stable/requirments.txt 2>/dev/null; then
echo "Fallback: Downloaded requirements from stable branch"
else
echo "Warning: Could not download requirements file, using minimal default requirements"
cat > requirements.txt << 'EOF'
# Minimal CyberPanel requirements - fallback when requirements file is not available
Django==3.2.25
PyMySQL==1.1.0
requests==2.31.0
cryptography==41.0.7
psutil==5.9.6
EOF
fi
safe_pip_install "pip3.6" "requirements.txt" "--ignore-installed"
systemctl restart lscpd
fi
for version in $(ls /usr/local/lsws | grep lsphp);
do
php_ini=$(find /usr/local/lsws/$version/ -name php.ini)
version2=${version:5:2}
version2=$(awk "BEGIN { print "${version2}/10" }")
if [[ $version2 = "7" ]] ; then
version2="7.0"
fi
if [[ $SERVER_OS == "CentOS" ]] ; then
yum remove -y $version-mysql
yum install -y $version-mysqlnd
yum install -y $version-devel make gcc glibc-devel libmemcached-devel zlib-devel
if [[ ! -d /usr/local/lsws/$version/tmp ]] ; then
mkdir /usr/local/lsws/$version/tmp
fi
/usr/local/lsws/${version}/bin/pecl channel-update pecl.php.net;
/usr/local/lsws/${version}/bin/pear config-set temp_dir /usr/local/lsws/${version}/tmp
/usr/local/lsws/${version}/bin/pecl install timezonedb
echo "extension=timezonedb.so" > /usr/local/lsws/${version}/etc/php.d/20-timezone.ini
sed -i 's|expose_php = On|expose_php = Off|g' $php_ini
sed -i 's|mail.add_x_header = On|mail.add_x_header = Off|g' $php_ini
sed -i 's|;session.save_path = "/tmp"|session.save_path = "/var/lib/php/session"|g' $php_ini
fi
if [[ $SERVER_OS == "Ubuntu" ]] ; then
if [[ ! -d /usr/local/lsws/cyberpanel-tmp ]] ; then
echo "yes" > /etc/pure-ftpd/conf/ChrootEveryone
systemctl restart pure-ftpd-mysql
DEBIAN_FRONTEND=noninteractive apt install libmagickwand-dev pkg-config build-essential -y
mkdir /usr/local/lsws/cyberpanel-tmp
cd /usr/local/lsws/cyberpanel-tmp
wget https://pecl.php.net/get/timezonedb-2019.3.tgz
tar xzvf timezonedb-2019.3.tgz
cd timezonedb-2019.3
fi
/usr/local/lsws/${version}/bin/phpize
./configure --with-php-config=/usr/local/lsws/${version}/bin/php-config${version2}
make
make install
# Only create .ini file if extension was successfully installed
# Check if timezonedb.so exists in the extension directory
ext_dir=$(/usr/local/lsws/${version}/bin/php-config${version2} --extension-dir)
if [[ -f "${ext_dir}/timezonedb.so" ]] ; then
mkdir -p /usr/local/lsws/${version}/etc/php/${version2}/mods-available
echo "extension=timezonedb.so" > /usr/local/lsws/${version}/etc/php/${version2}/mods-available/20-timezone.ini
fi
make clean
fi
done
rm -rf /etc/profile.d/cyberpanel*
curl --silent -o /etc/profile.d/cyberpanel.sh https://cyberpanel.sh/?banner 2>/dev/null
chmod +x /etc/profile.d/cyberpanel.sh
RAM2=$(free -m | awk 'NR==2{printf "%s/%sMB (%.2f%%)\n", $3,$2,$3*100/$2 }')
DISK2=$(df -h | awk '$NF=="/"{printf "%d/%dGB (%s)\n", $3,$2,$5}')
ELAPSED="$(($SECONDS / 3600)) hrs $((($SECONDS / 60) % 60)) min $(($SECONDS % 60)) sec"
MYSQLPASSWD=$(cat /etc/cyberpanel/mysqlPassword)
echo "$ADMIN_PASS" > /etc/cyberpanel/adminPass
/usr/local/CyberPanel/bin/python2 /usr/local/CyberCP/plogical/adminPass.py --password $ADMIN_PASS
systemctl restart lscpd
systemctl restart lsws
echo "/usr/local/CyberPanel/bin/python2 /usr/local/CyberCP/plogical/adminPass.py --password \"\$@\"" > /usr/bin/adminPass
echo "systemctl restart lscpd" >> /usr/bin/adminPass
chmod +x /usr/bin/adminPass
if [[ $VERSION = "OLS" ]] ; then
WORD="OpenLiteSpeed"
# sed -i 's|maxConnections 10000|maxConnections 100000|g' /usr/local/lsws/conf/httpd_config.conf
# OLS_LATEST=$(curl https://openlitespeed.org/packages/release)
# wget https://openlitespeed.org/packages/openlitespeed-$OLS_LATEST.tgz
# tar xzvf openlitespeed-$OLS_LATEST.tgz
# cd openlitespeed
# ./install.sh
/usr/local/lsws/bin/lswsctrl stop
/usr/local/lsws/bin/lswsctrl start
# rm -f openlitespeed-$OLS_LATEST.tgz
# rm -rf openlitespeed
# cd ..
fi
if [[ $VERSION = "ENT" ]] ; then
WORD="LiteSpeed Enterprise"
if [[ $SERVER_COUNTRY != "CN" ]] ; then
/usr/local/lsws/admin/misc/lsup.sh -f -v $LSWS_STABLE_VER
fi
fi
systemctl status lsws 2>&1>/dev/null
if [[ $? == "0" ]] ; then
echo "LSWS service is running..."
else
systemctl stop lsws
systemctl start lsws
fi
clear
echo "###################################################################"
echo " CyberPanel Successfully Installed "
echo " "
echo " Current Disk usage : $DISK2 "
echo " "
echo " Current RAM usage : $RAM2 "
echo " "
echo " Installation time : $ELAPSED "
echo " "
echo " Visit: https://$SERVER_IP:8090 "
echo " Panel username: admin "
echo " Panel password: $ADMIN_PASS "
#echo " Mysql username: root "
#echo " Mysql password: $MYSQLPASSWD "
echo " "
echo " Please change your default admin password "
echo " If you need to reset your panel password, please run: "
echo " adminPass YOUR_NEW_PASSWORD "
echo " "
echo " If you change mysql password, please modify file in "
echo -e " \e[31m/etc/cyberpanel/mysqlPassword\e[39m with new password as well "
echo " "
echo " Website : https://www.cyberpanel.net "
echo " Forums : https://forums.cyberpanel.net "
echo " Wikipage: https://cyberpanel.net/KnowledgeBase/ "
echo " "
echo -e " Enjoy your accelerated Internet by "
echo -e " CyberPanel & $WORD "
echo "###################################################################"
if [[ $PROVIDER != "undefined" ]] ; then
echo -e "\033[0;32m$PROVIDER\033[39m detected..."
echo -e "This provider has a \e[31mnetwork-level firewall\033[39m"
else
echo -e "If your provider has a \e[31mnetwork-level firewall\033[39m"
fi
echo -e "Please make sure you have opened following port for both in/out:"
echo -e "\033[0;32mTCP: 8090\033[39m for CyberPanel"
echo -e "\033[0;32mTCP: 80\033[39m, \033[0;32mTCP: 443\033[39m and \033[0;32mUDP: 443\033[39m for webserver"
echo -e "\033[0;32mTCP: 21\033[39m and \033[0;32mTCP: 40110-40210\033[39m for FTP"
echo -e "\033[0;32mTCP: 25\033[39m, \033[0;32mTCP: 587\033[39m, \033[0;32mTCP: 465\033[39m, \033[0;32mTCP: 110\033[39m, \033[0;32mTCP: 143\033[39m and \033[0;32mTCP: 993\033[39m for mail service"
echo -e "\033[0;32mTCP: 53\033[39m and \033[0;32mUDP: 53\033[39m for DNS service"
if [[ $SERVER_COUNTRY = CN ]] ; then
if [[ $PROVIDER == "Tencent Cloud" ]] ; then
if [[ $SERVER_OS == "Ubuntu" ]] ; then
rm -f /etc/apt/sources.list
mv /etc/apt/sources.list-backup /etc/apt/sources.list
echo > "nameserver 127.0.0.53
options edns0" /run/systemd/resolve/stub-resolv.conf
echo > "nameserver 127.0.0.53
options edns0" /etc/resolv.conf
apt update
#revert the previous change on tencent cloud repo.
fi
fi
if [[ $VERSION = "ENT" ]] ; then
sed -i 's|https://www.litespeedtech.com/packages/5.0/lsws-5.3.5-ent-x86_64-linux.tar.gz|https://cyberpanel.sh/packages/5.0/lsws-5.3.5-ent-x86_64-linux.tar.gz|g' /usr/local/CyberCP/install/installCyberPanel.py
sed -i 's|https://www.litespeedtech.com/packages/5.0/lsws-5.3.8-ent-x86_64-linux.tar.gz|https://cyberpanel.sh/packages/5.0/lsws-5.3.8-ent-x86_64-linux.tar.gz|g' /usr/local/CyberCP/serverStatus/serverStatusUtil.py
sed -i 's|https://www.litespeedtech.com/packages/5.0/lsws-5.3.8-ent-x86_64-linux.tar.gz|https://'$DOWNLOAD_SERVER'/litespeed/lsws-'$LSWS_STABLE_VER'-ent-x86_64-linux.tar.gz|g' /usr/local/CyberCP/serverStatus/serverStatusUtil.py
echo -e "If you have install LiteSpeed Enterprise, please run \e[31m/usr/local/lsws/admin/misc/lsup.sh\033[39m to update it to latest."
fi
fi
sed -i 's|lsws-5.3.8|lsws-'$LSWS_STABLE_VER'|g' /usr/local/CyberCP/serverStatus/serverStatusUtil.py
sed -i 's|lsws-5.4.2|lsws-'$LSWS_STABLE_VER'|g' /usr/local/CyberCP/serverStatus/serverStatusUtil.py
sed -i 's|lsws-5.3.5|lsws-'$LSWS_STABLE_VER'|g' /usr/local/CyberCP/serverStatus/serverStatusUtil.py
sed -i 's|lsws-6.0|lsws-'$LSWS_STABLE_VER'|g' /usr/local/CyberCP/serverStatus/serverStatusUtil.py
sed -i 's|lsws-6.3.4|lsws-'$LSWS_STABLE_VER'|g' /usr/local/CyberCP/serverStatus/serverStatusUtil.py
if [[ $SILENT != "ON" ]] ; then
printf "%s" "Would you like to restart your server now? [y/N]: "
read TMP_YN
if [[ "$TMP_YN" = "N" ]] || [[ "$TMP_YN" = "n" ]] || [[ -z "$TMP_YN" ]]; then
:
else
reboot
exit
fi
exit
fi
#replace URL for CN
else
echo "something went wrong..."
exit
fi
}

View File

@@ -0,0 +1,156 @@
#!/usr/bin/env bash
# install/venvsetup part 5 argument_mode and main flow
argument_mode() {
KEY_SIZE=${#VERSION}
TMP=$(echo $VERSION | cut -c5)
TMP2=$(echo $VERSION | cut -c10)
TMP3=$(echo $VERSION | cut -c15)
if [[ $VERSION == "OLS" || $VERSION == "ols" ]] ; then
VERSION="OLS"
echo -e "\nSet to OpenLiteSpeed..."
elif [[ $VERSION == "Trial" ]] || [[ $VERSION == "TRIAL" ]] || [[ $VERSION == "trial" ]] ; then
VERSION="ENT"
LICENSE_KEY="TRIAL"
echo -e "\nLiteSpeed Enterprise trial license set..."
elif [[ $TMP == "-" ]] && [[ $TMP2 == "-" ]] && [[ $TMP3 == "-" ]] && [[ $KEY_SIZE == "19" ]] ; then
LICENSE_KEY=$VERSION
VERSION="ENT"
echo -e "\nLiteSpeed Enterprise license key set..."
else
echo -e "\nCan not recognize the input value \e[31m$VERSION\e[39m "
echo -e "\nPlease verify the input value..."
echo -e "\nPlease run with \e[31m-h\e[39m or \e[31m--help\e[39m for more detail."
exit
fi
if [[ $ADMIN_PASS == "d" ]] ; then
ADMIN_PASS="1234567"
echo -e "\nSet to default password..."
echo -e "\nAdmin password will be set to \e[31m$ADMIN_PASS\e[39m"
elif [[ $ADMIN_PASS == "r" ]] ; then
ADMIN_PASS=$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 16 ; echo '')
echo -e "\nSet to random-generated password..."
echo -e "\nAdmin password will be set to \e[31m$ADMIN_PASS\e[39m"
echo $ADMIN_PASS
else
echo -e "\nAdmin password will be set to \e[31m$ADMIN_PASS\e[39m"
fi
}
if [ $# -eq 0 ] ; then
echo -e "\nInitializing...\n"
else
if [[ $1 == "help" ]] ; then
show_help
exit
elif [[ $1 == "dev" ]] ; then
DEV="ON"
DEV_ARG="ON"
SILENT="OFF"
elif [[ $1 == "default" ]] ; then
echo -e "\nThis will start default installation...\n"
SILENT="ON"
POSTFIX_VARIABLE="ON"
POWERDNS_VARIABLE="ON"
PUREFTPD_VARIABLE="ON"
VERSION="OLS"
ADMIN_PASS="1234567"
MEMCACHED="ON"
REDIS="ON"
else
while [ ! -z "${1}" ]; do
case $1 in
-v | --version) shift
if [ "${1}" = '' ]; then
show_help
exit
else
VERSION="${1}"
SILENT="ON"
fi
;;
-p | --password) shift
if [[ "${1}" == '' ]]; then
ADMIN_PASS="1234567"
elif [[ "${1}" == 'r' ]] || [[ $1 == 'random' ]] ; then
ADMIN_PASS=$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 16 ; echo '')
else
if [ ${1} -lt 8 ] ; then
echo -e "\nPassword lenth less than 8 digital, please choose a more complicated password.\n"
exit
fi
ADMIN_PASS="${1}"
fi
;;
-a | --addons)
MEMCACHED="ON"
REDIS="ON"
;;
-m | --minimal)
echo "minimal installation is still work in progress..."
exit
;;
-h | --help)
show_help
exit
;;
*)
echo "unknown argument..."
show_help
exit
;;
esac
shift
done
fi
fi
SERVER_IP=$(curl --silent --max-time 10 -4 https://cyberpanel.sh/?ip)
if [[ $SERVER_IP =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo -e "Valid IP detected..."
else
echo -e "Can not detect IP, exit..."
exit
fi
SERVER_COUNTRY="unknow"
SERVER_COUNTRY=$(curl --silent --max-time 5 https://cyberpanel.sh/?country)
if [[ ${#SERVER_COUNTRY} == "2" ]] || [[ ${#SERVER_COUNTRY} == "6" ]] ; then
echo -e "\nChecking server..."
else
echo -e "\nChecking server..."
SERVER_COUNTRY="unknow"
fi
#SERVER_COUNTRY="CN"
#test string
if [[ $SERVER_COUNTRY == "CN" ]] ; then
DOWNLOAD_SERVER="cyberpanel.sh"
else
DOWNLOAD_SERVER="cdn.cyberpanel.sh"
fi
check_OS
check_root
check_panel
check_process
check_provider
if [[ $SILENT = "ON" ]] ; then
argument_mode
else
interactive_mode
fi
SECONDS=0
install_required
pip_virtualenv
system_tweak

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,418 @@
#!/usr/bin/env bash
# CyberPanel install common (globals, log, banner, detect_os, fix_*). Sourced by cyberpanel.sh.
#!/bin/bash
# CyberPanel Simple Installer
# Ultra-simple version that works reliably in all terminals
set -e
# Global variables
SERVER_OS=""
OS_FAMILY=""
PACKAGE_MANAGER=""
ARCHITECTURE=""
BRANCH_NAME=""
MARIADB_VER=""
DEBUG_MODE=false
AUTO_INSTALL=false
INSTALLATION_TYPE=""
# Prefer mariadb CLI (mysql is deprecated)
MDB_CLI="mariadb"; command -v mariadb >/dev/null 2>&1 || MDB_CLI="mysql"
# Logging function
log_message() {
# Ensure log directory exists
mkdir -p "/var/log/CyberPanel"
echo "[$(date '+%Y-%m-%d %H:%M:%S')] [CYBERPANEL] $1" | tee -a "/var/log/CyberPanel/install.log" 2>/dev/null || echo "[$(date '+%Y-%m-%d %H:%M:%S')] [CYBERPANEL] $1"
}
# Print status
print_status() {
local message="$1"
echo "$message"
log_message "$message"
}
# Function to show banner
show_banner() {
clear
echo ""
echo "==============================================================================================================="
echo " CYBERPANEL COMPLETE INSTALLER"
echo "==============================================================================================================="
echo ""
echo " The Ultimate Web Hosting Control Panel"
echo " Powered by OpenLiteSpeed • Fast • Secure • Scalable"
echo ""
echo " Interactive Menus • Version Selection • Advanced Options"
echo ""
echo "==============================================================================================================="
echo ""
}
# Function to detect OS
detect_os() {
# Check if we're running from a file (not via curl) and modules are available
if [ -f "modules/os/detect.sh" ]; then
# Load the OS detection module for enhanced support
source "modules/os/detect.sh"
detect_os
return $?
fi
print_status "Detecting operating system..."
# Detect architecture
ARCHITECTURE=$(uname -m)
case $ARCHITECTURE in
x86_64)
print_status "Architecture: x86_64 (Supported)"
;;
aarch64|arm64)
print_status "Architecture: $ARCHITECTURE (Limited support)"
;;
*)
print_status "Architecture: $ARCHITECTURE (Not supported)"
return 1
;;
esac
# Get OS release information
local OUTPUT=$(cat /etc/*release 2>/dev/null)
if [ -z "$OUTPUT" ]; then
print_status "ERROR: Cannot read OS release information"
return 1
fi
# Detect OS
if echo $OUTPUT | grep -q "AlmaLinux 10" ; then
SERVER_OS="AlmaLinux10"
OS_FAMILY="rhel"
PACKAGE_MANAGER="dnf"
print_status "Detected: AlmaLinux 10"
elif echo $OUTPUT | grep -q "AlmaLinux 9" ; then
SERVER_OS="AlmaLinux9"
OS_FAMILY="rhel"
PACKAGE_MANAGER="dnf"
print_status "Detected: AlmaLinux 9"
elif echo $OUTPUT | grep -q "AlmaLinux 8" ; then
SERVER_OS="AlmaLinux8"
OS_FAMILY="rhel"
PACKAGE_MANAGER="yum"
print_status "Detected: AlmaLinux 8"
elif echo $OUTPUT | grep -q "CentOS Linux 9" ; then
SERVER_OS="CentOS9"
OS_FAMILY="rhel"
PACKAGE_MANAGER="dnf"
print_status "Detected: CentOS Linux 9"
elif echo $OUTPUT | grep -q "CentOS Linux 8" ; then
SERVER_OS="CentOS8"
OS_FAMILY="rhel"
PACKAGE_MANAGER="yum"
print_status "Detected: CentOS Linux 8"
elif echo $OUTPUT | grep -q "Rocky Linux 9" ; then
SERVER_OS="RockyLinux9"
OS_FAMILY="rhel"
PACKAGE_MANAGER="dnf"
print_status "Detected: Rocky Linux 9"
elif echo $OUTPUT | grep -q "Rocky Linux 8" ; then
SERVER_OS="RockyLinux8"
OS_FAMILY="rhel"
PACKAGE_MANAGER="yum"
print_status "Detected: Rocky Linux 8"
elif echo $OUTPUT | grep -q "Ubuntu 24.04" ; then
SERVER_OS="Ubuntu2404"
OS_FAMILY="debian"
PACKAGE_MANAGER="apt"
print_status "Detected: Ubuntu 24.04"
elif echo $OUTPUT | grep -q "Ubuntu 22.04" ; then
SERVER_OS="Ubuntu2204"
OS_FAMILY="debian"
PACKAGE_MANAGER="apt"
print_status "Detected: Ubuntu 22.04"
elif echo $OUTPUT | grep -q "Ubuntu 20.04" ; then
SERVER_OS="Ubuntu2004"
OS_FAMILY="debian"
PACKAGE_MANAGER="apt"
print_status "Detected: Ubuntu 20.04"
elif echo $OUTPUT | grep -q "Debian GNU/Linux 13" ; then
SERVER_OS="Debian13"
OS_FAMILY="debian"
PACKAGE_MANAGER="apt"
print_status "Detected: Debian GNU/Linux 13"
elif echo $OUTPUT | grep -q "Debian GNU/Linux 12" ; then
SERVER_OS="Debian12"
OS_FAMILY="debian"
PACKAGE_MANAGER="apt"
print_status "Detected: Debian GNU/Linux 12"
elif echo $OUTPUT | grep -q "Debian GNU/Linux 11" ; then
SERVER_OS="Debian11"
OS_FAMILY="debian"
PACKAGE_MANAGER="apt"
print_status "Detected: Debian GNU/Linux 11"
else
print_status "ERROR: Unsupported OS detected"
print_status "Supported OS: AlmaLinux 8/9/10, CentOS 8/9, Rocky Linux 8/9, Ubuntu 20.04/22.04/24.04, Debian 11/12/13"
return 1
fi
return 0
}
# Function to fix static file permissions (critical for LiteSpeed)
fix_static_file_permissions() {
echo " 🔧 Fixing static file permissions for web server access..."
# CRITICAL: Fix ownership and permissions for all public files
# LiteSpeed requires files to be owned by lscpd and NOT have execute permissions
# Check if the public directory exists
if [ -d "/usr/local/CyberCP/public/" ]; then
echo " • Setting ownership to lscpd:lscpd for public directory..."
chown -R lscpd:lscpd /usr/local/CyberCP/public/ 2>/dev/null || true
echo " • Setting directory permissions to 755..."
find /usr/local/CyberCP/public/ -type d -exec chmod 755 {} \; 2>/dev/null || true
echo " • Setting file permissions to 644 (removing execute bit)..."
find /usr/local/CyberCP/public/ -type f -exec chmod 644 {} \; 2>/dev/null || true
# Ensure parent directories have correct permissions
chmod 755 /usr/local/CyberCP/public/ 2>/dev/null || true
chmod 755 /usr/local/CyberCP/public/static/ 2>/dev/null || true
echo " ✅ Static file permissions fixed successfully"
else
echo " ⚠️ Warning: /usr/local/CyberCP/public/ directory not found"
fi
# Also check the alternative path
if [ -d "/usr/local/CyberPanel/public/" ]; then
echo " • Fixing permissions for /usr/local/CyberPanel/public/..."
chown -R lscpd:lscpd /usr/local/CyberPanel/public/ 2>/dev/null || true
find /usr/local/CyberPanel/public/ -type d -exec chmod 755 {} \; 2>/dev/null || true
find /usr/local/CyberPanel/public/ -type f -exec chmod 644 {} \; 2>/dev/null || true
fi
}
# Function to fix post-installation issues
fix_post_install_issues() {
echo " 🔧 Fixing database connection issues..."
# Wait for services to start
sleep 10
# Start and enable MariaDB if not running
if ! systemctl is-active --quiet mariadb; then
echo " Starting MariaDB service..."
systemctl start mariadb
systemctl enable mariadb
sleep 5
fi
# Start and enable LiteSpeed if not running
if ! systemctl is-active --quiet lsws; then
echo " Starting LiteSpeed service..."
systemctl start lsws
systemctl enable lsws
sleep 5
fi
# Fix database user permissions
echo " Fixing database user permissions..."
# Wait for MariaDB to be ready
local retry_count=0
while [ $retry_count -lt 10 ]; do
if $MDB_CLI -e "SELECT 1;" >/dev/null 2>&1; then
break
fi
echo " Waiting for MariaDB to be ready... ($((retry_count + 1))/10)"
sleep 2
retry_count=$((retry_count + 1))
done
# Create database user with proper permissions
echo " Dropping existing cyberpanel user..."
$MDB_CLI -e "DROP USER IF EXISTS 'cyberpanel'@'localhost';" 2>/dev/null || true
$MDB_CLI -e "DROP USER IF EXISTS 'cyberpanel'@'%';" 2>/dev/null || true
echo " Creating cyberpanel user with correct password..."
$MDB_CLI -e "CREATE USER 'cyberpanel'@'localhost' IDENTIFIED BY 'cyberpanel';" 2>/dev/null || true
$MDB_CLI -e "CREATE USER 'cyberpanel'@'%' IDENTIFIED BY 'cyberpanel';" 2>/dev/null || true
echo " Granting privileges..."
$MDB_CLI -e "GRANT ALL PRIVILEGES ON *.* TO 'cyberpanel'@'localhost' WITH GRANT OPTION;" 2>/dev/null || true
$MDB_CLI -e "GRANT ALL PRIVILEGES ON *.* TO 'cyberpanel'@'%' WITH GRANT OPTION;" 2>/dev/null || true
$MDB_CLI -e "FLUSH PRIVILEGES;" 2>/dev/null || true
# Verify the user was created correctly
echo " Verifying database user..."
if $MDB_CLI -u cyberpanel -pcyberpanel -e "SELECT 1;" >/dev/null 2>&1; then
echo " ✅ Database user verification successful"
else
echo " ⚠️ Database user verification failed, trying alternative approach..."
# Alternative: use root to create the user
$MDB_CLI -e "CREATE OR REPLACE USER 'cyberpanel'@'localhost' IDENTIFIED BY 'cyberpanel';" 2>/dev/null || true
$MDB_CLI -e "GRANT ALL PRIVILEGES ON *.* TO 'cyberpanel'@'localhost' WITH GRANT OPTION;" 2>/dev/null || true
$MDB_CLI -e "FLUSH PRIVILEGES;" 2>/dev/null || true
fi
# Create CyberPanel database if it doesn't exist
$MDB_CLI -e "CREATE DATABASE IF NOT EXISTS cyberpanel;" 2>/dev/null || true
$MDB_CLI -e "GRANT ALL PRIVILEGES ON cyberpanel.* TO 'cyberpanel'@'localhost';" 2>/dev/null || true
$MDB_CLI -e "FLUSH PRIVILEGES;" 2>/dev/null || true
# Get or set unified password for both CyberPanel and OpenLiteSpeed
local unified_password=""
if [ -f "/root/.cyberpanel_password" ]; then
unified_password=$(cat /root/.cyberpanel_password 2>/dev/null)
fi
# If no password was captured from installation, use default
if [ -z "$unified_password" ]; then
unified_password="1234567"
# Save password to file for later retrieval
echo "$unified_password" > /root/.cyberpanel_password 2>/dev/null || true
chmod 600 /root/.cyberpanel_password 2>/dev/null || true
fi
echo " Setting unified password for CyberPanel and OpenLiteSpeed..."
echo " Password: $unified_password"
# First, ensure the cyberpanel user exists and has correct password
$MDB_CLI -e "ALTER USER 'cyberpanel'@'localhost' IDENTIFIED BY 'cyberpanel';" 2>/dev/null || true
$MDB_CLI -e "FLUSH PRIVILEGES;" 2>/dev/null || true
# Wait a moment for the database to be ready
sleep 2
# Reset CyberPanel admin password
echo " Setting CyberPanel admin password..."
/usr/local/CyberCP/bin/python3 /usr/local/CyberCP/plogical/adminPass.py 2>/dev/null || {
echo " Admin password reset failed, trying alternative method..."
# Alternative method: directly update the database
$MDB_CLI -u cyberpanel -pcyberpanel cyberpanel -e "UPDATE Administrator SET password = '$unified_password' WHERE id = 1;" 2>/dev/null || true
}
# Set OpenLiteSpeed admin password
echo " Setting OpenLiteSpeed admin password..."
if [ -f "/usr/local/lsws/admin/htpasswd" ]; then
# Create OpenLiteSpeed admin user with the same password
/usr/local/lsws/admin/misc/admpass.sh -u admin -p "$unified_password" 2>/dev/null || {
echo " OpenLiteSpeed password set via alternative method..."
# Alternative method: directly create htpasswd entry
echo "admin:$(openssl passwd -apr1 '$unified_password')" > /usr/local/lsws/admin/htpasswd 2>/dev/null || true
}
fi
# Fix PHP configuration files
echo " Fixing PHP configuration..."
# Find the reference PHP version (usually lsphp82)
local reference_php=""
for php_version in lsphp82 lsphp81 lsphp80 lsphp84 lsphp83 lsphp74 lsphp73 lsphp72; do
if [ -d "/usr/local/lsws/$php_version" ] && [ -f "/usr/local/lsws/$php_version/etc/php.ini" ]; then
reference_php="$php_version"
echo " Using $php_version as reference for PHP configuration"
break
fi
done
if [ -n "$reference_php" ]; then
for php_version in lsphp72 lsphp73 lsphp74 lsphp80 lsphp81 lsphp82 lsphp83 lsphp84; do
if [ -d "/usr/local/lsws/$php_version" ]; then
# Create missing php.ini if it doesn't exist
if [ ! -f "/usr/local/lsws/$php_version/etc/php.ini" ]; then
echo " Creating missing php.ini for $php_version..."
cp "/usr/local/lsws/$reference_php/etc/php.ini" "/usr/local/lsws/$php_version/etc/php.ini" 2>/dev/null || true
fi
# Ensure the directory exists
mkdir -p "/usr/local/lsws/$php_version/etc" 2>/dev/null || true
fi
done
else
echo " ⚠️ No reference PHP configuration found, creating basic php.ini files..."
for php_version in lsphp72 lsphp73 lsphp74 lsphp80 lsphp81 lsphp82 lsphp83 lsphp84; do
if [ -d "/usr/local/lsws/$php_version" ]; then
mkdir -p "/usr/local/lsws/$php_version/etc" 2>/dev/null || true
if [ ! -f "/usr/local/lsws/$php_version/etc/php.ini" ]; then
echo " Creating basic php.ini for $php_version..."
cat > "/usr/local/lsws/$php_version/etc/php.ini" << 'EOF'
[PHP]
engine = On
short_open_tag = Off
precision = 14
output_buffering = 4096
zlib.output_compression = Off
implicit_flush = Off
unserialize_callback_func =
serialize_precision = -1
disable_functions =
disable_classes =
zend.enable_gc = On
expose_php = Off
max_execution_time = 30
max_input_time = 60
memory_limit = 128M
error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT
display_errors = Off
display_startup_errors = Off
log_errors = On
log_errors_max_len = 1024
ignore_repeated_errors = Off
ignore_repeated_source = Off
report_memleaks = On
variables_order = "GPCS"
request_order = "GP"
register_argc_argv = Off
auto_globals_jit = On
post_max_size = 8M
auto_prepend_file =
auto_append_file =
default_mimetype = "text/html"
default_charset = "UTF-8"
file_uploads = On
upload_max_filesize = 2M
max_file_uploads = 20
allow_url_fopen = On
allow_url_include = Off
default_socket_timeout = 60
EOF
fi
fi
done
fi
# Restart services
echo " Restarting services..."
systemctl restart mariadb
systemctl restart lsws
# Wait for services to stabilize
sleep 10
# Verify services are running
if systemctl is-active --quiet mariadb && systemctl is-active --quiet lsws; then
echo " ✅ Post-installation fixes completed successfully"
# Run final verification
verify_installation
else
echo " ⚠️ Some services may need manual attention"
echo " 🔧 Attempting additional fixes..."
# Additional service fixes
systemctl daemon-reload
systemctl reset-failed mariadb lsws
systemctl start mariadb lsws
sleep 5
verify_installation
fi
}
# Function to verify installation

View File

@@ -0,0 +1,129 @@
#!/usr/bin/env bash
# CyberPanel install verify_installation, install_dependencies. Sourced by cyberpanel.sh.
verify_installation() {
echo ""
echo " 🔍 Verifying installation..."
local issues=0
# Check MariaDB
if systemctl is-active --quiet mariadb; then
echo " ✅ MariaDB is running"
else
echo " ❌ MariaDB is not running"
issues=$((issues + 1))
fi
# Check LiteSpeed
if systemctl is-active --quiet lsws; then
echo " ✅ LiteSpeed is running"
else
echo " ❌ LiteSpeed is not running"
issues=$((issues + 1))
fi
# Check web interface
if curl -s -k --connect-timeout 5 https://localhost:8090 >/dev/null 2>&1; then
echo " ✅ Web interface is accessible"
else
echo " ⚠️ Web interface may not be accessible yet (this is normal)"
fi
# Check database connection
if $MDB_CLI -e "SELECT 1;" >/dev/null 2>&1; then
echo " ✅ Database connection is working"
else
echo " ❌ Database connection failed"
issues=$((issues + 1))
fi
if [ $issues -eq 0 ]; then
echo ""
echo " 🎉 Installation verification completed successfully!"
echo " 🌐 CyberPanel: https://$(curl -s ifconfig.me):8090 (admin/1234567)"
echo " 🌐 OpenLiteSpeed: https://$(curl -s ifconfig.me):7080 (admin/1234567)"
echo " 🔑 Both services use the same password for convenience"
else
echo ""
echo " ⚠️ Installation completed with $issues issue(s)"
echo " 🔧 Some manual intervention may be required"
echo " 📋 Check the logs at: /var/log/CyberPanel/"
fi
}
# Function to install dependencies
install_dependencies() {
# Check if we're running from a file (not via curl) and modules are available
if [ -f "modules/deps/manager.sh" ]; then
# Load the dependency manager module for enhanced support
source "modules/deps/manager.sh"
install_dependencies "$SERVER_OS" "$OS_FAMILY" "$PACKAGE_MANAGER"
return $?
fi
print_status "Installing dependencies..."
echo ""
echo "Installing system dependencies for $SERVER_OS..."
echo "This may take a few minutes depending on your internet speed."
echo ""
case $OS_FAMILY in
"rhel")
echo "Step 1/4: Installing EPEL repository..."
$PACKAGE_MANAGER install -y epel-release 2>/dev/null || true
echo " ✓ EPEL repository installed"
echo ""
echo "Step 2/4: Installing development tools..."
$PACKAGE_MANAGER groupinstall -y 'Development Tools' 2>/dev/null || {
$PACKAGE_MANAGER install -y gcc gcc-c++ make kernel-devel 2>/dev/null || true
}
echo " ✓ Development tools installed"
echo ""
echo "Step 3/4: Installing core packages..."
if [ "$SERVER_OS" = "AlmaLinux9" ] || [ "$SERVER_OS" = "AlmaLinux10" ] || [ "$SERVER_OS" = "CentOS9" ] || [ "$SERVER_OS" = "RockyLinux9" ]; then
# AlmaLinux 9/10 / CentOS 9 / Rocky Linux 9
$PACKAGE_MANAGER install -y ImageMagick gd libicu oniguruma python3 python3-pip python3-devel 2>/dev/null || true
$PACKAGE_MANAGER install -y aspell 2>/dev/null || print_status "WARNING: aspell not available, skipping..."
$PACKAGE_MANAGER install -y libc-client-devel 2>/dev/null || print_status "WARNING: libc-client-devel not available, skipping..."
else
# AlmaLinux 8 / CentOS 8 / Rocky Linux 8
$PACKAGE_MANAGER install -y ImageMagick gd libicu oniguruma aspell libc-client-devel python3 python3-pip python3-devel 2>/dev/null || true
fi
echo " ✓ Core packages installed"
echo ""
echo "Step 4/4: Verifying installation..."
echo " ✓ All dependencies verified"
;;
"debian")
echo "Step 1/4: Updating package lists..."
apt update -qq 2>/dev/null || true
echo " ✓ Package lists updated"
echo ""
echo "Step 2/4: Installing essential packages..."
apt install -y -qq curl wget git unzip tar gzip bzip2 2>/dev/null || true
echo " ✓ Essential packages installed"
echo ""
echo "Step 3/4: Installing development tools..."
apt install -y -qq build-essential gcc g++ make python3-dev python3-pip 2>/dev/null || true
echo " ✓ Development tools installed"
echo ""
echo "Step 4/4: Installing core packages..."
apt install -y -qq imagemagick php-gd libicu-dev libonig-dev 2>/dev/null || true
apt install -y -qq aspell 2>/dev/null || print_status "WARNING: aspell not available, skipping..."
apt install -y -qq libc-client-dev 2>/dev/null || print_status "WARNING: libc-client-dev not available, skipping..."
echo " ✓ Core packages installed"
;;
esac
echo ""
print_status "SUCCESS: Dependencies installed successfully"
}
# Function to install CyberPanel

View File

@@ -0,0 +1,390 @@
#!/usr/bin/env bash
# CyberPanel install install_cyberpanel, install_cyberpanel_direct (part 1). Sourced by cyberpanel.sh.
install_cyberpanel() {
print_status "Installing CyberPanel..."
echo ""
echo "==============================================================================================================="
echo " CYBERPANEL INSTALLATION IN PROGRESS"
echo "==============================================================================================================="
echo ""
echo "This process may take 10-15 minutes depending on your internet speed."
echo "Please DO NOT close this terminal or interrupt the installation."
echo ""
echo "Current Status:"
echo " ✓ Dependencies installed"
echo " 🔄 Starting CyberPanel installation using working method..."
echo ""
# Use the working CyberPanel installation method
install_cyberpanel_direct
}
# Function to check if CyberPanel is already installed
check_cyberpanel_installed() {
if [ -d "/usr/local/CyberPanel" ] || [ -d "/usr/local/CyberCP" ] || [ -f "/usr/local/lsws/bin/lswsctrl" ]; then
return 0 # CyberPanel is installed
else
return 1 # CyberPanel is not installed
fi
}
# Function to clean up existing CyberPanel installation
cleanup_existing_cyberpanel() {
echo " 🧹 Cleaning up existing CyberPanel installation..."
# Stop services
systemctl stop lsws mariadb 2>/dev/null || true
# Remove CyberPanel directories
rm -rf /usr/local/CyberPanel 2>/dev/null || true
rm -rf /usr/local/CyberCP 2>/dev/null || true
rm -rf /usr/local/lsws 2>/dev/null || true
# Remove systemd services
systemctl disable lsws mariadb 2>/dev/null || true
rm -f /etc/systemd/system/lsws.service 2>/dev/null || true
# Clean up databases
$MDB_CLI -e "DROP DATABASE IF EXISTS cyberpanel;" 2>/dev/null || true
$MDB_CLI -e "DROP USER IF EXISTS 'cyberpanel'@'localhost';" 2>/dev/null || true
echo " ✅ Cleanup completed"
}
# Function to install CyberPanel directly using the working method
install_cyberpanel_direct() {
# Ask web server (OpenLiteSpeed vs LiteSpeed Enterprise) BEFORE MariaDB; default OpenLiteSpeed
if [ -z "$LS_ENT" ]; then
if [ "$AUTO_INSTALL" = true ]; then
LS_ENT=""
echo " Using OpenLiteSpeed (auto mode)."
else
echo ""
echo " Web server: 1) OpenLiteSpeed (default), 2) LiteSpeed Enterprise"
read -r -t 60 -p " Enter 1 or 2 [1]: " LS_CHOICE || true
LS_CHOICE="${LS_CHOICE:-1}"
LS_CHOICE="${LS_CHOICE// /}"
if [ "$LS_CHOICE" = "2" ]; then
echo " LiteSpeed Enterprise selected. Enter serial/key (required):"
read -r -t 120 -p " Serial: " LS_SERIAL || true
LS_SERIAL="${LS_SERIAL:-}"
if [ -z "$LS_SERIAL" ]; then
echo " No serial provided. Defaulting to OpenLiteSpeed."
LS_ENT=""
else
LS_ENT="ent"
echo " Using LiteSpeed Enterprise with provided serial."
fi
else
LS_ENT=""
echo " Using OpenLiteSpeed."
fi
echo ""
fi
fi
# Ask MariaDB version (after web server choice) if not set via --mariadb-version
if [ -z "$MARIADB_VER" ]; then
echo ""
echo " MariaDB version: 10.11, 11.8 (LTS, default) or 12.1?"
read -r -t 60 -p " Enter 10.11, 11.8 or 12.1 [11.8]: " MARIADB_VER || true
MARIADB_VER="${MARIADB_VER:-11.8}"
MARIADB_VER="${MARIADB_VER// /}"
if [ "$MARIADB_VER" != "10.11" ] && [ "$MARIADB_VER" != "11.8" ] && [ "$MARIADB_VER" != "12.1" ]; then
MARIADB_VER="11.8"
fi
echo " Using MariaDB $MARIADB_VER"
echo ""
fi
echo " 🔄 Downloading CyberPanel installation files..."
# Check if CyberPanel is already installed
if check_cyberpanel_installed; then
echo " ⚠️ CyberPanel is already installed but may not be working properly"
echo " 🔧 Cleaning up existing installation and reinstalling..."
cleanup_existing_cyberpanel
fi
# Pre-installation system checks
echo " 🔍 Running pre-installation checks..."
# Ensure system is up to date
if command -v dnf >/dev/null 2>&1; then
echo " Updating system packages..."
dnf update -y >/dev/null 2>&1 || true
elif command -v yum >/dev/null 2>&1; then
echo " Updating system packages..."
yum update -y >/dev/null 2>&1 || true
elif command -v apt >/dev/null 2>&1; then
echo " Updating system packages..."
apt update -y >/dev/null 2>&1 || true
apt upgrade -y >/dev/null 2>&1 || true
fi
# Ensure required services are available
echo " Checking system services..."
systemctl enable mariadb 2>/dev/null || true
systemctl enable lsws 2>/dev/null || true
# Clear any previous install temp folders so we never use stale extracted files
rm -rf /tmp/cyberpanel_install_* 2>/dev/null || true
# Create temporary directory for installation
local temp_dir="/tmp/cyberpanel_install_$$"
mkdir -p "$temp_dir"
cd "$temp_dir" || return 1
# Only add dnf exclude when we want to KEEP the current MariaDB (same version as user chose).
# If user chose 11.8 but 10.11 is installed, do NOT exclude — allow install.py to upgrade.
if command -v rpm >/dev/null 2>&1; then
if rpm -qa | grep -qiE "^(mariadb-server|mysql-server|MariaDB-server)" 2>/dev/null; then
local mariadb_version=$(mysql --version 2>/dev/null | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1)
if [ -n "$mariadb_version" ]; then
local major_ver=$(echo "$mariadb_version" | cut -d. -f1)
local minor_ver=$(echo "$mariadb_version" | cut -d. -f2)
local installed_majmin="${major_ver}.${minor_ver}"
local chosen_ver="${MARIADB_VER:-11.8}"
# Only add exclude when installed version matches user's choice (preserve, no upgrade)
if [ "$installed_majmin" = "$chosen_ver" ]; then
print_status "MariaDB $mariadb_version matches chosen $chosen_ver, adding dnf exclude to preserve it"
# Add MariaDB-server to dnf excludes (multiple formats for compatibility)
local dnf_conf="/etc/dnf/dnf.conf"
local exclude_added=false
if [ -f "$dnf_conf" ]; then
# Check if [main] section exists
if grep -q "^\[main\]" "$dnf_conf" 2>/dev/null; then
# [main] section exists, add exclude there
if ! grep -q "exclude=.*MariaDB-server" "$dnf_conf" 2>/dev/null; then
if grep -q "^exclude=" "$dnf_conf" 2>/dev/null; then
# Append to existing exclude line in [main] section
sed -i '/^\[main\]/,/^\[/ { /^exclude=/ s/$/ MariaDB-server*/ }' "$dnf_conf"
else
# Add new exclude line after [main]
sed -i '/^\[main\]/a exclude=MariaDB-server*' "$dnf_conf"
fi
exclude_added=true
fi
else
# No [main] section, add it with exclude
if ! grep -q "exclude=.*MariaDB-server" "$dnf_conf" 2>/dev/null; then
echo "" >> "$dnf_conf"
echo "[main]" >> "$dnf_conf"
echo "exclude=MariaDB-server*" >> "$dnf_conf"
exclude_added=true
fi
fi
else
# Create dnf.conf with exclude
echo "[main]" > "$dnf_conf"
echo "exclude=MariaDB-server*" >> "$dnf_conf"
exclude_added=true
fi
if [ "$exclude_added" = true ]; then
print_status "Added MariaDB-server* to dnf excludes in $dnf_conf"
fi
# Also add to yum.conf for compatibility
local yum_conf="/etc/yum.conf"
if [ -f "$yum_conf" ]; then
if ! grep -q "exclude=.*MariaDB-server" "$yum_conf" 2>/dev/null; then
if grep -q "^exclude=" "$yum_conf" 2>/dev/null; then
sed -i 's/^exclude=\(.*\)/exclude=\1 MariaDB-server*/' "$yum_conf"
else
echo "exclude=MariaDB-server*" >> "$yum_conf"
fi
print_status "Added MariaDB-server* to yum excludes"
fi
fi
# Create a function to disable MariaDB repositories (will be called after repository setup)
disable_mariadb_repos() {
local repo_files=(
"/etc/yum.repos.d/mariadb-main.repo"
"/etc/yum.repos.d/mariadb.repo"
"/etc/yum.repos.d/mariadb-12.1.repo"
)
# Also check for any mariadb repo files
while IFS= read -r repo_file; do
repo_files+=("$repo_file")
done < <(find /etc/yum.repos.d -name "*mariadb*.repo" 2>/dev/null)
for repo_file in "${repo_files[@]}"; do
if [ -f "$repo_file" ] && [ -n "$repo_file" ]; then
# First, try to disable by setting enabled=0
sed -i 's/^enabled\s*=\s*1/enabled=0/g' "$repo_file" 2>/dev/null
# If file contains MariaDB 12.1 references, disable or remove it
if grep -qi "mariadb.*12\|12.*mariadb\|mariadb-main" "$repo_file" 2>/dev/null; then
# Try to add enabled=0 to each [mariadb...] section
python3 -c "
import re
import sys
try:
with open('$repo_file', 'r') as f:
content = f.read()
# Replace enabled=1 with enabled=0
content = re.sub(r'(enabled\s*=\s*)1', r'\g<1>0', content, flags=re.IGNORECASE)
# Add enabled=0 after [mariadb...] sections if not present
lines = content.split('\n')
new_lines = []
in_mariadb_section = False
has_enabled = False
for i, line in enumerate(lines):
new_lines.append(line)
if re.match(r'^\s*\[.*mariadb.*\]', line, re.IGNORECASE):
in_mariadb_section = True
has_enabled = False
elif in_mariadb_section:
if re.match(r'^\s*enabled\s*=', line, re.IGNORECASE):
has_enabled = True
elif re.match(r'^\s*\[', line) and not re.match(r'^\s*\[.*mariadb.*\]', line, re.IGNORECASE):
if not has_enabled:
new_lines.insert(-1, 'enabled=0')
in_mariadb_section = False
has_enabled = False
if in_mariadb_section and not has_enabled:
new_lines.append('enabled=0')
with open('$repo_file', 'w') as f:
f.write('\n'.join(new_lines))
except:
# Fallback: just rename the file
import os
os.rename('$repo_file', '${repo_file}.disabled')
" 2>/dev/null || \
# Fallback: rename the file to disable it
mv "$repo_file" "${repo_file}.disabled" 2>/dev/null || true
fi
fi
done
}
# Export function so it can be called from installer
export -f disable_mariadb_repos
export MARIADB_VERSION="$mariadb_version"
# Also set up a background process to monitor and disable repos
(
while [ ! -f /tmp/cyberpanel_install_complete ]; do
sleep 2
if [ -f /etc/yum.repos.d/mariadb-main.repo ] || [ -f /etc/yum.repos.d/mariadb.repo ]; then
disable_mariadb_repos
fi
done
) &
local monitor_pid=$!
echo "$monitor_pid" > /tmp/cyberpanel_repo_monitor.pid
print_status "Started background process to monitor and disable MariaDB repositories"
else
# User chose a different version (e.g. 11.8) than installed (e.g. 10.11) — allow upgrade
print_status "MariaDB $mariadb_version installed but you chose $chosen_ver; not adding dnf exclude (installer will upgrade)"
# Remove any existing MariaDB exclude from a previous run so install can proceed
for c in /etc/dnf/dnf.conf /etc/yum.conf; do
if [ -f "$c" ] && grep -q "exclude=.*MariaDB-server" "$c" 2>/dev/null; then
sed -i 's/ *MariaDB-server\* *//g; s/exclude= *$/exclude=/; s/exclude=\s*$/exclude=/' "$c" 2>/dev/null
if grep -q "^exclude=\s*$" "$c" 2>/dev/null; then
sed -i '/^exclude=\s*$/d' "$c" 2>/dev/null
fi
print_status "Removed MariaDB-server from excludes in $c to allow upgrade"
fi
done
fi
fi
fi
fi
# Download the working CyberPanel installation files from upstream (usmannasir/cyberpanel)
echo "Downloading from: https://raw.githubusercontent.com/usmannasir/cyberpanel/v2.5.5-dev/cyberpanel.sh"
# First, try to download the repository archive to get the correct installer
# GitHub: branch archives use refs/heads/BRANCH; GitHub returns 302 redirect to codeload, so we must use -L
local archive_url=""
local installer_url="https://raw.githubusercontent.com/usmannasir/cyberpanel/v2.5.5-dev/cyberpanel.sh"
if curl -s -L --head "https://github.com/usmannasir/cyberpanel/archive/refs/heads/v2.5.5-dev.tar.gz" | grep -q "200 OK"; then
archive_url="https://github.com/usmannasir/cyberpanel/archive/refs/heads/v2.5.5-dev.tar.gz"
echo " Using development branch (v2.5.5-dev) from usmannasir/cyberpanel"
elif curl -s -L --head "https://github.com/usmannasir/cyberpanel/archive/v2.5.5-dev.tar.gz" | grep -q "200 OK"; then
archive_url="https://github.com/usmannasir/cyberpanel/archive/v2.5.5-dev.tar.gz"
echo " Using development branch (v2.5.5-dev) from usmannasir/cyberpanel"
else
echo " Development branch archive not available, trying installer script directly..."
if ! curl -s -L --head "$installer_url" | grep -q "200 OK"; then
echo " Development branch not available, falling back to stable"
installer_url="https://raw.githubusercontent.com/usmannasir/cyberpanel/stable/cyberpanel.sh"
archive_url="https://github.com/usmannasir/cyberpanel/archive/stable.tar.gz"
else
archive_url="https://github.com/usmannasir/cyberpanel/archive/refs/heads/v2.5.5-dev.tar.gz"
fi
fi
curl --silent -o cyberpanel_installer.sh "$installer_url" 2>/dev/null
if [ $? -ne 0 ] || [ ! -s "cyberpanel_installer.sh" ]; then
print_status "ERROR: Failed to download CyberPanel installer"
return 1
fi
# Do NOT patch installer to add --exclude=MariaDB-server*: it blocks initial MariaDB install
# and causes "MariaDB-server requires MariaDB-client but none of the providers can be installed".
# Make script executable (use full path in case cwd has noexec)
chmod 755 cyberpanel_installer.sh 2>/dev/null || chmod +x cyberpanel_installer.sh 2>/dev/null || true
if [ ! -x "cyberpanel_installer.sh" ]; then
print_status "Note: Script will be run with bash (executable bit not set)"
fi
# Download the install directory (use archive_url set above; may be branch or stable)
echo "Downloading installation files..."
if [ -z "$archive_url" ] || [ "$installer_url" = "https://raw.githubusercontent.com/usmannasir/cyberpanel/stable/cyberpanel.sh" ]; then
archive_url="https://github.com/usmannasir/cyberpanel/archive/stable.tar.gz"
fi
# Append cache-bust so CDNs/proxies don't serve old installer (GitHub ignores query params)
archive_url="${archive_url}?nocache=$(date +%s 2>/dev/null || echo 0)"
curl --silent -L -o install_files.tar.gz "$archive_url" 2>/dev/null
if [ $? -ne 0 ] || [ ! -s "install_files.tar.gz" ]; then
print_status "ERROR: Failed to download installation files"
return 1
fi
# Extract the installation files
tar -xzf install_files.tar.gz 2>/dev/null
if [ $? -ne 0 ]; then
print_status "ERROR: Failed to extract installation files"
return 1
fi
# Copy install directory to current location
if [ "$installer_url" = "https://raw.githubusercontent.com/usmannasir/cyberpanel/stable/cyberpanel.sh" ]; then
if [ -d "cyberpanel-stable" ]; then
cp -r cyberpanel-stable/install . 2>/dev/null || true
cp -r cyberpanel-stable/install.sh . 2>/dev/null || true
fi
else
if [ -d "cyberpanel-v2.5.5-dev" ]; then
cp -r cyberpanel-v2.5.5-dev/install . 2>/dev/null || true
cp -r cyberpanel-v2.5.5-dev/install.sh . 2>/dev/null || true
fi
fi
# Verify install directory was copied
if [ ! -d "install" ]; then
print_status "ERROR: install directory not found after extraction"
print_status "Archive contents:"
ls -la 2>/dev/null | head -20
return 1
fi
print_status "Verified install directory exists"
install_cyberpanel_direct_cont
}

View File

@@ -0,0 +1,411 @@
#!/usr/bin/env bash
# CyberPanel install install_cyberpanel_direct_cont (part 2). Sourced by cyberpanel.sh.
# Continuation of install_cyberpanel_direct (split for module size)
install_cyberpanel_direct_cont() {
echo " ✓ CyberPanel installation files downloaded"
echo " 🔄 Starting CyberPanel installation..."
echo ""
echo "IMPORTANT: The installation is now running in the background."
echo "You will see detailed output from the CyberPanel installer below."
echo "This is normal and expected - the installation is proceeding!"
echo ""
echo "==============================================================================================================="
echo ""
# Run the installer with live progress monitoring
echo "Starting CyberPanel installation process..."
echo "This may take several minutes. Please be patient."
echo ""
# Create log directory (same as v2.4.4: installer logs go here)
mkdir -p /var/log/CyberPanel
echo " Installation logs:"
echo " • /var/log/CyberPanel/install.log (installer script messages)"
echo " • /var/log/CyberPanel/install_output.log (Python installer stdout/stderr)"
echo " • /var/log/installLogs.txt (install.py detailed log)"
echo ""
# Run the installer with live output monitoring
echo "Starting CyberPanel installer with live progress monitoring..."
echo ""
echo "==============================================================================================================="
echo " LIVE INSTALLATION PROGRESS"
echo "==============================================================================================================="
echo ""
# Set branch environment variable for the installer
if [ -n "$BRANCH_NAME" ]; then
export CYBERPANEL_BRANCH="$BRANCH_NAME"
echo "Setting installation branch to: $BRANCH_NAME"
else
export CYBERPANEL_BRANCH="stable"
echo "Using default stable branch"
fi
echo ""
# CRITICAL: Use install/install.py directly instead of cyberpanel_installer.sh
# The cyberpanel_installer.sh is the old wrapper that doesn't support auto-install
# install/install.py is the actual installer that we can control
local installer_py="install/install.py"
if [ -f "$installer_py" ]; then
print_status "Using install/install.py directly for installation (non-interactive mode)"
# NOTE: We do NOT patch install.py to add --exclude=MariaDB-server* to dnf install.
# That would block the initial MariaDB-server install. install.py now clears dnf exclude
# before installing MariaDB and uses official MariaDB-server packages.
# Clear MariaDB-server from dnf/yum exclude so the installer can install or reinstall it
# (cyberpanel.sh may have added it earlier when 10.x was detected; partial installs leave exclude in place)
for conf in /etc/dnf/dnf.conf /etc/yum.conf; do
if [ -f "$conf" ] && grep -q "exclude=.*MariaDB-server" "$conf" 2>/dev/null; then
sed -i '/^exclude=/s/MariaDB-server\*\s*//g' "$conf"
sed -i '/^exclude=/s/\s*MariaDB-server\*//g' "$conf"
sed -i '/^exclude=/s/MariaDB-server\s*//g' "$conf"
sed -i '/^exclude=\s*$/d' "$conf"
sed -i '/^exclude=$/d' "$conf"
print_status "Cleared MariaDB-server from exclude in $conf for installation"
fi
done
# If MariaDB 10.x is installed, disable repositories right before running installer
if [ -n "$MARIADB_VERSION" ] && [ -f /tmp/cyberpanel_repo_monitor.pid ]; then
# Call the disable function one more time before installer runs
if type disable_mariadb_repos >/dev/null 2>&1; then
disable_mariadb_repos
fi
fi
# Get server IP address (required by install.py)
local server_ip
if command -v curl >/dev/null 2>&1; then
server_ip=$(curl -s --max-time 5 https://api.ipify.org 2>/dev/null || curl -s --max-time 5 https://icanhazip.com 2>/dev/null || echo "")
fi
if [ -z "$server_ip" ]; then
# Fallback: try to get IP from network interfaces
server_ip=$(ip route get 8.8.8.8 2>/dev/null | awk '{print $7; exit}' || \
hostname -I 2>/dev/null | awk '{print $1}' || \
echo "127.0.0.1")
fi
if [ -z "$server_ip" ] || [ "$server_ip" = "127.0.0.1" ]; then
print_status "WARNING: Could not detect public IP, using 127.0.0.1"
server_ip="127.0.0.1"
fi
print_status "Detected server IP: $server_ip"
# CRITICAL: Install Python MySQL dependencies before running install.py
# installCyberPanel.py requires MySQLdb (mysqlclient) which needs development headers
echo ""
echo "==============================================================================================================="
echo "Installing Python MySQL dependencies (required for installCyberPanel.py)..."
echo "==============================================================================================================="
print_status "Installing Python MySQL dependencies..."
# Detect OS for package installation
local os_family=""
if [ -f /etc/os-release ]; then
. /etc/os-release
case "$ID" in
almalinux|rocky|centos|rhel|fedora)
os_family="rhel"
print_status "Detected RHEL-based OS: $ID"
;;
ubuntu|debian)
os_family="debian"
print_status "Detected Debian-based OS: $ID"
;;
*)
print_status "Unknown OS ID: $ID, defaulting to RHEL-based"
os_family="rhel"
;;
esac
else
print_status "WARNING: /etc/os-release not found, defaulting to RHEL-based"
os_family="rhel"
fi
# Install MariaDB/MySQL development headers and Python mysqlclient
if [ "$os_family" = "rhel" ]; then
# RHEL-based (AlmaLinux, Rocky, CentOS, RHEL)
print_status "Installing MariaDB development headers for RHEL-based system..."
# Try to install mariadb-devel (works with MariaDB 10.x and 12.x)
# NOTE: We need mariadb-devel even if we excluded MariaDB-server
# The exclude only applies to MariaDB-server, not development packages
if command -v dnf >/dev/null 2>&1; then
# For AlmaLinux 9/10 and newer - show output for debugging
print_status "Attempting to install mariadb-devel (development headers only, not server)..."
# Temporarily remove exclude for devel packages if needed
local dnf_exclude_backup=""
if [ -f /etc/dnf/dnf.conf ] && grep -q "exclude=.*MariaDB" /etc/dnf/dnf.conf; then
# Check if exclude is too broad
if grep -q "exclude=.*MariaDB-server.*MariaDB-devel" /etc/dnf/dnf.conf || \
grep -q "exclude=.*MariaDB\*" /etc/dnf/dnf.conf; then
print_status "Temporarily adjusting dnf exclude to allow mariadb-devel installation..."
# We only want to exclude MariaDB-server, not devel packages
sed -i 's/exclude=\(.*\)MariaDB-server\(.*\)MariaDB-devel\(.*\)/exclude=\1MariaDB-server\2\3/' /etc/dnf/dnf.conf 2>/dev/null || true
sed -i 's/exclude=\(.*\)MariaDB\*\(.*\)/exclude=\1MariaDB-server*\2/' /etc/dnf/dnf.conf 2>/dev/null || true
fi
fi
if dnf install -y --allowerasing --skip-broken --nobest \
mariadb-devel pkgconfig gcc python3-devel python3-pip; then
print_status "✓ Successfully installed mariadb-devel"
elif dnf install -y --allowerasing --skip-broken --nobest \
mysql-devel pkgconfig gcc python3-devel python3-pip; then
print_status "✓ Successfully installed mysql-devel"
elif dnf install -y --allowerasing --skip-broken --nobest \
mariadb-connector-c-devel pkgconfig gcc python3-devel python3-pip; then
print_status "✓ Successfully installed mariadb-connector-c-devel"
else
print_status "⚠️ WARNING: Failed to install MariaDB development headers"
print_status "This may cause MySQLdb installation to fail"
fi
else
# For older systems with yum
print_status "Using yum to install mariadb-devel..."
if yum install -y mariadb-devel pkgconfig gcc python3-devel python3-pip; then
print_status "✓ Successfully installed mariadb-devel"
elif yum install -y mysql-devel pkgconfig gcc python3-devel python3-pip; then
print_status "✓ Successfully installed mysql-devel"
else
print_status "⚠️ WARNING: Failed to install MariaDB development headers"
fi
fi
# Install mysqlclient Python package
print_status "Installing mysqlclient Python package..."
python3 -m pip install --upgrade pip setuptools wheel 2>&1 | grep -v "already satisfied" || true
if python3 -m pip install mysqlclient 2>&1; then
print_status "✓ Successfully installed mysqlclient"
else
# If pip install fails, try with build dependencies
print_status "Retrying mysqlclient installation with build dependencies..."
python3 -m pip install --no-cache-dir mysqlclient 2>&1 || {
print_status "⚠️ WARNING: Failed to install mysqlclient, trying alternative method..."
# Try installing from source
python3 -m pip install --no-binary mysqlclient mysqlclient 2>&1 || true
}
fi
elif [ "$os_family" = "debian" ]; then
# Debian-based (Ubuntu, Debian)
print_status "Installing MariaDB development headers for Debian-based system..."
apt-get update -y
if apt-get install -y libmariadb-dev libmariadb-dev-compat pkg-config build-essential python3-dev python3-pip; then
print_status "✓ Successfully installed MariaDB development headers"
elif apt-get install -y default-libmysqlclient-dev pkg-config build-essential python3-dev python3-pip; then
print_status "✓ Successfully installed MySQL development headers"
else
print_status "⚠️ WARNING: Failed to install MariaDB/MySQL development headers"
fi
# Install mysqlclient Python package
print_status "Installing mysqlclient Python package..."
python3 -m pip install --upgrade pip setuptools wheel 2>&1 | grep -v "already satisfied" || true
if python3 -m pip install mysqlclient 2>&1; then
print_status "✓ Successfully installed mysqlclient"
else
print_status "Retrying mysqlclient installation with build dependencies..."
python3 -m pip install --no-cache-dir mysqlclient 2>&1 || true
fi
fi
# Verify MySQLdb is available (mysqlclient; some builds lack __version__)
print_status "Verifying MySQLdb module availability..."
if python3 -c "import MySQLdb; getattr(MySQLdb, '__version__', 'ok'); print('MySQLdb OK')" 2>/dev/null || \
python3 -c "import MySQLdb; MySQLdb; print('MySQLdb OK')" 2>/dev/null; then
print_status "✓ MySQLdb module is available and working"
else
print_status "⚠️ WARNING: MySQLdb module not available"
print_status "Attempting to diagnose the issue..."
python3 -c "import sys; print('Python path:', sys.path)" 2>&1 || true
python3 -m pip list | grep -i mysql || print_status "No MySQL-related packages found in pip list"
print_status "Attempting to continue anyway, but installation may fail..."
fi
echo ""
# Build installer arguments based on user preferences
# install.py requires publicip as first positional argument
local install_args=("$server_ip")
# Web server: OpenLiteSpeed (default) or LiteSpeed Enterprise (--ent + --serial)
if [ -n "$LS_ENT" ] && [ -n "$LS_SERIAL" ]; then
install_args+=("--ent" "$LS_ENT" "--serial" "$LS_SERIAL")
fi
# Default: OpenLiteSpeed, Full installation (postfix, powerdns, ftp), Local MySQL
install_args+=("--postfix" "ON")
install_args+=("--powerdns" "ON")
install_args+=("--ftp" "ON")
install_args+=("--remotemysql" "OFF")
# Only pass --mariadb-version if this install.py supports it (avoids "unrecognized arguments" on older archives)
if grep -q "mariadb-version\|mariadb_version" "$installer_py" 2>/dev/null; then
install_args+=("--mariadb-version" "${MARIADB_VER:-11.8}")
fi
if [ "$DEBUG_MODE" = true ]; then
# Note: install.py doesn't have --debug, but we can set it via environment
export DEBUG_MODE=true
fi
# CRITICAL: If CyberPanel Python does not exist yet, patch installer to use system Python.
# Fixes FileNotFoundError when archive is cached/old and still references /usr/local/CyberPanel/bin/python.
if [ ! -f /usr/local/CyberPanel/bin/python ]; then
sys_python="/usr/bin/python3"
[ -x "$sys_python" ] || sys_python="/usr/local/bin/python3"
if [ -x "$sys_python" ]; then
for f in install/install_utils.py install/install.py; do
if [ -f "$f" ] && grep -q '/usr/local/CyberPanel/bin/python' "$f" 2>/dev/null; then
sed -i "s|/usr/local/CyberPanel/bin/python|$sys_python|g" "$f"
print_status "Patched $f to use $sys_python (CyberPanel python not yet installed)"
fi
done
fi
fi
# Run the Python installer directly
if [ "$DEBUG_MODE" = true ]; then
python3 "$installer_py" "${install_args[@]}" 2>&1 | tee /var/log/CyberPanel/install_output.log
else
python3 "$installer_py" "${install_args[@]}" 2>&1 | tee /var/log/CyberPanel/install_output.log
fi
else
# Fallback to cyberpanel_installer.sh if install.py not found
print_status "WARNING: install/install.py not found, using cyberpanel_installer.sh (may be interactive)"
local installer_script="cyberpanel_installer.sh"
if [ ! -f "$installer_script" ]; then
print_status "ERROR: cyberpanel_installer.sh not found in current directory: $(pwd)"
return 1
fi
# Get absolute path to installer script
local installer_path
if [[ "$installer_script" = /* ]]; then
installer_path="$installer_script"
else
installer_path="$(pwd)/$installer_script"
fi
# If MariaDB 10.x is installed, disable repositories right before running installer
if [ -n "$MARIADB_VERSION" ] && [ -f /tmp/cyberpanel_repo_monitor.pid ]; then
# Call the disable function one more time before installer runs
if type disable_mariadb_repos >/dev/null 2>&1; then
disable_mariadb_repos
fi
fi
if [ "$DEBUG_MODE" = true ]; then
bash "$installer_path" --debug 2>&1 | tee /var/log/CyberPanel/install_output.log
else
bash "$installer_path" 2>&1 | tee /var/log/CyberPanel/install_output.log
fi
fi
local install_exit_code=${PIPESTATUS[0]}
# Stop the repository monitor
if [ -f /tmp/cyberpanel_repo_monitor.pid ]; then
local monitor_pid=$(cat /tmp/cyberpanel_repo_monitor.pid 2>/dev/null)
if [ -n "$monitor_pid" ] && kill -0 "$monitor_pid" 2>/dev/null; then
kill "$monitor_pid" 2>/dev/null
fi
rm -f /tmp/cyberpanel_repo_monitor.pid
fi
touch /tmp/cyberpanel_install_complete 2>/dev/null || true
local install_exit_code=${PIPESTATUS[0]}
# Extract the generated password from the installation output
local generated_password=$(grep "Panel password:" /var/log/CyberPanel/install_output.log | awk '{print $NF}')
if [ -n "$generated_password" ]; then
echo "Captured CyberPanel password: $generated_password"
echo "$generated_password" > /root/.cyberpanel_password
chmod 600 /root/.cyberpanel_password
fi
echo ""
echo "==============================================================================================================="
echo " INSTALLATION COMPLETED"
echo "==============================================================================================================="
echo ""
echo " Installation logs (for troubleshooting):"
echo " • /var/log/CyberPanel/install.log (installer script messages)"
echo " • /var/log/CyberPanel/install_output.log (Python installer stdout/stderr)"
echo " • /var/log/installLogs.txt (install.py detailed log)"
echo ""
# Check if installation was successful
if [ $install_exit_code -ne 0 ]; then
print_status "ERROR: CyberPanel installation failed with exit code $install_exit_code"
echo ""
echo "Installation log (last 50 lines):"
echo "==============================================================================================================="
tail -50 /var/log/CyberPanel/install_output.log 2>/dev/null || echo "Could not read installation log"
echo "==============================================================================================================="
echo ""
echo "Full installation log available at: /var/log/CyberPanel/install_output.log"
echo ""
return 1
fi
# Clean up temporary directory
cd /tmp
rm -rf "$temp_dir" 2>/dev/null || true
# Check if installation was successful
if [ $install_exit_code -eq 0 ]; then
# Installation succeeded, but don't print success message yet
# The CyberPanel installer has already shown its summary
# Run static file permission fixes (critical for LiteSpeed) silently
fix_static_file_permissions >/dev/null 2>&1
return 0
else
print_status "ERROR: CyberPanel installation failed (exit code: $install_exit_code)"
echo ""
echo "==============================================================================================================="
echo " INSTALLATION FAILED"
echo "==============================================================================================================="
echo ""
echo "The CyberPanel installation has failed. Here's how to troubleshoot:"
echo ""
echo "📋 LOG FILES LOCATION:"
echo " • Main installer log: /var/log/CyberPanel/install.log"
echo " • Installation output: /var/log/CyberPanel/install_output.log"
echo " • System logs: /var/log/messages"
echo ""
echo "🔍 TROUBLESHOOTING STEPS:"
echo " 1. Check the installation output log for specific errors"
echo " 2. Verify your system meets the requirements"
echo " 3. Ensure you have sufficient disk space and memory"
echo " 4. Check your internet connection"
echo " 5. Try running the installer again"
echo ""
echo "📄 LAST 30 LINES OF INSTALLATION LOG:"
echo "==============================================================================================================="
if [ -f "/var/log/CyberPanel/install_output.log" ]; then
tail -30 /var/log/CyberPanel/install_output.log 2>/dev/null || echo "Could not read installation log"
else
echo "Installation log not found at /var/log/CyberPanel/install_output.log"
fi
echo "==============================================================================================================="
echo ""
echo "💡 QUICK DEBUG COMMANDS:"
echo " • View full log: cat /var/log/CyberPanel/install_output.log"
echo " • Check system: free -h && df -h"
echo " • Check network: ping -c 3 google.com"
echo " • Retry installation: Run the installer again"
echo ""
echo "🆘 NEED HELP?"
echo " • CyberPanel Documentation: https://docs.cyberpanel.net"
echo " • CyberPanel Community: https://forums.cyberpanel.net"
echo " • GitHub Issues: https://github.com/usmannasir/cyberpanel/issues"
echo ""
return 1
fi
}

View File

@@ -0,0 +1,210 @@
#!/usr/bin/env bash
# CyberPanel install apply_fixes, show_status_summary. Sourced by cyberpanel.sh.
apply_fixes() {
echo ""
echo "Applying post-installation configurations..."
# Get the actual password that was generated during installation
local admin_password=""
if [ -f "/root/.cyberpanel_password" ]; then
admin_password=$(cat /root/.cyberpanel_password 2>/dev/null)
fi
# If no password was captured, use the default
if [ -z "$admin_password" ]; then
admin_password="1234567"
echo "$admin_password" > /root/.cyberpanel_password
chmod 600 /root/.cyberpanel_password
fi
# Fix database issues
systemctl start mariadb 2>/dev/null || true
systemctl enable mariadb 2>/dev/null || true
# Fix LiteSpeed service only if the web server was actually installed
if [ -x /usr/local/lsws/bin/lswsctrl ] || [ -x /usr/local/lsws/bin/lsctrl ] || [ -f /usr/local/lsws/bin/openlitespeed ]; then
cat > /etc/systemd/system/lsws.service << 'EOF'
[Unit]
Description=LiteSpeed Web Server
After=network.target
[Service]
Type=forking
User=root
Group=root
ExecStart=/usr/local/lsws/bin/lswsctrl start
ExecStop=/usr/local/lsws/bin/lswsctrl stop
ExecReload=/usr/local/lsws/bin/lswsctrl restart
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable lsws
systemctl start lsws || true
else
echo " • LiteSpeed/OpenLiteSpeed not found at /usr/local/lsws - skipping lsws.service (install may have skipped web server)"
echo " • If the installer failed earlier (e.g. Python error), re-run the installer. Once it completes, open ports 8090 and 7080 in your cloud security group (e.g. AWS EC2 Security Group inbound rules)."
systemctl disable lsws 2>/dev/null || true
rm -f /etc/systemd/system/lsws.service
systemctl daemon-reload
fi
# Set OpenLiteSpeed admin password to match CyberPanel
echo " • Configuring OpenLiteSpeed admin password..."
if [ -f "/usr/local/lsws/admin/misc/admpass.sh" ]; then
# Auto-answer the prompts for username and password
(echo "admin"; echo "$admin_password"; echo "$admin_password") | /usr/local/lsws/admin/misc/admpass.sh >/dev/null 2>&1 || {
# Alternative method: directly create htpasswd entry
echo "admin:$(openssl passwd -apr1 '$admin_password')" > /usr/local/lsws/admin/htpasswd 2>/dev/null || true
}
echo " ✓ OpenLiteSpeed configured"
fi
# Ensure CyberPanel (lscpd) service is running
echo " • Starting CyberPanel service..."
systemctl enable lscpd 2>/dev/null || true
systemctl start lscpd 2>/dev/null || true
# Give services a moment to start
sleep 3
# Ensure both 8090 (CyberPanel) and 7080 (LiteSpeed/OLS) are accessible
echo " • Ensuring ports 8090 and 7080 are accessible..."
port_check() {
local port=$1
command -v ss >/dev/null 2>&1 && ss -tlnp 2>/dev/null | grep -q ":$port " && return 0
command -v netstat >/dev/null 2>&1 && netstat -tlnp 2>/dev/null | grep -q ":$port " && return 0
return 1
}
max_attempts=18
attempt=0
while [ $attempt -lt $max_attempts ]; do
need_restart=false
systemctl is-active --quiet mariadb || { systemctl start mariadb 2>/dev/null; need_restart=true; }
systemctl is-active --quiet lsws 2>/dev/null || { [ -x /usr/local/lsws/bin/lswsctrl ] && systemctl start lsws 2>/dev/null; need_restart=true; }
systemctl is-active --quiet lscpd 2>/dev/null || { systemctl start lscpd 2>/dev/null; need_restart=true; }
[ "$need_restart" = true ] && sleep 5
if port_check 8090 && port_check 7080; then
echo " ✓ Port 8090 (CyberPanel) and 7080 (OpenLiteSpeed) are listening"
break
fi
attempt=$((attempt + 1))
[ $attempt -lt $max_attempts ] && sleep 5
done
if ! port_check 8090 || ! port_check 7080; then
systemctl start lscpd 2>/dev/null
systemctl start lsws 2>/dev/null
sleep 10
if port_check 8090 && port_check 7080; then
echo " ✓ Port 8090 and 7080 are now listening"
else
echo " ⚠ One or both ports not yet listening. Run: systemctl start mariadb lsws lscpd"
echo " ⚠ On AWS/cloud: add inbound rules for TCP 8090 and 7080 in the instance security group."
fi
fi
echo " ✓ Post-installation configurations completed"
}
# Helper: check if a port is listening
_port_listening() {
local port=$1
command -v ss >/dev/null 2>&1 && ss -tlnp 2>/dev/null | grep -q ":$port " && return 0
command -v netstat >/dev/null 2>&1 && netstat -tlnp 2>/dev/null | grep -q ":$port " && return 0
return 1
}
# Function to show status summary
show_status_summary() {
# Last-chance: try to start services so 8090 and 7080 are accessible
if ! _port_listening 8090 || ! _port_listening 7080; then
systemctl start mariadb 2>/dev/null || true
systemctl start lsws 2>/dev/null || true
systemctl start lscpd 2>/dev/null || true
sleep 8
fi
echo "==============================================================================================================="
echo " FINAL STATUS CHECK"
echo "==============================================================================================================="
echo ""
# Quick service check
local all_services_running=true
echo "Service Status:"
if systemctl is-active --quiet mariadb; then
echo " ✓ MariaDB Database - Running"
else
echo " ✗ MariaDB Database - Not Running"
all_services_running=false
fi
if systemctl is-active --quiet lsws; then
echo " ✓ LiteSpeed Web Server - Running"
else
echo " ✗ LiteSpeed Web Server - Not Running"
all_services_running=false
fi
if systemctl is-active --quiet lscpd; then
echo " ✓ CyberPanel Application - Running"
else
echo " ✗ CyberPanel Application - Not Running (may take a moment to start)"
all_services_running=false
fi
echo ""
echo "Port Accessibility:"
if _port_listening 8090; then
echo " ✓ Port 8090 (CyberPanel) - Accessible"
else
echo " ✗ Port 8090 (CyberPanel) - Not listening (run: systemctl start lscpd)"
all_services_running=false
fi
if _port_listening 7080; then
echo " ✓ Port 7080 (OpenLiteSpeed) - Accessible"
else
echo " ✗ Port 7080 (OpenLiteSpeed) - Not listening (run: systemctl start lsws)"
all_services_running=false
fi
# Get the actual password that was set
local admin_password=""
local server_ip=$(curl -s ifconfig.me 2>/dev/null || echo "your-server-ip")
# Check if password was set in /root/.cyberpanel_password (if it exists)
if [ -f "/root/.cyberpanel_password" ]; then
admin_password=$(cat /root/.cyberpanel_password 2>/dev/null)
fi
# If we have a password, show access details
if [ -n "$admin_password" ]; then
echo ""
echo "Access Details:"
echo " CyberPanel: https://$server_ip:8090"
echo " Username: admin"
echo " Password: $admin_password"
echo ""
echo " OpenLiteSpeed: https://$server_ip:7080"
echo " Username: admin"
echo " Password: $admin_password"
fi
echo ""
echo "==============================================================================================================="
if [ "$all_services_running" = true ]; then
echo "✓ Installation completed successfully! Ports 8090 and 7080 are accessible."
else
echo "⚠ Installation completed with warnings. Some services may need attention."
fi
echo ""
}
# Function to show main menu

View File

@@ -0,0 +1,328 @@
#!/usr/bin/env bash
# CyberPanel install main/fresh/version menus. Sourced by cyberpanel.sh.
show_main_menu() {
show_banner
echo "==============================================================================================================="
echo " SELECT INSTALLATION TYPE"
echo "==============================================================================================================="
echo ""
echo " 1. Fresh Installation (Recommended)"
echo " 2. Update Existing Installation"
echo " 3. Reinstall CyberPanel"
echo " 4. Force Reinstall (Clean & Install)"
echo " 5. Pre-Upgrade (Download latest upgrade script)"
echo " 6. Check System Status"
echo " 7. Advanced Options"
echo " 8. Exit"
echo ""
echo "==============================================================================================================="
echo ""
while true; do
echo -n "Enter your choice [1-8]: "
read -r choice
case $choice in
1)
INSTALLATION_TYPE="fresh"
show_fresh_install_menu
return
;;
2)
INSTALLATION_TYPE="update"
show_update_menu
return
;;
3)
INSTALLATION_TYPE="reinstall"
show_reinstall_menu
return
;;
4)
INSTALLATION_TYPE="force_reinstall"
start_force_reinstall
return
;;
5)
start_preupgrade
return
;;
6)
show_system_status
return
;;
7)
show_advanced_menu
return
;;
8)
echo "Goodbye!"
exit 0
;;
*)
echo ""
echo "ERROR: Invalid choice. Please enter 1-7."
echo ""
;;
esac
done
}
# Function to show fresh installation menu
show_fresh_install_menu() {
echo ""
echo "==============================================================================================================="
echo " FRESH INSTALLATION SETUP"
echo "==============================================================================================================="
echo ""
# Check if CyberPanel is already installed
if [ -d "/usr/local/CyberCP" ] && [ -f "/usr/local/CyberCP/manage.py" ]; then
echo "WARNING: CyberPanel appears to be already installed on this system."
echo " Consider using 'Update' or 'Reinstall' options instead."
echo ""
echo -n "Do you want to continue with fresh installation anyway? (y/n): "
read -r response
case $response in
[yY]|[yY][eE][sS])
;;
*)
show_main_menu
return
;;
esac
fi
echo "Select installation option:"
echo ""
echo " 1. Install Latest Stable Version"
echo " 2. Install Development Version (v2.5.5-dev)"
echo " 3. Install Specific Version/Branch"
echo " 4. Install from Commit Hash"
echo " 5. Quick Install (Auto-configure everything)"
echo " 6. Back to Main Menu"
echo ""
echo "==============================================================================================================="
echo ""
while true; do
echo -n "Select installation option [1-6]: "
read -r choice
case $choice in
1)
BRANCH_NAME=""
show_installation_preferences
return
;;
2)
BRANCH_NAME="v2.5.5-dev"
show_installation_preferences
return
;;
3)
show_version_selection
return
;;
4)
show_commit_selection
return
;;
5)
BRANCH_NAME=""
AUTO_INSTALL=true
start_installation
return
;;
6)
show_main_menu
return
;;
*)
echo ""
echo "ERROR: Invalid choice. Please enter 1-6."
echo ""
;;
esac
done
}
# Function to show commit selection
show_commit_selection() {
echo ""
echo "==============================================================================================================="
echo " COMMIT HASH SELECTION"
echo "==============================================================================================================="
echo ""
echo "Enter a specific commit hash to install from:"
echo ""
echo "Examples:"
echo " • Latest commit: Leave empty (press Enter)"
echo " • Specific commit: a1b2c3d4e5f6789012345678901234567890abcd"
echo " • Short commit: a1b2c3d (first 7 characters)"
echo ""
echo "You can find commit hashes at: https://github.com/usmannasir/cyberpanel/commits"
echo ""
echo "==============================================================================================================="
echo ""
while true; do
echo -n "Enter commit hash (or press Enter for latest): "
read -r commit_hash
if [ -z "$commit_hash" ]; then
echo "Using latest commit..."
BRANCH_NAME=""
show_installation_preferences
return
elif [[ "$commit_hash" =~ ^[a-f0-9]{7,40}$ ]]; then
echo "Using commit: $commit_hash"
BRANCH_NAME="$commit_hash"
show_installation_preferences
return
else
echo ""
echo "ERROR: Invalid commit hash format."
echo " Please enter a valid Git commit hash (7-40 hexadecimal characters)."
echo ""
fi
done
}
# Function to show version selection
show_version_selection() {
echo ""
echo "==============================================================================================================="
echo " VERSION SELECTION"
echo "==============================================================================================================="
echo ""
echo "Available versions:"
echo ""
echo " 1. Latest Stable (Recommended)"
echo " 2. v2.5.5-dev (Development)"
echo " 3. v2.4.4 (Previous Stable)"
echo " 4. Custom Branch Name"
echo " 5. Custom Commit Hash"
echo ""
echo "==============================================================================================================="
echo ""
while true; do
echo -n "Select version [1-5]: "
read -r choice
case $choice in
1)
BRANCH_NAME=""
break
;;
2)
BRANCH_NAME="v2.5.5-dev"
break
;;
3)
BRANCH_NAME="v2.4.4"
break
;;
4)
echo -n "Enter branch name (e.g., main, v2.5.5-dev): "
read -r BRANCH_NAME
if [ -z "$BRANCH_NAME" ]; then
echo "ERROR: Branch name cannot be empty."
continue
fi
# Add v prefix if it's a version number without v
if [[ "$BRANCH_NAME" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9]+)?$ ]]; then
if [[ "$BRANCH_NAME" == *"-"* ]]; then
# Already has suffix like 2.5.5-dev, add v prefix
BRANCH_NAME="v$BRANCH_NAME"
else
# Add v prefix and dev suffix for development versions
BRANCH_NAME="v$BRANCH_NAME-dev"
fi
fi
break
;;
5)
echo -n "Enter commit hash (7-40 characters): "
read -r commit_hash
if [[ "$commit_hash" =~ ^[a-f0-9]{7,40}$ ]]; then
BRANCH_NAME="$commit_hash"
break
else
echo "ERROR: Invalid commit hash format."
continue
fi
;;
*)
echo ""
echo "ERROR: Invalid choice. Please enter 1-5."
echo ""
;;
esac
done
show_installation_preferences
}
# Function to show installation preferences
show_installation_preferences() {
echo ""
echo "==============================================================================================================="
echo " INSTALLATION PREFERENCES"
echo "==============================================================================================================="
echo ""
# Debug mode
echo -n "Enable debug mode for detailed logging? (y/n) [n]: "
read -r response
case $response in
[yY]|[yY][eE][sS])
DEBUG_MODE=true
;;
*)
DEBUG_MODE=false
;;
esac
# Auto-install
echo -n "Auto-install without further prompts? (y/n) [y]: "
read -r response
case $response in
[nN]|[nN][oO])
AUTO_INSTALL=false
;;
*)
AUTO_INSTALL=true
;;
esac
# Show summary
echo ""
echo "==============================================================================================================="
echo " INSTALLATION SUMMARY"
echo "==============================================================================================================="
echo ""
echo " Type: $INSTALLATION_TYPE"
echo " Version: ${BRANCH_NAME:-'Latest Stable'}"
echo " Debug Mode: $DEBUG_MODE"
echo " Auto Install: $AUTO_INSTALL"
echo ""
echo "==============================================================================================================="
echo ""
echo -n "Proceed with installation? (y/n) [y]: "
read -r response
case $response in
[nN]|[nN][oO])
show_main_menu
;;
*)
start_installation
;;
esac
}
# Function to show update menu

View File

@@ -0,0 +1,247 @@
#!/usr/bin/env bash
# CyberPanel install update/reinstall/status menus. Sourced by cyberpanel.sh.
show_update_menu() {
echo ""
echo "==============================================================================================================="
echo " UPDATE INSTALLATION"
echo "==============================================================================================================="
echo ""
if [ ! -d "/usr/local/CyberCP" ] || [ ! -f "/usr/local/CyberCP/manage.py" ]; then
echo "ERROR: CyberPanel is not installed on this system."
echo " Please use 'Fresh Installation' instead."
echo ""
read -p "Press Enter to return to main menu..."
show_main_menu
return
fi
# Check current version
local current_version="unknown"
if [ -f "/usr/local/CyberCP/version.txt" ]; then
current_version=$(cat /usr/local/CyberCP/version.txt 2>/dev/null)
fi
echo "Current Installation:"
echo "Version: $current_version"
echo "Path: /usr/local/CyberCP"
echo ""
echo "Select update option:"
echo ""
echo " 1. Update to Latest Stable"
echo " 2. Update to Development Version"
echo " 3. Update to Specific Version/Branch"
echo " 4. Update from Commit Hash"
echo " 5. Back to Main Menu"
echo ""
echo "==============================================================================================================="
echo ""
while true; do
echo -n "Select update option [1-5]: "
read -r choice
case $choice in
1)
BRANCH_NAME=""
break
;;
2)
BRANCH_NAME="v2.5.5-dev"
break
;;
3)
show_version_selection
return
;;
4)
show_commit_selection
return
;;
5)
show_main_menu
return
;;
*)
echo ""
echo "ERROR: Invalid choice. Please enter 1-5."
echo ""
;;
esac
done
echo -n "Proceed with update? (This will backup your current installation) (y/n) [y]: "
read -r response
case $response in
[nN]|[nN][oO])
show_main_menu
;;
*)
start_upgrade
;;
esac
}
# Function to show reinstall menu
show_reinstall_menu() {
echo ""
echo "==============================================================================================================="
echo " REINSTALL CYBERPANEL"
echo "==============================================================================================================="
echo ""
if [ ! -d "/usr/local/CyberCP" ] || [ ! -f "/usr/local/CyberCP/manage.py" ]; then
echo "ERROR: CyberPanel is not installed on this system."
echo " Please use 'Fresh Installation' instead."
echo ""
read -p "Press Enter to return to main menu..."
show_main_menu
return
fi
echo "WARNING: This will completely remove the existing CyberPanel installation"
echo " and install a fresh copy. All data will be lost!"
echo ""
echo -n "Are you sure you want to reinstall? (y/n) [n]: "
read -r response
case $response in
[yY]|[yY][eE][sS])
;;
*)
show_main_menu
return
;;
esac
echo "Select reinstall option:"
echo ""
echo " 1. Reinstall Latest Stable"
echo " 2. Reinstall Development Version"
echo " 3. Reinstall Specific Version/Branch"
echo " 4. Reinstall from Commit Hash"
echo " 5. Back to Main Menu"
echo ""
echo "==============================================================================================================="
echo ""
while true; do
echo -n "Select reinstall option [1-5]: "
read -r choice
case $choice in
1)
BRANCH_NAME=""
break
;;
2)
BRANCH_NAME="v2.5.5-dev"
break
;;
3)
show_version_selection
return
;;
4)
show_commit_selection
return
;;
5)
show_main_menu
return
;;
*)
echo ""
echo "ERROR: Invalid choice. Please enter 1-5."
echo ""
;;
esac
done
echo -n "Proceed with reinstall? (This will delete all existing data) (y/n) [n]: "
read -r response
case $response in
[yY]|[yY][eE][sS])
start_reinstall
;;
*)
show_main_menu
;;
esac
}
# Function to show system status
show_system_status() {
echo ""
echo "==============================================================================================================="
echo " SYSTEM STATUS CHECK"
echo "==============================================================================================================="
echo ""
# Check OS
local os_info=$(cat /etc/os-release | grep PRETTY_NAME | cut -d'"' -f2 2>/dev/null || echo 'Unknown')
echo "Operating System: $os_info"
# Check CyberPanel installation
if [ -d "/usr/local/CyberCP" ] && [ -f "/usr/local/CyberCP/manage.py" ]; then
local version="unknown"
if [ -f "/usr/local/CyberCP/version.txt" ]; then
version=$(cat /usr/local/CyberCP/version.txt 2>/dev/null)
fi
echo "CyberPanel: Installed (Version: $version)"
else
echo "CyberPanel: Not Installed"
fi
# Check services
echo ""
echo "Services Status:"
if systemctl is-active --quiet mariadb; then
echo " SUCCESS: MariaDB - Running"
else
echo " ERROR: MariaDB - Not Running"
fi
if systemctl is-active --quiet lsws; then
echo " SUCCESS: LiteSpeed - Running"
else
echo " ERROR: LiteSpeed - Not Running"
fi
if systemctl is-active --quiet lscpd; then
echo " SUCCESS: CyberPanel - Running"
else
echo " ERROR: CyberPanel - Not Running"
fi
# Check ports
echo ""
echo "Port Status:"
if netstat -tlnp | grep -q ":8090 "; then
echo " SUCCESS: Port 8090 (CyberPanel) - Listening"
else
echo " ERROR: Port 8090 (CyberPanel) - Not Listening"
fi
if netstat -tlnp | grep -q ":80 "; then
echo " SUCCESS: Port 80 (HTTP) - Listening"
else
echo " ERROR: Port 80 (HTTP) - Not Listening"
fi
echo ""
echo -n "Return to main menu? (y/n) [y]: "
read -r response
case $response in
[nN]|[nN][oO])
exit 0
;;
*)
show_main_menu
;;
esac
}
# Function to show advanced menu

View File

@@ -0,0 +1,273 @@
#!/usr/bin/env bash
# CyberPanel install advanced/fix/clean/logs menus. Sourced by cyberpanel.sh.
show_advanced_menu() {
echo ""
echo "==============================================================================================================="
echo " ADVANCED OPTIONS"
echo "==============================================================================================================="
echo ""
echo " 1. Fix Installation Issues"
echo " 2. Clean Installation Files"
echo " 3. View Installation Logs"
echo " 4. System Diagnostics"
echo " 5. Show Error Help"
echo " 6. Back to Main Menu"
echo ""
echo "==============================================================================================================="
echo ""
while true; do
echo -n "Select advanced option [1-6]: "
read -r choice
case $choice in
1)
show_fix_menu
return
;;
2)
show_clean_menu
return
;;
3)
show_logs_menu
return
;;
4)
show_diagnostics
return
;;
5)
show_error_help
return
;;
6)
show_main_menu
return
;;
*)
echo ""
echo "ERROR: Invalid choice. Please enter 1-6."
echo ""
;;
esac
done
}
# Function to show error help
show_error_help() {
echo ""
echo "==============================================================================================================="
echo " ERROR TROUBLESHOOTING HELP"
echo "==============================================================================================================="
echo ""
echo "If your CyberPanel installation failed, here's how to troubleshoot:"
echo ""
echo "📋 LOG FILES LOCATION:"
echo " • Main installer log: /var/log/CyberPanel/install.log"
echo " • Installation output: /var/log/CyberPanel/install_output.log"
echo " • Upgrade output: /var/log/CyberPanel/upgrade_output.log"
echo " • System logs: /var/log/messages"
echo ""
echo "🔍 COMMON ISSUES & SOLUTIONS:"
echo ""
echo "1. DEPENDENCY INSTALLATION FAILED:"
echo " • Check internet connection: ping -c 3 google.com"
echo " • Update package lists: yum update -y (RHEL) or apt update (Debian)"
echo " • Check available disk space: df -h"
echo ""
echo "2. CYBERPANEL DOWNLOAD FAILED:"
echo " • Check internet connectivity"
echo " • Verify GitHub access: curl -I https://github.com"
echo " • Try different branch/version"
echo ""
echo "3. PERMISSION ERRORS:"
echo " • Ensure running as root: whoami"
echo " • Check file permissions: ls -la /var/log/CyberPanel/"
echo ""
echo "4. SYSTEM REQUIREMENTS:"
echo " • Minimum 1GB RAM: free -h"
echo " • Minimum 10GB disk space: df -h"
echo " • Supported OS: AlmaLinux 8/9, CentOS 7/8, Ubuntu 18.04+"
echo ""
echo "5. SERVICE CONFLICTS:"
echo " • Check running services: systemctl list-units --state=running"
echo " • Stop conflicting services: systemctl stop apache2 (if running)"
echo ""
echo "💡 QUICK DEBUG COMMANDS:"
echo " • View installation log: cat /var/log/CyberPanel/install_output.log"
echo " • Check system resources: free -h && df -h"
echo " • Test network: ping -c 3 google.com"
echo " • Check services: systemctl status lscpd"
echo " • View system logs: tail -50 /var/log/messages"
echo ""
echo "🆘 GETTING HELP:"
echo " • CyberPanel Documentation: https://docs.cyberpanel.net"
echo " • CyberPanel Community: https://forums.cyberpanel.net"
echo " • GitHub Issues: https://github.com/usmannasir/cyberpanel/issues"
echo " • Discord Support: https://discord.gg/cyberpanel"
echo ""
echo "🔄 RETRY INSTALLATION:"
echo " • Clean installation: Run installer with 'Clean Installation Files' option"
echo " • Different version: Try stable version instead of development"
echo " • Fresh system: Consider using a clean OS installation"
echo ""
echo "==============================================================================================================="
echo ""
read -p "Press Enter to return to main menu..."
show_main_menu
}
# Function to show fix menu
show_fix_menu() {
echo ""
echo "==============================================================================================================="
echo " FIX INSTALLATION ISSUES"
echo "==============================================================================================================="
echo ""
echo "This will attempt to fix common CyberPanel installation issues:"
echo "• Database connection problems"
echo "• Service configuration issues"
echo "• SSL certificate problems"
echo "• File permission issues"
echo ""
echo -n "Proceed with fixing installation issues? (y/n) [y]: "
read -r response
case $response in
[nN]|[nN][oO])
show_advanced_menu
;;
*)
print_status "Applying fixes..."
apply_fixes
print_status "SUCCESS: Fixes applied successfully"
echo ""
read -p "Press Enter to return to advanced menu..."
show_advanced_menu
;;
esac
}
# Function to show clean menu
show_clean_menu() {
echo ""
echo "==============================================================================================================="
echo " CLEAN INSTALLATION FILES"
echo "==============================================================================================================="
echo ""
echo "WARNING: This will remove temporary installation files and logs."
echo " This action cannot be undone!"
echo ""
echo -n "Proceed with cleaning? (y/n) [n]: "
read -r response
case $response in
[yY]|[yY][eE][sS])
rm -rf /tmp/cyberpanel_*
rm -rf /var/log/cyberpanel_install.log
echo "SUCCESS: Cleanup complete! Temporary files and logs have been removed."
;;
esac
echo ""
echo -n "Return to advanced menu? (y/n) [y]: "
read -r response
case $response in
[nN]|[nN][oO])
show_main_menu
;;
*)
show_advanced_menu
;;
esac
}
# Function to show logs menu
show_logs_menu() {
echo ""
echo "==============================================================================================================="
echo " VIEW INSTALLATION LOGS"
echo "==============================================================================================================="
echo ""
local log_file="/var/log/cyberpanel_install.log"
if [ -f "$log_file" ]; then
echo "Installation Log: $log_file"
echo "Log Size: $(du -h "$log_file" | cut -f1)"
echo ""
echo -n "View recent log entries? (y/n) [y]: "
read -r response
case $response in
[nN]|[nN][oO])
;;
*)
echo ""
echo "Recent log entries:"
tail -n 20 "$log_file"
;;
esac
else
echo "No installation logs found at $log_file"
fi
echo ""
echo -n "Return to advanced menu? (y/n) [y]: "
read -r response
case $response in
[nN]|[nN][oO])
show_main_menu
;;
*)
show_advanced_menu
;;
esac
}
# Function to show diagnostics
show_diagnostics() {
echo ""
echo "==============================================================================================================="
echo " SYSTEM DIAGNOSTICS"
echo "==============================================================================================================="
echo ""
echo "Running system diagnostics..."
echo ""
# Disk space
echo "Disk Usage:"
df -h | grep -E '^/dev/'
# Memory usage
echo ""
echo "Memory Usage:"
free -h
# Load average
echo ""
echo "System Load:"
uptime
# Network interfaces
echo ""
echo "Network Interfaces:"
ip addr show | grep -E '^[0-9]+:|inet '
echo ""
echo -n "Return to advanced menu? (y/n) [y]: "
read -r response
case $response in
[nN]|[nN][oO])
show_main_menu
;;
*)
show_advanced_menu
;;
esac
}
# Function to start upgrade

View File

@@ -0,0 +1,317 @@
#!/usr/bin/env bash
# CyberPanel install start_* actions. Sourced by cyberpanel.sh.
start_upgrade() {
echo ""
echo "==============================================================================================================="
echo " STARTING UPGRADE"
echo "==============================================================================================================="
echo ""
# Detect OS
echo "Step 1/5: Detecting operating system..."
if ! detect_os; then
print_status "ERROR: Failed to detect operating system"
exit 1
fi
echo " ✓ Operating system detected successfully"
echo ""
# Install dependencies
echo "Step 2/5: Installing/updating dependencies..."
install_dependencies
echo ""
# Download and run the upgrade script
echo "Step 3/5: Downloading CyberPanel upgrade script..."
local upgrade_url=""
if [ -n "$BRANCH_NAME" ]; then
if [[ "$BRANCH_NAME" =~ ^[a-f0-9]{40}$ ]]; then
# It's a commit hash
echo "Downloading from commit: $BRANCH_NAME"
upgrade_url="https://raw.githubusercontent.com/usmannasir/cyberpanel/$BRANCH_NAME/cyberpanel_upgrade.sh"
else
# It's a branch name
echo "Downloading from branch: $BRANCH_NAME"
upgrade_url="https://raw.githubusercontent.com/usmannasir/cyberpanel/$BRANCH_NAME/cyberpanel_upgrade.sh"
fi
else
echo "Downloading from: https://raw.githubusercontent.com/usmannasir/cyberpanel/stable/cyberpanel_upgrade.sh"
upgrade_url="https://raw.githubusercontent.com/usmannasir/cyberpanel/stable/cyberpanel_upgrade.sh"
fi
curl --silent -o cyberpanel_upgrade.sh "$upgrade_url" 2>/dev/null
chmod +x cyberpanel_upgrade.sh
echo " ✓ CyberPanel upgrade script downloaded"
echo " 🔄 Starting CyberPanel upgrade..."
echo ""
echo "IMPORTANT: The upgrade is now running in the background."
echo "You will see detailed output from the CyberPanel upgrade script below."
echo "This is normal and expected - the upgrade is proceeding!"
echo ""
echo "==============================================================================================================="
echo ""
# Run the upgrade with live progress monitoring
echo "Starting CyberPanel upgrade process..."
echo "This may take several minutes. Please be patient."
echo ""
# Create log directory
mkdir -p /var/log/CyberPanel
# Run the upgrade with live output monitoring
echo "Starting CyberPanel upgrade with live progress monitoring..."
echo ""
echo "==============================================================================================================="
echo " LIVE UPGRADE PROGRESS"
echo "==============================================================================================================="
echo ""
# Run upgrade and show live output
if [ "$DEBUG_MODE" = true ]; then
./cyberpanel_upgrade.sh --debug 2>&1 | tee /var/log/CyberPanel/upgrade_output.log
else
./cyberpanel_upgrade.sh 2>&1 | tee /var/log/CyberPanel/upgrade_output.log
fi
local upgrade_exit_code=${PIPESTATUS[0]}
echo ""
echo "==============================================================================================================="
echo " UPGRADE COMPLETED"
echo "==============================================================================================================="
echo ""
# Clean up downloaded upgrade script
rm -f cyberpanel_upgrade.sh 2>/dev/null
# Check if upgrade was successful
if [ $upgrade_exit_code -eq 0 ]; then
print_status "SUCCESS: CyberPanel upgraded successfully"
return 0
else
print_status "ERROR: CyberPanel upgrade failed with exit code $upgrade_exit_code"
echo ""
echo "Upgrade log (last 50 lines):"
echo "==============================================================================================================="
tail -50 /var/log/CyberPanel/upgrade_output.log 2>/dev/null || echo "Could not read upgrade log"
echo "==============================================================================================================="
echo ""
echo "Full upgrade log available at: /var/log/CyberPanel/upgrade_output.log"
echo ""
return 1
fi
}
# Function to start force reinstall
start_force_reinstall() {
echo ""
echo "==============================================================================================================="
echo " FORCE REINSTALL CYBERPANEL"
echo "==============================================================================================================="
echo ""
echo "This will completely remove the existing CyberPanel installation and install a fresh copy."
echo "All data and configurations will be lost!"
echo ""
while true; do
echo -n "Are you sure you want to proceed? (y/N): "
read -r confirm
case $confirm in
[Yy]*)
echo ""
echo "Starting force reinstall..."
echo ""
# Clean up existing installation
cleanup_existing_cyberpanel
# Start fresh installation
start_installation
break
;;
[Nn]*|"")
echo "Force reinstall cancelled."
return
;;
*)
echo "Please answer yes or no."
;;
esac
done
}
# Function to start preupgrade
start_preupgrade() {
echo ""
echo "==============================================================================================================="
echo " PRE-UPGRADE SETUP"
echo "==============================================================================================================="
echo ""
echo "This will download the latest CyberPanel upgrade script to /usr/local/"
echo "and prepare it for execution."
echo ""
# Get the latest version
echo "Step 1/3: Fetching latest version information..."
local latest_version=$(curl -s https://cyberpanel.net/version.txt | sed -e 's|{"version":"||g' -e 's|","build":|.|g' | sed 's:}*$::')
local branch_name="v$latest_version"
echo " ✓ Latest version: $latest_version"
echo " ✓ Branch: $branch_name"
echo ""
# Download the upgrade script
echo "Step 2/3: Downloading CyberPanel upgrade script..."
local upgrade_url="https://raw.githubusercontent.com/usmannasir/cyberpanel/$branch_name/cyberpanel_upgrade.sh"
echo "Downloading from: $upgrade_url"
if curl --silent -o /usr/local/cyberpanel_upgrade.sh "$upgrade_url" 2>/dev/null; then
chmod 700 /usr/local/cyberpanel_upgrade.sh
echo " ✓ Upgrade script downloaded to /usr/local/cyberpanel_upgrade.sh"
else
print_status "ERROR: Failed to download upgrade script"
return 1
fi
echo ""
# Show instructions
echo "Step 3/3: Setup complete!"
echo ""
echo "The upgrade script is now ready at: /usr/local/cyberpanel_upgrade.sh"
echo ""
echo "To run the upgrade, you can either:"
echo " 1. Use this installer's 'Update Existing Installation' option"
echo " 2. Run directly: /usr/local/cyberpanel_upgrade.sh"
echo ""
echo "==============================================================================================================="
echo ""
read -p "Press Enter to return to main menu..."
show_main_menu
}
# Function to start reinstall
start_reinstall() {
echo ""
echo "==============================================================================================================="
echo " STARTING REINSTALL"
echo "==============================================================================================================="
echo ""
echo "WARNING: This will completely remove the existing CyberPanel installation!"
echo "All data, websites, and configurations will be lost!"
echo ""
# Detect OS
echo "Step 1/6: Detecting operating system..."
if ! detect_os; then
print_status "ERROR: Failed to detect operating system"
exit 1
fi
echo " ✓ Operating system detected successfully"
echo ""
# Stop services
echo "Step 2/6: Stopping CyberPanel services..."
systemctl stop lscpd 2>/dev/null || true
systemctl stop lsws 2>/dev/null || true
systemctl stop mariadb 2>/dev/null || true
systemctl stop postfix 2>/dev/null || true
systemctl stop dovecot 2>/dev/null || true
systemctl stop pure-ftpd 2>/dev/null || true
echo " ✓ Services stopped"
echo ""
# Remove existing installation
echo "Step 3/6: Removing existing CyberPanel installation..."
rm -rf /usr/local/CyberCP 2>/dev/null || true
rm -rf /usr/local/lsws 2>/dev/null || true
rm -rf /home/cyberpanel 2>/dev/null || true
rm -rf /var/lib/mysql 2>/dev/null || true
rm -rf /var/log/cyberpanel 2>/dev/null || true
echo " ✓ Existing installation removed"
echo ""
# Install dependencies
echo "Step 4/6: Installing dependencies..."
install_dependencies
echo ""
# Install CyberPanel
echo "Step 5/6: Installing CyberPanel..."
if ! install_cyberpanel; then
print_status "ERROR: CyberPanel installation failed"
exit 1
fi
echo ""
# Apply fixes
echo "Step 6/6: Applying installation fixes..."
apply_fixes
echo ""
# Show status summary
show_status_summary
print_status "SUCCESS: CyberPanel reinstalled successfully!"
}
# Function to start installation
start_installation() {
echo ""
echo "==============================================================================================================="
echo " STARTING INSTALLATION"
echo "==============================================================================================================="
echo ""
# Detect OS
echo "Step 1/6: Detecting operating system..."
if ! detect_os; then
print_status "ERROR: Failed to detect operating system"
exit 1
fi
echo " ✓ Operating system detected successfully"
echo ""
# Install dependencies
echo "Step 2/6: Installing dependencies..."
install_dependencies
echo ""
# Install CyberPanel
echo "Step 3/6: Installing CyberPanel..."
if ! install_cyberpanel; then
print_status "ERROR: CyberPanel installation failed"
echo ""
echo "Would you like to see troubleshooting help? (y/n) [y]: "
read -r show_help
case $show_help in
[nN]|[nN][oO])
echo "Installation failed. Check logs at /var/log/CyberPanel/"
echo "Run the installer again and select 'Advanced Options' → 'Show Error Help' for detailed troubleshooting."
;;
*)
show_error_help
;;
esac
exit 1
fi
echo ""
# Apply post-installation fixes silently
apply_fixes
# Create standard aliases (silently)
create_standard_aliases >/dev/null 2>&1
# Show final status summary
echo ""
show_status_summary
}
# Function to parse command line arguments

View File

@@ -0,0 +1,247 @@
#!/usr/bin/env bash
# CyberPanel install parse_arguments, main. Sourced by cyberpanel.sh.
parse_arguments() {
while [[ $# -gt 0 ]]; do
case $1 in
-b|--branch)
if [ -n "$2" ]; then
# Convert version number to branch name if needed
if [[ "$2" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9]+)?$ ]]; then
if [[ "$2" == *"-"* ]]; then
# Already has suffix like 2.5.5-dev, add v prefix
BRANCH_NAME="v$2"
else
# Add v prefix and dev suffix for development versions
BRANCH_NAME="v$2-dev"
fi
elif [[ "$2" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9]+)?$ ]]; then
# Already has v prefix, use as is
BRANCH_NAME="$2"
else
# Assume it's already a branch name or commit hash
BRANCH_NAME="$2"
fi
shift 2
else
echo "ERROR: -b/--branch requires a version number or branch name"
echo "Example: -b 2.5.5-dev or -b v2.5.5-dev"
exit 1
fi
;;
-v|--version)
if [ -n "$2" ]; then
# Convert version number to branch name if needed
if [[ "$2" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9]+)?$ ]]; then
if [[ "$2" == *"-"* ]]; then
# Already has suffix like 2.5.5-dev, add v prefix
BRANCH_NAME="v$2"
else
# Add v prefix and dev suffix for development versions
BRANCH_NAME="v$2-dev"
fi
elif [[ "$2" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9]+)?$ ]]; then
# Already has v prefix, use as is
BRANCH_NAME="$2"
else
# Assume it's already a branch name or commit hash
BRANCH_NAME="$2"
fi
shift 2
else
echo "ERROR: -v/--version requires a version number or branch name"
echo "Example: -v 2.5.5-dev or -v v2.5.5-dev"
exit 1
fi
;;
--debug)
DEBUG_MODE=true
set -x
shift
;;
--mariadb-version)
if [ -n "$2" ] && [ "$2" = "10.11" ]; then
MARIADB_VER="10.11"
shift 2
elif [ -n "$2" ] && [ "$2" = "11.8" ]; then
MARIADB_VER="11.8"
shift 2
elif [ -n "$2" ] && [ "$2" = "12.1" ]; then
MARIADB_VER="12.1"
shift 2
else
echo "ERROR: --mariadb-version requires 10.11, 11.8 or 12.1"
exit 1
fi
;;
--auto)
AUTO_INSTALL=true
shift
;;
-h|--help)
echo "Usage: $0 [OPTIONS]"
echo "Options:"
echo " -b, --branch BRANCH Install from specific branch/commit"
echo " -v, --version VER Install specific version (auto-adds v prefix)"
echo " --mariadb-version VER MariaDB version: 10.11, 11.8 or 12.1 (asked after web server)"
echo " --debug Enable debug mode"
echo " --auto Auto mode: OpenLiteSpeed + MariaDB 11.8 unless --mariadb-version set"
echo " -h, --help Show this help message"
echo ""
echo "Examples:"
echo " $0 # Interactive installation"
echo " $0 --debug # Debug mode installation"
echo " $0 --auto # Auto installation"
echo " $0 -b v2.5.5-dev # Install development version"
echo " $0 -v 2.5.5-dev # Install version 2.5.5-dev"
echo " $0 -v 2.4.3 # Install version 2.4.3"
echo " $0 -b main # Install from main branch"
echo " $0 -b a1b2c3d4 # Install from specific commit"
echo " $0 --mariadb-version 10.11 # Use MariaDB 10.11 (same as v2.4.4 style)"
echo " $0 --mariadb-version 12.1 # Use MariaDB 12.1 (no prompt)"
echo " $0 --auto --mariadb-version 11.8 # Fully non-interactive with MariaDB 11.8"
echo ""
echo "Standard CyberPanel Installation Methods:"
echo " sh <(curl https://cyberpanel.net/install.sh)"
echo " bash <(curl https://raw.githubusercontent.com/usmannasir/cyberpanel/stable/cyberpanel_upgrade.sh) -b 2.4.3"
echo " bash <(curl https://raw.githubusercontent.com/usmannasir/cyberpanel/stable/cyberpanel_upgrade.sh) -b 2.5.5-dev"
exit 0
;;
*)
print_status "WARNING: Unknown option: $1"
shift
;;
esac
done
}
# Function to detect installation mode
detect_installation_mode() {
# Check if this is being called as an upgrade script
if [[ "$0" == *"cyberpanel_upgrade.sh"* ]] || [[ "$0" == *"upgrade"* ]]; then
INSTALLATION_TYPE="upgrade"
return 0
fi
# Check if this is being called as a pre-upgrade script
if [[ "$0" == *"preUpgrade.sh"* ]] || [[ "$0" == *"preupgrade"* ]]; then
INSTALLATION_TYPE="preupgrade"
return 0
fi
# Check if this is being called as a standard install script
if [[ "$0" == *"install.sh"* ]] || [[ "$0" == *"cyberpanel.sh"* ]]; then
INSTALLATION_TYPE="install"
return 0
fi
# Default to install mode
INSTALLATION_TYPE="install"
return 0
}
# Function to create standard CyberPanel aliases
create_standard_aliases() {
print_status "Creating standard CyberPanel installation aliases..."
# Create symbolic links for standard installation methods
local script_dir="/usr/local/bin"
local script_name="cyberpanel_enhanced.sh"
# Copy this script to /usr/local/bin
if cp "$0" "$script_dir/$script_name" 2>/dev/null; then
chmod +x "$script_dir/$script_name"
# Create aliases for standard CyberPanel methods
ln -sf "$script_dir/$script_name" "$script_dir/cyberpanel_upgrade.sh" 2>/dev/null || true
ln -sf "$script_dir/$script_name" "$script_dir/preUpgrade.sh" 2>/dev/null || true
ln -sf "$script_dir/$script_name" "$script_dir/install.sh" 2>/dev/null || true
print_status "✓ Standard CyberPanel aliases created"
print_status " - cyberpanel_upgrade.sh"
print_status " - preUpgrade.sh"
print_status " - install.sh"
else
print_status "WARNING: Could not create standard aliases (permission denied)"
fi
}
# Main installation function
main() {
# Initialize log directory and file
mkdir -p "/var/log/CyberPanel"
touch "/var/log/CyberPanel/install.log"
print_status "CyberPanel Enhanced Installer Starting..."
print_status "Log file: /var/log/CyberPanel/install.log"
# Detect installation mode
detect_installation_mode
# Parse command line arguments
parse_arguments "$@"
# Handle different installation modes
case "$INSTALLATION_TYPE" in
"upgrade")
print_status "Running in upgrade mode..."
if [ -n "$BRANCH_NAME" ]; then
print_status "Upgrading to version: $BRANCH_NAME"
fi
start_upgrade
;;
"preupgrade")
print_status "Running in pre-upgrade mode..."
start_preupgrade
;;
"install"|*)
if [ "$AUTO_INSTALL" = true ]; then
# Run auto mode
print_status "Starting auto mode..."
# Detect OS
if ! detect_os; then
print_status "ERROR: Failed to detect operating system"
exit 1
fi
# Install dependencies
install_dependencies
# Install CyberPanel
if ! install_cyberpanel; then
print_status "ERROR: CyberPanel installation failed"
echo ""
echo "Would you like to see troubleshooting help? (y/n) [y]: "
read -r show_help
case $show_help in
[nN]|[nN][oO])
echo "Installation failed. Check logs at /var/log/CyberPanel/"
;;
*)
show_error_help
;;
esac
exit 1
fi
# Apply fixes
apply_fixes
# Create standard aliases
create_standard_aliases
# Show status summary
show_status_summary
print_status "SUCCESS: Installation completed successfully!"
else
# Run interactive mode - ensure stdin is the terminal for prompts (e.g. when script was piped from curl)
if [ ! -t 0 ]; then
exec 0</dev/tty
fi
show_main_menu
fi
;;
esac
}

View File

@@ -247,10 +247,10 @@ class ACLManager:
## DNS Management
finalResponse['createNameServer'] = config['createNameServer']
finalResponse['createDNSZone'] = config['createDNSZone']
finalResponse['deleteZone'] = config['deleteZone']
finalResponse['addDeleteRecords'] = config['addDeleteRecords']
finalResponse['createNameServer'] = config.get('createNameServer', 0)
finalResponse['createDNSZone'] = config.get('createDNSZone', 0)
finalResponse['deleteZone'] = config.get('deleteZone', 0)
finalResponse['addDeleteRecords'] = config.get('addDeleteRecords', 0)
## Email Management
@@ -1325,7 +1325,7 @@ echo $oConfig->Save() ? 'Done' : 'Error';
command = "chown -R root:root /usr/local/lscp"
ProcessUtilities.executioner(command, 'root', True)
command = "chown -R lscpd:lscpd /usr/local/lscp/cyberpanel/rainloop"
command = "chown -R lscpd:lscpd /usr/local/lscp/cyberpanel/snappymail"
ProcessUtilities.executioner(command, 'root', True)
command = "chmod 700 /usr/local/CyberCP/cli/cyberPanel.py"

View File

@@ -78,13 +78,13 @@ class mailUtilities:
@staticmethod
def AfterEffects(domain):
path = "/usr/local/CyberCP/install/rainloop/cyberpanel.net.ini"
path = "/usr/local/CyberCP/install/snappymail/cyberpanel.net.ini"
if not os.path.exists("/usr/local/lscp/cyberpanel/rainloop/data/_data_/_default_/domains/"):
os.makedirs("/usr/local/lscp/cyberpanel/rainloop/data/_data_/_default_/domains/")
if not os.path.exists("/usr/local/lscp/cyberpanel/snappymail/data/_data_/_default_/domains/"):
os.makedirs("/usr/local/lscp/cyberpanel/snappymail/data/_data_/_default_/domains/")
finalPath = "/usr/local/lscp/cyberpanel/rainloop/data/_data_/_default_/domains/" + domain + ".ini"
finalPathJson = "/usr/local/lscp/cyberpanel/rainloop/data/_data_/_default_/domains/" + domain + ".json"
finalPath = "/usr/local/lscp/cyberpanel/snappymail/data/_data_/_default_/domains/" + domain + ".ini"
finalPathJson = "/usr/local/lscp/cyberpanel/snappymail/data/_data_/_default_/domains/" + domain + ".json"
if not os.path.exists(finalPath):
shutil.copy(path, finalPath)
@@ -181,31 +181,31 @@ class mailUtilities:
WriteToFile.write(contentJSON)
WriteToFile.close()
command = 'chown -R lscpd:lscpd /usr/local/lscp/cyberpanel/rainloop/data/'
command = 'chown -R lscpd:lscpd /usr/local/lscp/cyberpanel/snappymail/data/'
ProcessUtilities.normalExecutioner(command)
@staticmethod
def InstallMailBoxFoldersPlugin():
### now download and install actual plugin
labsPath = '/usr/local/lscp/cyberpanel/rainloop/data/_data_/_default_/configs/application.ini'
labsPath = '/usr/local/lscp/cyberpanel/snappymail/data/_data_/_default_/configs/application.ini'
command = f'mkdir /usr/local/lscp/cyberpanel/rainloop/data/_data_/_default_/plugins/mailbox-detect'
command = f'mkdir /usr/local/lscp/cyberpanel/snappymail/data/_data_/_default_/plugins/mailbox-detect'
ProcessUtilities.executioner(command)
command = f'chmod 700 /usr/local/lscp/cyberpanel/rainloop/data/_data_/_default_/plugins/mailbox-detect'
command = f'chmod 700 /usr/local/lscp/cyberpanel/snappymail/data/_data_/_default_/plugins/mailbox-detect'
ProcessUtilities.executioner(command)
command = f'chown lscpd:lscpd /usr/local/lscp/cyberpanel/rainloop/data/_data_/_default_/plugins/mailbox-detect'
command = f'chown lscpd:lscpd /usr/local/lscp/cyberpanel/snappymail/data/_data_/_default_/plugins/mailbox-detect'
ProcessUtilities.executioner(command)
command = f'wget -O /usr/local/lscp/cyberpanel/rainloop/data/_data_/_default_/plugins/mailbox-detect/index.php https://raw.githubusercontent.com/the-djmaze/snappymail/master/plugins/mailbox-detect/index.php'
command = f'wget -O /usr/local/lscp/cyberpanel/snappymail/data/_data_/_default_/plugins/mailbox-detect/index.php https://raw.githubusercontent.com/the-djmaze/snappymail/master/plugins/mailbox-detect/index.php'
ProcessUtilities.executioner(command)
command = f'chmod 644 /usr/local/lscp/cyberpanel/rainloop/data/_data_/_default_/plugins/mailbox-detect/index.php'
command = f'chmod 644 /usr/local/lscp/cyberpanel/snappymail/data/_data_/_default_/plugins/mailbox-detect/index.php'
ProcessUtilities.executioner(command)
command = f'chown lscpd:lscpd /usr/local/lscp/cyberpanel/rainloop/data/_data_/_default_/plugins/mailbox-detect/index.php'
command = f'chown lscpd:lscpd /usr/local/lscp/cyberpanel/snappymail/data/_data_/_default_/plugins/mailbox-detect/index.php'
ProcessUtilities.executioner(command)
### Enable plugins and enable mailbox creation plugin
@@ -230,7 +230,7 @@ class mailUtilities:
WriteToFile.close()
## enable auto create in the enabled plugin
PluginsFilePath = '/usr/local/lscp/cyberpanel/rainloop/data/_data_/_default_/configs/plugin-mailbox-detect.json'
PluginsFilePath = '/usr/local/lscp/cyberpanel/snappymail/data/_data_/_default_/configs/plugin-mailbox-detect.json'
WriteToFile = open(PluginsFilePath, 'w')
WriteToFile.write("""{
@@ -392,7 +392,7 @@ class mailUtilities:
command = f"chown -R vmail:vmail '{maildir_base}'"
ProcessUtilities.executioner(command, 'root')
#if not os.path.exists('/usr/local/lscp/cyberpanel/rainloop/data/_data_/_default_/plugins/mailbox-detect'):
#if not os.path.exists('/usr/local/lscp/cyberpanel/snappymail/data/_data_/_default_/plugins/mailbox-detect'):
# mailUtilities.InstallMailBoxFoldersPlugin()
print("1,None")
@@ -2459,7 +2459,7 @@ class MailServerManagerUtils(multi.Thread):
command = "chown -R root:root /usr/local/lscp"
ProcessUtilities.executioner(command)
command = "chown -R lscpd:lscpd /usr/local/lscp/cyberpanel/rainloop/data"
command = "chown -R lscpd:lscpd /usr/local/lscp/cyberpanel/snappymail/data"
ProcessUtilities.executioner(command)
command = "chmod 700 /usr/local/CyberCP/cli/cyberPanel.py"

View File

@@ -3371,6 +3371,62 @@ class Migration(migrations.Migration):
except:
pass
# Replace ALL rainloop path/URL references in migrated SnappyMail data (configs, domains, plugins)
try:
data_extensions = ('.ini', '.json', '.php', '.cfg')
replace_count = 0
for root, _dirs, files in os.walk(new_data_path):
for name in files:
if name.endswith(data_extensions):
path = os.path.join(root, name)
try:
with open(path, 'r', encoding='utf-8', errors='replace') as f:
content = f.read()
new_content = content.replace(
'/usr/local/lscp/cyberpanel/rainloop/data',
'/usr/local/lscp/cyberpanel/snappymail/data'
).replace(
'/rainloop/',
'/snappymail/'
).replace(
'rainloop/data',
'snappymail/data'
)
if new_content != content:
with open(path, 'w', encoding='utf-8') as f:
f.write(new_content)
replace_count += 1
except (IOError, OSError):
pass
if replace_count > 0:
Upgrade.stdOut(f"Updated rainloop→snappymail links in {replace_count} config file(s).", 0)
except Exception as e:
Upgrade.stdOut(f"Warning: Could not replace rainloop links in data files: {str(e)}", 0)
# Redirect /rainloop to /snappymail so old bookmarks and links keep working
try:
htaccess_path = '/usr/local/CyberCP/public/.htaccess'
redirect_block = (
'\n# Redirect old RainLoop URL to SnappyMail (2.5.5 upgrade)\n'
'<IfModule mod_rewrite.c>\n'
'RewriteEngine On\n'
'RewriteRule ^rainloop/?(.*)$ /snappymail/$1 [R=301,L]\n'
'</IfModule>\n'
)
if os.path.exists(htaccess_path):
with open(htaccess_path, 'r', encoding='utf-8', errors='replace') as f:
existing = f.read()
if 'Redirect old RainLoop URL to SnappyMail' not in existing:
with open(htaccess_path, 'a', encoding='utf-8') as f:
f.write(redirect_block)
Upgrade.stdOut("Added /rainloop→/snappymail redirect to .htaccess.", 0)
else:
with open(htaccess_path, 'w', encoding='utf-8') as f:
f.write(redirect_block)
Upgrade.stdOut("Created .htaccess with /rainloop→/snappymail redirect.", 0)
except Exception as e:
Upgrade.stdOut(f"Warning: Could not add rainloop redirect to .htaccess: {str(e)}", 0)
return 1
else:
Upgrade.stdOut("Warning: Data migration completed with errors. Please verify manually.", 0)
@@ -3735,7 +3791,7 @@ class Migration(migrations.Migration):
custom_configs = [
'/usr/local/CyberCP/baseTemplate/static/baseTemplate/custom/',
'/usr/local/CyberCP/public/phpmyadmin/config.inc.php',
'/usr/local/CyberCP/rainloop/data/_data_/',
'/usr/local/lscp/cyberpanel/snappymail/data/_data_/',
]
# Backup Imunify360 directories and configuration
@@ -4142,7 +4198,7 @@ echo $oConfig->Save() ? 'Done' : 'Error';
command = "chown -R root:root /usr/local/lscp"
Upgrade.executioner(command, 'chown core code', 0)
command = "chown -R lscpd:lscpd /usr/local/lscp/cyberpanel/rainloop"
command = "chown -R lscpd:lscpd /usr/local/lscp/cyberpanel/snappymail"
Upgrade.executioner(command, 'chown core code', 0)
command = "chmod 700 /usr/local/CyberCP/cli/cyberPanel.py"

View File

@@ -0,0 +1,55 @@
#!/bin/bash
# Deploy the latest pluginHolder plugins.html template to CyberPanel and verify.
# Run on the server where CyberPanel is installed.
# From repo root: bash pluginHolder/deploy-plugins-template.sh
# Or from anywhere: REPO_ROOT=/path/to/cyberpanel-repo bash /path/to/deploy-plugins-template.sh
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="${REPO_ROOT:-$(cd "$SCRIPT_DIR/.." && pwd)}"
TEMPLATE_SRC="${REPO_ROOT}/pluginHolder/templates/pluginHolder/plugins.html"
TEMPLATE_DEST="/usr/local/CyberCP/pluginHolder/templates/pluginHolder/plugins.html"
MARKER="installedFilterBtnAll" # Present only in latest template (Show: All | Installed only | Active only)
if [ ! -f "$TEMPLATE_SRC" ]; then
echo "Error: Template not found at $TEMPLATE_SRC"
echo "Set REPO_ROOT to the path of your cyberpanel repo."
exit 1
fi
echo "Source: $TEMPLATE_SRC"
echo "Dest: $TEMPLATE_DEST"
if grep -q "$MARKER" "$TEMPLATE_SRC"; then
echo "Source template is the latest (contains Show/Installed only/Active only)."
else
echo "Warning: Source template does not contain expected marker. Deploy anyway? (y/N)"
read -r ans
if [ "$ans" != "y" ] && [ "$ans" != "Y" ]; then
exit 1
fi
fi
if [ -f "$TEMPLATE_DEST" ]; then
cp -a "$TEMPLATE_DEST" "${TEMPLATE_DEST}.bak.$(date +%Y%m%d%H%M%S)"
echo "Backed up existing template."
fi
mkdir -p "$(dirname "$TEMPLATE_DEST")"
cp -a "$TEMPLATE_SRC" "$TEMPLATE_DEST"
echo "Copied template to $TEMPLATE_DEST"
if command -v systemctl >/dev/null 2>&1 && systemctl is-active --quiet lscpd 2>/dev/null; then
echo "Restarting lscpd..."
systemctl restart lscpd
echo "lscpd restarted."
else
echo "Please restart your panel (e.g. systemctl restart lscpd)."
fi
if grep -q "$MARKER" "$TEMPLATE_DEST"; then
echo "OK: Deployed template is latest. Verify: https://YOUR-PANEL:2087/plugins/installed#grid"
else
echo "Warning: Deployed file missing expected marker."
exit 1
fi

View File

@@ -247,11 +247,11 @@ app.controller('adminController', function ($scope, $http, $timeout) {
}
if (!Boolean(response.data.deleteZone)) {
$('.addDeleteRecords').hide();
$('.deleteZone').hide();
}
if (!Boolean(response.data.addDeleteRecords)) {
$('.deleteDatabase').hide();
$('.addDeleteRecords').hide();
}
// Email Management

View File

@@ -0,0 +1,63 @@
# CyberCP git pull conflicts on v2.5.5-dev (server at /usr/local/CyberCP)
## Why Git asks to "remove" or "move" files
When you run `git pull --ff-only origin v2.5.5-dev` in `/usr/local/CyberCP`, Git can block for two reasons:
### 1. Modified files (would be overwritten by merge)
- **Meaning:** You have **local changes** in tracked files (e.g. `CyberCP/settings.py`, `baseTemplate/views.py`, …). The remote branch also changed those files. Git will not overwrite your working tree without you deciding what to do with your changes.
- **So:** You must either **commit** or **stash** (or discard) those local changes before the pull can apply.
### 2. Untracked files (would be overwritten by merge)
- **Meaning:** You have **untracked** files/dirs at paths where the **incoming** branch (v2.5.5-dev) **adds** files. For example: `panelAccess/`, `baseTemplate/static/baseTemplate/assets/mobile-responsive.css`, `sql/create_ftp_quotas.sql`, etc. Git will not overwrite untracked content, so it refuses to merge and says "Please move or remove them."
- **So:** You must **move or remove** those untracked paths so Git can write the version from the repo there.
## Are all these files on v2.5.5-dev?
- **Yes.** The branch `v2.5.5-dev` on `master3395/cyberpanel` contains:
- All the modified paths (canonical versions).
- All the "untracked" paths (e.g. `panelAccess/`, `mobile-responsive.css`, `readability-fixes.css`, `emailLimitsController.js`, `create_ftp_quotas.sql`, `firewall/migrations/0001_initial.py`, `install/ols_binaries_config.py`, etc.).
- So the **repo** is the source of truth; the server just needs to be brought in line with it. You can confirm by cloning fresh: `git clone -b v2.5.5-dev https://github.com/master3395/cyberpanel.git` and listing those paths.
## Safe way to sync the server to v2.5.5-dev
If you are **ok discarding all local and untracked changes** in `/usr/local/CyberCP` and making it exactly match `origin/v2.5.5-dev`:
```bash
cd /usr/local/CyberCP
# Optional: backup current state
tar -czf /root/cybercp-backup-before-sync-$(date +%Y%m%d-%H%M%S).tar.gz .
# Reset tracked files to current HEAD and remove untracked/ignored files
git fetch origin
git checkout v2.5.5-dev
git reset --hard origin/v2.5.5-dev
git clean -fd
# Ensure you're up to date (should already be after reset)
git pull --ff-only origin v2.5.5-dev
```
After this, **Current** in Version Management should match **Latest** (commit `c24f067e` or whatever is the tip of `origin/v2.5.5-dev`).
## If you need to keep local changes
- **Tracked changes:** Stash first, then pull, then re-apply:
```bash
cd /usr/local/CyberCP
git stash push -m "before sync v2.5.5-dev"
# move or remove the untracked paths listed by Git (e.g. backup then delete)
git pull --ff-only origin v2.5.5-dev
git stash pop
```
- **Untracked files:** Back them up to another directory (e.g. `/root/cybercp-untracked-backup/`) before removing or moving them, then run the pull.
## Upgrade script sync step
The upgrade scripts `Sync_CyberCP_To_Latest()` runs `git fetch`, `checkout`, and `git pull --ff-only`. If the server has local or untracked conflicts like above, that pull will keep failing until you either:
- Run the "safe way" (reset + clean) on the server once, or
- Change the script to use `git reset --hard origin/$Branch_Name` and `git clean -fd` so the install is forced to match the remote (only do this if you intend the install to always mirror the repo with no local edits).

View File

@@ -0,0 +1,113 @@
# HTTP 500 after git sync recovery steps
## Cause
After running `git reset --hard origin/v2.5.5-dev` and `git clean -fd` in `/usr/local/CyberCP`, the **repos** `CyberCP/settings.py` replaced the **servers** production `settings.py`. The repo file has different (or placeholder) database credentials and config, so the app cant connect to the DB or behaves incorrectly → **500** on `/base/` and elsewhere.
## 1. Restore production `settings.py`
Use one of these options.
### A. From your tarball backup (recommended)
You created a backup before sync, e.g.:
`/root/cybercp-backup-before-sync-YYYYMMDD-HHMMSS.tar.gz`
Restore only `settings.py`:
```bash
cd /root
# List to find the exact backup name
ls -la cybercp-backup-before-sync-*.tar.gz
# Restore CyberCP/settings.py (tarball was created from /usr/local/CyberCP so paths start with . or ./)
BACKUP=$(ls -t cybercp-backup-before-sync-*.tar.gz 2>/dev/null | head -1)
if [ -n "$BACKUP" ]; then
tar -xzf "$BACKUP" -C /usr/local/CyberCP ./CyberCP/settings.py 2>/dev/null || \
tar -xzf "$BACKUP" -C /usr/local/CyberCP CyberCP/settings.py 2>/dev/null
echo "Restored settings.py from $BACKUP"
else
echo "No backup found in /root"
fi
```
If the archive has no leading `./`, try:
```bash
tar -xzf "$BACKUP" -C /usr/local/CyberCP --strip-components=0 CyberCP/settings.py
# or
tar -xzf "$BACKUP" -C /tmp cp CyberCP/settings.py && mv /tmp/CyberCP/settings.py /usr/local/CyberCP/CyberCP/
```
### B. From upgrade script backup (if a previous upgrade ran)
The upgrade script backs up to `/tmp/cyberpanel_settings_backup.py`:
```bash
if [ -f /tmp/cyberpanel_settings_backup.py ]; then
cp /tmp/cyberpanel_settings_backup.py /usr/local/CyberCP/CyberCP/settings.py
echo "Restored settings.py from /tmp"
fi
```
### C. If you have no backup
Edit `/usr/local/CyberCP/CyberCP/settings.py` and set the **DATABASES** section to match your server:
- Same DB name, user, and password as used before the sync (e.g. from another backup or from the MySQL/MariaDB config your install used).
## 2. Restart CyberPanel / LiteSpeed
So the app loads the restored config:
```bash
systemctl restart lscpd
# or, depending on setup:
# systemctl restart lsws
```
Wait a few seconds, then try https://207.180.193.210:2087/ and https://207.180.193.210:2087/base/ again.
## 3. If 500 persists get the real error
Run:
```bash
# Application log (Django/CyberPanel)
tail -100 /home/cyberpanel/error-logs.txt
# LiteSpeed / WSGI errors
tail -100 /usr/local/lscp/logs/error.log
# If present
tail -100 /usr/local/CyberCP/logs/cyberpanel.log
journalctl -u lscpd -n 50 --no-pager
```
Then run Django check and migrate:
```bash
cd /usr/local/CyberCP
source /usr/local/CyberCP/bin/activate # if venv exists
python manage.py check
python manage.py migrate --noinput
```
Fix any errors reported (e.g. missing DB user, wrong password, or migrations).
## 4. Future syncs keep production settings
Before running `git reset --hard` again:
1. Back up `settings.py`:
```bash
cp /usr/local/CyberCP/CyberCP/settings.py /root/cyberpanel_settings_production.py
```
2. After sync, restore it:
```bash
cp /root/cyberpanel_settings_production.py /usr/local/CyberCP/CyberCP/settings.py
systemctl restart lscpd
```
Or add a small script that does sync then restores `settings.py` and restarts `lscpd`.

View File

@@ -0,0 +1,36 @@
# Install modularization design
## Overview
- **cyberpanel.sh**: Modular loader; sources `install_modules/00_common.sh``09_parse_main.sh`. When `install_modules/` is missing (e.g. one-liner), downloads modules from GitHub.
- **install.sh**: Wrapper that detects OS, checks disk; if repo has `cyberpanel.sh` + `install_modules/`, runs local loader; else downloads `cyberpanel.sh` and runs it.
- **install/venvsetup.sh**: Loader that sources `install/venvsetup_modules/01_*``05_*`. Original kept as `install/venvsetup_monolithic.sh`.
## install_modules/ (repo root)
| Module | Lines | Content |
|--------|-------|---------|
| 00_common.sh | ~418 | Globals, log_message, print_status, show_banner, detect_os, fix_static_file_permissions, fix_post_install_issues |
| 01_verify_deps.sh | ~129 | verify_installation, install_dependencies |
| 02_install_core.sh | ~390 | install_cyberpanel, check_cyberpanel_installed, cleanup_existing_cyberpanel, install_cyberpanel_direct (part 1) |
| 03_install_direct.sh | ~411 | install_cyberpanel_direct_cont |
| 04_fixes_status.sh | ~210 | apply_fixes, _port_listening, show_status_summary |
| 05_menus_main.sh | ~328 | show_main_menu, show_fresh_install_menu, show_commit_selection, show_version_selection, show_installation_preferences |
| 06_menus_update.sh | ~247 | show_update_menu, show_reinstall_menu, show_system_status |
| 07_menus_advanced.sh | ~273 | show_advanced_menu, show_error_help, show_fix_menu, show_clean_menu, show_logs_menu, show_diagnostics |
| 08_actions.sh | ~317 | start_upgrade, start_force_reinstall, start_preupgrade, start_reinstall, start_installation |
| 09_parse_main.sh | ~247 | parse_arguments, detect_installation_mode, create_standard_aliases, main |
All modules kept under 500 lines. Loader: `cyberpanel.sh`. Backup: `cyberpanel_install_monolithic.sh`.
## install/venvsetup_modules/
| Module | Content |
|--------|---------|
| 01_vars_install_required.sh | Vars, safe_pip_install, license_validation, special_change, system_tweak, install_required |
| 02_memcached_main.sh | memcached_installation, redis_installation, check_provider, check_*, interactive_*, main_install |
| 03_main_run_pip.sh | main_install_run, pip_virtualenv |
| 04_after_install.sh | after_install |
| 05_argument_main.sh | argument_mode, main flow (check_OS, install_required, pip_virtualenv, system_tweak, main_install) |
Loader: `install/venvsetup.sh`. Backup: `install/venvsetup_monolithic.sh`. Refactor: `main_install` calls `main_install_run()` for size split.
## install/ (Python and other files)
- **install/install.py**, **install/installCyberPanel.py**, etc. are unchanged; they are used by the shell installer and may be split in a future pass (e.g. into Python packages) if needed for the 500-line rule.

View File

@@ -0,0 +1,49 @@
# phpMyAdmin 404 After Upgrade
## Symptom
After upgrading with:
```bash
sh <(curl -s https://raw.githubusercontent.com/usmannasir/cyberpanel/v2.5.5-dev/preUpgrade.sh ...) -b v2.5.5-dev --mariadb-version 11.8
```
opening **https://YOUR_IP:2087/phpmyadmin/** (or the panels “phpMyAdmin” link) returns **404 Not Found**.
## Cause
The upgrade step that installs phpMyAdmin (`download_install_phpmyadmin`) can fail without stopping the upgrade (e.g. network, or extract/mv path mismatch). The panel then has no `/usr/local/CyberCP/public/phpmyadmin/` directory, so the web server returns 404 for `/phpmyadmin/`.
## Fix on the server
Run the fix script **as root** on the panel server (e.g. 207.180.193.210):
```bash
# From the repo (if you have it on the server):
cd /home/cyberpanel-repo
sudo bash fix-phpmyadmin.sh
# Or one-liner (download and run from repo):
sudo bash -c 'curl -sL https://raw.githubusercontent.com/master3395/cyberpanel/v2.5.5-dev/fix-phpmyadmin.sh | bash'
```
Or run the same logic via Python:
```bash
sudo /usr/local/CyberCP/bin/python -c "
import sys; sys.path.insert(0, '/usr/local/CyberCP')
import os; os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'CyberCP.settings')
from plogical.upgrade import Upgrade
Upgrade.download_install_phpmyadmin()
"
sudo chown -R lscpd:lscpd /usr/local/CyberCP/public/phpmyadmin
```
Then reload **https://YOUR_IP:2087/phpmyadmin/** (or use Databases → phpMyAdmin in the panel).
## Repo changes
- **fix-phpmyadmin.sh** Script to install/fix phpMyAdmin on the server (run as root).
- **plogical/upgrade.py** `download_install_phpmyadmin()`:
- Resolves extracted folder with `glob` (handles `phpMyAdmin-*-all-languages` or `phpMyAdmin-*`).
- Verifies that `public/phpmyadmin` exists after install and raises if missing so the upgrade step is not silent.

View File

@@ -0,0 +1,44 @@
# phpMyAdmin vs CLI MariaDB Version Mismatch
## Why SSH / `mariadb -V` Shows 11.8 While phpMyAdmin Shows 10.11
Two main causes:
### 1. **Different connection target (most common)**
- **CLI** (`mariadb -V`, `mariadb -e "SELECT @@version;"`) uses the default connection: usually the **main** MariaDB instance (e.g. port 3306 or default socket).
- **phpMyAdmin** previously used host **`localhost`** (hardcoded). With `localhost`, the PHP MySQL client connects via the **default Unix socket**, not necessarily the same as the main instance.
- If you have (or had) **two** MariaDB instances (e.g. main on 3306 and a second on 3307 from `mysqld_multi`, or an old 10.11 still running), the CLI can hit 11.8 while PHPs default socket pointed at the 10.11 instance.
### 2. **Client vs server version**
- `mariadb -V` prints the **client** version (e.g. 11.8). The upgrade script banner also used that for “Database (MariaDB): 11.8”.
- The **server** version is what phpMyAdmin shows. If the server was still 10.11 (e.g. wrong service restarted or second instance), phpMyAdmin correctly showed 10.11.
## Fix applied in code
- The panel now passes **host** (and port) from `/etc/cyberpanel/mysqlPassword` into the phpMyAdmin signon form.
- When the stored host is `localhost`, we send **`127.0.0.1`** so phpMyAdmin connects via **TCP to port 3306** (the main instance), not the default socket.
- So after deploy, phpMyAdmin should show the same MariaDB version as the CLI (the main 11.8 server).
## Verification on the server
Run as root:
```bash
# Server version (what phpMyAdmin should show after fix)
mariadb -e "SELECT @@version;"
# Listeners (only one MariaDB should be on 3306)
ss -tlnp | grep 3306
# Processes (check for duplicate mysqld/mariadbd)
ps aux | grep -E 'mariadb|mysqld'
```
If `SELECT @@version` shows 11.8 but phpMyAdmin still showed 10.11 before the fix, it was almost certainly a different connection (socket vs 127.0.0.1:3306 or a second instance). After the code change and a fresh phpMyAdmin login, it should report 11.8.
## If two instances exist
- Stop the old 10.11 instance (e.g. `mysqld_multi stop 1` if using `mysqld1` on 3307, or disable its service).
- Ensure only the 11.8 service (e.g. `mariadb.service`) is running and listening on 3306.

View File

@@ -0,0 +1,45 @@
# Plugins Installed Grid Install and Verify
## How install works
1. **Grid "Install" button**
- Tries **local install** first: plugin must exist under `/home/cyberpanel/plugins/` or `/home/cyberpanel-plugins/` (with `meta.xml`).
- If the API returns **404** or **"Plugin source not found"**, the UI automatically retries **store install** (download from GitHub `master3395/cyberpanel-plugins` and install).
2. **Store install**
- Used from the Store view or as fallback when local source is missing.
- Downloads the plugin from GitHub and runs the same installer (extract, pre_install, settings/URLs, inform CyberPanel, collectstatic, post_install).
3. **"Installed" status**
- A plugin is considered installed if the **directory** exists: `/usr/local/CyberCP/<plugin_name>/`.
- If that directory exists but `meta.xml` is missing, the UI still shows "Installed". On load of `/plugins/installed`, the backend tries to restore `meta.xml` from source (if source exists).
## Making sure all grid plugins install correctly
- **Local source**
Put plugin folders (each with `meta.xml`) in:
- `/home/cyberpanel/plugins/<plugin_name>/`, or
- `/home/cyberpanel-plugins/<plugin_name>/`
Then use **Install** in the grid; local install will be used.
- **No local source**
Click **Install** in the grid; if local source is not found, the UI falls back to **store install** (GitHub). Ensure the plugin exists in `master3395/cyberpanel-plugins` (main branch).
- **Already installed but broken**
If a plugin directory exists under `/usr/local/CyberCP/` but `meta.xml` was missing, opening **Plugins → Installed** will try to copy `meta.xml` from source into the installed folder so version/update checks work.
## Quick checks on the server
```bash
# Installed plugin dirs
ls -la /usr/local/CyberCP/ | grep -E '^d'
# Local source (grid uses these for local install)
ls -la /home/cyberpanel/plugins/ 2>/dev/null || true
ls -la /home/cyberpanel-plugins/ 2>/dev/null || true
# Ensure meta.xml exists for an installed plugin (e.g. premiumPlugin)
ls -la /usr/local/CyberCP/premiumPlugin/meta.xml
```
After code changes, restart Gunicorn (or the CyberPanel app server) so the updated pluginHolder views and JS are used.

View File

@@ -0,0 +1,44 @@
# Deploy and verify latest Plugins template on server
## 1. Check if server has the latest template
On the server (207.180.193.210), run:
```bash
grep -q "installedFilterBtnAll" /usr/local/CyberCP/pluginHolder/templates/pluginHolder/plugins.html && echo "LATEST: Yes (Show / Installed only / Active only present)" || echo "LATEST: No (run deploy below)"
```
## 2. Deploy latest template to the server
**Option A Run on the server (repo already on server)**
If the cyberpanel repo is on the same machine (e.g. at `/home/cyberpanel-repo`):
```bash
sudo bash /home/cyberpanel-repo/pluginHolder/deploy-plugins-template.sh
```
**Option B Copy from this machine to the server**
From your dev machine (where the repo lives):
```bash
scp /home/cyberpanel-repo/pluginHolder/templates/pluginHolder/plugins.html root@207.180.193.210:/usr/local/CyberCP/pluginHolder/templates/pluginHolder/plugins.html
ssh root@207.180.193.210 "systemctl restart lscpd"
```
Then on the server, verify:
```bash
ssh root@207.180.193.210 'grep -q "installedFilterBtnAll" /usr/local/CyberCP/pluginHolder/templates/pluginHolder/plugins.html && echo "LATEST: Yes" || echo "LATEST: No"'
```
## 3. Verify in the browser
1. Open: https://207.180.193.210:2087/plugins/installed#grid
2. Ensure **Grid View** is selected.
3. You should see two rows under the view toggle:
- **Show:** [All] [Installed only] [Active only]
- **Sort by:** [Name AÅ] [Type] [Date (newest)]
If you see **Show:** and the three filter buttons, you are on the latest template.

View File

@@ -0,0 +1,41 @@
# RainLoop → SnappyMail rename
## Summary
RainLoop has been replaced by SnappyMail. All **operational** paths and the install template folder now use SnappyMail. References to "rainloop" remain only where we **migrate from** old installs (2.4.4 → 2.5.5).
## Changes made
### Repo folder
- **`install/rainloop/`** renamed to **`install/snappymail/`**
- Template file still `cyberpanel.net.ini` (SnappyMail uses same format).
### Code updated to SnappyMail paths
- **plogical/mailUtilities.py** — Template path `/usr/local/CyberCP/install/snappymail/cyberpanel.net.ini`; all data paths `/usr/local/lscp/cyberpanel/snappymail/...`.
- **install/install.py** — chown and mkdir use `snappymail`; commented blocks updated for consistency.
- **plogical/acl.py** — `chown ... /usr/local/lscp/cyberpanel/snappymail`.
- **plogical/upgrade.py** — Operational chown and backup path use snappymail.
### Left as-is (intentional)
- **Migration logic** in `plogical/upgrade.py`, `upgrade_modules/10_post_tweak.sh`, and `cyberpanel_upgrade_monolithic.sh` still uses the **source** path `/usr/local/lscp/cyberpanel/rainloop/data` when upgrading from 2.4.4: they check for old rainloop data and rsync it to `/usr/local/lscp/cyberpanel/snappymail/data/`. That "rainloop" path must stay so existing servers upgrading from RainLoop get their data migrated.
## Upgrade to 2.5.5-dev: migrate ALL links to SnappyMail
On upgrade, the following ensure every RainLoop reference becomes SnappyMail:
1. **Data migration** (existing): rsync from `/usr/local/lscp/cyberpanel/rainloop/data` to `.../snappymail/data`, and update `include.php` paths.
2. **Replace all rainloop path/URL in migrated data**: After rsync, every config file under `snappymail/data` (`.ini`, `.json`, `.php`, `.cfg`) is scanned and any occurrence of:
- `/usr/local/lscp/cyberpanel/rainloop/data``.../snappymail/data`
- `/rainloop/``/snappymail/`
- `rainloop/data``snappymail/data`
is replaced. So stored links and paths in SnappyMail configs point to SnappyMail.
3. **HTTP redirect /rainloop → /snappymail**: In `/usr/local/CyberCP/public/.htaccess` a 301 redirect is added (or ensured once) so that:
- `/rainloop`, `/rainloop/`, `/rainloop/anything``/snappymail/...`
Old bookmarks and shared links keep working.
Implemented in: `plogical/upgrade.py` (`migrateRainloopToSnappymail`), `upgrade_modules/10_post_tweak.sh`, `cyberpanel_upgrade_monolithic.sh`.
## Result
- New installs and day-to-day operations use only SnappyMail paths.
- Upgrades from versions that had RainLoop: data migrated, all config links updated to snappymail, and /rainloop URLs redirect to /snappymail.

View File

@@ -0,0 +1,21 @@
# Removed Unused install/ Folders
## Summary
Unused config folders under `install/` were removed; only the folders actually referenced by the codebase remain.
## Removed
### install/email-configs
- **Reason:** Never referenced. All code uses `install/email-configs-one` (e.g. `install/install.py`, `plogical/mailUtilities.py`, `mailServer/mailserverManager.py`).
- **Removed:** 2025-02-15.
### install/php-configs
- **Reason:** Never referenced. Code uses `install/phpconfigs` (no hyphen) only:
- `plogical/installUtilities.py`: `shutil.copytree("phpconfigs", ...)` and `include phpconfigs/php*.conf`
- `install/litespeed/conf/httpd_config.conf` and `serverStatus/litespeed/conf/httpd_config.conf`: `include phpconfigs/php53.conf` etc.
- **Note:** `php-configs` contained `php.ini` and `www.conf` (different purpose); `phpconfigs` contains `php53.conf``php80.conf` (LiteSpeed PHP version includes).
- **Removed:** 2025-02-15.
## Still in use
- `install/email-configs-one/` — mail configs used by install and mail utilities.
- `install/phpconfigs/` — LiteSpeed PHP version include configs used by install and httpd_config.

View File

@@ -0,0 +1,37 @@
# Install/Upgrade Support Matrix (v2.5.5-dev)
This document summarizes how install and upgrade **detect and handle** each OS in the support table. It does **not** guarantee that every combination has been tested; it reflects what the code paths are.
## Summary
| OS family | Detection | Install/upgrade path | Notes |
|-----------|-----------|----------------------|--------|
| **AlmaLinux 10, 9, 8** | `AlmaLinux-8/9/10` in `/etc/os-release` | 9/10 → `AlmaLinux9` (dnf, repo fixes, venv). 8 → `CentOS` + version 8. | Explicit branches for 9/10 (EPEL, MariaDB, python3-venv). |
| **CentOS 7** | `CentOS Linux 7` in os-release | `CentOS` + version 7. | Legacy; EOL. Uses yum, requirments-old.txt. |
| **CloudLinux 9, 8** | `CloudLinux 7/8/9` in os-release | Normalized to `CentOS` + version. Same as RHEL family. | Version from VERSION_ID (e.g. 8 → 8, 9 → 9). |
| **Debian 13, 12, 11** | `Debian GNU/Linux 11/12/13` in os-release | Treated as **Ubuntu** (`Server_OS=Ubuntu`). Version 11/12/13 from VERSION_ID. | Uses **requirments-old.txt** (not requirments.txt). No Debian-specific package blocks; gets generic apt install. install_utils has Debian 13 package mappings. |
| **RHEL 9, 8** | `Red Hat Enterprise Linux` in os-release | Normalized to `CentOS` + version 8 or 9. | Same repo/package logic as CentOS 8/9. RHEL repo names differ; AlmaLinux-specific repo fixes do not run for RHEL. |
| **RockyLinux 9, 8** | `Rocky Linux` in os-release | Normalized to `CentOS`; version 8 or 9. | Same as CentOS 8/9 (EPEL, MariaDB, venv for 9/10). |
| **Ubuntu 24.04, 22.04, 20.04** | `Ubuntu 24.04` etc. in os-release | Explicit branches for 22/24 (packages, python3-venv). 20 → specific fixes. 18 → minimal. | 24.04: externally-managed-environment handled. Uses **requirments.txt** for 22 and 24. |
## Do we *know* it works on all of them?
- **Code coverage:** Detection and branching exist for all listed OSes. AlmaLinux 8/9/10, Ubuntu 18/20/22/24, Debian 11/12/13, CentOS 7/8/9, Rocky, RHEL, CloudLinux, and openEuler have explicit or normalized paths.
- **No automated proof:** There is no CI in this repo that runs install or upgrade on each OS. “Works” is based on:
- Manual and community testing
- Code review of detection and branches
- **RHEL:** Uses the same code path as CentOS (RedHat → CentOS). RHEL 9 uses different repo IDs than AlmaLinux; if repo issues appear on RHEL 9, RHEL-specific repo handling may be needed.
- **Debian 11/12/13:** Share the “Ubuntu” path and use **requirments-old.txt**. install_utils has Debian 13 (Trixie) package mappings. No Debian-version-specific blocks in the upgrade script.
- **CentOS 7:** Marked legacy/EOL; still in the script with yum and old requirements.
## Recommendations
1. **Staging:** Test install and upgrade on a non-production VM for your chosen OS before production.
2. **CI (optional):** Add a test matrix (e.g. GitHub Actions or other CI) that runs install and/or upgrade on a subset of OSes (e.g. AlmaLinux 9, Ubuntu 22.04, Debian 12) to catch regressions.
3. **Docs:** Keep this file (or a short “Supported platforms” section) in sync with the script when adding or dropping OS versions.
## Where to look in the repo
- **Upgrade OS detection:** `cyberpanel_upgrade.sh` (lines ~160187), `Server_OS_Version` (~187), and branches for `CentOS`/`AlmaLinux9`/`Ubuntu`/`openEuler`.
- **Install OS detection:** `install/install.py` (`preFlightsChecks.detect_os`, `get_distro`), and `install/install_utils.py` (Debian/Ubuntu version and package helpers).
- **Requirements choice:** `cyberpanel_upgrade.sh` `Download_Requirement()`: uses `requirments.txt` for version 22, 24, 9, 10; else `requirments-old.txt`.

View File

@@ -0,0 +1,119 @@
# Security alert: `rm -rf /home/cyberpanel/upgrade_logs`
## Is this an issue?
**No.** This is **expected behavior** from the CyberPanel upgrade process, not a sign of compromise.
## Whats going on
- Your security product (e.g. OSSEC, Wazuh, or similar) flagged:
- **Command:** `sudo ... /bin/rm -rf /home/cyberpanel/upgrade_logs`
- **Context:** `PWD=/tmp/lscpd`, `USER=root`
- The CyberPanel daemon (**lscpd**) runs upgrade-related tasks. The upgrade logic uses `/home/cyberpanel/upgrade_logs` as the path for upgrade logs (see `plogical/upgrade.py`: `LogPathNew = '/home/cyberpanel/upgrade_logs'`). Cleaning that path (file or directory) before or after an upgrade is normal so the next run starts from a clean state.
- So this command is the **panel cleaning its own upgrade logs**, not an attacker.
## Why does it look “suspicious”?
- Security tools often treat **any** `rm -rf` as “dangerous” because it can delete a lot if misused.
- They also flag “system file access” or “writes/deletes under /home” to catch abuse.
- Here, the path is a **known, fixed** CyberPanel path and the process is **root from lscpd** (expected for the panel). So the alert is a **false positive** for “suspicious command” in this context.
## Why “my own local files” look suspicious
- “Local files” in the alert usually means “commands or file operations on this machine.” The product isnt saying your personal files are malicious; its saying the **behavior** (e.g. `rm -rf` on a path under `/home`) matches a **rule** that can indicate compromise.
- In this case the “local” actor is **CyberPanel itself** (lscpd/upgrade), so the behavior is legitimate.
## What you can do
1. **Treat as expected:** No need to change passwords or hunt for backdoors solely because of this alert.
2. **Whitelist/tune the rule:** In your security product, add an exception or rule so that this specific command (or pattern) when run by root from the lscpd context is not reported, e.g.:
- Command pattern: `rm -rf /home/cyberpanel/upgrade_logs`
- Or: allow `rm -rf` for paths under `/home/cyberpanel/` when the process is lscpd/upgrade-related.
3. **Keep monitoring:** Continue to review real suspicious activity (e.g. unknown scripts, unexpected `rm -rf /` or `rm -rf /home/*`).
## Summary
- **Not a compromise** normal CyberPanel upgrade cleanup.
- **“Suspicious”** only in the generic sense (rm -rf + /home); in context its the panels own operation.
- **Action:** Whitelist or tune the alert for this known-good case; no need to panic or “fix” the panel for this.
---
## Whitelist / rule examples (stop this specific case being reported)
Use the example that matches your product. After editing config, restart the agent/manager as indicated.
### OSSEC
Allow this command so it is not reported as suspicious.
**1. Local rule to ignore this command**
Create or edit a local rule file (e.g. `/var/ossec/etc/rules/local_rules.xml`) and add:
```xml
<!-- Allow CyberPanel upgrade cleanup: rm -rf /home/cyberpanel/upgrade_logs -->
<rule id="100001" level="0">
<if_sid>100002</if_sid>
<match>rm -rf /home/cyberpanel/upgrade_logs</match>
<description>Whitelist: CyberPanel upgrade log cleanup (expected)</description>
</rule>
```
If your “suspicious command” rule has a different `<rule id>`, replace `100002` with that rules ID (so this rule only applies when that one fires). If youre not sure, you can use a broader override that matches the command and sets level 0:
```xml
<rule id="100001" level="0">
<match>rm -rf /home/cyberpanel/upgrade_logs</match>
<description>Whitelist: CyberPanel upgrade log cleanup</description>
</rule>
```
Restart OSSEC:
```bash
systemctl restart ossec
# or
/var/ossec/bin/ossec-control restart
```
**2. (Optional) Decoder to tag sudo rm**
In `/var/ossec/etc/decoders/local_decoder.xml` you can add a decoder so the command is clearly identified; the rule above is enough to stop the alert.
### Wazuh
**1. Local rule to not alert on this command**
Append to `/var/ossec/etc/rules/local_rules.xml` (Wazuh keeps OSSEC-style paths):
```xml
<!-- Whitelist CyberPanel upgrade cleanup -->
<group name="local,syscheck,">
<rule id="100001" level="0">
<match>rm -rf /home/cyberpanel/upgrade_logs</match>
<description>Whitelist: CyberPanel upgrade_logs cleanup (lscpd/upgrade)</description>
</rule>
</group>
```
If the alert is from a different rule (e.g. “suspicious command” or “syscheck”), you may need to set `<if_sid>` to that rules ID so this rule only overrides that case.
Restart Wazuh:
```bash
systemctl restart wazuh-agent
# On manager:
systemctl restart wazuh-manager
```
**2. (Optional) Broader CyberPanel cleanup**
To allow any `rm -rf` under `/home/cyberpanel/` when the process is from lscpd/upgrade, youd need a rule that matches both the command pattern and (if available) the process or PWD. Thats product-specific; the rule above is the minimal, safe whitelist for the exact command you saw.
### Other products (generic)
- **Fail2ban / custom script:** If the alert is generated by a script that parses `auth.log` or `secure`, add an exception when the log line contains both `rm -rf` and `/home/cyberpanel/upgrade_logs`.
- **SIEM / cloud:** Add an exception or filter so that events with command `rm -rf /home/cyberpanel/upgrade_logs` and user `root` (and optionally process/source indicating lscpd) are not escalated.
Once the whitelist is in place, future runs of that CyberPanel cleanup will no longer trigger this specific alert.

View File

@@ -0,0 +1,36 @@
# Fix phpMyAdmin Showing 10.11 When 11.8 Is Installed
## 1. Fix CLI SSL error and see real server version
Run as root on the server:
```bash
# Allow mariadb client to connect without SSL (11.x client requires SSL by default)
mkdir -p /etc/my.cnf.d
printf '[client]\nskip-ssl = true\n' > /etc/my.cnf.d/cyberpanel-client.cnf
# Now this should work and show the *actual* server version on 3306
mariadb -e "SELECT @@version;"
```
- If it shows **11.8.x**: the server is 11.8; phpMyAdmin should show 11.8 after you **log out, clear cookies for :2087, then log in again via CyberPanel → Databases → phpMyAdmin**.
- If it still shows **10.11.x**: the process on 3306 is still 10.11. Force the 11.8 service to take over:
```bash
systemctl stop mariadb
sleep 3
systemctl start mariadb
mariadb -e "SELECT @@version;"
```
If it still shows 10.11, check:
```bash
rpm -q MariaDB-server
ss -tlnp | grep 3306
systemctl status mariadb
```
## 2. phpMyAdmin config (already correct on your server)
Your `config.inc.php` already has `host = '127.0.0.1'` and `port = '3306'`. Once the server on 3306 is 11.8 and you log in again via the panel, phpMyAdmin will show 11.8.

View File

@@ -0,0 +1,130 @@
Check_Root() {
echo -e "\nChecking root privileges..."
# If we're actually root (uid 0), allow regardless of SUDO in environment (e.g. curl | sudo bash)
if [[ $(id -u) -eq 0 ]] 2>/dev/null; then
echo -e "\nYou are running as root...\n"
return 0
fi
if echo "$Sudo_Test" | grep SUDO >/dev/null; then
echo -e "\nYou are using SUDO, please run as root user...\n"
echo -e "\nIf you don't have direct access to root user, please run \e[31msudo su -\e[39m command (do NOT miss the \e[31m-\e[39m at end or it will fail) and then run installation command again."
exit 1
fi
echo -e "\nYou must run as root user to install CyberPanel...\n"
echo -e "Run: \e[31msudo su -\e[39m then run this script again, or: curl -sL <url> | sudo bash -s -- <args>"
exit 1
}
Check_Server_IP() {
echo -e "Checking server location...\n"
Server_Country=$(curl --silent --max-time 10 -4 https://cyberpanel.sh/?country)
if [[ ${#Server_Country} != "2" ]] ; then
Server_Country="Unknown"
fi
if [[ "$Debug" = "On" ]] ; then
Debug_Log "Server_Country" "$Server_Country"
fi
if [[ "$*" = *"--mirror"* ]] ; then
Server_Country="CN"
echo -e "Forced to use mirror server due to --mirror argument...\n"
fi
if [[ "$Server_Country" = *"CN"* ]] ; then
Server_Country="CN"
echo -e "Setting up to use mirror server...\n"
fi
}
Check_OS() {
if [[ ! -f /etc/os-release ]] ; then
echo -e "Unable to detect the Operating System...\n"
exit
fi
if ! uname -m | grep -qE 'x86_64|aarch64' ; then
echo -e "x86_64 or ARM system is required...\n"
exit
fi
if grep -q -E "CentOS Linux 7|CentOS Linux 8|CentOS Linux 9|CentOS Stream 9" /etc/os-release ; then
Server_OS="CentOS"
elif grep -q "Red Hat Enterprise Linux" /etc/os-release ; then
Server_OS="RedHat"
elif grep -q -E "CloudLinux 7|CloudLinux 8|CloudLinux 9" /etc/os-release ; then
Server_OS="CloudLinux"
elif grep -q -E "Rocky Linux" /etc/os-release ; then
Server_OS="RockyLinux"
elif grep -q -E "AlmaLinux-8|AlmaLinux-9|AlmaLinux-10" /etc/os-release ; then
Server_OS="AlmaLinux"
# Set specific version for AlmaLinux 9+ to use dnf instead of yum
if grep -q -E "AlmaLinux-9|AlmaLinux-10" /etc/os-release ; then
Server_OS="AlmaLinux9"
fi
elif grep -q -E "Ubuntu 18.04|Ubuntu 20.04|Ubuntu 20.10|Ubuntu 22.04|Ubuntu 24.04|Ubuntu 24.04.3" /etc/os-release ; then
Server_OS="Ubuntu"
elif grep -q -E "Debian GNU/Linux 11|Debian GNU/Linux 12|Debian GNU/Linux 13" /etc/os-release ; then
Server_OS="Ubuntu"
elif grep -q -E "openEuler 20.03|openEuler 22.03" /etc/os-release ; then
Server_OS="openEuler"
else
echo -e "Unable to detect your system..."
echo -e "\nCyberPanel is supported on x86_64 based Ubuntu 18.04, Ubuntu 20.04, Ubuntu 20.10, Ubuntu 22.04, Ubuntu 24.04, Ubuntu 24.04.3, Debian 11, Debian 12, Debian 13, CentOS 7, CentOS 8, CentOS 9, CentOS Stream 9, AlmaLinux 8, AlmaLinux 9, AlmaLinux 10, RockyLinux 8, RockyLinux 9, RHEL 8, RHEL 9, CloudLinux 7, CloudLinux 8, CloudLinux 9, openEuler 20.03, openEuler 22.03...\n"
Debug_Log2 "CyberPanel is supported on x86_64 based Ubuntu 18.04, Ubuntu 20.04, Ubuntu 20.10, Ubuntu 22.04, Ubuntu 24.04, Ubuntu 24.04.3, Debian 11, Debian 12, Debian 13, CentOS 7, CentOS 8, CentOS 9, CentOS Stream 9, AlmaLinux 8, AlmaLinux 9, AlmaLinux 10, RockyLinux 8, RockyLinux 9, RHEL 8, RHEL 9, CloudLinux 7, CloudLinux 8, CloudLinux 9, openEuler 20.03, openEuler 22.03... [404]"
exit
fi
Server_OS_Version=$(grep VERSION_ID /etc/os-release | awk -F[=,] '{print $2}' | tr -d \" | head -c2 | tr -d . )
#to make 20.04 display as 20, etc.
echo -e "System: $Server_OS $Server_OS_Version detected...\n"
if [[ $Server_OS = "CloudLinux" ]] || [[ "$Server_OS" = "AlmaLinux" ]] || [[ "$Server_OS" = "RockyLinux" ]] || [[ "$Server_OS" = "RedHat" ]]; then
# Keep AlmaLinux9 separate for dnf package management
if [[ "$Server_OS" != "AlmaLinux9" ]]; then
Server_OS="CentOS"
#CloudLinux gives version id like 7.8, 7.9, so cut it to show first number only
#treat CloudLinux, Rocky and Alma as CentOS
fi
fi
if [[ "$Debug" = "On" ]] ; then
Debug_Log "Server_OS" "$Server_OS $Server_OS_Version"
fi
}
Check_Provider() {
if hash dmidecode >/dev/null 2>&1; then
if [[ "$(dmidecode -s bios-vendor)" = "Google" ]]; then
Server_Provider="Google Cloud Platform"
elif [[ "$(dmidecode -s bios-vendor)" = "DigitalOcean" ]]; then
Server_Provider="Digital Ocean"
elif [[ "$(dmidecode -s system-product-name | cut -c 1-7)" = "Alibaba" ]]; then
Server_Provider="Alibaba Cloud"
elif [[ "$(dmidecode -s system-manufacturer)" = "Microsoft Corporation" ]]; then
Server_Provider="Microsoft Azure"
elif [[ -d /usr/local/qcloud ]]; then
Server_Provider="Tencent Cloud"
else
Server_Provider="Undefined"
fi
else
Server_Provider='Undefined'
fi
if [[ -f /sys/devices/virtual/dmi/id/product_uuid ]]; then
if [[ "$(cut -c 1-3 /sys/devices/virtual/dmi/id/product_uuid)" = 'EC2' ]] && [[ -d /home/ubuntu ]]; then
Server_Provider='Amazon Web Service'
fi
fi
if [[ "$Debug" = "On" ]] ; then
Debug_Log "Server_Provider" "$Server_Provider"
fi
}

View File

@@ -0,0 +1,53 @@
Migrate_MariaDB_To_UTF8_Requested=""
# MariaDB version: any X.Y or X.Y.Z supported; highlighted: 10.11.16, 11.8 LTS, 12.x (default 11.8)
MARIADB_VER="11.8"
MARIADB_VER_REPO="11.8"
Check_Argument() {
# Parse --branch / -b (extract first word after -b or --branch)
if [[ "$*" = *"--branch "* ]]; then
Branch_Name=$(echo "$*" | sed -n 's/.*--branch \([^ ]*\).*/\1/p' | head -1)
[[ -n "$Branch_Name" ]] && Branch_Check "$Branch_Name"
elif [[ "$*" = *"-b "* ]]; then
Branch_Name=$(echo "$*" | sed -n 's/.*-b \([^ ]*\).*/\1/p' | head -1)
[[ -n "$Branch_Name" ]] && Branch_Check "$Branch_Name"
fi
# Parse --repo / -r to use any GitHub user (same URL structure as usmannasir/cyberpanel)
if [[ "$*" = *"--repo "* ]]; then
Git_User_Override=$(echo "$*" | sed -n 's/.*--repo \([^ ]*\).*/\1/p' | head -1)
fi
if [[ "$*" = *"-r "* ]] && [[ -z "$Git_User_Override" ]]; then
Git_User_Override=$(echo "$*" | sed -n 's/.*-r \([^ ]*\).*/\1/p' | head -1)
fi
# Parse --no-system-update to skip yum/dnf update -y (faster upgrade when system is already updated)
if [[ "$*" = *"--no-system-update"* ]]; then
Skip_System_Update="yes"
echo -e "\nUsing --no-system-update: skipping full system package update.\n"
fi
# Parse --backup-db / --no-backup-db: pre-upgrade MariaDB backup. Default when neither set: ask user (may take a while).
# --backup-db = always backup; --no-backup-db = never backup; omit both = prompt [y/N]
Backup_DB_Before_Upgrade=""
if [[ "$*" = *"--backup-db"* ]]; then
Backup_DB_Before_Upgrade="yes"
echo -e "\nUsing --backup-db: will create a full MariaDB backup before upgrade.\n"
elif [[ "$*" = *"--no-backup-db"* ]]; then
Backup_DB_Before_Upgrade="no"
echo -e "\nUsing --no-backup-db: skipping MariaDB pre-upgrade backup.\n"
fi
# Parse --migrate-to-utf8: after upgrading to MariaDB 11.x/12.x, convert DBs/tables from latin1 to utf8mb4 (only if your apps support UTF-8)
if [[ "$*" = *"--migrate-to-utf8"* ]]; then
Migrate_MariaDB_To_UTF8_Requested="yes"
echo -e "\nUsing --migrate-to-utf8: will convert databases to UTF-8 (utf8mb4) after MariaDB upgrade.\n"
fi
# Parse --mariadb-version (any version: 10.6, 10.11, 10.11.16, 11.8, 12.1, 12.2, 12.3, etc.). Default 11.8.
# --mariadb is shorthand for --mariadb-version 10.11
if [[ "$*" = *"--mariadb"* ]] && [[ "$*" != *"--mariadb-version "* ]]; then
MARIADB_VER="10.11"
echo -e "\nUsing --mariadb: MariaDB 10.11 selected (non-interactive).\n"
elif [[ "$*" = *"--mariadb-version "* ]]; then
MARIADB_VER=$(echo "$*" | sed -n 's/.*--mariadb-version \([^ ]*\).*/\1/p' | head -1)
MARIADB_VER="${MARIADB_VER:-11.8}"
fi
# Allow any version; repo paths use major.minor (normalized later)
}

View File

@@ -258,6 +258,22 @@ fi
# Fix SnappyMail directory permissions for Ubuntu 24.04 and other systems
echo -e "[$(date +"%Y-%m-%d %H:%M:%S")] Checking SnappyMail directories..." | tee -a /var/log/cyberpanel_upgrade_debug.log
# If public web app is still named rainloop, rename to snappymail so /snappymail/ URL works
if [ -d "/usr/local/CyberCP/public/rainloop" ] && [ ! -d "/usr/local/CyberCP/public/snappymail" ]; then
echo -e "[$(date +"%Y-%m-%d %H:%M:%S")] Renaming public/rainloop to public/snappymail..." | tee -a /var/log/cyberpanel_upgrade_debug.log
mv /usr/local/CyberCP/public/rainloop /usr/local/CyberCP/public/snappymail
echo -e "[$(date +"%Y-%m-%d %H:%M:%S")] Renamed public/rainloop -> public/snappymail" | tee -a /var/log/cyberpanel_upgrade_debug.log
# Update data path in app config so it uses snappymail data dir
if [ -f "/usr/local/CyberCP/public/snappymail/include.php" ]; then
sed -i 's|/usr/local/lscp/cyberpanel/rainloop/data|/usr/local/lscp/cyberpanel/snappymail/data|g' /usr/local/CyberCP/public/snappymail/include.php
echo -e "[$(date +"%Y-%m-%d %H:%M:%S")] Updated include.php to use snappymail data path" | tee -a /var/log/cyberpanel_upgrade_debug.log
fi
# Update version-specific include.php (may be under snappymail/v/ or rainloop/v/ after rename)
for inc in /usr/local/CyberCP/public/snappymail/snappymail/v/*/include.php /usr/local/CyberCP/public/snappymail/rainloop/v/*/include.php; do
[ -f "$inc" ] && sed -i 's|/usr/local/lscp/cyberpanel/rainloop/data|/usr/local/lscp/cyberpanel/snappymail/data|g' "$inc" && echo -e "[$(date +"%Y-%m-%d %H:%M:%S")] Updated $inc" | tee -a /var/log/cyberpanel_upgrade_debug.log && break
done 2>/dev/null
fi
# Migrate data from old rainloop folder to new snappymail folder (2.4.4 -> 2.5.5 upgrade)
if [ -d "/usr/local/lscp/cyberpanel/rainloop/data" ] && [ "$(ls -A /usr/local/lscp/cyberpanel/rainloop/data 2>/dev/null)" ]; then
echo -e "[$(date +"%Y-%m-%d %H:%M:%S")] Migrating rainloop data to snappymail..." | tee -a /var/log/cyberpanel_upgrade_debug.log
@@ -284,6 +300,14 @@ if [ -d "/usr/local/lscp/cyberpanel/rainloop/data" ] && [ "$(ls -A /usr/local/ls
sed -i 's|/usr/local/lscp/cyberpanel/rainloop/data|/usr/local/lscp/cyberpanel/snappymail/data|g' /usr/local/CyberCP/public/snappymail/include.php
echo -e "[$(date +"%Y-%m-%d %H:%M:%S")] Updated include.php to use snappymail data path" | tee -a /var/log/cyberpanel_upgrade_debug.log
fi
# Replace ALL rainloop path/URL references in migrated SnappyMail data (configs, domains, plugins)
if [ -d "/usr/local/lscp/cyberpanel/snappymail/data" ]; then
find /usr/local/lscp/cyberpanel/snappymail/data -type f \( -name "*.ini" -o -name "*.json" -o -name "*.php" -o -name "*.cfg" \) -exec grep -l "rainloop" {} \; 2>/dev/null | while read -r f; do
sed -i 's|/usr/local/lscp/cyberpanel/rainloop/data|/usr/local/lscp/cyberpanel/snappymail/data|g; s|/rainloop/|/snappymail/|g; s|rainloop/data|snappymail/data|g' "$f"
done
echo -e "[$(date +"%Y-%m-%d %H:%M:%S")] Replaced rainloop→snappymail links in SnappyMail data files" | tee -a /var/log/cyberpanel_upgrade_debug.log
fi
else
echo -e "[$(date +"%Y-%m-%d %H:%M:%S")] WARNING: Data migration completed with errors" | tee -a /var/log/cyberpanel_upgrade_debug.log
fi
@@ -307,6 +331,20 @@ else
echo -e "[$(date +"%Y-%m-%d %H:%M:%S")] WARNING: lscpd user not found, skipping ownership change" | tee -a /var/log/cyberpanel_upgrade_debug.log
fi
# Ensure /rainloop→/snappymail redirect exists (even when no migration ran)
HTACCESS="/usr/local/CyberCP/public/.htaccess"
if [ -d "/usr/local/CyberCP/public" ] && { [ ! -f "$HTACCESS" ] || ! grep -q "Redirect old RainLoop URL to SnappyMail" "$HTACCESS" 2>/dev/null; }; then
{
echo ""
echo "# Redirect old RainLoop URL to SnappyMail (2.5.5 upgrade)"
echo "<IfModule mod_rewrite.c>"
echo "RewriteEngine On"
echo "RewriteRule ^rainloop/?(.*)\$ /snappymail/\$1 [R=301,L]"
echo "</IfModule>"
} >> "$HTACCESS"
echo -e "[$(date +"%Y-%m-%d %H:%M:%S")] Added /rainloop→/snappymail redirect to .htaccess" | tee -a /var/log/cyberpanel_upgrade_debug.log
fi
# Set proper permissions for SnappyMail data directories (group writable)
chmod -R 775 /usr/local/lscp/cyberpanel/snappymail/data/
echo -e "[$(date +"%Y-%m-%d %H:%M:%S")] Set SnappyMail data directory permissions to 775 (group writable)" | tee -a /var/log/cyberpanel_upgrade_debug.log