360 lines
No EOL
11 KiB
Bash
360 lines
No EOL
11 KiB
Bash
#!/bin/bash
|
|
|
|
# Script configuration
|
|
SCRIPT_VERSION="1.0.0"
|
|
SCRIPT_LOG_FILE="/var/log/server_setup.log"
|
|
BACKUP_DIR="/var/backups/server_setup"
|
|
MYSQL_ROOT_PASSWORD=$(openssl rand -base64 16)
|
|
PROMETHEUS_VERSION="2.37.0"
|
|
NODE_EXPORTER_VERSION="1.3.1"
|
|
|
|
# Color codes for output
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
NC='\033[0m' # No Color
|
|
|
|
# Logging function
|
|
log() {
|
|
local level=$1
|
|
shift
|
|
local message=$@
|
|
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
|
|
echo -e "${timestamp} [${level}] ${message}" | tee -a ${SCRIPT_LOG_FILE}
|
|
}
|
|
|
|
# Error handling function
|
|
handle_error() {
|
|
local exit_code=$?
|
|
local line_number=$1
|
|
if [ $exit_code -ne 0 ]; then
|
|
log "ERROR" "Failed at line ${line_number} with exit code ${exit_code}"
|
|
exit $exit_code
|
|
fi
|
|
}
|
|
trap 'handle_error ${LINENO}' ERR
|
|
|
|
# System health check function
|
|
check_system_health() {
|
|
log "INFO" "Performing system health checks..."
|
|
|
|
# Check disk space
|
|
local disk_usage=$(df -h / | awk 'NR==2 {print $5}' | sed 's/%//')
|
|
if [ $disk_usage -gt 85 ]; then
|
|
log "WARNING" "Disk usage is above 85% (${disk_usage}%)"
|
|
return 1
|
|
fi
|
|
|
|
# Check available memory
|
|
local available_memory=$(free -m | awk 'NR==2 {print $7}')
|
|
if [ $available_memory -lt 1024 ]; then
|
|
log "WARNING" "Available memory is less than 1GB (${available_memory}MB)"
|
|
return 1
|
|
fi
|
|
|
|
log "INFO" "System health checks passed"
|
|
return 0
|
|
}
|
|
|
|
# Backup function
|
|
create_backup() {
|
|
local backup_date=$(date +%Y%m%d_%H%M%S)
|
|
local backup_path="${BACKUP_DIR}/${backup_date}"
|
|
|
|
log "INFO" "Creating backup at ${backup_path}"
|
|
mkdir -p "${backup_path}" || handle_error ${LINENO}
|
|
|
|
# Backup existing configurations
|
|
if [ -d "/etc/nginx" ]; then
|
|
cp -r /etc/nginx "${backup_path}/nginx" || handle_error ${LINENO}
|
|
fi
|
|
if [ -d "/etc/php" ]; then
|
|
cp -r /etc/php "${backup_path}/php" || handle_error ${LINENO}
|
|
fi
|
|
|
|
log "INFO" "Backup completed successfully"
|
|
}
|
|
|
|
# Prepare Installation Function
|
|
prepare_installation() {
|
|
log "INFO" "Preparing for installation"
|
|
|
|
# Your original prepare installing block, enhanced with logging and error handling
|
|
rm -rf /var/lib/dpkg/lock || handle_error ${LINENO}
|
|
rm -rf /var/lib/dpkg/lock-frontend || handle_error ${LINENO}
|
|
rm -rf /var/cache/apt/archives/lock || handle_error ${LINENO}
|
|
|
|
log "INFO" "Updating package lists"
|
|
sudo apt-get update || handle_error ${LINENO}
|
|
|
|
log "SUCCESS" "Installation preparation completed"
|
|
}
|
|
|
|
# Setup NGINX Function
|
|
setup_nginx() {
|
|
log "INFO" "Setting up NGINX"
|
|
|
|
# Remove Apache
|
|
log "INFO" "Removing Apache if exists"
|
|
sudo apt-get purge apache -y || log "WARNING" "Apache removal returned non-zero exit code"
|
|
sudo apt-get purge apache* -y || log "WARNING" "Apache cleanup returned non-zero exit code"
|
|
sudo kill -9 $(sudo lsof -t -i:80) 2>/dev/null || true
|
|
sudo kill -9 $(sudo lsof -t -i:443) 2>/dev/null || true
|
|
|
|
# Install NGINX
|
|
log "INFO" "Installing NGINX"
|
|
sudo apt-get update || handle_error ${LINENO}
|
|
sudo apt install nginx -y || handle_error ${LINENO}
|
|
|
|
# Configure firewall
|
|
log "INFO" "Configuring firewall for NGINX"
|
|
echo "y" | sudo ufw enable
|
|
sudo ufw allow 'Nginx HTTP' || handle_error ${LINENO}
|
|
sudo ufw allow 'Nginx HTTPS' || handle_error ${LINENO}
|
|
sudo ufw allow '8443' || handle_error ${LINENO}
|
|
sudo ufw allow OpenSSH || handle_error ${LINENO}
|
|
|
|
log "SUCCESS" "NGINX setup completed"
|
|
}
|
|
|
|
# Setup PHP Function
|
|
setup_php() {
|
|
log "INFO" "Setting up PHP"
|
|
|
|
# Install PHP 8.2
|
|
sudo apt-get update || handle_error ${LINENO}
|
|
sudo apt install lsb-release ca-certificates apt-transport-https software-properties-common -y || handle_error ${LINENO}
|
|
sudo add-apt-repository ppa:ondrej/php -y || handle_error ${LINENO}
|
|
|
|
# Install PHP and extensions
|
|
log "INFO" "Installing PHP 8.2 and extensions"
|
|
sudo apt install php8.2 php8.2-fpm php8.2-common redis-server php8.2-redis openssl \
|
|
php8.2-curl php8.2-mbstring php8.2-mysql php8.2-xml php8.2-zip php8.2-gd \
|
|
php8.2-cli php8.2-imagick php8.2-intl -y || handle_error ${LINENO}
|
|
|
|
# Install PHP 8.3
|
|
log "INFO" "Installing PHP 8.3 and extensions"
|
|
sudo apt install php8.3 php8.3-fpm php8.3-redis openssl php8.3-common \
|
|
php8.3-curl php8.3-mbstring php8.3-mysql php8.3-xml php8.3-zip php8.3-gd \
|
|
php8.3-cli php8.3-imagick php8.3-intl -y || handle_error ${LINENO}
|
|
|
|
log "SUCCESS" "PHP setup completed"
|
|
}
|
|
|
|
# Setup Redis Function
|
|
setup_redis() {
|
|
log "INFO" "Setting up Redis"
|
|
|
|
sudo apt-get install redis-server -y || handle_error ${LINENO}
|
|
|
|
# Configure Redis
|
|
sudo cp /etc/redis/redis.conf /etc/redis/redis.conf.backup || handle_error ${LINENO}
|
|
sudo sed -i 's/# maxmemory <bytes>/maxmemory 512mb/' /etc/redis/redis.conf
|
|
sudo sed -i 's/# maxmemory-policy noeviction/maxmemory-policy allkeys-lru/' /etc/redis/redis.conf
|
|
|
|
sudo systemctl restart redis-server || handle_error ${LINENO}
|
|
|
|
log "SUCCESS" "Redis setup completed"
|
|
}
|
|
|
|
# Setup Domain Function
|
|
setup_domain() {
|
|
local domain=$1
|
|
log "INFO" "Setting up domain: ${domain}"
|
|
|
|
# Create nginx configuration
|
|
sudo rm -rf /etc/nginx/sites-available/default /etc/nginx/sites-enabled/default
|
|
sudo touch /etc/nginx/sites-available/$domain || handle_error ${LINENO}
|
|
|
|
# Your original nginx configuration block here
|
|
sudo bash -c "cat > /etc/nginx/sites-available/$domain << 'EOF'
|
|
server {
|
|
listen 80;
|
|
listen [::]:80;
|
|
root /var/www/html/$domain/public;
|
|
index index.php index.html index.htm index.nginx-debian.html;
|
|
server_name $domain www.$domain;
|
|
|
|
# Enhanced security headers
|
|
add_header X-Frame-Options "SAMEORIGIN";
|
|
add_header X-XSS-Protection "1; mode=block";
|
|
add_header X-Content-Type-Options "nosniff";
|
|
|
|
location / {
|
|
try_files \$uri \$uri/ /index.php?\$query_string;
|
|
}
|
|
|
|
location ~ \.php$ {
|
|
include snippets/fastcgi-php.conf;
|
|
fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
|
|
fastcgi_param SCRIPT_FILENAME \$document_root\$fastcgi_script_name;
|
|
include fastcgi_params;
|
|
}
|
|
|
|
location ~ /\.ht {
|
|
deny all;
|
|
}
|
|
|
|
# Enhanced static file caching
|
|
location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
|
|
expires 30d;
|
|
add_header Cache-Control "public, no-transform";
|
|
}
|
|
}
|
|
EOF" || handle_error ${LINENO}
|
|
|
|
# Create symbolic link and directory structure
|
|
ln -s /etc/nginx/sites-available/$domain /etc/nginx/sites-enabled/ || handle_error ${LINENO}
|
|
sudo mkdir -p /var/www/html/$domain/public || handle_error ${LINENO}
|
|
|
|
log "SUCCESS" "Domain setup completed"
|
|
}
|
|
|
|
# Setup SSL Function
|
|
setup_ssl() {
|
|
local domain=$1
|
|
log "INFO" "Setting up SSL for domain: ${domain}"
|
|
|
|
# Install certbot if not already installed
|
|
if ! command -v certbot &> /dev/null; then
|
|
log "INFO" "Installing Certbot"
|
|
sudo snap install --classic certbot || handle_error ${LINENO}
|
|
sudo ln -s /snap/bin/certbot /usr/bin/certbot || handle_error ${LINENO}
|
|
fi
|
|
|
|
# Generate SSL certificate
|
|
log "INFO" "Generating SSL certificate"
|
|
certbot --nginx -d $domain -d www.$domain --non-interactive --agree-tos -m admin@$domain || handle_error ${LINENO}
|
|
|
|
log "SUCCESS" "SSL setup completed"
|
|
}
|
|
|
|
# Setup Database Function
|
|
setup_mysql() {
|
|
log "INFO" "Setting up MySQL"
|
|
|
|
if ! command -v mysql &> /dev/null; then
|
|
export DEBIAN_FRONTEND=noninteractive
|
|
|
|
# Install MySQL
|
|
echo debconf mysql-server/root_password password $MYSQL_ROOT_PASSWORD | sudo debconf-set-selections
|
|
echo debconf mysql-server/root_password_again password $MYSQL_ROOT_PASSWORD | sudo debconf-set-selections
|
|
sudo apt-get -y install mysql-server || handle_error ${LINENO}
|
|
|
|
# Secure MySQL installation
|
|
sudo mysql_secure_installation --password="$MYSQL_ROOT_PASSWORD" << EOF
|
|
y
|
|
0
|
|
n
|
|
y
|
|
y
|
|
y
|
|
y
|
|
EOF
|
|
|
|
# Save MySQL password securely
|
|
echo $MYSQL_ROOT_PASSWORD | sudo tee /root/.mysql_root_password > /dev/null
|
|
chmod 600 /root/.mysql_root_password
|
|
|
|
log "SUCCESS" "MySQL setup completed. Root password saved to /root/.mysql_root_password"
|
|
else
|
|
log "INFO" "MySQL is already installed"
|
|
fi
|
|
}
|
|
|
|
# Setup Monitoring Function
|
|
setup_monitoring() {
|
|
log "INFO" "Setting up monitoring with Prometheus and Node Exporter"
|
|
|
|
# Install Node Exporter
|
|
useradd --no-create-home --shell /bin/false node_exporter || log "WARNING" "User node_exporter already exists"
|
|
wget "https://github.com/prometheus/node_exporter/releases/download/v${NODE_EXPORTER_VERSION}/node_exporter-${NODE_EXPORTER_VERSION}.linux-amd64.tar.gz" || handle_error ${LINENO}
|
|
tar xvf "node_exporter-${NODE_EXPORTER_VERSION}.linux-amd64.tar.gz"
|
|
sudo cp node_exporter-${NODE_EXPORTER_VERSION}.linux-amd64/node_exporter /usr/local/bin/ || handle_error ${LINENO}
|
|
|
|
# Create Node Exporter service
|
|
sudo bash -c 'cat > /etc/systemd/system/node_exporter.service << EOF
|
|
[Unit]
|
|
Description=Node Exporter
|
|
After=network.target
|
|
|
|
[Service]
|
|
User=node_exporter
|
|
Group=node_exporter
|
|
Type=simple
|
|
ExecStart=/usr/local/bin/node_exporter
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
EOF'
|
|
|
|
# Start and enable services
|
|
sudo systemctl daemon-reload
|
|
sudo systemctl start node_exporter || handle_error ${LINENO}
|
|
sudo systemctl enable node_exporter || handle_error ${LINENO}
|
|
|
|
log "SUCCESS" "Monitoring setup completed"
|
|
}
|
|
|
|
# Main function
|
|
main() {
|
|
local domain=""
|
|
|
|
# Parse command line arguments
|
|
while getopts "d:h" flag; do
|
|
case "${flag}" in
|
|
d) domain=${OPTARG};;
|
|
h)
|
|
echo "Usage: $0 -d domain.com"
|
|
exit 0
|
|
;;
|
|
*)
|
|
echo "Invalid option. Usage: $0 -d domain.com"
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
|
|
if [ -z "$domain" ]; then
|
|
log "ERROR" "Domain parameter is required. Usage: $0 -d domain.com"
|
|
exit 1
|
|
fi
|
|
|
|
# Start installation process
|
|
log "INFO" "Starting server setup for ${domain}"
|
|
|
|
# Perform system health check
|
|
check_system_health || {
|
|
log "ERROR" "System health check failed. Please resolve the issues before continuing."
|
|
exit 1
|
|
}
|
|
|
|
# Create initial backup
|
|
create_backup
|
|
|
|
# Run installation steps
|
|
prepare_installation
|
|
setup_nginx
|
|
setup_php
|
|
setup_redis
|
|
setup_domain "$domain"
|
|
setup_ssl "$domain"
|
|
setup_mysql
|
|
setup_monitoring
|
|
|
|
# Create final backup
|
|
create_backup
|
|
|
|
# Print completion message
|
|
log "INFO" "Installation completed successfully"
|
|
echo -e "${GREEN}Installation completed successfully!${NC}"
|
|
echo -e "${YELLOW}Important Information:${NC}"
|
|
echo -e "MySQL Root Password: ${MYSQL_ROOT_PASSWORD}"
|
|
echo -e "Installation Log: ${SCRIPT_LOG_FILE}"
|
|
echo -e "Backup Directory: ${BACKUP_DIR}"
|
|
echo -e "Monitoring URLs:"
|
|
echo -e " - Node Exporter: http://localhost:9100/metrics"
|
|
}
|
|
|
|
# Start script execution
|
|
main "$@" |