#!/bin/bash # Apache Server Setup Script for Bike Service Application # Run this script on your Ubuntu 22.04 server after initial setup set -e echo "🚀 Setting up Ubuntu 22.04 server with Apache and MySQL for Bike Service Application..." # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' # No Color print_status() { echo -e "${GREEN}[INFO]${NC} $1" } print_warning() { echo -e "${YELLOW}[WARNING]${NC} $1" } print_error() { echo -e "${RED}[ERROR]${NC} $1" } # Check if running as root if [[ $EUID -ne 0 ]]; then print_error "This script must be run as root (use sudo)" exit 1 fi # Check Ubuntu version UBUNTU_VERSION=$(lsb_release -rs) if [[ "$UBUNTU_VERSION" != "22.04" ]]; then print_warning "This script is designed for Ubuntu 22.04. You're running $UBUNTU_VERSION" read -p "Continue anyway? (y/N): " -n 1 -r echo if [[ ! $REPLY =~ ^[Yy]$ ]]; then exit 0 fi fi print_status "Starting server setup..." # Update system print_status "Updating system packages..." apt update && apt upgrade -y # Install required software print_status "Installing required software..." # Install Apache apt install apache2 -y # Install PHP 8.2 and extensions apt install software-properties-common -y add-apt-repository ppa:ondrej/php -y apt update apt install php8.2 libapache2-mod-php8.2 php8.2-mysql php8.2-xml php8.2-mbstring php8.2-curl php8.2-zip php8.2-gd php8.2-cli php8.2-common php8.2-bcmath php8.2-json php8.2-tokenizer php8.2-fileinfo php8.2-opcache -y # Install Composer print_status "Installing Composer..." curl -sS https://getcomposer.org/installer | php mv composer.phar /usr/local/bin/composer chmod +x /usr/local/bin/composer # Install Node.js and npm print_status "Installing Node.js..." curl -fsSL https://deb.nodesource.com/setup_18.x | bash - apt-get install -y nodejs # Install Git apt install git -y # Install MySQL print_status "Installing MySQL..." apt install mysql-server -y # Install additional tools apt install unzip curl wget htop ufw fail2ban -y # Configure PHP print_status "Configuring PHP..." PHP_INI="/etc/php/8.2/apache2/php.ini" # Backup original file cp $PHP_INI $PHP_INI.backup # Update PHP configuration sed -i 's/memory_limit = .*/memory_limit = 256M/' $PHP_INI sed -i 's/upload_max_filesize = .*/upload_max_filesize = 64M/' $PHP_INI sed -i 's/post_max_size = .*/post_max_size = 64M/' $PHP_INI sed -i 's/max_execution_time = .*/max_execution_time = 300/' $PHP_INI sed -i 's/;opcache.enable=.*/opcache.enable=1/' $PHP_INI sed -i 's/;opcache.memory_consumption=.*/opcache.memory_consumption=128/' $PHP_INI sed -i 's/;opcache.max_accelerated_files=.*/opcache.max_accelerated_files=4000/' $PHP_INI # Enable OPcache echo "opcache.enable=1" >> $PHP_INI echo "opcache.memory_consumption=128" >> $PHP_INI echo "opcache.max_accelerated_files=4000" >> $PHP_INI # Enable Apache modules print_status "Enabling Apache modules..." a2enmod rewrite a2enmod ssl a2enmod headers a2enmod deflate a2enmod expires a2enmod php8.2 # Configure Apache print_status "Configuring Apache..." # Create application directory mkdir -p /var/www/bikeservice chown -R www-data:www-data /var/www/bikeservice # Create Apache virtual host cat > /etc/apache2/sites-available/bikeservice.conf << 'EOF' ServerName _ DocumentRoot /var/www/bikeservice/backend/public AllowOverride All Require all granted # Laravel specific rules RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^(.*)$ index.php [QSA,L] # Security headers Header always set X-Frame-Options "SAMEORIGIN" Header always set X-XSS-Protection "1; mode=block" Header always set X-Content-Type-Options "nosniff" Header always set Referrer-Policy "no-referrer-when-downgrade" # Gzip compression SetOutputFilter DEFLATE SetEnvIfNoCase Request_URI \ \.(?:gif|jpe?g|png)$ no-gzip dont-vary SetEnvIfNoCase Request_URI \ \.(?:exe|t?gz|zip|bz2|sit|rar)$ no-gzip dont-vary # Cache static assets ExpiresActive On ExpiresDefault "access plus 1 year" Header append Cache-Control "public, immutable" # Logging ErrorLog ${APACHE_LOG_DIR}/bikeservice_error.log CustomLog ${APACHE_LOG_DIR}/bikeservice_access.log combined # Client max body size (for file uploads) LimitRequestBody 67108864 EOF # Enable site a2ensite bikeservice.conf a2dissite 000-default.conf # Test Apache configuration apache2ctl configtest # Restart Apache systemctl restart apache2 systemctl enable apache2 # Configure MySQL print_status "Configuring MySQL..." systemctl start mysql systemctl enable mysql # Secure MySQL installation print_warning "You will need to secure MySQL installation manually:" print_warning "Run: sudo mysql_secure_installation" # Configure firewall print_status "Configuring firewall..." ufw --force enable ufw allow ssh ufw allow 'Apache Full' ufw allow 80 ufw allow 443 # Configure fail2ban print_status "Configuring fail2ban..." systemctl enable fail2ban systemctl start fail2ban # Create systemd service for queue worker print_status "Creating queue worker service..." cat > /etc/systemd/system/bikeservice-queue.service << 'EOF' [Unit] Description=Bike Service Queue Worker After=network.target Wants=network.target [Service] Type=simple User=www-data Group=www-data WorkingDirectory=/var/www/bikeservice/backend ExecStart=/usr/bin/php artisan queue:work --sleep=3 --tries=3 --max-time=3600 --memory=512 ExecReload=/bin/kill -USR1 $MAINPID Restart=always RestartSec=10 StandardOutput=journal StandardError=journal SyslogIdentifier=bikeservice-queue Environment=APP_ENV=production Environment=APP_DEBUG=false LimitNOFILE=65536 LimitNPROC=32768 NoNewPrivileges=true PrivateTmp=true ProtectSystem=strict ReadWritePaths=/var/www/bikeservice/backend/storage ProtectHome=true [Install] WantedBy=multi-user.target EOF # Reload systemd and enable queue service systemctl daemon-reload systemctl enable bikeservice-queue # Set up cron for Laravel scheduler print_status "Setting up Laravel scheduler..." (crontab -l 2>/dev/null; echo "* * * * * cd /var/www/bikeservice/backend && php artisan schedule:run >> /dev/null 2>&1") | crontab - # Create deployment user print_status "Creating deployment user..." useradd -m -s /bin/bash deploy usermod -aG sudo deploy echo "deploy:$(openssl rand -base64 32)" | chpasswd # Set up SSH key authentication for deploy user mkdir -p /home/deploy/.ssh chmod 700 /home/deploy/.ssh touch /home/deploy/.ssh/authorized_keys chmod 600 /home/deploy/.ssh/authorized_keys chown -R deploy:deploy /home/deploy/.ssh print_warning "Please add your SSH public key to /home/deploy/.ssh/authorized_keys" print_warning "You can do this by running: ssh-copy-id deploy@your-server-ip" # Set proper permissions for application directory chown -R deploy:www-data /var/www/bikeservice chmod -R 775 /var/www/bikeservice # Create log files touch /var/log/apache2/bikeservice_access.log touch /var/log/apache2/bikeservice_error.log chown www-data:adm /var/log/apache2/bikeservice_*.log print_status "Server setup completed!" echo echo "Next steps:" echo "1. Secure MySQL installation: sudo mysql_secure_installation" echo "2. Create database and user (use setup-mysql.sh script)" echo "3. Add your SSH public key to the deploy user:" echo " ssh-copy-id deploy@your-server-ip" echo "4. Upload your application files to /var/www/bikeservice" echo "5. Configure your .env file with database credentials" echo "6. Run the deployment script" echo echo "Useful commands:" echo "- Check service status: systemctl status apache2 mysql bikeservice-queue" echo "- View logs: journalctl -u bikeservice-queue -f" echo "- Check Apache logs: tail -f /var/log/apache2/bikeservice_error.log" echo "- Test Apache config: apache2ctl configtest" echo "- Restart Apache: systemctl restart apache2" echo echo "Security notes:" echo "- SSH key authentication is required for deploy user" echo "- Firewall is enabled (SSH and HTTP/HTTPS only)" echo "- fail2ban is configured to protect against brute force attacks" echo "- MySQL needs to be secured manually"