Files
nginx-server-manager/uninstall.sh
Adewale Ayokanmi Adeleye 4799665932 Fix installation issues (#4)
* Fix installation issues with nginx-manager service

- Add missing email-validator package to requirements.txt
- Fix PATH environment variable in systemd service to include system binary paths
- Service now properly finds nginx binary at /usr/sbin/nginx
- Resolves service startup failures due to missing dependencies

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Fix sudo permission issues in systemd service

- Add use_sudo configuration option to handle both systemd and development modes
- Update nginx_service.py to gracefully handle NoNewPrivileges=true in systemd
- Modify config validation to work without sudo when running as systemd service
- Add fallback logic for nginx commands when sudo is unavailable
- Update systemd service file with proper capabilities and groups
- Fix regex escape sequences in nginx templates
- Make sudo permissions optional in install script

This fixes the "no new privileges" error when adding sites through the web interface
while running as a systemd service with security restrictions enabled.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Fix nginx validation errors for log files and ports

- Replace /var/log/nginx paths with temp directory during validation
- Replace low ports (80, 443) with high ports (8080, 8443) for testing
- Create temporary log directory for validation testing
- Clean up temporary log files after validation

This fixes the "Read-only file system" and "Permission denied" errors
when validating nginx configurations in the systemd service context.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Fix site enabling with systemd NoNewPrivileges restrictions

- Update enable_site to handle permission issues gracefully
- Modify reload_nginx to skip config test when permissions insufficient
- Handle authentication errors for systemctl commands
- Provide clear messages when manual nginx reload is required
- Continue with site enabling even when reload fails due to permissions

Sites can now be enabled successfully in systemd service mode, with
clear feedback when manual nginx reload is needed due to security restrictions.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Add automated nginx reload with security wrapper script

- Create nginx-wrapper.sh for secure nginx operations without NoNewPrivileges issues
- Add setup_nginx_wrapper() function to install script for automated setup
- Configure specific sudoers rules for controlled nginx operations
- Update config to use wrapper script for all nginx commands
- Enable full automation: sites can be created, enabled, and nginx reloaded automatically
- Maintain systemd security settings while providing nginx management capabilities
- Add comprehensive logging for nginx operations

Users no longer need manual nginx reloads - the system handles everything automatically
while maintaining security through controlled sudo access to specific operations.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Fix nginx site enablement with systemd NoNewPrivileges restriction

- Updated nginx service to use wrapper script for nginx operations
- Prevents "no new privileges" errors when running under systemd service
- Improved reliability of site enablement and nginx reloading
- Made uninstall script executable

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Fix site enablement issues under systemd NoNewPrivileges restriction

- Enhanced permission error detection in enable_site method
- Updated config.yaml.example to use systemd-compatible settings (use_sudo: false)
- Fixed install.sh to set proper default admin password
- Improved error handling for "Cannot use sudo" and "restricted environment" messages

These changes ensure fresh installations work properly with site creation and enablement through the UI.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Fix site disable functionality with comprehensive permission error handling

- Added same permission error detection logic to disable_site method
- Fixed "Cannot use sudo: Running in restricted environment" error for site disabling
- Added rollback logic to restore symlink if real nginx reload failure occurs
- Improved error differentiation between permission issues and actual nginx problems

Now both site enable and disable work perfectly under systemd NoNewPrivileges restriction.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Fix httpx SSLError AttributeError in site testing functionality

- Replace deprecated httpx.SSLError with httpx.ConnectError
- Add intelligent SSL error detection by checking error message content
- Maintain backward compatibility with proper error handling
- Resolves "module 'httpx' has no attribute 'SSLError'" error

The site test endpoint now works correctly with httpx 0.25.2.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Fix site testing to use local nginx server with Host headers

- Test local nginx server (127.0.0.1) instead of external domains
- Use proper Host headers to simulate domain requests
- Fix remaining URL reference in RequestError handler
- Resolves "Connection failed" errors when testing sites

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Fix session expiration handling and toast function errors

- Fix 'this.showToast is not a function' by using global showToast function
- Add comprehensive JWT token expiration checking and validation
- Implement global fetch interceptor to catch 401 responses
- Enhanced authentication error handling with automatic redirects
- Improved session validation on app startup
- Better error handling for expired tokens

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Add automatic nginx reload after site enable/disable operations

- Implement systemd path watcher for automatic nginx reloads
- Create nginx-reload.path to monitor /etc/nginx/sites-enabled changes
- Create nginx-reload.service to safely reload nginx with validation
- Update enable_site/disable_site messages to indicate auto-reload
- Simplify reload_nginx wrapper script logic
- Fix permission issues with NoNewPrivileges=true restriction

Now nginx automatically reloads whenever sites are enabled/disabled,
eliminating the need for manual reloads and fixing the 404 issues.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

---------

Co-authored-by: Ubuntu <ubuntu@ip-172-31-25-103.ec2.internal>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: ubuntu <ubuntu@nginx-manager.local>
2025-09-01 20:15:38 +01:00

483 lines
16 KiB
Bash
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
# Nginx Site Manager Uninstall Script
# Safely removes the application and optionally cleans up system changes
# Version: 1.0
set -e
set -o pipefail
# Color codes for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
PURPLE='\033[0;35m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color
# Uninstall variables
SCRIPT_VERSION="1.0"
UNINSTALL_LOG="/tmp/nginx-manager-uninstall.log"
CURRENT_USER=$(whoami)
BACKUP_DIR="/tmp/nginx-manager-uninstall-backup-$(date +%Y%m%d_%H%M%S)"
# Function to print colored output
print_header() {
echo -e "\n${PURPLE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo -e "${PURPLE} $1${NC}"
echo -e "${PURPLE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}\n"
}
print_status() {
echo -e "${GREEN}${NC} $1"
echo "$(date '+%Y-%m-%d %H:%M:%S') [INFO] $1" >> "$UNINSTALL_LOG"
}
print_warning() {
echo -e "${YELLOW}${NC} $1"
echo "$(date '+%Y-%m-%d %H:%M:%S') [WARN] $1" >> "$UNINSTALL_LOG"
}
print_error() {
echo -e "${RED}${NC} $1"
echo "$(date '+%Y-%m-%d %H:%M:%S') [ERROR] $1" >> "$UNINSTALL_LOG"
}
print_info() {
echo -e "${BLUE}${NC} $1"
echo "$(date '+%Y-%m-%d %H:%M:%S') [INFO] $1" >> "$UNINSTALL_LOG"
}
print_step() {
echo -e "\n${CYAN}${NC} ${CYAN}$1${NC}"
echo "$(date '+%Y-%m-%d %H:%M:%S') [STEP] $1" >> "$UNINSTALL_LOG"
}
# Function to check if service exists and is running
service_exists() {
systemctl list-units --full -all | grep -Fq "$1.service"
}
service_running() {
systemctl is-active --quiet "$1" 2>/dev/null
}
# Function to safely remove file/directory with backup
safe_remove() {
local item="$1"
local description="$2"
if [[ -e "$item" ]]; then
print_info "Backing up $description..."
mkdir -p "$BACKUP_DIR"
cp -r "$item" "$BACKUP_DIR/" 2>/dev/null || true
print_info "Removing $description..."
sudo rm -rf "$item"
print_status "Removed $description"
else
print_info "$description not found (already removed or never existed)"
fi
}
# Function to get user confirmation
confirm_action() {
local message="$1"
local default="$2"
if [[ "$default" == "y" ]]; then
prompt="$message [Y/n]: "
else
prompt="$message [y/N]: "
fi
while true; do
read -p "$prompt" response
response=${response,,} # Convert to lowercase
if [[ -z "$response" ]]; then
response="$default"
fi
case "$response" in
y|yes)
return 0
;;
n|no)
return 1
;;
*)
echo "Please answer yes or no."
;;
esac
done
}
# Function to show uninstall options
show_uninstall_options() {
print_header "Nginx Site Manager Uninstall Options"
echo -e "${CYAN}Choose what to uninstall:${NC}"
echo -e "${BLUE}1.${NC} Application only (keep sites, configs, and system packages)"
echo -e "${BLUE}2.${NC} Application + generated configs (remove nginx sites created by this tool)"
echo -e "${BLUE}3.${NC} Full uninstall (remove everything including system packages)"
echo -e "${BLUE}4.${NC} Cancel uninstallation"
echo ""
while true; do
read -p "Select option [1-4]: " choice
case $choice in
1)
UNINSTALL_LEVEL="app"
break
;;
2)
UNINSTALL_LEVEL="configs"
break
;;
3)
UNINSTALL_LEVEL="full"
break
;;
4)
echo "Uninstallation cancelled."
exit 0
;;
*)
echo "Please select a valid option (1-4)."
;;
esac
done
# Confirm the choice
case $UNINSTALL_LEVEL in
app)
confirm_text="Remove only the Nginx Site Manager application"
;;
configs)
confirm_text="Remove application and generated nginx configurations"
;;
full)
confirm_text="Remove everything including system packages (nginx, certbot, etc.)"
;;
esac
print_warning "This will: $confirm_text"
if ! confirm_action "Are you sure you want to continue?" "n"; then
echo "Uninstallation cancelled."
exit 0
fi
}
# Function to stop and remove service
remove_service() {
print_step "Removing systemd service"
if service_exists "nginx-manager"; then
if service_running "nginx-manager"; then
print_info "Stopping nginx-manager service..."
sudo systemctl stop nginx-manager
print_status "Service stopped"
fi
print_info "Disabling nginx-manager service..."
sudo systemctl disable nginx-manager
safe_remove "/etc/systemd/system/nginx-manager.service" "systemd service file"
print_info "Reloading systemd daemon..."
sudo systemctl daemon-reload
print_status "Systemd service removed"
else
print_info "Nginx-manager service not found"
fi
}
# Function to remove sudo permissions
remove_sudo_permissions() {
print_step "Removing sudo permissions"
safe_remove "/etc/sudoers.d/nginx-manager" "sudo permissions file"
}
# Function to remove user from groups
remove_user_from_groups() {
print_step "Removing user from groups"
# Remove user from www-data group
if groups "$CURRENT_USER" | grep -q "www-data"; then
print_info "Removing $CURRENT_USER from www-data group..."
sudo gpasswd -d "$CURRENT_USER" www-data || print_warning "Failed to remove user from www-data group"
print_status "User removed from www-data group"
fi
# Remove www-data from user's group
if groups "www-data" | grep -q "$CURRENT_USER"; then
print_info "Removing www-data from $CURRENT_USER group..."
sudo gpasswd -d www-data "$CURRENT_USER" || print_warning "Failed to remove www-data from user group"
print_status "www-data removed from user group"
fi
}
# Function to remove application files
remove_application() {
print_step "Removing application files"
# Remove Python virtual environment
if [[ -d "venv" ]]; then
print_info "Removing Python virtual environment..."
rm -rf venv
print_status "Virtual environment removed"
fi
# Remove data directory (with confirmation for important data)
if [[ -d "data" ]]; then
print_warning "The data directory contains your database and site backups"
if confirm_action "Remove data directory? (This will delete all your sites and settings)" "n"; then
safe_remove "data" "data directory"
else
print_info "Keeping data directory"
fi
fi
# Remove log directory
safe_remove "/var/log/nginx-manager" "log directory"
print_status "Application files cleaned up"
}
# Function to remove nginx configurations
remove_nginx_configs() {
print_step "Removing nginx configurations"
# List sites created by nginx-manager
local sites_found=()
if [[ -d "/etc/nginx/sites-available" ]]; then
# Look for sites that might have been created by nginx-manager
while IFS= read -r -d '' file; do
if grep -q "# Generated by Nginx Site Manager" "$file" 2>/dev/null; then
sites_found+=("$(basename "$file")")
fi
done < <(find /etc/nginx/sites-available -name "*" -type f -print0 2>/dev/null)
fi
if [[ ${#sites_found[@]} -gt 0 ]]; then
print_info "Found nginx sites created by Site Manager:"
for site in "${sites_found[@]}"; do
echo " - $site"
done
if confirm_action "Remove these nginx configurations?" "y"; then
for site in "${sites_found[@]}"; do
# Remove from sites-enabled
safe_remove "/etc/nginx/sites-enabled/$site" "nginx enabled site: $site"
# Remove from sites-available
safe_remove "/etc/nginx/sites-available/$site" "nginx available site: $site"
done
# Test nginx configuration
if sudo nginx -t 2>/dev/null; then
print_info "Reloading nginx..."
sudo systemctl reload nginx || print_warning "Failed to reload nginx"
else
print_warning "Nginx configuration test failed after removing sites"
fi
fi
else
print_info "No nginx sites created by Site Manager found"
fi
print_status "Nginx configurations processed"
}
# Function to remove SSL certificates and directories
remove_ssl_certificates() {
print_step "Removing SSL certificates"
if [[ -d "$HOME/.letsencrypt" ]]; then
print_warning "This will remove all SSL certificates stored in ~/.letsencrypt/"
if confirm_action "Remove SSL certificates and Let's Encrypt configuration?" "n"; then
safe_remove "$HOME/.letsencrypt" "SSL certificates directory"
else
print_info "Keeping SSL certificates"
fi
else
print_info "No SSL certificates directory found"
fi
}
# Function to remove system packages
remove_system_packages() {
print_step "Removing system packages"
print_warning "This will attempt to remove nginx, certbot, and related packages"
print_warning "This may affect other applications that use these packages"
if confirm_action "Remove system packages (nginx, certbot)?" "n"; then
# Detect package manager
if command -v apt >/dev/null 2>&1; then
PACKAGE_MANAGER="apt"
elif command -v dnf >/dev/null 2>&1; then
PACKAGE_MANAGER="dnf"
elif command -v yum >/dev/null 2>&1; then
PACKAGE_MANAGER="yum"
else
print_warning "Cannot detect package manager, skipping package removal"
return
fi
local packages_to_remove=("certbot" "python3-certbot-nginx")
# Ask about nginx separately since it might be used by other applications
if confirm_action "Remove nginx? (This may affect other websites)" "n"; then
packages_to_remove+=("nginx")
fi
if [[ ${#packages_to_remove[@]} -gt 0 ]]; then
print_info "Removing packages: ${packages_to_remove[*]}"
case "$PACKAGE_MANAGER" in
apt)
sudo apt remove -y "${packages_to_remove[@]}" || print_warning "Some packages may not have been removed"
if confirm_action "Run apt autoremove to clean up unused dependencies?" "y"; then
sudo apt autoremove -y
fi
;;
dnf)
sudo dnf remove -y "${packages_to_remove[@]}" || print_warning "Some packages may not have been removed"
;;
yum)
sudo yum remove -y "${packages_to_remove[@]}" || print_warning "Some packages may not have been removed"
;;
esac
print_status "System packages removed"
fi
else
print_info "Keeping system packages"
fi
}
# Function to clean up web directories
cleanup_web_directories() {
print_step "Cleaning up web directories"
# Only clean up directories we know were created by the installer
if [[ -d "/var/www" ]]; then
print_info "Checking /var/www for Site Manager content..."
# Look for sites that might belong to Site Manager
local site_dirs=()
if [[ -d "data" && -f "data/sites.db" ]]; then
print_info "Found Site Manager database, checking for managed sites..."
# This is a simple approach - in a real implementation, you might query the database
fi
print_info "Web directory cleanup completed (manual review recommended)"
fi
}
# Function to show completion message
show_completion_message() {
local uninstall_description
case $UNINSTALL_LEVEL in
app)
uninstall_description="Application-only uninstall completed"
;;
configs)
uninstall_description="Application and configuration uninstall completed"
;;
full)
uninstall_description="Full uninstall completed"
;;
esac
print_header "🗑️ Uninstall Complete"
echo -e "${GREEN}$uninstall_description${NC}\n"
echo -e "${CYAN}━━━ WHAT WAS REMOVED ━━━${NC}"
echo -e "${GREEN}${NC} Nginx Site Manager application"
echo -e "${GREEN}${NC} Systemd service"
echo -e "${GREEN}${NC} Sudo permissions"
if [[ "$UNINSTALL_LEVEL" != "app" ]]; then
echo -e "${GREEN}${NC} Generated nginx configurations"
echo -e "${GREEN}${NC} SSL certificates (if confirmed)"
fi
if [[ "$UNINSTALL_LEVEL" == "full" ]]; then
echo -e "${GREEN}${NC} System packages (if confirmed)"
fi
echo -e "\n${CYAN}━━━ BACKUP INFORMATION ━━━${NC}"
echo -e "${BLUE}${NC} Backups created in: ${YELLOW}$BACKUP_DIR${NC}"
echo -e "${BLUE}${NC} Uninstall log: ${YELLOW}$UNINSTALL_LOG${NC}"
echo -e "\n${CYAN}━━━ MANUAL CLEANUP (if needed) ━━━${NC}"
echo -e "${BLUE}${NC} Review remaining files in /var/www/"
echo -e "${BLUE}${NC} Check nginx configuration: sudo nginx -t"
echo -e "${BLUE}${NC} Remove project directory if desired"
if [[ "$UNINSTALL_LEVEL" != "full" ]]; then
echo -e "${BLUE}${NC} Remove nginx/certbot manually if no longer needed"
fi
echo -e "\n${YELLOW}Note: You may need to log out and back in for group changes to take effect${NC}"
echo -e "\n${GREEN}Thank you for using Nginx Site Manager!${NC}"
}
# Main uninstall function
main() {
print_header "Nginx Site Manager Uninstall Script v$SCRIPT_VERSION"
# Initialize log file
echo "=== Nginx Site Manager Uninstall Log ===" > "$UNINSTALL_LOG"
echo "Date: $(date)" >> "$UNINSTALL_LOG"
echo "User: $CURRENT_USER" >> "$UNINSTALL_LOG"
echo "Script Version: $SCRIPT_VERSION" >> "$UNINSTALL_LOG"
echo "=======================================" >> "$UNINSTALL_LOG"
# Check if running as root
if [[ $EUID -eq 0 ]]; then
print_error "This script should not be run as root"
print_info "Please run as the same user who installed Nginx Site Manager"
exit 1
fi
# Show options and get user choice
show_uninstall_options
print_info "Starting uninstall process (level: $UNINSTALL_LEVEL)..."
# Common uninstall steps for all levels
remove_service
remove_sudo_permissions
remove_user_from_groups
remove_application
# Configuration-level and full uninstall steps
if [[ "$UNINSTALL_LEVEL" != "app" ]]; then
remove_nginx_configs
remove_ssl_certificates
cleanup_web_directories
fi
# Full uninstall steps
if [[ "$UNINSTALL_LEVEL" == "full" ]]; then
remove_system_packages
fi
show_completion_message
}
# Run main uninstall
main "$@"