diff --git a/apache-bikeservice.conf b/apache-bikeservice.conf new file mode 100644 index 0000000..1adcdab --- /dev/null +++ b/apache-bikeservice.conf @@ -0,0 +1,115 @@ + + ServerName your-domain.com + ServerAlias www.your-domain.com + 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" + Header always set Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline'" + + # 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 + SetEnvIfNoCase Request_URI \ + \.(?:pdf|mov|avi|mp3|mp4|rm)$ no-gzip dont-vary + + + # Cache static assets + + ExpiresActive On + ExpiresDefault "access plus 1 year" + Header append Cache-Control "public, immutable" + Header append Vary Accept-Encoding + + + # Cache API responses (no cache) + + Header set Cache-Control "no-cache, no-store, must-revalidate" + Header set Pragma "no-cache" + Header set Expires "0" + + + # Deny access to sensitive files + + Require all denied + + + # Deny access to hidden files + + Require all denied + + + # Health check endpoint + + SetHandler server-status + Require all granted + + + # 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 + + # Timeouts + Timeout 300 + KeepAliveTimeout 5 + MaxKeepAliveRequests 100 + + +# SSL Configuration (uncomment after obtaining SSL certificate) +# +# ServerName your-domain.com +# ServerAlias www.your-domain.com +# DocumentRoot /var/www/bikeservice/backend/public +# +# SSLEngine on +# SSLCertificateFile /etc/letsencrypt/live/your-domain.com/fullchain.pem +# SSLCertificateKeyFile /etc/letsencrypt/live/your-domain.com/privkey.pem +# +# # Include all the same configuration as above +# +# AllowOverride All +# Require all granted +# +# RewriteEngine On +# RewriteCond %{REQUEST_FILENAME} !-f +# RewriteCond %{REQUEST_FILENAME} !-d +# RewriteRule ^(.*)$ index.php [QSA,L] +# +# +# # Security headers +# Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains" +# 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" +# +# # Same configuration as HTTP version... +# + +# Redirect HTTP to HTTPS (uncomment after SSL setup) +# +# ServerName your-domain.com +# ServerAlias www.your-domain.com +# Redirect permanent / https://your-domain.com/ +# diff --git a/bikeservice-queue.service b/bikeservice-queue.service new file mode 100644 index 0000000..3e9c8af --- /dev/null +++ b/bikeservice-queue.service @@ -0,0 +1,36 @@ +[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 variables +Environment=APP_ENV=production +Environment=APP_DEBUG=false + +# Resource limits +LimitNOFILE=65536 +LimitNPROC=32768 + +# Security settings +NoNewPrivileges=true +PrivateTmp=true +ProtectSystem=strict +ReadWritePaths=/var/www/bikeservice/backend/storage +ProtectHome=true + +[Install] +WantedBy=multi-user.target + diff --git a/deploy-apache.md b/deploy-apache.md new file mode 100644 index 0000000..5d1f9cf --- /dev/null +++ b/deploy-apache.md @@ -0,0 +1,411 @@ +# Apache Deployment Guide for Bike Service Application + +This guide will help you deploy your Laravel + Vue.js application to Ubuntu 22.04 with Apache and MySQL. + +## Prerequisites + +- Ubuntu 22.04 server with root/sudo access +- Domain name (optional but recommended) +- SSH access to your server + +## Server Setup + +### 1. Update System +```bash +sudo apt update && sudo apt upgrade -y +``` + +### 2. Install Required Software +```bash +# Install Apache +sudo apt install apache2 -y + +# Install PHP 8.2 and extensions +sudo apt install software-properties-common -y +sudo add-apt-repository ppa:ondrej/php -y +sudo apt update +sudo 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 +curl -sS https://getcomposer.org/installer | php +sudo mv composer.phar /usr/local/bin/composer + +# Install Node.js and npm +curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash - +sudo apt-get install -y nodejs + +# Install Git +sudo apt install git -y + +# Install MySQL +sudo apt install mysql-server -y + +# Install additional tools +sudo apt install unzip curl wget htop ufw fail2ban -y +``` + +### 3. Configure MySQL +```bash +# Secure MySQL installation +sudo mysql_secure_installation + +# Create database and user +sudo mysql -u root -p +``` + +In MySQL console: +```sql +CREATE DATABASE bikeservice_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; +CREATE USER 'bikeservice_user'@'localhost' IDENTIFIED BY 'your_secure_password'; +GRANT ALL PRIVILEGES ON bikeservice_db.* TO 'bikeservice_user'@'localhost'; +FLUSH PRIVILEGES; +EXIT; +``` + +### 4. Configure PHP +```bash +# Edit PHP configuration +sudo nano /etc/php/8.2/apache2/php.ini + +# Set these values: +# memory_limit = 256M +# upload_max_filesize = 64M +# post_max_size = 64M +# max_execution_time = 300 +# opcache.enable = 1 +# opcache.memory_consumption = 128 +# opcache.max_accelerated_files = 4000 + +# Restart Apache +sudo systemctl restart apache2 +sudo systemctl enable apache2 +``` + +### 5. Enable Apache Modules +```bash +sudo a2enmod rewrite +sudo a2enmod ssl +sudo a2enmod headers +sudo a2enmod deflate +sudo a2enmod expires +sudo systemctl restart apache2 +``` + +## Application Deployment + +### 1. Create Application Directory +```bash +sudo mkdir -p /var/www/bikeservice +sudo chown -R $USER:$USER /var/www/bikeservice +cd /var/www/bikeservice +``` + +### 2. Clone Your Repository +```bash +git clone . +# Or upload your files via SCP/SFTP +``` + +### 3. Backend Setup (Laravel) +```bash +cd backend + +# Install dependencies +composer install --no-dev --optimize-autoloader + +# Set permissions +sudo chown -R www-data:www-data storage bootstrap/cache +sudo chmod -R 775 storage bootstrap/cache + +# Create .env file +cp .env.example .env + +# Generate application key +php artisan key:generate + +# Configure database in .env file +# DB_CONNECTION=mysql +# DB_HOST=127.0.0.1 +# DB_PORT=3306 +# DB_DATABASE=bikeservice_db +# DB_USERNAME=bikeservice_user +# DB_PASSWORD=your_secure_password + +# Run migrations +php artisan migrate --force + +# Clear and cache config +php artisan config:cache +php artisan route:cache +php artisan view:cache + +# Set production environment +echo "APP_ENV=production" >> .env +echo "APP_DEBUG=false" >> .env +``` + +### 4. Frontend Setup (Vue.js) +```bash +cd ../frontend + +# Install dependencies +npm install + +# Build for production +npm run build + +# Copy built files to Laravel public directory +cp -r dist/* ../backend/public/ +``` + +## Apache Configuration + +### 1. Create Apache Virtual Host +```bash +sudo nano /etc/apache2/sites-available/bikeservice.conf +``` + +Add this configuration: +```apache + + ServerName your-domain.com + ServerAlias www.your-domain.com + DocumentRoot /var/www/bikeservice/backend/public + + + AllowOverride All + Require all granted + + + # 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 + LoadModule deflate_module modules/mod_deflate.so + + 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 + +``` + +### 2. Enable Site and Restart Apache +```bash +sudo a2ensite bikeservice.conf +sudo a2dissite 000-default.conf +sudo apache2ctl configtest +sudo systemctl restart apache2 +``` + +## SSL Certificate (Optional but Recommended) + +### 1. Install Certbot +```bash +sudo apt install certbot python3-certbot-apache -y +``` + +### 2. Obtain SSL Certificate +```bash +sudo certbot --apache -d your-domain.com -d www.your-domain.com +``` + +## Final Configuration + +### 1. Set Proper Permissions +```bash +sudo chown -R www-data:www-data /var/www/bikeservice +sudo chmod -R 755 /var/www/bikeservice +sudo chmod -R 775 /var/www/bikeservice/backend/storage +sudo chmod -R 775 /var/www/bikeservice/backend/bootstrap/cache +``` + +### 2. Configure Queue Worker (if using queues) +```bash +# Create systemd service for queue worker +sudo nano /etc/systemd/system/bikeservice-queue.service +``` + +Add this content: +```ini +[Unit] +Description=Bike Service Queue Worker +After=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 +Restart=always +RestartSec=10 + +[Install] +WantedBy=multi-user.target +``` + +Enable and start the service: +```bash +sudo systemctl enable bikeservice-queue +sudo systemctl start bikeservice-queue +``` + +### 3. Set up Cron for Laravel Scheduler +```bash +crontab -e +``` + +Add this line: +``` +* * * * * cd /var/www/bikeservice/backend && php artisan schedule:run >> /dev/null 2>&1 +``` + +## Deployment Script + +Create a deployment script for future updates: +```bash +#!/bin/bash +# deploy-apache.sh + +cd /var/www/bikeservice + +# Pull latest changes +git pull origin main + +# Backend deployment +cd backend +composer install --no-dev --optimize-autoloader +php artisan config:cache +php artisan route:cache +php artisan view:cache + +# Frontend deployment +cd ../frontend +npm install +npm run build +cp -r dist/* ../backend/public/ + +# Set permissions +sudo chown -R www-data:www-data /var/www/bikeservice +sudo chmod -R 755 /var/www/bikeservice +sudo chmod -R 775 /var/www/bikeservice/backend/storage +sudo chmod -R 775 /var/www/bikeservice/backend/bootstrap/cache + +# Restart services +sudo systemctl restart apache2 + +echo "Deployment completed!" +``` + +Make it executable: +```bash +chmod +x deploy-apache.sh +``` + +## Monitoring and Maintenance + +### 1. Check Application Status +```bash +# Check Apache status +sudo systemctl status apache2 + +# Check MySQL status +sudo systemctl status mysql + +# Check queue worker status +sudo systemctl status bikeservice-queue + +# Check Laravel logs +tail -f /var/www/bikeservice/backend/storage/logs/laravel.log +``` + +### 2. Regular Maintenance +```bash +# Update system packages +sudo apt update && sudo apt upgrade -y + +# Clear Laravel caches +cd /var/www/bikeservice/backend +php artisan cache:clear +php artisan config:clear +php artisan route:clear +php artisan view:clear + +# Rebuild caches +php artisan config:cache +php artisan route:cache +php artisan view:cache +``` + +## Troubleshooting + +### Common Issues: +1. **Permission denied errors**: Check file ownership and permissions +2. **500 Internal Server Error**: Check Apache error logs and Laravel logs +3. **Database connection issues**: Verify MySQL configuration in .env +4. **Static assets not loading**: Check Apache configuration and file paths +5. **URL rewriting not working**: Ensure mod_rewrite is enabled + +### Useful Commands: +```bash +# Check Apache error logs +sudo tail -f /var/log/apache2/error.log + +# Check Apache access logs +sudo tail -f /var/log/apache2/access.log + +# Test Apache configuration +sudo apache2ctl configtest + +# Restart all services +sudo systemctl restart apache2 mysql bikeservice-queue + +# Check MySQL status +sudo mysql -u root -p -e "SHOW DATABASES;" + +# Check PHP version and modules +php -v +php -m +``` + +## Security Considerations + +1. **Firewall**: Configure UFW firewall +2. **SSH**: Use key-based authentication and change default port +3. **Database**: Use strong passwords and limit access +4. **Updates**: Keep system and packages updated +5. **Backups**: Set up regular backups of your application and database +6. **Apache Security**: Disable server signature and unnecessary modules + +## Performance Optimization + +1. **OPcache**: Enable PHP OPcache for better performance +2. **MySQL**: Optimize MySQL configuration +3. **Apache**: Enable compression and caching +4. **CDN**: Use a CDN for static assets +5. **Monitoring**: Set up application monitoring + +## Apache vs Nginx Differences + +- **Configuration**: Apache uses `.htaccess` files and virtual hosts +- **Modules**: Apache modules need to be enabled with `a2enmod` +- **Sites**: Apache sites are enabled with `a2ensite` +- **Logs**: Apache logs are in `/var/log/apache2/` +- **Restart**: Use `sudo systemctl restart apache2` diff --git a/deploy-apache.sh b/deploy-apache.sh new file mode 100755 index 0000000..b87224d --- /dev/null +++ b/deploy-apache.sh @@ -0,0 +1,263 @@ +#!/bin/bash + +# Apache Deployment Script for Bike Service Application +# Make sure to run this script from the project root directory + +set -e # Exit on any error + +echo "🚀 Starting Apache deployment..." + +# Check if we're in the right directory +if [ ! -f "backend/artisan" ] || [ ! -f "frontend/package.json" ]; then + echo "❌ Error: Please run this script from the project root directory" + exit 1 +fi + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +# Function to print colored output +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 on Ubuntu server +if [[ "$OSTYPE" != "linux-gnu"* ]]; then + print_warning "This script is designed for Ubuntu servers. Some commands may not work on your system." +fi + +# Check if running as root +if [[ $EUID -eq 0 ]]; then + print_error "Please don't run this script as root. Use a regular user with sudo privileges." + exit 1 +fi + +# Check if required commands exist +check_command() { + if ! command -v $1 &> /dev/null; then + print_error "$1 is not installed. Please install it first." + exit 1 + fi +} + +print_status "Checking required commands..." +check_command "php" +check_command "composer" +check_command "npm" +check_command "git" +check_command "mysql" + +# Get current branch +CURRENT_BRANCH=$(git branch --show-current) +print_status "Current branch: $CURRENT_BRANCH" + +# Ask for confirmation +read -p "Do you want to deploy from branch '$CURRENT_BRANCH'? (y/N): " -n 1 -r +echo +if [[ ! $REPLY =~ ^[Yy]$ ]]; then + print_warning "Deployment cancelled." + exit 0 +fi + +# Pull latest changes +print_status "Pulling latest changes from git..." +git pull origin $CURRENT_BRANCH + +# Backend deployment +print_status "Deploying Laravel backend..." +cd backend + +# Install/update dependencies +print_status "Installing Composer dependencies..." +composer install --no-dev --optimize-autoloader + +# Check if .env exists, if not copy from example +if [ ! -f ".env" ]; then + print_warning ".env file not found, copying from .env.example..." + if [ -f ".env.example" ]; then + cp .env.example .env + print_warning "Please configure your .env file before continuing!" + print_warning "Make sure to set up your MySQL database configuration." + read -p "Press Enter after configuring .env file..." + else + print_error ".env.example file not found!" + exit 1 + fi +fi + +# Generate key if not set +if ! grep -q "APP_KEY=base64:" .env; then + print_status "Generating application key..." + php artisan key:generate +fi + +# Check database connection +print_status "Testing database connection..." +if php artisan migrate:status > /dev/null 2>&1; then + print_status "Database connection successful!" +else + print_error "Database connection failed! Please check your .env configuration." + print_warning "Make sure MySQL is running and your database credentials are correct." + exit 1 +fi + +# Run migrations +print_status "Running database migrations..." +php artisan migrate --force + +# Clear and rebuild caches +print_status "Clearing and rebuilding caches..." +php artisan config:clear +php artisan route:clear +php artisan view:clear +php artisan cache:clear + +php artisan config:cache +php artisan route:cache +php artisan view:cache + +# Set production environment +if ! grep -q "APP_ENV=production" .env; then + print_status "Setting production environment..." + sed -i 's/APP_ENV=.*/APP_ENV=production/' .env +fi + +if ! grep -q "APP_DEBUG=false" .env; then + print_status "Disabling debug mode..." + sed -i 's/APP_DEBUG=.*/APP_DEBUG=false/' .env +fi + +cd .. + +# Frontend deployment +print_status "Deploying Vue.js frontend..." +cd frontend + +# Install/update dependencies +print_status "Installing npm dependencies..." +npm install + +# Build for production +print_status "Building frontend for production..." +npm run build + +# Copy built files to Laravel public directory +print_status "Copying built files to Laravel public directory..." +if [ -d "dist" ]; then + cp -r dist/* ../backend/public/ + print_status "Frontend files copied successfully" +else + print_error "dist directory not found! Build may have failed." + exit 1 +fi + +cd .. + +# Set proper permissions +print_status "Setting proper permissions..." +if command -v sudo &> /dev/null; then + sudo chown -R www-data:www-data backend/storage backend/bootstrap/cache + sudo chmod -R 775 backend/storage backend/bootstrap/cache + print_status "Permissions set successfully" +else + print_warning "sudo not available, skipping permission changes" +fi + +# Restart services (if running on server) +if command -v sudo &> /dev/null; then + print_status "Restarting services..." + + # Check if Apache is running and restart it + if sudo systemctl is-active --quiet apache2; then + sudo systemctl restart apache2 + print_status "Apache restarted" + else + print_warning "Apache is not running. Please start it manually: sudo systemctl start apache2" + fi + + # Check if MySQL is running + if sudo systemctl is-active --quiet mysql; then + print_status "MySQL is running" + else + print_warning "MySQL is not running. Please start it manually: sudo systemctl start mysql" + fi + + # Check if queue worker service exists and restart it + if sudo systemctl list-units --type=service | grep -q "bikeservice-queue"; then + sudo systemctl restart bikeservice-queue + print_status "Queue worker restarted" + else + print_warning "Queue worker service not found. You may need to set it up manually." + fi +else + print_warning "sudo not available, skipping service restarts" +fi + +# Final checks +print_status "Running final checks..." + +# Check if Laravel is working +cd backend +if php artisan --version &> /dev/null; then + print_status "Laravel is working correctly" +else + print_error "Laravel is not working correctly" + exit 1 +fi + +# Check if frontend files are accessible +if [ -f "public/index.html" ]; then + print_status "Frontend files are in place" +else + print_error "Frontend files are missing" + exit 1 +fi + +# Check Apache configuration +if command -v sudo &> /dev/null && command -v apache2ctl &> /dev/null; then + print_status "Testing Apache configuration..." + if sudo apache2ctl configtest > /dev/null 2>&1; then + print_status "Apache configuration is valid" + else + print_warning "Apache configuration has issues. Run 'sudo apache2ctl configtest' for details." + fi +fi + +cd .. + +echo +echo -e "${GREEN}✅ Apache deployment completed successfully!${NC}" +echo +echo "Next steps:" +echo "1. Test your application in the browser" +echo "2. Check application logs if there are any issues" +echo "3. Verify all features are working correctly" +echo "4. Set up SSL certificate if needed" +echo +echo "Useful commands:" +echo "- Check Laravel logs: tail -f backend/storage/logs/laravel.log" +echo "- Check Apache error logs: sudo tail -f /var/log/apache2/error.log" +echo "- Check Apache access logs: sudo tail -f /var/log/apache2/access.log" +echo "- Test Apache config: sudo apache2ctl configtest" +echo "- Restart Apache: sudo systemctl restart apache2" +echo "- Check MySQL status: sudo systemctl status mysql" +echo +echo "Database information:" +echo "- Make sure MySQL is running: sudo systemctl start mysql" +echo "- Check database connection: mysql -u your_username -p your_database" +echo +echo "Apache configuration:" +echo "- Virtual host: /etc/apache2/sites-available/bikeservice.conf" +echo "- Enable site: sudo a2ensite bikeservice.conf" +echo "- Disable default: sudo a2dissite 000-default.conf" diff --git a/deploy.sh b/deploy.sh new file mode 100755 index 0000000..e32c06a --- /dev/null +++ b/deploy.sh @@ -0,0 +1,223 @@ +#!/bin/bash + +# Deployment script for Bike Service Application +# Make sure to run this script from the project root directory + +set -e # Exit on any error + +echo "🚀 Starting deployment..." + +# Check if we're in the right directory +if [ ! -f "backend/artisan" ] || [ ! -f "frontend/package.json" ]; then + echo "❌ Error: Please run this script from the project root directory" + exit 1 +fi + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +# Function to print colored output +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 on Ubuntu server +if [[ "$OSTYPE" != "linux-gnu"* ]]; then + print_warning "This script is designed for Ubuntu servers. Some commands may not work on your system." +fi + +# Check if running as root +if [[ $EUID -eq 0 ]]; then + print_error "Please don't run this script as root. Use a regular user with sudo privileges." + exit 1 +fi + +# Check if required commands exist +check_command() { + if ! command -v $1 &> /dev/null; then + print_error "$1 is not installed. Please install it first." + exit 1 + fi +} + +print_status "Checking required commands..." +check_command "php" +check_command "composer" +check_command "npm" +check_command "git" + +# Get current branch +CURRENT_BRANCH=$(git branch --show-current) +print_status "Current branch: $CURRENT_BRANCH" + +# Ask for confirmation +read -p "Do you want to deploy from branch '$CURRENT_BRANCH'? (y/N): " -n 1 -r +echo +if [[ ! $REPLY =~ ^[Yy]$ ]]; then + print_warning "Deployment cancelled." + exit 0 +fi + +# Pull latest changes +print_status "Pulling latest changes from git..." +git pull origin $CURRENT_BRANCH + +# Backend deployment +print_status "Deploying Laravel backend..." +cd backend + +# Install/update dependencies +print_status "Installing Composer dependencies..." +composer install --no-dev --optimize-autoloader + +# Check if .env exists, if not copy from example +if [ ! -f ".env" ]; then + print_warning ".env file not found, copying from .env.example..." + if [ -f ".env.example" ]; then + cp .env.example .env + print_warning "Please configure your .env file before continuing!" + read -p "Press Enter after configuring .env file..." + else + print_error ".env.example file not found!" + exit 1 + fi +fi + +# Generate key if not set +if ! grep -q "APP_KEY=base64:" .env; then + print_status "Generating application key..." + php artisan key:generate +fi + +# Run migrations +print_status "Running database migrations..." +php artisan migrate --force + +# Clear and rebuild caches +print_status "Clearing and rebuilding caches..." +php artisan config:clear +php artisan route:clear +php artisan view:clear +php artisan cache:clear + +php artisan config:cache +php artisan route:cache +php artisan view:cache + +# Set production environment +if ! grep -q "APP_ENV=production" .env; then + print_status "Setting production environment..." + sed -i 's/APP_ENV=.*/APP_ENV=production/' .env +fi + +if ! grep -q "APP_DEBUG=false" .env; then + print_status "Disabling debug mode..." + sed -i 's/APP_DEBUG=.*/APP_DEBUG=false/' .env +fi + +cd .. + +# Frontend deployment +print_status "Deploying Vue.js frontend..." +cd frontend + +# Install/update dependencies +print_status "Installing npm dependencies..." +npm install + +# Build for production +print_status "Building frontend for production..." +npm run build + +# Copy built files to Laravel public directory +print_status "Copying built files to Laravel public directory..." +if [ -d "dist" ]; then + cp -r dist/* ../backend/public/ + print_status "Frontend files copied successfully" +else + print_error "dist directory not found! Build may have failed." + exit 1 +fi + +cd .. + +# Set proper permissions +print_status "Setting proper permissions..." +if command -v sudo &> /dev/null; then + sudo chown -R www-data:www-data backend/storage backend/bootstrap/cache + sudo chmod -R 775 backend/storage backend/bootstrap/cache + print_status "Permissions set successfully" +else + print_warning "sudo not available, skipping permission changes" +fi + +# Restart services (if running on server) +if command -v sudo &> /dev/null; then + print_status "Restarting services..." + + # Check if services exist and restart them + if sudo systemctl list-units --type=service | grep -q "php8.2-fpm"; then + sudo systemctl restart php8.2-fpm + print_status "PHP-FPM restarted" + fi + + if sudo systemctl list-units --type=service | grep -q "nginx"; then + sudo systemctl restart nginx + print_status "Nginx restarted" + fi + + if sudo systemctl list-units --type=service | grep -q "bikeservice-queue"; then + sudo systemctl restart bikeservice-queue + print_status "Queue worker restarted" + fi +else + print_warning "sudo not available, skipping service restarts" +fi + +# Final checks +print_status "Running final checks..." + +# Check if Laravel is working +cd backend +if php artisan --version &> /dev/null; then + print_status "Laravel is working correctly" +else + print_error "Laravel is not working correctly" + exit 1 +fi + +# Check if frontend files are accessible +if [ -f "public/index.html" ]; then + print_status "Frontend files are in place" +else + print_error "Frontend files are missing" + exit 1 +fi + +cd .. + +echo +echo -e "${GREEN}✅ Deployment completed successfully!${NC}" +echo +echo "Next steps:" +echo "1. Test your application in the browser" +echo "2. Check application logs if there are any issues" +echo "3. Verify all features are working correctly" +echo +echo "Useful commands:" +echo "- Check Laravel logs: tail -f backend/storage/logs/laravel.log" +echo "- Check Nginx logs: sudo tail -f /var/log/nginx/error.log" +echo "- Check PHP-FPM logs: sudo tail -f /var/log/php8.2-fpm.log" +echo "- Restart all services: sudo systemctl restart nginx php8.2-fpm" + diff --git a/deployment-guide.md b/deployment-guide.md new file mode 100644 index 0000000..370338b --- /dev/null +++ b/deployment-guide.md @@ -0,0 +1,354 @@ +# Deployment Guide for Bike Service Application + +This guide will help you deploy your Laravel + Vue.js application to an Ubuntu server. + +## Prerequisites + +- Ubuntu 20.04+ server with root/sudo access +- Domain name (optional but recommended) +- SSH access to your server + +## Server Setup + +### 1. Update System +```bash +sudo apt update && sudo apt upgrade -y +``` + +### 2. Install Required Software +```bash +# Install Nginx +sudo apt install nginx -y + +# Install PHP 8.2 and extensions +sudo apt install software-properties-common -y +sudo add-apt-repository ppa:ondrej/php -y +sudo apt update +sudo apt install php8.2-fpm php8.2-mysql php8.2-sqlite3 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 -y + +# Install Composer +curl -sS https://getcomposer.org/installer | php +sudo mv composer.phar /usr/local/bin/composer + +# Install Node.js and npm +curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash - +sudo apt-get install -y nodejs + +# Install Git +sudo apt install git -y + +# Install SQLite (if using SQLite) +sudo apt install sqlite3 -y +``` + +### 3. Configure PHP-FPM +```bash +# Edit PHP-FPM configuration +sudo nano /etc/php/8.2/fpm/php.ini + +# Set these values: +# memory_limit = 256M +# upload_max_filesize = 64M +# post_max_size = 64M +# max_execution_time = 300 + +# Restart PHP-FPM +sudo systemctl restart php8.2-fpm +sudo systemctl enable php8.2-fpm +``` + +## Application Deployment + +### 1. Create Application Directory +```bash +sudo mkdir -p /var/www/bikeservice +sudo chown -R $USER:$USER /var/www/bikeservice +cd /var/www/bikeservice +``` + +### 2. Clone Your Repository +```bash +git clone . +# Or upload your files via SCP/SFTP +``` + +### 3. Backend Setup (Laravel) +```bash +cd backend + +# Install dependencies +composer install --no-dev --optimize-autoloader + +# Set permissions +sudo chown -R www-data:www-data storage bootstrap/cache +sudo chmod -R 775 storage bootstrap/cache + +# Create .env file +cp .env.example .env + +# Generate application key +php artisan key:generate + +# Configure database (update .env file) +# For production, consider using MySQL/PostgreSQL instead of SQLite + +# Run migrations +php artisan migrate --force + +# Clear and cache config +php artisan config:cache +php artisan route:cache +php artisan view:cache + +# Set production environment +echo "APP_ENV=production" >> .env +echo "APP_DEBUG=false" >> .env +``` + +### 4. Frontend Setup (Vue.js) +```bash +cd ../frontend + +# Install dependencies +npm install + +# Build for production +npm run build + +# Copy built files to Laravel public directory +cp -r dist/* ../backend/public/ +``` + +## Nginx Configuration + +### 1. Create Nginx Site Configuration +```bash +sudo nano /etc/nginx/sites-available/bikeservice +``` + +Add this configuration: +```nginx +server { + listen 80; + server_name your-domain.com www.your-domain.com; + root /var/www/bikeservice/backend/public; + index index.php index.html index.htm; + + # Security headers + add_header X-Frame-Options "SAMEORIGIN" always; + add_header X-XSS-Protection "1; mode=block" always; + add_header X-Content-Type-Options "nosniff" always; + add_header Referrer-Policy "no-referrer-when-downgrade" always; + add_header Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline'" always; + + location / { + try_files $uri $uri/ /index.php?$query_string; + } + + location ~ \.php$ { + fastcgi_pass unix:/var/run/php/php8.2-fpm.sock; + fastcgi_index index.php; + fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name; + include fastcgi_params; + } + + location ~ /\.(?!well-known).* { + deny all; + } + + # Cache static assets + location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ { + expires 1y; + add_header Cache-Control "public, immutable"; + } +} +``` + +### 2. Enable Site and Restart Nginx +```bash +sudo ln -s /etc/nginx/sites-available/bikeservice /etc/nginx/sites-enabled/ +sudo nginx -t +sudo systemctl restart nginx +sudo systemctl enable nginx +``` + +## SSL Certificate (Optional but Recommended) + +### 1. Install Certbot +```bash +sudo apt install certbot python3-certbot-nginx -y +``` + +### 2. Obtain SSL Certificate +```bash +sudo certbot --nginx -d your-domain.com -d www.your-domain.com +``` + +## Final Configuration + +### 1. Set Proper Permissions +```bash +sudo chown -R www-data:www-data /var/www/bikeservice +sudo chmod -R 755 /var/www/bikeservice +sudo chmod -R 775 /var/www/bikeservice/backend/storage +sudo chmod -R 775 /var/www/bikeservice/backend/bootstrap/cache +``` + +### 2. Configure Queue Worker (if using queues) +```bash +# Create systemd service for queue worker +sudo nano /etc/systemd/system/bikeservice-queue.service +``` + +Add this content: +```ini +[Unit] +Description=Bike Service Queue Worker +After=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 +Restart=always +RestartSec=10 + +[Install] +WantedBy=multi-user.target +``` + +Enable and start the service: +```bash +sudo systemctl enable bikeservice-queue +sudo systemctl start bikeservice-queue +``` + +### 3. Set up Cron for Laravel Scheduler +```bash +crontab -e +``` + +Add this line: +``` +* * * * * cd /var/www/bikeservice/backend && php artisan schedule:run >> /dev/null 2>&1 +``` + +## Deployment Script + +Create a deployment script for future updates: +```bash +#!/bin/bash +# deploy.sh + +cd /var/www/bikeservice + +# Pull latest changes +git pull origin main + +# Backend deployment +cd backend +composer install --no-dev --optimize-autoloader +php artisan config:cache +php artisan route:cache +php artisan view:cache + +# Frontend deployment +cd ../frontend +npm install +npm run build +cp -r dist/* ../backend/public/ + +# Set permissions +sudo chown -R www-data:www-data /var/www/bikeservice +sudo chmod -R 755 /var/www/bikeservice +sudo chmod -R 775 /var/www/bikeservice/backend/storage +sudo chmod -R 775 /var/www/bikeservice/backend/bootstrap/cache + +# Restart services +sudo systemctl restart php8.2-fpm +sudo systemctl restart nginx + +echo "Deployment completed!" +``` + +Make it executable: +```bash +chmod +x deploy.sh +``` + +## Monitoring and Maintenance + +### 1. Check Application Status +```bash +# Check Nginx status +sudo systemctl status nginx + +# Check PHP-FPM status +sudo systemctl status php8.2-fpm + +# Check queue worker status +sudo systemctl status bikeservice-queue + +# Check Laravel logs +tail -f /var/www/bikeservice/backend/storage/logs/laravel.log +``` + +### 2. Regular Maintenance +```bash +# Update system packages +sudo apt update && sudo apt upgrade -y + +# Clear Laravel caches +cd /var/www/bikeservice/backend +php artisan cache:clear +php artisan config:clear +php artisan route:clear +php artisan view:clear + +# Rebuild caches +php artisan config:cache +php artisan route:cache +php artisan view:cache +``` + +## Troubleshooting + +### Common Issues: +1. **Permission denied errors**: Check file ownership and permissions +2. **500 Internal Server Error**: Check Laravel logs and PHP-FPM logs +3. **Database connection issues**: Verify database configuration in .env +4. **Static assets not loading**: Check Nginx configuration and file paths + +### Useful Commands: +```bash +# Check Nginx error logs +sudo tail -f /var/log/nginx/error.log + +# Check PHP-FPM logs +sudo tail -f /var/log/php8.2-fpm.log + +# Test Nginx configuration +sudo nginx -t + +# Restart all services +sudo systemctl restart nginx php8.2-fpm bikeservice-queue +``` + +## Security Considerations + +1. **Firewall**: Configure UFW firewall +2. **SSH**: Use key-based authentication and change default port +3. **Database**: Use strong passwords and limit access +4. **Updates**: Keep system and packages updated +5. **Backups**: Set up regular backups of your application and database + +## Performance Optimization + +1. **OPcache**: Enable PHP OPcache for better performance +2. **Redis**: Consider using Redis for caching and sessions +3. **CDN**: Use a CDN for static assets +4. **Database**: Optimize database queries and indexes +5. **Monitoring**: Set up application monitoring (Laravel Telescope, etc.) + diff --git a/env-apache-template.txt b/env-apache-template.txt new file mode 100644 index 0000000..23dd02c --- /dev/null +++ b/env-apache-template.txt @@ -0,0 +1,69 @@ +# Laravel Environment Configuration for Apache/MySQL Deployment +# Copy this file to .env and update the values + +APP_NAME="Bike Service" +APP_ENV=production +APP_KEY= +APP_DEBUG=false +APP_URL=http://your-domain.com + +# Database Configuration for MySQL +DB_CONNECTION=mysql +DB_HOST=127.0.0.1 +DB_PORT=3306 +DB_DATABASE=bikeservice_db +DB_USERNAME=bikeservice_user +DB_PASSWORD=your_secure_password + +# Cache Configuration +CACHE_DRIVER=file +FILESYSTEM_DISK=local +QUEUE_CONNECTION=sync +SESSION_DRIVER=file +SESSION_LIFETIME=120 + +# Mail Configuration (update with your mail settings) +MAIL_MAILER=smtp +MAIL_HOST=mailpit +MAIL_PORT=1025 +MAIL_USERNAME=null +MAIL_PASSWORD=null +MAIL_ENCRYPTION=null +MAIL_FROM_ADDRESS="hello@example.com" +MAIL_FROM_NAME="${APP_NAME}" + +# AWS Configuration (if using S3) +AWS_ACCESS_KEY_ID= +AWS_SECRET_ACCESS_KEY= +AWS_DEFAULT_REGION=us-east-1 +AWS_BUCKET= +AWS_USE_PATH_STYLE_ENDPOINT=false + +# Pusher Configuration (if using real-time features) +PUSHER_APP_ID= +PUSHER_APP_KEY= +PUSHER_APP_SECRET= +PUSHER_HOST= +PUSHER_PORT=443 +PUSHER_SCHEME=https +PUSHER_APP_CLUSTER=mt1 + +# Vite Configuration +VITE_APP_NAME="${APP_NAME}" +VITE_PUSHER_APP_KEY="${PUSHER_APP_KEY}" +VITE_PUSHER_HOST="${PUSHER_HOST}" +VITE_PUSHER_PORT="${PUSHER_PORT}" +VITE_PUSHER_SCHEME="${PUSHER_SCHEME}" +VITE_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}" + +# Additional Configuration +LOG_CHANNEL=stack +LOG_DEPRECATIONS_CHANNEL=null +LOG_LEVEL=debug + +# Security +SANCTUM_STATEFUL_DOMAINS=localhost,127.0.0.1,127.0.0.1:8000,::1,your-domain.com +SESSION_DOMAIN=null + +# Performance +BROADCAST_DRIVER=log diff --git a/mysql-setup.sql b/mysql-setup.sql new file mode 100644 index 0000000..002e3be --- /dev/null +++ b/mysql-setup.sql @@ -0,0 +1,27 @@ +-- MySQL Database Setup for Bike Service Application +-- Run this script as root user: mysql -u root -p < mysql-setup.sql + +-- Create database +CREATE DATABASE IF NOT EXISTS bikeservice_db +CHARACTER SET utf8mb4 +COLLATE utf8mb4_unicode_ci; + +-- Create user (replace 'your_secure_password' with a strong password) +CREATE USER IF NOT EXISTS 'bikeservice_user'@'localhost' +IDENTIFIED BY 'your_secure_password'; + +-- Grant privileges +GRANT ALL PRIVILEGES ON bikeservice_db.* TO 'bikeservice_user'@'localhost'; + +-- Grant additional privileges for Laravel +GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX, ALTER, CREATE TEMPORARY TABLES, LOCK TABLES ON bikeservice_db.* TO 'bikeservice_user'@'localhost'; + +-- Flush privileges +FLUSH PRIVILEGES; + +-- Show created database and user +SHOW DATABASES; +SELECT User, Host FROM mysql.user WHERE User = 'bikeservice_user'; + +-- Display success message +SELECT 'Database and user created successfully!' as Status; diff --git a/nginx-bikeservice.conf b/nginx-bikeservice.conf new file mode 100644 index 0000000..0fde4e7 --- /dev/null +++ b/nginx-bikeservice.conf @@ -0,0 +1,106 @@ +server { + listen 80; + server_name your-domain.com www.your-domain.com; + root /var/www/bikeservice/backend/public; + index index.php index.html index.htm; + + # Security headers + add_header X-Frame-Options "SAMEORIGIN" always; + add_header X-XSS-Protection "1; mode=block" always; + add_header X-Content-Type-Options "nosniff" always; + add_header Referrer-Policy "no-referrer-when-downgrade" always; + add_header Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline'" always; + + # Gzip compression + gzip on; + gzip_vary on; + gzip_min_length 1024; + gzip_proxied any; + gzip_comp_level 6; + gzip_types + text/plain + text/css + text/xml + text/javascript + application/json + application/javascript + application/xml+rss + application/atom+xml + image/svg+xml; + + # Handle Laravel routes + location / { + try_files $uri $uri/ /index.php?$query_string; + } + + # Handle PHP files + location ~ \.php$ { + fastcgi_pass unix:/var/run/php/php8.2-fpm.sock; + fastcgi_index index.php; + fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name; + include fastcgi_params; + + # FastCGI optimizations + fastcgi_buffer_size 128k; + fastcgi_buffers 4 256k; + fastcgi_busy_buffers_size 256k; + fastcgi_read_timeout 300; + } + + # Deny access to hidden files + location ~ /\.(?!well-known).* { + deny all; + } + + # Deny access to sensitive files + location ~* \.(env|log|sql|md|txt|yml|yaml|ini)$ { + deny all; + } + + # Cache static assets + location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ { + expires 1y; + add_header Cache-Control "public, immutable"; + add_header Vary Accept-Encoding; + + # Enable gzip for static assets + gzip_static on; + } + + # Cache API responses (adjust as needed) + location ~* ^/api/ { + add_header Cache-Control "no-cache, no-store, must-revalidate"; + add_header Pragma "no-cache"; + add_header Expires "0"; + } + + # Rate limiting for API endpoints + location ~* ^/api/ { + limit_req zone=api burst=10 nodelay; + limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s; + } + + # Health check endpoint + location /health { + access_log off; + return 200 "healthy\n"; + add_header Content-Type text/plain; + } + + # Logging + access_log /var/log/nginx/bikeservice_access.log; + error_log /var/log/nginx/bikeservice_error.log; + + # Client max body size (for file uploads) + client_max_body_size 64M; + + # Timeouts + client_body_timeout 60s; + client_header_timeout 60s; + send_timeout 60s; +} + +# Rate limiting configuration (add this to http block or create separate file) +# limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s; +# limit_req_zone $binary_remote_addr zone=general:10m rate=30r/s; + diff --git a/server-setup-apache.sh b/server-setup-apache.sh new file mode 100755 index 0000000..615ffc5 --- /dev/null +++ b/server-setup-apache.sh @@ -0,0 +1,294 @@ +#!/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" diff --git a/server-setup.sh b/server-setup.sh new file mode 100755 index 0000000..649b767 --- /dev/null +++ b/server-setup.sh @@ -0,0 +1,284 @@ +#!/bin/bash + +# Server Setup Script for Bike Service Application +# Run this script on your Ubuntu server after initial setup + +set -e + +echo "🚀 Setting up Ubuntu server 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" != "20.04" && "$UBUNTU_VERSION" != "22.04" && "$UBUNTU_VERSION" != "24.04" ]]; then + print_warning "This script is tested on Ubuntu 20.04, 22.04, and 24.04. You're running $UBUNTU_VERSION" +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 Nginx +apt install nginx -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-fpm php8.2-mysql php8.2-sqlite3 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 SQLite +apt install sqlite3 -y + +# Install additional tools +apt install unzip curl wget htop ufw fail2ban -y + +# Configure PHP-FPM +print_status "Configuring PHP-FPM..." +PHP_INI="/etc/php/8.2/fpm/php.ini" +PHP_FPM_INI="/etc/php/8.2/fpm/php.ini" + +# Backup original files +cp $PHP_INI $PHP_INI.backup +cp $PHP_FPM_INI $PHP_FPM_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 + +# Restart PHP-FPM +systemctl restart php8.2-fpm +systemctl enable php8.2-fpm + +# Configure Nginx +print_status "Configuring Nginx..." + +# Create application directory +mkdir -p /var/www/bikeservice +chown -R www-data:www-data /var/www/bikeservice + +# Create Nginx site configuration +cat > /etc/nginx/sites-available/bikeservice << 'EOF' +server { + listen 80; + server_name _; + root /var/www/bikeservice/backend/public; + index index.php index.html index.htm; + + # Security headers + add_header X-Frame-Options "SAMEORIGIN" always; + add_header X-XSS-Protection "1; mode=block" always; + add_header X-Content-Type-Options "nosniff" always; + add_header Referrer-Policy "no-referrer-when-downgrade" always; + + # Gzip compression + gzip on; + gzip_vary on; + gzip_min_length 1024; + gzip_proxied any; + gzip_comp_level 6; + gzip_types + text/plain + text/css + text/xml + text/javascript + application/json + application/javascript + application/xml+rss + application/atom+xml + image/svg+xml; + + location / { + try_files $uri $uri/ /index.php?$query_string; + } + + location ~ \.php$ { + fastcgi_pass unix:/var/run/php/php8.2-fpm.sock; + fastcgi_index index.php; + fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name; + include fastcgi_params; + + fastcgi_buffer_size 128k; + fastcgi_buffers 4 256k; + fastcgi_busy_buffers_size 256k; + fastcgi_read_timeout 300; + } + + location ~ /\.(?!well-known).* { + deny all; + } + + location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ { + expires 1y; + add_header Cache-Control "public, immutable"; + } + + client_max_body_size 64M; +} +EOF + +# Enable site +ln -sf /etc/nginx/sites-available/bikeservice /etc/nginx/sites-enabled/ +rm -f /etc/nginx/sites-enabled/default + +# Test Nginx configuration +nginx -t + +# Restart Nginx +systemctl restart nginx +systemctl enable nginx + +# Configure firewall +print_status "Configuring firewall..." +ufw --force enable +ufw allow ssh +ufw allow 'Nginx 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/nginx/bikeservice_access.log +touch /var/log/nginx/bikeservice_error.log +chown www-data:adm /var/log/nginx/bikeservice_*.log + +print_status "Server setup completed!" +echo +echo "Next steps:" +echo "1. Add your SSH public key to the deploy user:" +echo " ssh-copy-id deploy@your-server-ip" +echo "2. Upload your application files to /var/www/bikeservice" +echo "3. Configure your .env file" +echo "4. Run the deployment script" +echo +echo "Useful commands:" +echo "- Check service status: systemctl status nginx php8.2-fpm bikeservice-queue" +echo "- View logs: journalctl -u bikeservice-queue -f" +echo "- Check Nginx logs: tail -f /var/log/nginx/bikeservice_error.log" +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" + diff --git a/setup-mysql.sh b/setup-mysql.sh new file mode 100755 index 0000000..ebb4125 --- /dev/null +++ b/setup-mysql.sh @@ -0,0 +1,136 @@ +#!/bin/bash + +# MySQL Setup Script for Bike Service Application +# This script will create the database and user for the application + +set -e + +echo "🗄️ Setting up MySQL database 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 MySQL is running +if ! systemctl is-active --quiet mysql; then + print_error "MySQL is not running. Please start MySQL first:" + echo "sudo systemctl start mysql" + exit 1 +fi + +# Get database credentials +echo "Enter MySQL root password:" +read -s MYSQL_ROOT_PASSWORD + +# Get application database credentials +echo "Enter database name (default: bikeservice_db):" +read DB_NAME +DB_NAME=${DB_NAME:-bikeservice_db} + +echo "Enter database username (default: bikeservice_user):" +read DB_USER +DB_USER=${DB_USER:-bikeservice_user} + +echo "Enter database password:" +read -s DB_PASSWORD + +# Validate password strength +if [ ${#DB_PASSWORD} -lt 8 ]; then + print_warning "Password is less than 8 characters. Consider using a stronger password." +fi + +print_status "Creating database and user..." + +# Create SQL script +cat > /tmp/mysql_setup.sql << EOF +-- Create database +CREATE DATABASE IF NOT EXISTS ${DB_NAME} +CHARACTER SET utf8mb4 +COLLATE utf8mb4_unicode_ci; + +-- Create user +CREATE USER IF NOT EXISTS '${DB_USER}'@'localhost' +IDENTIFIED BY '${DB_PASSWORD}'; + +-- Grant privileges +GRANT ALL PRIVILEGES ON ${DB_NAME}.* TO '${DB_USER}'@'localhost'; + +-- Grant additional privileges for Laravel +GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX, ALTER, CREATE TEMPORARY TABLES, LOCK TABLES ON ${DB_NAME}.* TO '${DB_USER}'@'localhost'; + +-- Flush privileges +FLUSH PRIVILEGES; + +-- Show created database and user +SHOW DATABASES; +SELECT User, Host FROM mysql.user WHERE User = '${DB_USER}'; + +-- Display success message +SELECT 'Database and user created successfully!' as Status; +EOF + +# Execute SQL script +if mysql -u root -p"$MYSQL_ROOT_PASSWORD" < /tmp/mysql_setup.sql; then + print_status "Database and user created successfully!" + + # Create .env database configuration + cat > /tmp/database_config.env << EOF +# Database Configuration +DB_CONNECTION=mysql +DB_HOST=127.0.0.1 +DB_PORT=3306 +DB_DATABASE=${DB_NAME} +DB_USERNAME=${DB_USER} +DB_PASSWORD=${DB_PASSWORD} +EOF + + print_status "Database configuration saved to /tmp/database_config.env" + print_warning "Copy these settings to your Laravel .env file:" + echo + cat /tmp/database_config.env + echo + + # Test database connection + print_status "Testing database connection..." + if mysql -u "$DB_USER" -p"$DB_PASSWORD" -e "USE ${DB_NAME}; SELECT 1;" > /dev/null 2>&1; then + print_status "Database connection test successful!" + else + print_error "Database connection test failed!" + exit 1 + fi + +else + print_error "Failed to create database and user!" + exit 1 +fi + +# Clean up +rm -f /tmp/mysql_setup.sql + +print_status "MySQL setup completed!" +echo +echo "Next steps:" +echo "1. Copy the database configuration to your Laravel .env file" +echo "2. Run Laravel migrations: php artisan migrate" +echo "3. Test your application" +echo +echo "Database credentials:" +echo "- Database: ${DB_NAME}" +echo "- Username: ${DB_USER}" +echo "- Password: [hidden]" +echo "- Host: 127.0.0.1" +echo "- Port: 3306"