Files
server-manager/install.sh

361 lines
11 KiB
Bash
Executable File

#!/bin/bash
# ============================================================================
# ServerManager - Installation Script
# For Ubuntu Server 22.04+ / 24.04+
# ============================================================================
set -e
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
log_info() { echo -e "${GREEN}[INFO]${NC} $1"; }
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
log_step() { echo -e "\n${BLUE}=== $1 ===${NC}"; }
APP_DIR="/var/www/servermanager"
NGINX_CONFIG="/etc/nginx/sites-available/servermanager"
KEY_FILE="/etc/servermanager/master.key"
PHP_VERSION="${PHP_VERSION:-8.3}"
check_root() {
if [[ $EUID -ne 0 ]]; then
log_error "This script must be run as root (use sudo)"
exit 1
fi
}
install_system_packages() {
return
log_step "Installing System Packages"
apt-get update -qq
apt-get install -y -qq \
nginx \
mysql-server \
php${PHP_VERSION} \
php${PHP_VERSION}-fpm \
php${PHP_VERSION}-cli \
php${PHP_VERSION}-mysql \
php${PHP_VERSION}-mbstring \
php${PHP_VERSION}-xml \
php${PHP_VERSION}-curl \
php${PHP_VERSION}-zip \
php${PHP_VERSION}-gd \
php${PHP_VERSION}-openssl \
php${PHP_VERSION}-json \
composer \
unzip \
git \
curl \
wget \
openssl
log_info "System packages installed successfully"
}
configure_php() {
log_step "Configuring PHP ${PHP_VERSION}"
PHP_INI="/etc/php/${PHP_VERSION}/fpm/php.ini"
PHP_CLI_INI="/etc/php/${PHP_VERSION}/cli/php.ini"
for INI in "$PHP_INI" "$PHP_CLI_INI"; do
if [ -f "$INI" ]; then
sed -i 's/^memory_limit = .*/memory_limit = 256M/' "$INI"
sed -i 's/^max_execution_time = .*/max_execution_time = 300/' "$INI"
sed -i 's/^post_max_size = .*/post_max_size = 64M/' "$INI"
sed -i 's/^upload_max_filesize = .*/upload_max_filesize = 32M/' "$INI"
sed -i 's/^;?max_input_vars = .*/max_input_vars = 3000/' "$INI"
log_info "Configured: $INI"
fi
done
systemctl restart php${PHP_VERSION}-fpm
log_info "PHP-FPM restarted"
}
configure_mysql() {
log_step "Configuring MySQL"
DB_NAME="servermanager"
DB_USER="servermanager"
DB_PASS=$(openssl rand -base64 32)
if mysql -e "SELECT 1" &>/dev/null; then
mysql -e "CREATE DATABASE IF NOT EXISTS \`${DB_NAME}\` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
mysql -e "CREATE USER IF NOT EXISTS '${DB_USER}'@'localhost' IDENTIFIED BY '${DB_PASS}';"
mysql -e "GRANT ALL PRIVILEGES ON \`${DB_NAME}\`.* TO '${DB_USER}'@'localhost';"
mysql -e "FLUSH PRIVILEGES;"
mysql "${DB_NAME}" < "${APP_DIR}/database/migrations/001_initial_schema.sql"
log_info "Database '${DB_NAME}' created and migrated"
log_info "DB Username: ${DB_USER}"
log_info "DB Password: ${DB_PASS} (saved in .env)"
else
log_error "Could not connect to MySQL. Please configure manually."
DB_PASS="CHANGE_ME"
fi
echo "$DB_PASS" > /tmp/servermanager_db_pass
chmod 600 /tmp/servermanager_db_pass
}
generate_master_key() {
log_step "Generating Master Encryption Key"
if [ -f "$KEY_FILE" ]; then
log_warn "Master key already exists at ${KEY_FILE}"
log_warn "Skipping generation (backup existing key first if you want to regenerate)"
return
fi
MASTER_KEY=$(openssl rand -hex 32)
echo "$MASTER_KEY" > "$KEY_FILE"
chmod 600 "$KEY_FILE"
chown rafael:rafael "$KEY_FILE"
log_info "Master key generated: ${KEY_FILE}"
log_warn "IMPORTANT: Store this key securely. If lost, ALL SSH credentials become unrecoverable!"
}
deploy_application() {
log_step "Deploying Application"
mkdir -p "$APP_DIR"
if [ -f "./composer.json" ]; then
cp -r ./* "$APP_DIR/"
cp .env.example "$APP_DIR/.env"
cp .env "$APP_DIR/.env" 2>/dev/null || true
fi
chown -R rafael:rafael "$APP_DIR"
chmod -R 755 "$APP_DIR"
mkdir -p "${APP_DIR}/logs"
mkdir -p "${APP_DIR}/storage/ssh_keys"
chown -R rafael:rafael "${APP_DIR}/logs" "${APP_DIR}/storage"
chmod -R 750 "${APP_DIR}/logs" "${APP_DIR}/storage"
chmod 700 "${APP_DIR}/storage/ssh_keys"
log_info "Application deployed to ${APP_DIR}"
}
configure_env() {
log_step "Configuring Environment"
DB_PASS=$(cat /tmp/servermanager_db_pass 2>/dev/null || echo "CHANGE_ME")
MASTER_KEY=$(cat "$KEY_FILE" 2>/dev/null || echo "")
sed -i "s|DB_HOST=.*|DB_HOST=127.0.0.1|" "${APP_DIR}/.env"
sed -i "s|DB_PORT=.*|DB_PORT=3306|" "${APP_DIR}/.env"
sed -i "s|DB_DATABASE=.*|DB_DATABASE=servermanager|" "${APP_DIR}/.env"
sed -i "s|DB_USERNAME=.*|DB_USERNAME=servermanager|" "${APP_DIR}/.env"
sed -i "s|DB_PASSWORD=.*|DB_PASSWORD=${DB_PASS}|" "${APP_DIR}/.env"
sed -i "s|SESSION_SECURE=.*|SESSION_SECURE=true|" "${APP_DIR}/.env"
sed -i "s|SESSION_HTTP_ONLY=.*|SESSION_HTTP_ONLY=true|" "${APP_DIR}/.env"
sed -i "s|SESSION_SAME_SITE=.*|SESSION_SAME_SITE=Lax|" "${APP_DIR}/.env"
sed -i "s|MASTER_ENCRYPTION_KEY=.*|MASTER_ENCRYPTION_KEY=${MASTER_KEY}|" "${APP_DIR}/.env"
sed -i "s|MASTER_ENCRYPTION_KEY_FILE=.*|MASTER_ENCRYPTION_KEY_FILE=${KEY_FILE}|" "${APP_DIR}/.env"
sed -i "s|APP_ENV=.*|APP_ENV=production|" "${APP_DIR}/.env"
sed -i "s|APP_DEBUG=.*|APP_DEBUG=false|" "${APP_DIR}/.env"
log_info ".env file configured"
rm -f /tmp/servermanager_db_pass
}
install_composer_dependencies() {
log_step "Installing Composer Dependencies"
cd "$APP_DIR"
sudo -u www-data composer install --no-dev --optimize-autoloader --no-interaction
log_info "Dependencies installed"
}
configure_nginx() {
log_step "Configuring Nginx"
cat > "$NGINX_CONFIG" << 'NGINXEOF'
server {
listen 80;
listen [::]:80;
server_name _;
root /var/www/servermanager/public;
index index.php;
charset utf-8;
client_max_body_size 64M;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php8.3-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
location ~ /\.(?!well-known).* {
deny all;
}
location ~* \.(env|log|json|lock|key|sql|md)$ {
deny all;
}
location /assets/ {
expires 30d;
add_header Cache-Control "public, immutable";
}
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "DENY" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
}
NGINXEOF
ln -sf "$NGINX_CONFIG" /etc/nginx/sites-enabled/servermanager
rm -f /etc/nginx/sites-enabled/default
nginx -t && systemctl reload nginx
log_info "Nginx configured and reloaded"
}
configure_cron() {
log_step "Configuring Cron Jobs"
cat > /etc/cron.d/servermanager << CRONEOF
# ServerManager Monitoring Cron
# Collect metrics every minute
* * * * * www-data /usr/bin/php ${APP_DIR}/bin/monitor.php >> ${APP_DIR}/logs/cron.log 2>&1
# Cleanup old logs weekly
0 3 * * 0 www-data find ${APP_DIR}/logs/ -name "*.log" -mtime +30 -delete
CRONEOF
chmod 644 /etc/cron.d/servermanager
log_info "Cron jobs configured"
}
create_binaries() {
log_step "Creating CLI Scripts"
mkdir -p "${APP_DIR}/bin"
cat > "${APP_DIR}/bin/monitor.php" << 'PHPEOF'
<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use ServerManager\Core\App;
use ServerManager\Services\MonitoringService;
try {
$app = App::getInstance();
$app->boot(dirname(__DIR__));
$monitoring = new MonitoringService();
$results = $monitoring->collectAllMetrics();
$online = count(array_filter($results, fn($r) => $r && ($r['status'] ?? '') === 'online'));
$offline = count($results) - $online;
echo sprintf("[%s] Metrics collected: %d servers (%d online, %d offline)\n",
date('Y-m-d H:i:s'), count($results), $online, $offline);
} catch (\Throwable $e) {
echo sprintf("[%s] ERROR: %s\n", date('Y-m-d H:i:s'), $e->getMessage());
exit(1);
}
PHPEOF
cat > "${APP_DIR}/bin/generate-key.php" << 'PHPEOF'
<?php
declare(strict_types=1);
$keyFile = '/etc/servermanager/master.key';
if ($argc > 1 && $argv[1] === '--force') {
echo "Generating new master encryption key...\n";
} elseif (file_exists($keyFile)) {
echo "Master key already exists at {$keyFile}\n";
echo "Use --force to regenerate (WARNING: this will make existing encrypted data unreadable)\n";
exit(1);
}
$key = bin2hex(random_bytes(32));
file_put_contents($keyFile, $key, LOCK_EX);
chmod($keyFile, 0600);
echo "Master key generated: {$keyFile}\n";
echo "IMPORTANT: Store this key securely!\n";
PHPEOF
chmod +x "${APP_DIR}/bin/monitor.php"
chmod +x "${APP_DIR}/bin/generate-key.php"
chown -R rafael:rafael "${APP_DIR}/bin"
log_info "CLI scripts created"
}
show_completion_message() {
log_step "Installation Complete"
echo ""
echo -e "${GREEN}╔════════════════════════════════════════════════════════╗${NC}"
echo -e "${GREEN}║ ServerManager Installation Completed! ║${NC}"
echo -e "${GREEN}╚════════════════════════════════════════════════════════╝${NC}"
echo ""
echo -e " URL: ${BLUE}http://$(hostname -I | awk '{print $1}')${NC}"
echo -e " Username: ${YELLOW}admin${NC}"
echo -e " Password: ${YELLOW}Admin@123${NC} ${RED}(CHANGE IMMEDIATELY!)${NC}"
echo -e " Key File: ${YELLOW}${KEY_FILE}${NC}"
echo ""
echo -e " ${RED}IMPORTANT:${NC}"
echo -e " 1. Change the default admin password immediately"
echo -e " 2. Backup your master encryption key: ${KEY_FILE}"
echo -e " 3. Configure HTTPS with Let's Encrypt:"
echo -e " ${BLUE}certbot --nginx -d your-domain.com${NC}"
echo -e " 4. Review logs at: ${APP_DIR}/logs/"
echo ""
}
main() {
echo ""
echo -e "${GREEN}╔════════════════════════════════════════════════════════╗${NC}"
echo -e "${GREEN}║ ServerManager - Automated Installer ║${NC}"
echo -e "${GREEN}╚════════════════════════════════════════════════════════╝${NC}"
echo ""
check_root
install_system_packages
deploy_application
configure_mysql
generate_master_key
configure_env
install_composer_dependencies
configure_php
configure_nginx
create_binaries
configure_cron
show_completion_message
}
main "$@"