Production Deployment - luckydeva03/barbershop_app GitHub Wiki
Panduan lengkap deploy aplikasi barbershop management system ke production server.
- OS: Ubuntu 20.04+ / CentOS 8+ / Debian 10+
- Web Server: Nginx atau Apache
- PHP: 8.2+ dengan extensions yang dibutuhkan
- Database: MySQL 8.0+ atau PostgreSQL 13+
- Memory: Minimum 1GB RAM (Recommended 2GB+)
- Storage: Minimum 5GB free space
- SSL Certificate: Untuk HTTPS
- Domain name yang sudah pointing ke server
- SSL certificate (Let's Encrypt recommended)
# Update package list
sudo apt update && sudo apt upgrade -y
# Install required packages
sudo apt install -y software-properties-common curl wget git unzip
# Add PHP 8.2 repository
sudo add-apt-repository ppa:ondrej/php -y
sudo apt update
# Install PHP 8.2 and extensions
sudo apt install -y php8.2 php8.2-fpm php8.2-mysql php8.2-xml php8.2-gd \
php8.2-curl php8.2-mbstring php8.2-zip php8.2-bcmath php8.2-intl
# Install Composer
curl -sS https://getcomposer.org/installer | php
sudo mv composer.phar /usr/local/bin/composer
# Install Node.js 18
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
sudo apt install -y nodejs
# Install Nginx
sudo apt install -y nginx
# Install MySQL
sudo apt install -y mysql-server
sudo mysql_secure_installation
# Update system
sudo dnf update -y
# Install EPEL and Remi repositories
sudo dnf install -y epel-release
sudo dnf install -y https://rpms.remirepo.net/enterprise/remi-release-8.rpm
# Enable PHP 8.2
sudo dnf module enable php:remi-8.2 -y
# Install PHP and extensions
sudo dnf install -y php php-fpm php-mysql php-xml php-gd php-curl \
php-mbstring php-zip php-bcmath php-intl
# Install other dependencies
sudo dnf install -y composer nodejs npm nginx mysql-server git
# Start and enable MySQL
sudo systemctl start mysql
sudo systemctl enable mysql
# Create database and user
sudo mysql -u root -p
# In MySQL prompt:
CREATE DATABASE barbershop_production CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'barbershop_user'@'localhost' IDENTIFIED BY 'strong_password_here';
GRANT ALL PRIVILEGES ON barbershop_production.* TO 'barbershop_user'@'localhost';
FLUSH PRIVILEGES;
EXIT;
# Create web directory
sudo mkdir -p /var/www/barbershop
cd /var/www
# Clone repository
sudo git clone https://github.com/luckydeva03/barbershop_app.git barbershop
cd barbershop
# Set ownership
sudo chown -R www-data:www-data /var/www/barbershop
sudo chmod -R 755 /var/www/barbershop
# Install PHP dependencies
composer install --no-dev --optimize-autoloader
# Install Node.js dependencies
npm ci --only=production
# Build production assets
npm run build
# Copy environment file
cp .env.example .env
# Edit environment file
nano .env
APP_NAME="Barbershop Management System"
APP_ENV=production
APP_DEBUG=false
APP_URL=https://yourdomain.com
# Database Configuration
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=barbershop_production
DB_USERNAME=barbershop_user
DB_PASSWORD=strong_password_here
# Security
APP_KEY=base64:your_app_key_here
SESSION_DRIVER=database
SESSION_ENCRYPT=true
SESSION_LIFETIME=60
SESSION_EXPIRE_ON_CLOSE=true
# Cache & Queue
CACHE_DRIVER=redis
QUEUE_CONNECTION=redis
SESSION_DRIVER=redis
# Redis Configuration
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
# Mail Configuration (if needed)
MAIL_MAILER=smtp
MAIL_HOST=smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=your_username
MAIL_PASSWORD=your_password
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS=[email protected]
MAIL_FROM_NAME="${APP_NAME}"
# Google OAuth (Production URLs)
GOOGLE_CLIENT_ID=your_google_client_id
GOOGLE_CLIENT_SECRET=your_google_client_secret
GOOGLE_REDIRECT_URL=https://yourdomain.com/auth/google/callback
# WhatsApp Integration
WHATSAPP_API_TOKEN=your_whatsapp_token
WHATSAPP_PHONE_NUMBER=your_whatsapp_number
# Generate application key
php artisan key:generate
# Run database migrations
php artisan migrate --force
# Seed database (optional, for demo data)
php artisan db:seed --force
# Create storage link
php artisan storage:link
# Optimize application for production
php artisan config:cache
php artisan route:cache
php artisan view:cache
php artisan event:cache
# Clear any existing caches
php artisan cache:clear
# Set proper ownership
sudo chown -R www-data:www-data /var/www/barbershop
# Set directory permissions
sudo find /var/www/barbershop -type d -exec chmod 755 {} \;
sudo find /var/www/barbershop -type f -exec chmod 644 {} \;
# Set writable permissions for Laravel
sudo chmod -R 775 /var/www/barbershop/storage
sudo chmod -R 775 /var/www/barbershop/bootstrap/cache
Create Nginx server block:
sudo nano /etc/nginx/sites-available/barbershop
server {
listen 80;
server_name yourdomain.com www.yourdomain.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name yourdomain.com www.yourdomain.com;
root /var/www/barbershop/public;
# SSL Configuration
ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
# 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;
# Index and try files
index index.php;
charset utf-8;
# Main location block
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_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
fastcgi_hide_header X-Powered-By;
}
# Deny access to hidden files
location ~ /\. {
deny all;
}
# Asset optimization
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
expires 1y;
add_header Cache-Control "public, immutable";
try_files $uri =404;
}
# Gzip compression
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_proxied expired no-cache no-store private must-revalidate auth;
gzip_types
text/plain
text/css
text/xml
text/javascript
application/javascript
application/xml+rss
application/json;
# Client max body size for file uploads
client_max_body_size 100M;
# Rate limiting (optional)
limit_req_zone $binary_remote_addr zone=login:10m rate=5r/m;
location /admin {
limit_req zone=login burst=5 nodelay;
try_files $uri $uri/ /index.php?$query_string;
}
}
Enable the site:
# Enable the site
sudo ln -s /etc/nginx/sites-available/barbershop /etc/nginx/sites-enabled/
# Test Nginx configuration
sudo nginx -t
# Restart Nginx
sudo systemctl restart nginx
sudo systemctl enable nginx
If using Apache instead of Nginx:
sudo nano /etc/apache2/sites-available/barbershop.conf
<VirtualHost *:80>
ServerName yourdomain.com
ServerAlias www.yourdomain.com
Redirect permanent / https://yourdomain.com/
</VirtualHost>
<VirtualHost *:443>
ServerName yourdomain.com
ServerAlias www.yourdomain.com
DocumentRoot /var/www/barbershop/public
# SSL Configuration
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/yourdomain.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/yourdomain.com/privkey.pem
# Security Headers
Header always set X-Frame-Options "SAMEORIGIN"
Header always set X-Content-Type-Options "nosniff"
Header always set X-XSS-Protection "1; mode=block"
# Laravel Configuration
<Directory /var/www/barbershop/public>
AllowOverride All
Require all granted
</Directory>
# Log files
ErrorLog ${APACHE_LOG_DIR}/barbershop_error.log
CustomLog ${APACHE_LOG_DIR}/barbershop_access.log combined
</VirtualHost>
Enable modules and site:
# Enable required modules
sudo a2enmod rewrite ssl headers
# Enable the site
sudo a2ensite barbershop.conf
# Restart Apache
sudo systemctl restart apache2
sudo systemctl enable apache2
# Install Certbot
sudo apt install -y certbot python3-certbot-nginx
# Obtain SSL certificate
sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com
# Test auto-renewal
sudo certbot renew --dry-run
# Set up auto-renewal
echo "0 12 * * * /usr/bin/certbot renew --quiet" | sudo crontab -
# Install Redis
sudo apt install -y redis-server
# Configure Redis
sudo nano /etc/redis/redis.conf
# Set password (optional but recommended)
requirepass your_redis_password
# Restart Redis
sudo systemctl restart redis-server
sudo systemctl enable redis-server
Update .env
untuk Redis:
CACHE_DRIVER=redis
QUEUE_CONNECTION=redis
SESSION_DRIVER=redis
REDIS_PASSWORD=your_redis_password
sudo nano /etc/php/8.2/fpm/pool.d/www.conf
; Optimize for production
pm = dynamic
pm.max_children = 50
pm.start_servers = 10
pm.min_spare_servers = 5
pm.max_spare_servers = 20
pm.process_idle_timeout = 60s
pm.max_requests = 1000
; Security
security.limit_extensions = .php
# Restart PHP-FPM
sudo systemctl restart php8.2-fpm
sudo systemctl enable php8.2-fpm
-- Add production indexes untuk performance
USE barbershop_production;
-- Indexes untuk query yang sering digunakan
CREATE INDEX idx_users_email_verified ON users(email_verified_at);
CREATE INDEX idx_history_points_type_created ON history_points(type, created_at);
CREATE INDEX idx_reviews_created_at ON reviews(created_at DESC);
CREATE INDEX idx_reedem_codes_used_active ON reedem_codes(used_count, is_active, expires_at);
-- Optimize tables
OPTIMIZE TABLE users, history_points, reviews, stores, reedem_codes;
# Enable UFW firewall
sudo ufw enable
# Allow SSH (change port if not default)
sudo ufw allow 22/tcp
# Allow HTTP and HTTPS
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
# Allow MySQL (only from localhost)
sudo ufw allow from 127.0.0.1 to any port 3306
# Check status
sudo ufw status
# Install Fail2Ban
sudo apt install -y fail2ban
# Configure for Nginx
sudo nano /etc/fail2ban/jail.local
[DEFAULT]
bantime = 3600
findtime = 600
maxretry = 5
[nginx-http-auth]
enabled = true
filter = nginx-http-auth
port = http,https
logpath = /var/log/nginx/error.log
[nginx-limit-req]
enabled = true
filter = nginx-limit-req
port = http,https
logpath = /var/log/nginx/error.log
maxretry = 10
# Restart Fail2Ban
sudo systemctl restart fail2ban
sudo systemctl enable fail2ban
# Hide Nginx version
sudo nano /etc/nginx/nginx.conf
# Add in http block:
server_tokens off;
# Hide PHP version
sudo nano /etc/php/8.2/fpm/php.ini
# Set:
expose_php = Off
# Configure log rotation
sudo nano /etc/logrotate.d/barbershop
/var/www/barbershop/storage/logs/*.log {
daily
missingok
rotate 30
compress
notifempty
create 644 www-data www-data
postrotate
/bin/systemctl reload php8.2-fpm > /dev/null 2>&1 || true
endscript
}
# Install monitoring tools
sudo apt install -y htop iotop nethogs
# Monitor disk space
echo "0 6 * * * df -h | mail -s 'Disk Space Report' [email protected]" | sudo crontab -
# Monitor application logs
sudo nano /etc/logwatch/conf/logfiles/laravel.conf
Create health check endpoint:
// routes/web.php
Route::get('/health', function () {
return response()->json([
'status' => 'healthy',
'timestamp' => now(),
'database' => DB::connection()->getPdo() ? 'connected' : 'disconnected',
'cache' => Cache::store()->getStore() ? 'connected' : 'disconnected',
]);
});
sudo nano /usr/local/bin/backup-barbershop.sh
#!/bin/bash
# Configuration
DB_NAME="barbershop_production"
DB_USER="barbershop_user"
DB_PASS="strong_password_here"
BACKUP_DIR="/var/backups/barbershop"
DATE=$(date +%Y%m%d_%H%M%S)
# Create backup directory
mkdir -p $BACKUP_DIR
# Database backup
mysqldump -u $DB_USER -p$DB_PASS $DB_NAME | gzip > $BACKUP_DIR/db_backup_$DATE.sql.gz
# Application backup (exclude vendor and node_modules)
tar -czf $BACKUP_DIR/app_backup_$DATE.tar.gz \
--exclude='vendor' \
--exclude='node_modules' \
--exclude='storage/logs' \
--exclude='storage/framework/cache' \
-C /var/www barbershop
# Clean old backups (keep last 7 days)
find $BACKUP_DIR -name "*.gz" -mtime +7 -delete
echo "Backup completed: $DATE"
# Make executable
sudo chmod +x /usr/local/bin/backup-barbershop.sh
# Add to crontab (daily at 2 AM)
echo "0 2 * * * /usr/local/bin/backup-barbershop.sh" | sudo crontab -
# Install rclone for cloud backup
curl https://rclone.org/install.sh | sudo bash
# Configure cloud storage (example: Google Drive)
rclone config
# Add to backup script
rclone copy $BACKUP_DIR remote:barbershop-backups/
sudo nano /usr/local/bin/deploy-barbershop.sh
#!/bin/bash
# Configuration
APP_DIR="/var/www/barbershop"
BRANCH="main"
echo "Starting deployment..."
# Navigate to app directory
cd $APP_DIR
# Enable maintenance mode
php artisan down
# Pull latest changes
git pull origin $BRANCH
# Install/update dependencies
composer install --no-dev --optimize-autoloader
# Update Node.js dependencies and build assets
npm ci --only=production
npm run build
# Run database migrations
php artisan migrate --force
# Clear and cache config
php artisan config:cache
php artisan route:cache
php artisan view:cache
# Clear application cache
php artisan cache:clear
# Disable maintenance mode
php artisan up
echo "Deployment completed successfully!"
# Using symlinks for zero-downtime
sudo nano /usr/local/bin/zero-downtime-deploy.sh
#!/bin/bash
REPO_URL="https://github.com/luckydeva03/barbershop_app.git"
DEPLOY_DIR="/var/www/releases"
APP_DIR="/var/www/barbershop"
BRANCH="main"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
RELEASE_DIR="$DEPLOY_DIR/$TIMESTAMP"
# Create release directory
mkdir -p $RELEASE_DIR
# Clone repository
git clone $REPO_URL $RELEASE_DIR
cd $RELEASE_DIR
git checkout $BRANCH
# Copy .env from current release
cp $APP_DIR/.env $RELEASE_DIR/
# Install dependencies
composer install --no-dev --optimize-autoloader
npm ci --only=production
npm run build
# Run Laravel commands
php artisan migrate --force
php artisan config:cache
php artisan route:cache
php artisan view:cache
# Create symlink
ln -nfs $RELEASE_DIR /var/www/barbershop-new
mv /var/www/barbershop-new $APP_DIR
# Clean old releases (keep last 3)
cd $DEPLOY_DIR
ls -t | tail -n +4 | xargs rm -rf
echo "Zero-downtime deployment completed!"
# Install only for non-production environments
composer require laravel/telescope --dev
# Publish and migrate
php artisan telescope:install
php artisan migrate
Setup basic monitoring with:
- New Relic or Datadog for APM
- Uptime monitoring services
- Log aggregation with ELK stack or similar
# Check Laravel logs
tail -f /var/www/barbershop/storage/logs/laravel.log
# Check Nginx/Apache error logs
sudo tail -f /var/log/nginx/error.log
sudo tail -f /var/log/apache2/error.log
# Check PHP-FPM logs
sudo tail -f /var/log/php8.2-fpm.log
# Fix permissions
sudo chown -R www-data:www-data /var/www/barbershop
sudo chmod -R 775 /var/www/barbershop/storage
sudo chmod -R 775 /var/www/barbershop/bootstrap/cache
# Test database connection
php artisan tinker
DB::connection()->getPdo();
# Check MySQL status
sudo systemctl status mysql
# Enable query logging
# Add to .env
DB_LOG_QUERIES=true
# Monitor slow queries
sudo mysql -e "SHOW PROCESSLIST;"
# Check server resources
htop
iotop
- Check error logs
- Monitor disk space
- Verify backup completion
- Update system packages
- Review security logs
- Check SSL certificate expiry
- Update application dependencies
- Review performance metrics
- Test backup restoration
- Security audit
Congratulations! 🎉 Your Barbershop Management System is now running in production!
For ongoing maintenance and troubleshooting, refer to: