initial commit
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
<VirtualHost *:80>
|
||||
ServerName your-domain.com
|
||||
ServerAlias www.your-domain.com
|
||||
DocumentRoot /var/www/bikeservice/backend/public
|
||||
|
||||
<Directory /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]
|
||||
</Directory>
|
||||
|
||||
# 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
|
||||
<Location />
|
||||
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
|
||||
</Location>
|
||||
|
||||
# Cache static assets
|
||||
<LocationMatch "\.(css|js|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$">
|
||||
ExpiresActive On
|
||||
ExpiresDefault "access plus 1 year"
|
||||
Header append Cache-Control "public, immutable"
|
||||
Header append Vary Accept-Encoding
|
||||
</LocationMatch>
|
||||
|
||||
# Cache API responses (no cache)
|
||||
<LocationMatch "^/api/">
|
||||
Header set Cache-Control "no-cache, no-store, must-revalidate"
|
||||
Header set Pragma "no-cache"
|
||||
Header set Expires "0"
|
||||
</LocationMatch>
|
||||
|
||||
# Deny access to sensitive files
|
||||
<FilesMatch "\.(env|log|sql|md|txt|yml|yaml|ini)$">
|
||||
Require all denied
|
||||
</FilesMatch>
|
||||
|
||||
# Deny access to hidden files
|
||||
<FilesMatch "^\.">
|
||||
Require all denied
|
||||
</FilesMatch>
|
||||
|
||||
# Health check endpoint
|
||||
<Location /health>
|
||||
SetHandler server-status
|
||||
Require all granted
|
||||
</Location>
|
||||
|
||||
# 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
|
||||
</VirtualHost>
|
||||
|
||||
# SSL Configuration (uncomment after obtaining SSL certificate)
|
||||
# <VirtualHost *:443>
|
||||
# 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
|
||||
# <Directory /var/www/bikeservice/backend/public>
|
||||
# AllowOverride All
|
||||
# Require all granted
|
||||
#
|
||||
# RewriteEngine On
|
||||
# RewriteCond %{REQUEST_FILENAME} !-f
|
||||
# RewriteCond %{REQUEST_FILENAME} !-d
|
||||
# RewriteRule ^(.*)$ index.php [QSA,L]
|
||||
# </Directory>
|
||||
#
|
||||
# # 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...
|
||||
# </VirtualHost>
|
||||
|
||||
# Redirect HTTP to HTTPS (uncomment after SSL setup)
|
||||
# <VirtualHost *:80>
|
||||
# ServerName your-domain.com
|
||||
# ServerAlias www.your-domain.com
|
||||
# Redirect permanent / https://your-domain.com/
|
||||
# </VirtualHost>
|
||||
@@ -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
|
||||
|
||||
@@ -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 <your-repository-url> .
|
||||
# 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
|
||||
<VirtualHost *:80>
|
||||
ServerName your-domain.com
|
||||
ServerAlias www.your-domain.com
|
||||
DocumentRoot /var/www/bikeservice/backend/public
|
||||
|
||||
<Directory /var/www/bikeservice/backend/public>
|
||||
AllowOverride All
|
||||
Require all granted
|
||||
</Directory>
|
||||
|
||||
# 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
|
||||
<Location />
|
||||
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
|
||||
</Location>
|
||||
|
||||
# Cache static assets
|
||||
<LocationMatch "\.(css|js|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$">
|
||||
ExpiresActive On
|
||||
ExpiresDefault "access plus 1 year"
|
||||
Header append Cache-Control "public, immutable"
|
||||
</LocationMatch>
|
||||
|
||||
# Logging
|
||||
ErrorLog ${APACHE_LOG_DIR}/bikeservice_error.log
|
||||
CustomLog ${APACHE_LOG_DIR}/bikeservice_access.log combined
|
||||
</VirtualHost>
|
||||
```
|
||||
|
||||
### 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`
|
||||
Executable
+263
@@ -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"
|
||||
@@ -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"
|
||||
|
||||
@@ -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 <your-repository-url> .
|
||||
# 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.)
|
||||
|
||||
@@ -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
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
|
||||
Executable
+294
@@ -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'
|
||||
<VirtualHost *:80>
|
||||
ServerName _
|
||||
DocumentRoot /var/www/bikeservice/backend/public
|
||||
|
||||
<Directory /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]
|
||||
</Directory>
|
||||
|
||||
# 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
|
||||
<Location />
|
||||
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
|
||||
</Location>
|
||||
|
||||
# Cache static assets
|
||||
<LocationMatch "\.(css|js|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$">
|
||||
ExpiresActive On
|
||||
ExpiresDefault "access plus 1 year"
|
||||
Header append Cache-Control "public, immutable"
|
||||
</LocationMatch>
|
||||
|
||||
# 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
|
||||
</VirtualHost>
|
||||
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"
|
||||
Executable
+284
@@ -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"
|
||||
|
||||
Executable
+136
@@ -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"
|
||||
Reference in New Issue
Block a user