diff --git a/scripts/ssl-manager/ssl_manager.sh b/scripts/ssl-manager/ssl_manager.sh
index 338c739..432b937 100644
--- a/scripts/ssl-manager/ssl_manager.sh
+++ b/scripts/ssl-manager/ssl_manager.sh
@@ -122,43 +122,23 @@ update_litespeed_config() {
cp "$config_file" "$backup_file"
log "Created backup of LiteSpeed configuration at $backup_file"
- # First, clean up any redundant listeners for this domain
+ # Clean up any redundant listeners for this domain
cleanup_redundant_listeners "$config_file" "$DOMAIN"
- # After cleaning up redundant listeners but before adding domain mappings,
- # create a virtual host for the domain
- create_domain_virtual_host "$DOMAIN"
-
- # Check if the required listeners exist and contain correct cert paths
- local need_cert_update=false
- local has_domain_listener=false
-
- # Check if domain exists in HTTPS and HTTPS-ipv6 listeners with correct cert paths
- if grep -A30 "HTTPS" "$config_file" | grep -q "$DOMAIN" && \
- grep -A30 "HTTPS-ipv6" "$config_file" | grep -q "$DOMAIN"; then
- # Domain exists in both listeners, check cert paths
- if ! grep -A30 "HTTPS" "$config_file" | grep -q "$key_file" || \
- ! grep -A30 "HTTPS-ipv6" "$config_file" | grep -q "$key_file"; then
- need_cert_update=true
- log "Certificate paths need updating"
- else
- log "Domain mappings and certificate paths are already correct"
- fi
- else
- log "Domain mappings need to be added"
+ # Create domain-specific virtual host
+ if ! create_domain_virtual_host "$DOMAIN"; then
+ log "ERROR: Failed to create virtual host for $DOMAIN. Aborting configuration update."
+ return 1
fi
- # Update certificate paths if needed
- if [ "$need_cert_update" = true ]; then
- log "Updating certificate paths..."
- # Update keyFile and certFile for all listeners that match our domain
- sed -i "//,/<\/listener>/ s|.*letsencrypt/live/$DOMAIN/.*|$key_file|g" "$config_file"
- sed -i "//,/<\/listener>/ s|.*letsencrypt/live/$DOMAIN/.*|$cert_file|g" "$config_file"
+ # Create domain-specific listener
+ if ! create_domain_listener "$DOMAIN"; then
+ log "ERROR: Failed to create listener for $DOMAIN. Aborting configuration update."
+ return 1
fi
- # Add domain mapping to listeners (modified function will use the correct virtual host)
- add_domain_mapping "HTTPS"
- add_domain_mapping "HTTPS-ipv6"
+ # Remove domain from shared listeners - safer to avoid certificate mismatch errors
+ remove_domain_from_shared_listeners
# Final validation of the complete file
if ! validate_xml_config "$config_file" "$backup_file"; then
@@ -167,7 +147,7 @@ update_litespeed_config() {
return 1
fi
- log "LiteSpeed configuration updated successfully with proper domain-to-virtualhost mapping."
+ log "LiteSpeed configuration updated successfully with dedicated domain configuration."
return 0
}
@@ -439,68 +419,53 @@ install_xml_tools() {
return 0
}
-# New function to create or update domain-specific virtual host
-create_domain_virtual_host() {
- local domain="$1"
- local config_file="/var/www/conf/httpd_config.xml"
- local vhost_name="${domain//./_}" # Replace dots with underscores for uniqueness
-
- log "Checking if virtual host for $domain needs to be created..."
-
- # Check if virtual host already exists
- if grep -q "$vhost_name" "$config_file"; then
- log "Virtual host '$vhost_name' already exists, skipping creation."
- return 0
- fi
-
- log "Creating virtual host for $domain..."
- local temp_file=$(mktemp)
-
- # Create the virtual host definition
- local vhost_config="\n $vhost_name\n /var/www/webroot/\n \$SERVER_ROOT/conf/vhconf.xml\n 1\n 1\n 1\n 0\n 0\n"
-
- # Insert the virtual host before the end of virtualHostList tag
- awk -v vhost="$vhost_config" '
- /<\/virtualHostList>/ { print " " vhost; }
- { print }
- ' "$config_file" > "$temp_file"
-
- # Check if file looks valid
- if [ -s "$temp_file" ] && grep -q "" "$temp_file" && grep -q "" "$temp_file"; then
- cp "$temp_file" "$config_file"
- log "Virtual host for $domain created successfully."
- else
- log "Error: Generated configuration appears invalid. Virtual host not created."
- rm -f "$temp_file"
- return 1
- fi
-
- rm -f "$temp_file"
- return 0
-}
-
-# Add a new function to create a domain-specific HTTPS listener
+# Function to create or update a domain-specific HTTPS listener
create_domain_listener() {
local domain="$1"
+ local config_file="/var/www/conf/httpd_config.xml"
+ local vhost_name="${domain//[.]/_}"
local key_file="/etc/letsencrypt/live/$domain/privkey.pem"
local cert_file="/etc/letsencrypt/live/$domain/fullchain.pem"
- local config_file="/var/www/conf/httpd_config.xml"
- local vhost_name="${domain%%.*}"
+ local timestamp=$(date +%Y%m%d%H%M%S)
+ local backup_file="${config_file}.backup.${timestamp}"
- log "Creating domain-specific HTTPS listener for $domain..."
+ log "Creating/updating domain-specific HTTPS listener for $domain..."
+
+ # Create backup if not already done
+ if [ ! -f "$backup_file" ]; then
+ cp "$config_file" "$backup_file"
+ log "Created backup of LiteSpeed configuration at $backup_file"
+ fi
# Check if listener already exists
if grep -q "HTTPS-$domain" "$config_file"; then
- log "HTTPS listener for $domain already exists, updating certificate paths..."
- sed -i "/HTTPS-$domain<\/name>/,/<\/listener>/s|.*|$key_file|" "$config_file"
- sed -i "/HTTPS-$domain<\/name>/,/<\/listener>/s|.*|$cert_file|" "$config_file"
+ log "HTTPS listener for $domain already exists, updating configuration..."
+
+ # Update certificate paths in existing listener
+ sed -i "/HTTPS-$domain<\/name>/,/<\/listener>/ s|.*|$key_file|" "$config_file"
+ sed -i "/HTTPS-$domain<\/name>/,/<\/listener>/ s|.*|$cert_file|" "$config_file"
+
+ # Verify updates were applied
+ if grep -A5 "HTTPS-$domain" "$config_file" | grep -q "$key_file"; then
+ log "Certificate paths updated successfully for $domain listener."
+ else
+ log "ERROR: Failed to update certificate paths for $domain listener."
+ return 1
+ fi
+
return 0
fi
- # Create a new listener with domain-specific settings
- local temp_file=$(mktemp)
+ log "Creating new HTTPS listener for $domain..."
- # Insert the new listener before the end of listenerList
+ # Create a temporary file for XML editing
+ local temp_file=$(mktemp)
+ if [ ! -f "$temp_file" ]; then
+ log "ERROR: Failed to create temporary file for configuration update."
+ return 1
+ fi
+
+ # Insert new listener into configuration before listenerList end tag
awk -v domain="$domain" -v vhost="$vhost_name" -v key="$key_file" -v cert="$cert_file" '
/<\/listenerList>/ {
print " "
@@ -522,12 +487,233 @@ create_domain_listener() {
print " 1"
print " 15"
print " "
+ print $0
+ next
}
{ print }
' "$config_file" > "$temp_file"
- mv "$temp_file" "$config_file"
- log "Domain-specific HTTPS listener created for $domain."
+ # Validate the temporary file
+ if [ ! -s "$temp_file" ]; then
+ log "ERROR: Generated configuration is empty. Keeping original configuration."
+ rm -f "$temp_file"
+ return 1
+ fi
+
+ # Check for basic XML validity
+ if ! grep -q "" "$temp_file" || ! grep -q "" "$temp_file"; then
+ log "ERROR: Generated configuration appears invalid. Keeping original configuration."
+ rm -f "$temp_file"
+ return 1
+ fi
+
+ # Apply changes
+ cp "$temp_file" "$config_file"
+ if [ $? -ne 0 ]; then
+ log "ERROR: Failed to update configuration file. Keeping original configuration."
+ rm -f "$temp_file"
+ return 1
+ fi
+
+ # Clean up temp file
+ rm -f "$temp_file"
+
+ log "Domain-specific HTTPS listener for $domain created successfully."
+ return 0
+}
+
+# Function to create or update domain-specific virtual host
+create_domain_virtual_host() {
+ local domain="$1"
+ local config_file="/var/www/conf/httpd_config.xml"
+ local vhost_name="${domain//[.]/_}"
+
+ log "Checking if virtual host for $domain needs to be created..."
+
+ # Check if virtual host already exists
+ if grep -q "$vhost_name" "$config_file"; then
+ log "Virtual host '$vhost_name' already exists, skipping creation."
+ return 0
+ fi
+
+ log "Creating virtual host for $domain..."
+ local temp_file=$(mktemp)
+ if [ ! -f "$temp_file" ]; then
+ log "ERROR: Failed to create temporary file for virtual host creation."
+ return 1
+ fi
+
+ # Insert new virtual host before virtualHostList end tag
+ awk -v vhost="$vhost_name" '
+ /<\/virtualHostList>/ {
+ print " "
+ print " " vhost ""
+ print " /var/www/webroot/"
+ print " $SERVER_ROOT/conf/vhconf.xml"
+ print " 1"
+ print " 1"
+ print " 1"
+ print " 0"
+ print " 0"
+ print " "
+ print $0
+ next
+ }
+ { print }
+ ' "$config_file" > "$temp_file"
+
+ # Validate the temporary file
+ if [ ! -s "$temp_file" ]; then
+ log "ERROR: Generated virtual host configuration is empty. Keeping original configuration."
+ rm -f "$temp_file"
+ return 1
+ fi
+
+ # Apply changes
+ cp "$temp_file" "$config_file"
+ if [ $? -ne 0 ]; then
+ log "ERROR: Failed to update configuration with new virtual host. Keeping original configuration."
+ rm -f "$temp_file"
+ return 1
+ fi
+
+ # Clean up
+ rm -f "$temp_file"
+
+ log "Virtual host for $domain created successfully."
+ return 0
+}
+
+# Function to remove domain from shared listeners to avoid certificate mismatch
+remove_domain_from_shared_listeners() {
+ local config_file="/var/www/conf/httpd_config.xml"
+ local domain="$DOMAIN"
+
+ log "Removing $domain from shared listeners to prevent certificate mismatch..."
+
+ # Create temporary file
+ local temp_file=$(mktemp)
+ if [ ! -f "$temp_file" ]; then
+ log "ERROR: Failed to create temporary file for shared listener cleanup."
+ return 1
+ fi
+
+ # For HTTPS listener
+ awk -v domain="$domain" '
+ /HTTPS<\/name>/,/<\/listener>/ {
+ if ($0 ~ //) {
+ in_vhostmap = 1
+ vhostmap_buffer = $0 "\n"
+ next
+ }
+ if (in_vhostmap) {
+ vhostmap_buffer = vhostmap_buffer $0 "\n"
+ if ($0 ~ /<\/vhostMap>/) {
+ if (vhostmap_buffer !~ domain) {
+ printf "%s", vhostmap_buffer
+ }
+ in_vhostmap = 0
+ vhostmap_buffer = ""
+ }
+ next
+ }
+ }
+ { print }
+ ' "$config_file" > "$temp_file"
+
+ # Check if changes were made correctly
+ if [ ! -s "$temp_file" ]; then
+ log "ERROR: Generated configuration is empty after domain removal. Keeping original configuration."
+ rm -f "$temp_file"
+ return 1
+ fi
+
+ cp "$temp_file" "$config_file"
+ rm -f "$temp_file"
+
+ # For HTTPS-ipv6 listener - repeat the process
+ temp_file=$(mktemp)
+ if [ ! -f "$temp_file" ]; then
+ log "ERROR: Failed to create temporary file for shared listener cleanup."
+ return 1
+ fi
+
+ awk -v domain="$domain" '
+ /HTTPS-ipv6<\/name>/,/<\/listener>/ {
+ if ($0 ~ //) {
+ in_vhostmap = 1
+ vhostmap_buffer = $0 "\n"
+ next
+ }
+ if (in_vhostmap) {
+ vhostmap_buffer = vhostmap_buffer $0 "\n"
+ if ($0 ~ /<\/vhostMap>/) {
+ if (vhostmap_buffer !~ domain) {
+ printf "%s", vhostmap_buffer
+ }
+ in_vhostmap = 0
+ vhostmap_buffer = ""
+ }
+ next
+ }
+ }
+ { print }
+ ' "$config_file" > "$temp_file"
+
+ if [ ! -s "$temp_file" ]; then
+ log "ERROR: Generated configuration is empty after domain removal. Keeping original configuration."
+ rm -f "$temp_file"
+ return 1
+ fi
+
+ cp "$temp_file" "$config_file"
+ rm -f "$temp_file"
+
+ log "Domain successfully removed from shared listeners."
+ return 0
+}
+
+# Restart LiteSpeed with extra verification
+restart_litespeed() {
+ log "Restarting LiteSpeed web server..."
+
+ # Verify configuration before restart
+ if command -v /usr/local/lsws/bin/lshttpd > /dev/null; then
+ log "Verifying LiteSpeed configuration before restart..."
+ /usr/local/lsws/bin/lshttpd -t
+ if [ $? -ne 0 ]; then
+ log "ERROR: LiteSpeed configuration test failed. Not restarting server."
+ return 1
+ fi
+ log "LiteSpeed configuration verified successfully."
+ fi
+
+ # Now restart the service
+ if systemctl is-active --quiet lsws; then
+ systemctl restart lsws
+ if [ $? -ne 0 ]; then
+ log "ERROR: Failed to restart LiteSpeed. Please check logs."
+ return 1
+ fi
+
+ # Verify LiteSpeed is running after restart
+ sleep 2
+ if ! systemctl is-active --quiet lsws; then
+ log "ERROR: LiteSpeed failed to start after restart. Please check logs."
+ return 1
+ fi
+
+ log "LiteSpeed successfully restarted."
+ else
+ systemctl start lsws
+ if [ $? -ne 0 ]; then
+ log "ERROR: Failed to start LiteSpeed. Please check logs."
+ return 1
+ fi
+ log "LiteSpeed was not running. Started the service."
+ fi
+
+ return 0
}
# Parse input parameters
@@ -609,18 +795,6 @@ fi
CERTBOT_CMD="certbot certonly --webroot -w /var/www/webroot/ROOT -d $DOMAIN --agree-tos --non-interactive"
[[ -n "${EMAIL:-}" ]] && CERTBOT_CMD+=" --email $EMAIL"
-# Improved LiteSpeed service handling
-restart_litespeed() {
- log "Restarting LiteSpeed web server..."
- if systemctl is-active --quiet lsws; then
- systemctl reload lsws || systemctl restart lsws
- log "LiteSpeed successfully restarted."
- else
- systemctl start lsws
- log "LiteSpeed was not running. Started the service."
- fi
-}
-
# After Certbot installation and before existing certificate check
install_xml_tools