initial commit

This commit is contained in:
2025-09-06 14:31:22 +02:00
parent aee2d81e26
commit 1bc3056c77
12 changed files with 2318 additions and 0 deletions
+115
View File
@@ -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>
+36
View File
@@ -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
+411
View File
@@ -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`
+263
View File
@@ -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"
Executable
+223
View File
@@ -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"
+354
View File
@@ -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.)
+69
View File
@@ -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
+27
View File
@@ -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;
+106
View File
@@ -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;
+294
View File
@@ -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"
+284
View File
@@ -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
View File
@@ -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"