From 0b211915f16032469b52d93aa981dc2f2c4d88ce Mon Sep 17 00:00:00 2001 From: arifal Date: Wed, 11 Jun 2025 19:02:02 +0700 Subject: [PATCH] add update nginx config to domain and create production setup docker --- DOCKER-README.md | 73 +++---- ENVIRONMENT-SETUP.md | 276 ++++++++++++++++++++++++++ PRODUCTION-DEPLOYMENT.md | 360 ++++++++++++++++++++++++++++++++++ docker-compose.prod.yml | 40 +++- docker-deploy-prod.sh | 332 +++++++++++++++++++++++++++++++ docker-quick-setup.sh | 24 ++- docker-setup-env.sh | 233 ++++++++++++++++++++++ docker-ssl-setup.sh | 283 ++++++++++++++++++++++++++ docker-start.sh | 24 ++- docker/env.example | 44 +++-- docker/env.example.local | 64 ++++++ docker/env.example.production | 78 ++++++++ docker/nginx-proxy.conf | 142 ++++++++++++++ 13 files changed, 1899 insertions(+), 74 deletions(-) create mode 100644 ENVIRONMENT-SETUP.md create mode 100644 PRODUCTION-DEPLOYMENT.md create mode 100755 docker-deploy-prod.sh create mode 100755 docker-setup-env.sh create mode 100755 docker-ssl-setup.sh create mode 100644 docker/env.example.local create mode 100644 docker/env.example.production create mode 100644 docker/nginx-proxy.conf diff --git a/DOCKER-README.md b/DOCKER-README.md index 08eb2d5..933872c 100644 --- a/DOCKER-README.md +++ b/DOCKER-README.md @@ -23,9 +23,9 @@ Dokumentasi ini menjelaskan cara menjalankan aplikasi CKB menggunakan Docker unt ## Prerequisites -- Docker Engine 20.10+ -- Docker Compose 2.0+ -- Git +- Docker Engine 20.10+ +- Docker Compose 2.0+ +- Git ## Setup untuk Local Development @@ -46,19 +46,20 @@ ls ckb.sql ``` Script ini akan otomatis: -- Setup environment file -- Start semua containers -- Import database dari ckb.sql -- Generate application key -- Setup Laravel application + +- Setup environment file +- Start semua containers +- Import database dari ckb.sql +- Generate application key +- Setup Laravel application ### 2. Manual Setup Jika Anda ingin setup manual: ```bash -# Copy environment file -cp docker/env.example .env +# Setup local environment +./docker-setup-env.sh local # Start containers docker-compose up -d --build @@ -82,11 +83,11 @@ docker-compose up -d ### 3. Akses Aplikasi -- **Web Application**: http://localhost:8000 -- **Database (phpMyAdmin)**: http://localhost:8080 -- **Mail Testing (MailHog)**: http://localhost:8025 -- **MySQL Direct**: localhost:3306 -- **Redis**: localhost:6379 +- **Web Application**: http://localhost:8000 +- **Database (phpMyAdmin)**: http://localhost:8080 +- **Mail Testing (MailHog)**: http://localhost:8025 +- **MySQL Direct**: localhost:3306 +- **Redis**: localhost:6379 ### 4. Menjalankan Laravel Commands @@ -183,9 +184,10 @@ docker-compose -f docker-compose.prod.yml logs -f ### 2. Debugging dengan Xdebug (Development) Xdebug sudah dikonfigurasi untuk development environment: -- Port: 9003 -- IDE Key: PHPSTORM -- Host: host.docker.internal + +- Port: 9003 +- IDE Key: PHPSTORM +- Host: host.docker.internal ### 3. Monitoring Resources @@ -207,7 +209,7 @@ Untuk mengimport database dari file backup ckb.sql: # Import ke development environment ./docker-import-db.sh dev -# Import ke production environment +# Import ke production environment ./docker-import-db.sh prod # Import file SQL khusus @@ -215,11 +217,12 @@ Untuk mengimport database dari file backup ckb.sql: ``` Script import akan otomatis: -- Backup database yang sudah ada (safety) -- Drop dan recreate database -- Import data dari file SQL -- Jalankan migrations jika diperlukan -- Clear cache Laravel + +- Backup database yang sudah ada (safety) +- Drop dan recreate database +- Import data dari file SQL +- Jalankan migrations jika diperlukan +- Clear cache Laravel ### 2. Backup Database @@ -262,9 +265,10 @@ docker-compose build --no-cache --pull ``` **Common Build Errors:** -- **curl extension error**: Fixed dengan menambah `libcurl4-openssl-dev` dan `pkg-config` -- **gd extension error**: Pastikan `libfreetype6-dev` dan `libjpeg62-turbo-dev` terinstall -- **Out of space**: Jalankan `docker system prune -a -f` untuk cleanup + +- **curl extension error**: Fixed dengan menambah `libcurl4-openssl-dev` dan `pkg-config` +- **gd extension error**: Pastikan `libfreetype6-dev` dan `libjpeg62-turbo-dev` terinstall +- **Out of space**: Jalankan `docker system prune -a -f` untuk cleanup ### 2. Permission Issues @@ -345,9 +349,10 @@ docker-compose exec app php artisan cache:clear ``` **Common Redis Errors:** -- **Class Redis not found**: Fixed dengan install `pecl install redis` -- **Connection refused**: Pastikan Redis container berjalan -- **Config not loaded**: Jalankan `php artisan config:clear` + +- **Class Redis not found**: Fixed dengan install `pecl install redis` +- **Connection refused**: Pastikan Redis container berjalan +- **Config not loaded**: Jalankan `php artisan config:clear` ## Security Notes untuk Production @@ -371,9 +376,9 @@ docker-compose exec app composer install --optimize-autoloader --no-dev ### 2. Docker Optimizations -- Gunakan multi-stage builds untuk image yang lebih kecil -- Leverage Docker layer caching -- Optimize .dockerignore untuk build speed +- Gunakan multi-stage builds untuk image yang lebih kecil +- Leverage Docker layer caching +- Optimize .dockerignore untuk build speed ## Backup Strategy @@ -396,4 +401,4 @@ tar -czf "backup_${DATE}.tar.gz" backup_${DATE}.sql storage/ docker run --rm -v ckb_mysql_data:/data -v $(pwd):/backup alpine tar czf /backup/mysql_backup.tar.gz /data ``` -Untuk pertanyaan lebih lanjut atau issues, silakan buat issue di repository ini. \ No newline at end of file +Untuk pertanyaan lebih lanjut atau issues, silakan buat issue di repository ini. diff --git a/ENVIRONMENT-SETUP.md b/ENVIRONMENT-SETUP.md new file mode 100644 index 0000000..a22a094 --- /dev/null +++ b/ENVIRONMENT-SETUP.md @@ -0,0 +1,276 @@ +# Environment Setup Guide + +Panduan lengkap untuk setup environment file CKB Laravel Application dengan file template terpisah untuk local dan production. + +## ๐Ÿ“‚ File Structure + +``` +docker/ +โ”œโ”€โ”€ env.example.local # Template untuk local development +โ”œโ”€โ”€ env.example.production # Template untuk production +โ””โ”€โ”€ (env.example) # File lama, dapat dihapus +``` + +## ๐Ÿ”ง Quick Setup + +### Local Development + +```bash +# Setup environment untuk local development +./docker-setup-env.sh local + +# Atau manual copy +cp docker/env.example.local .env +``` + +### Production Deployment + +```bash +# Setup environment untuk production +./docker-setup-env.sh production + +# IMPORTANT: Edit .env dan ganti semua CHANGE_THIS_* values! +nano .env +``` + +## ๐Ÿ“‹ Template Comparison + +### ๐Ÿ  Local Development (`env.example.local`) + +| Setting | Value | Description | +| ------------------- | ----------------------- | ----------------------- | +| `APP_ENV` | `local` | Development environment | +| `APP_DEBUG` | `true` | Debug mode enabled | +| `APP_URL` | `http://localhost:8000` | Local URL | +| `LOG_LEVEL` | `debug` | Verbose logging | +| `DB_DATABASE` | `ckb_db` | Development database | +| `DB_USERNAME` | `root` | Simple credentials | +| `DB_PASSWORD` | `root` | Simple credentials | +| `REDIS_PASSWORD` | `null` | No password needed | +| `MAIL_HOST` | `mailhog` | Local mail testing | +| `QUEUE_CONNECTION` | `sync` | Synchronous queue | +| `TELESCOPE_ENABLED` | `true` | Debugging tool enabled | + +### ๐Ÿš€ Production (`env.example.production`) + +| Setting | Value | Description | +| ------------------- | ---------------------------------- | ----------------------- | +| `APP_ENV` | `production` | Production environment | +| `APP_DEBUG` | `false` | Debug mode disabled | +| `APP_URL` | `https://bengkel.digitaloasis.xyz` | Production domain | +| `LOG_LEVEL` | `error` | Error-only logging | +| `DB_DATABASE` | `ckb_production` | Production database | +| `DB_USERNAME` | `ckb_user` | Secure username | +| `DB_PASSWORD` | `CHANGE_THIS_*` | **Must be changed!** | +| `REDIS_PASSWORD` | `CHANGE_THIS_*` | **Must be changed!** | +| `MAIL_HOST` | `smtp.gmail.com` | Real SMTP server | +| `QUEUE_CONNECTION` | `redis` | Redis-based queue | +| `TELESCOPE_ENABLED` | `false` | Debugging tool disabled | + +## ๐Ÿ” Security Configuration for Production + +### Required Changes + +**MUST CHANGE** these values in production `.env`: + +```env +# Strong database passwords +DB_PASSWORD=your_super_secure_password_here +DB_ROOT_PASSWORD=your_root_password_here + +# Redis security +REDIS_PASSWORD=your_redis_password_here + +# Mail configuration +MAIL_USERNAME=your-email@domain.com +MAIL_PASSWORD=your-app-specific-password +``` + +### Optional but Recommended + +```env +# AWS S3 for file storage +AWS_ACCESS_KEY_ID=your-aws-key +AWS_SECRET_ACCESS_KEY=your-aws-secret + +# Real-time features +PUSHER_APP_ID=your-pusher-app-id +PUSHER_APP_KEY=your-pusher-key +PUSHER_APP_SECRET=your-pusher-secret +``` + +## ๐Ÿ› ๏ธ Environment Helper Script + +### Usage + +```bash +# Setup local environment +./docker-setup-env.sh local + +# Setup production environment +./docker-setup-env.sh production + +# Show current environment info +./docker-setup-env.sh +``` + +### Features + +- โœ… **Auto-backup** existing `.env` before changes +- โœ… **Environment validation** checks required variables +- โœ… **Security warnings** for production misconfiguration +- โœ… **Configuration summary** shows current settings +- โœ… **Next steps guidance** for deployment + +## ๐Ÿ“Š Environment Comparison + +### Local Development Features + +- ๐Ÿ› **Debug Mode**: Full error reporting and debugging tools +- ๐Ÿ“ง **MailHog**: Local email testing server +- ๐Ÿ—„๏ธ **Simple DB**: Basic MySQL credentials +- ๐Ÿ”“ **No SSL**: HTTP-only for speed +- ๐Ÿงช **Development Tools**: Telescope, Debugbar enabled +- โšก **Sync Queue**: Immediate processing for testing + +### Production Features + +- ๐Ÿ”’ **Security First**: Strong passwords and encryption +- ๐Ÿ“ง **Real SMTP**: Professional email delivery +- ๐Ÿ—„๏ธ **Secure DB**: Production-grade credentials +- ๐Ÿ” **SSL/HTTPS**: Let's Encrypt certificates +- ๐Ÿ“Š **Monitoring**: Error-only logging +- ๐Ÿš€ **Redis Queue**: Background job processing + +## ๐Ÿšจ Common Issues & Solutions + +### 1. "CHANGE*THIS*\*" Values in Production + +**Problem**: Forgot to change template values + +```bash +# Check for remaining template values +grep "CHANGE_THIS" .env +``` + +**Solution**: + +```bash +# Use the helper script to check +./docker-setup-env.sh +# It will warn about CHANGE_THIS_* values +``` + +### 2. Wrong Environment File + +**Problem**: Using local config in production + +```bash +# Check current environment +grep "APP_ENV=" .env +``` + +**Solution**: + +```bash +# Recreate with correct template +./docker-setup-env.sh production +``` + +### 3. Missing Environment Variables + +**Problem**: Laravel errors about missing config + +```bash +# Validate current .env +./docker-setup-env.sh validate +``` + +**Solution**: Check required variables list and add missing ones + +## ๐Ÿ“ Environment Variables Reference + +### Core Application + +```env +APP_NAME="CKB Bengkel System" +APP_ENV=production|local +APP_KEY=base64:... +APP_DEBUG=true|false +APP_URL=https://domain.com +``` + +### Database + +```env +DB_CONNECTION=mysql +DB_HOST=db +DB_PORT=3306 +DB_DATABASE=ckb_production|ckb_db +DB_USERNAME=username +DB_PASSWORD=password +DB_ROOT_PASSWORD=root_password +``` + +### Cache & Session + +```env +REDIS_HOST=redis +REDIS_PASSWORD=password|null +REDIS_PORT=6379 +CACHE_DRIVER=redis +SESSION_DRIVER=redis +QUEUE_CONNECTION=redis|sync +``` + +### Mail Configuration + +```env +MAIL_MAILER=smtp +MAIL_HOST=smtp.domain.com +MAIL_PORT=587 +MAIL_USERNAME=email@domain.com +MAIL_PASSWORD=password +MAIL_ENCRYPTION=tls +MAIL_FROM_ADDRESS=noreply@domain.com +MAIL_FROM_NAME="${APP_NAME}" +``` + +### Security + +```env +TRUSTED_PROXIES=* +SESSION_SECURE_COOKIE=true +SESSION_SAME_SITE=strict +``` + +## ๐Ÿ”„ Migration Guide + +### From Old Single Template + +If you're migrating from the old `docker/env.example`: + +```bash +# Backup current .env +cp .env .env.backup + +# Choose appropriate template +./docker-setup-env.sh local # for development +./docker-setup-env.sh production # for production + +# Compare and migrate custom settings +diff .env.backup .env +``` + +## ๐Ÿ“ž Support + +For environment setup issues: + +- **Documentation**: This file +- **Helper Script**: `./docker-setup-env.sh` +- **Validation**: Built-in security checks +- **Backup**: Automatic .env backup before changes + +--- + +**๐Ÿ’ก Pro Tip**: Always use the helper script `./docker-setup-env.sh` instead of manual copying to ensure proper configuration and security checks! diff --git a/PRODUCTION-DEPLOYMENT.md b/PRODUCTION-DEPLOYMENT.md new file mode 100644 index 0000000..7ffd557 --- /dev/null +++ b/PRODUCTION-DEPLOYMENT.md @@ -0,0 +1,360 @@ +# CKB Production Deployment Guide + +Panduan deployment aplikasi CKB Laravel ke production server dengan domain `bengkel.digitaloasis.xyz`. + +## ๐Ÿš€ Quick Start + +### 1. Deploy ke Production + +```bash +# Full deployment (recommended untuk pertama kali) +./docker-deploy-prod.sh deploy + +# Hanya build containers +./docker-deploy-prod.sh build + +# Setup SSL certificate +./docker-deploy-prod.sh ssl + +# Check deployment status +./docker-deploy-prod.sh status +``` + +### 2. Akses Aplikasi + +- **Domain**: https://bengkel.digitaloasis.xyz +- **Health Check**: https://bengkel.digitaloasis.xyz/health + +## ๐Ÿ“‹ Prerequisites + +### Server Requirements + +- **OS**: Ubuntu 20.04+ atau CentOS 7+ +- **Memory**: Minimum 2GB RAM (4GB recommended) +- **Storage**: Minimum 20GB SSD +- **Docker**: Version 20.10+ +- **Docker Compose**: Version 2.0+ + +### Domain Setup + +1. **DNS Configuration**: + + ``` + A Record: bengkel.digitaloasis.xyz โ†’ [Server IP] + CNAME: www.bengkel.digitaloasis.xyz โ†’ bengkel.digitaloasis.xyz + ``` + +2. **Firewall Configuration**: + + ```bash + # Allow HTTP/HTTPS traffic + sudo ufw allow 80/tcp + sudo ufw allow 443/tcp + + # Allow SSH (if needed) + sudo ufw allow 22/tcp + ``` + +## ๐Ÿ›ก๏ธ Security Configuration + +### 1. Environment Variables + +Edit `.env` file untuk production: + +```env +# Application +APP_ENV=production +APP_DEBUG=false +APP_URL=https://bengkel.digitaloasis.xyz +APP_KEY=base64:... + +# Database (GANTI dengan credentials yang aman!) +DB_HOST=db +DB_DATABASE=ckb_production +DB_USERNAME=ckb_user +DB_PASSWORD=secure_password_here +DB_ROOT_PASSWORD=secure_root_password_here + +# Redis +REDIS_HOST=redis +REDIS_PASSWORD=secure_redis_password + +# Mail +MAIL_MAILER=smtp +MAIL_HOST=your-smtp-host +MAIL_PORT=587 +MAIL_USERNAME=your-email@domain.com +MAIL_PASSWORD=your-email-password +MAIL_ENCRYPTION=tls + +# Session & Cache +SESSION_DRIVER=redis +CACHE_DRIVER=redis +QUEUE_CONNECTION=redis + +# Trusted Proxies +TRUSTED_PROXIES=* +``` + +### 2. Database Security + +```bash +# Setelah deployment, jalankan MySQL secure installation +docker-compose -f docker-compose.prod.yml exec db mysql_secure_installation +``` + +## ๐Ÿ”ง Deployment Process + +### Manual Step-by-Step + +1. **Persiapan Server**: + + ```bash + # Update system + sudo apt update && sudo apt upgrade -y + + # Install Docker + curl -fsSL https://get.docker.com -o get-docker.sh + sudo sh get-docker.sh + + # Install Docker Compose + sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose + sudo chmod +x /usr/local/bin/docker-compose + ``` + +2. **Clone Repository**: + + ```bash + git clone https://github.com/your-repo/ckb.git + cd ckb + ``` + +3. **Setup Environment**: + + ```bash + # For production environment + ./docker-setup-env.sh production + + # Edit production settings (IMPORTANT!) + nano .env + # Change all CHANGE_THIS_* values with secure passwords + ``` + +4. **Deploy Application**: + + ```bash + ./docker-deploy-prod.sh deploy + ``` + +5. **Setup SSL Certificate**: + ```bash + ./docker-deploy-prod.sh ssl + ``` + +## ๐Ÿ“Š Monitoring & Maintenance + +### 1. Health Checks + +```bash +# Check application status +./docker-deploy-prod.sh status + +# Check specific service logs +docker-compose -f docker-compose.prod.yml logs -f app +docker-compose -f docker-compose.prod.yml logs -f nginx-proxy +docker-compose -f docker-compose.prod.yml logs -f db +``` + +### 2. Database Backup + +```bash +# Manual backup +docker-compose -f docker-compose.prod.yml exec -T db mysqldump -u root -p"$DB_ROOT_PASSWORD" ckb_production > backup_$(date +%Y%m%d).sql + +# Automated backup (add to crontab) +0 2 * * * /path/to/ckb/docker-backup.sh +``` + +### 3. SSL Certificate Renewal + +Certificate akan otomatis renewal. Untuk manual renewal: + +```bash +# Test renewal +docker-compose -f docker-compose.prod.yml run --rm certbot renew --dry-run + +# Manual renewal +./docker-ssl-renew.sh + +# Setup auto-renewal (add to crontab) +0 12 * * * /path/to/ckb/docker-ssl-renew.sh +``` + +## ๐Ÿ” Troubleshooting + +### Common Issues + +1. **Application Not Loading**: + + ```bash + # Check container status + docker-compose -f docker-compose.prod.yml ps + + # Check application logs + docker-compose -f docker-compose.prod.yml logs app + + # Restart application + docker-compose -f docker-compose.prod.yml restart app + ``` + +2. **SSL Certificate Issues**: + + ```bash + # Check certificate status + openssl s_client -connect bengkel.digitaloasis.xyz:443 -servername bengkel.digitaloasis.xyz + + # Re-setup SSL + ./docker-ssl-setup.sh + ``` + +3. **Database Connection Issues**: + + ```bash + # Check database logs + docker-compose -f docker-compose.prod.yml logs db + + # Test database connection + docker-compose -f docker-compose.prod.yml exec app php artisan tinker + >>> DB::connection()->getPdo(); + ``` + +4. **Permission Issues**: + ```bash + # Fix Laravel permissions + ./docker-fix-permissions.sh prod + ``` + +### Performance Issues + +```bash +# Check resource usage +docker stats + +# Clean up Docker system +docker system prune -a -f + +# Optimize Laravel +docker-compose -f docker-compose.prod.yml exec app php artisan optimize +``` + +## ๐Ÿšฆ Load Testing + +Before going live, test your application: + +```bash +# Install testing tools +sudo apt install apache2-utils + +# Basic load test +ab -n 1000 -c 10 https://bengkel.digitaloasis.xyz/ + +# More comprehensive testing with siege +sudo apt install siege +siege -c 25 -t 60s https://bengkel.digitaloasis.xyz/ +``` + +## ๐Ÿ“ˆ Performance Optimization + +### 1. Laravel Optimizations + +```bash +# Run after each deployment +docker-compose -f docker-compose.prod.yml exec app php artisan config:cache +docker-compose -f docker-compose.prod.yml exec app php artisan route:cache +docker-compose -f docker-compose.prod.yml exec app php artisan view:cache +docker-compose -f docker-compose.prod.yml exec app composer install --optimize-autoloader --no-dev +``` + +### 2. Database Optimization + +```bash +# MySQL tuning +docker-compose -f docker-compose.prod.yml exec db mysql -u root -p -e " + SET GLOBAL innodb_buffer_pool_size = 1073741824; + SET GLOBAL query_cache_size = 67108864; + SET GLOBAL query_cache_type = 1; +" +``` + +### 3. Nginx Optimization + +Edit `docker/nginx-proxy.conf` untuk mengoptimalkan: + +- Gzip compression +- Browser caching +- Connection pooling + +## ๐Ÿ”„ Updates & Maintenance + +### Application Updates + +```bash +# Pull latest code +git pull origin main + +# Backup before update +./docker-deploy-prod.sh backup + +# Deploy updates +./docker-deploy-prod.sh deploy +``` + +### Security Updates + +```bash +# Update base images +docker-compose -f docker-compose.prod.yml pull + +# Rebuild with latest security patches +./docker-deploy-prod.sh build +``` + +## ๐Ÿ“ž Support & Contact + +Untuk bantuan deployment atau issues: + +- **Email**: admin@digitaloasis.xyz +- **Documentation**: https://github.com/your-repo/ckb/docs +- **Issues**: https://github.com/your-repo/ckb/issues + +## ๐Ÿ“„ File Structure + +``` +ckb/ +โ”œโ”€โ”€ docker/ +โ”‚ โ”œโ”€โ”€ nginx-proxy.conf # Main nginx configuration +โ”‚ โ”œโ”€โ”€ nginx-temp.conf # Temporary config for SSL setup +โ”‚ โ”œโ”€โ”€ env.example # Environment template +โ”‚ โ””โ”€โ”€ ... +โ”œโ”€โ”€ docker-compose.prod.yml # Production compose file +โ”œโ”€โ”€ docker-deploy-prod.sh # Main deployment script +โ”œโ”€โ”€ docker-ssl-setup.sh # SSL certificate setup +โ”œโ”€โ”€ docker-ssl-renew.sh # SSL renewal script +โ””โ”€โ”€ PRODUCTION-DEPLOYMENT.md # This file +``` + +## โœ… Production Checklist + +- [ ] Domain DNS configured +- [ ] Firewall rules configured +- [ ] .env file configured with production values +- [ ] Database credentials changed from defaults +- [ ] SSL certificate obtained and configured +- [ ] Backup system configured +- [ ] Monitoring setup +- [ ] Load testing completed +- [ ] Security audit completed + +--- + +**๐Ÿšจ Remember**: Always test in staging environment before deploying to production! diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml index 08a9533..1bcf611 100644 --- a/docker-compose.prod.yml +++ b/docker-compose.prod.yml @@ -10,11 +10,11 @@ services: - ./storage:/var/www/html/storage - ./bootstrap/cache:/var/www/html/bootstrap/cache - ./docker/php.ini:/usr/local/etc/php/conf.d/local.ini - ports: - - "80:80" environment: - APP_ENV=production - APP_DEBUG=false + - APP_URL=https://bengkel.digitaloasis.xyz + - TRUSTED_PROXIES=* depends_on: - db - redis @@ -34,8 +34,8 @@ services: volumes: - mysql_data:/var/lib/mysql - ./docker/mysql.cnf:/etc/mysql/conf.d/mysql.cnf:ro - ports: - - "3306:3306" + expose: + - "3306" networks: - ckb-network command: --default-authentication-plugin=mysql_native_password @@ -47,8 +47,8 @@ services: command: redis-server --appendonly yes ${REDIS_PASSWORD:+--requirepass $REDIS_PASSWORD} volumes: - redis_data:/data - ports: - - "6379:6379" + expose: + - "6379" networks: - ckb-network @@ -57,20 +57,44 @@ services: container_name: ckb-nginx-proxy restart: unless-stopped ports: + - "80:80" - "443:443" volumes: - - ./docker/nginx-proxy.conf:/etc/nginx/nginx.conf - - ./docker/ssl:/etc/nginx/ssl + - ./docker/nginx-proxy.conf:/etc/nginx/nginx.conf:ro + - ssl_certificates:/etc/nginx/ssl:ro + - certbot_www:/var/www/certbot:ro + - nginx_logs:/var/log/nginx depends_on: - app networks: - ckb-network + environment: + - DOMAIN=bengkel.digitaloasis.xyz + + certbot: + image: certbot/certbot + container_name: ckb-certbot + restart: "no" + volumes: + - ssl_certificates:/etc/letsencrypt + - certbot_www:/var/www/certbot + command: certonly --webroot --webroot-path=/var/www/certbot --email admin@digitaloasis.xyz --agree-tos --no-eff-email -d bengkel.digitaloasis.xyz -d www.bengkel.digitaloasis.xyz + depends_on: + - nginx-proxy + networks: + - ckb-network volumes: mysql_data: driver: local redis_data: driver: local + ssl_certificates: + driver: local + certbot_www: + driver: local + nginx_logs: + driver: local networks: ckb-network: diff --git a/docker-deploy-prod.sh b/docker-deploy-prod.sh new file mode 100755 index 0000000..81b096d --- /dev/null +++ b/docker-deploy-prod.sh @@ -0,0 +1,332 @@ +#!/bin/bash + +# Script untuk deploy CKB Laravel Application ke production dengan domain bengkel.digitaloasis.xyz +# Usage: ./docker-deploy-prod.sh [build|deploy|ssl|status] + +set -e + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Configuration +DOMAIN="bengkel.digitaloasis.xyz" +EMAIL="admin@digitaloasis.xyz" +COMPOSE_FILE="docker-compose.prod.yml" +ENV_FILE=".env" + +# Default action +ACTION="deploy" + +# Parse arguments +while [[ $# -gt 0 ]]; do + case $1 in + build) + ACTION="build" + shift + ;; + deploy) + ACTION="deploy" + shift + ;; + ssl) + ACTION="ssl" + shift + ;; + status) + ACTION="status" + shift + ;; + *) + echo "Unknown option $1" + echo "Usage: $0 [build|deploy|ssl|status]" + exit 1 + ;; + esac +done + +# Function to print colored output +print_status() { + echo -e "${BLUE}[INFO]${NC} $1" +} + +print_success() { + echo -e "${GREEN}[SUCCESS]${NC} $1" +} + +print_warning() { + echo -e "${YELLOW}[WARNING]${NC} $1" +} + +print_error() { + echo -e "${RED}[ERROR]${NC} $1" +} + +# Function to check prerequisites +check_prerequisites() { + print_status "Checking prerequisites..." + + # Check Docker + if ! docker info > /dev/null 2>&1; then + print_error "Docker is not running. Please start Docker first." + exit 1 + fi + + # Check Docker Compose + if ! docker-compose --version > /dev/null 2>&1; then + print_error "Docker Compose is not installed." + exit 1 + fi + + # Check if .env file exists + if [[ ! -f $ENV_FILE ]]; then + print_warning "Environment file not found. Creating from production template..." + if [[ -f docker/env.example.production ]]; then + cp docker/env.example.production $ENV_FILE + print_warning "โš ๏ธ IMPORTANT: Edit $ENV_FILE and change all CHANGE_THIS_* passwords before continuing!" + print_status "Production template copied. Please configure:" + echo " - DB_PASSWORD and DB_ROOT_PASSWORD" + echo " - REDIS_PASSWORD" + echo " - MAIL_* settings" + echo " - AWS_* settings (if using S3)" + exit 1 + else + print_error "Production environment template not found: docker/env.example.production" + exit 1 + fi + fi + + print_success "Prerequisites check passed!" +} + +# Function to setup production environment +setup_production_env() { + print_status "Setting up production environment variables..." + + # Update .env for production + sed -i "s|APP_ENV=.*|APP_ENV=production|g" $ENV_FILE + sed -i "s|APP_DEBUG=.*|APP_DEBUG=false|g" $ENV_FILE + sed -i "s|APP_URL=.*|APP_URL=https://$DOMAIN|g" $ENV_FILE + + # Check if database credentials are set + if grep -q "DB_PASSWORD=password" $ENV_FILE; then + print_warning "Please update database credentials in $ENV_FILE for production!" + print_warning "Current settings are for development only." + fi + + print_success "Production environment configured!" +} + +# Function to build containers +build_containers() { + print_status "Building production containers..." + + # Pull latest images + docker-compose -f $COMPOSE_FILE pull + + # Build application container + docker-compose -f $COMPOSE_FILE build --no-cache app + + print_success "Containers built successfully!" +} + +# Function to deploy application +deploy_application() { + print_status "Deploying CKB Laravel Application to production..." + + # Stop existing containers + print_status "Stopping existing containers..." + docker-compose -f $COMPOSE_FILE down || true + + # Start database and redis first + print_status "Starting database and Redis..." + docker-compose -f $COMPOSE_FILE up -d db redis + + # Wait for database to be ready + print_status "Waiting for database to be ready..." + sleep 20 + + # Start application + print_status "Starting application..." + docker-compose -f $COMPOSE_FILE up -d app + + # Wait for application to be ready + sleep 15 + + # Run Laravel setup commands + print_status "Running Laravel setup commands..." + docker-compose -f $COMPOSE_FILE exec -T app php artisan key:generate --force || true + docker-compose -f $COMPOSE_FILE exec -T app php artisan migrate --force + docker-compose -f $COMPOSE_FILE exec -T app php artisan config:cache + docker-compose -f $COMPOSE_FILE exec -T app php artisan route:cache + docker-compose -f $COMPOSE_FILE exec -T app php artisan view:cache + docker-compose -f $COMPOSE_FILE exec -T app php artisan storage:link || true + + # Start nginx proxy + print_status "Starting nginx proxy..." + docker-compose -f $COMPOSE_FILE up -d nginx-proxy + + print_success "Application deployed successfully!" +} + +# Function to setup SSL +setup_ssl() { + print_status "Setting up SSL certificate..." + + if [[ -f docker-ssl-setup.sh ]]; then + chmod +x docker-ssl-setup.sh + ./docker-ssl-setup.sh + else + print_error "SSL setup script not found!" + exit 1 + fi +} + +# Function to show deployment status +show_status() { + print_status "CKB Production Deployment Status" + echo "================================================" + + # Show container status + print_status "Container Status:" + docker-compose -f $COMPOSE_FILE ps + echo "" + + # Show application health + print_status "Application Health:" + if curl -s --max-time 10 http://localhost/health > /dev/null 2>&1; then + print_success "โœ… Application is responding on HTTP" + else + print_warning "โŒ Application not responding on HTTP" + fi + + if curl -s --max-time 10 https://$DOMAIN/health > /dev/null 2>&1; then + print_success "โœ… Application is responding on HTTPS" + else + print_warning "โŒ Application not responding on HTTPS" + fi + + # Show SSL certificate status + print_status "SSL Certificate Status:" + if openssl s_client -connect $DOMAIN:443 -servername $DOMAIN < /dev/null 2>/dev/null | openssl x509 -noout -dates 2>/dev/null; then + print_success "โœ… SSL certificate is active" + else + print_warning "โŒ SSL certificate not found or invalid" + fi + + # Show disk usage + print_status "Docker Disk Usage:" + docker system df + echo "" + + # Show logs summary + print_status "Recent Application Logs:" + docker-compose -f $COMPOSE_FILE logs --tail=10 app || true + + echo "" + print_status "Access URLs:" + echo " ๐ŸŒ Application: https://$DOMAIN" + echo " ๐Ÿ” Health Check: https://$DOMAIN/health" + echo "" + + print_status "Useful Commands:" + echo " - View logs: docker-compose -f $COMPOSE_FILE logs -f [service]" + echo " - Enter container: docker-compose -f $COMPOSE_FILE exec app bash" + echo " - Update SSL: ./docker-ssl-setup.sh" + echo " - Restart app: docker-compose -f $COMPOSE_FILE restart app" +} + +# Function to backup before deployment +backup_before_deploy() { + print_status "Creating backup before deployment..." + + BACKUP_DIR="backups/$(date +%Y%m%d_%H%M%S)" + mkdir -p $BACKUP_DIR + + # Backup database + if docker-compose -f $COMPOSE_FILE ps db | grep -q "Up"; then + print_status "Backing up database..." + docker-compose -f $COMPOSE_FILE exec -T db mysqldump -u root -p"${DB_ROOT_PASSWORD:-rootpassword}" "${DB_DATABASE:-ckb_production}" > "$BACKUP_DIR/database.sql" + print_success "Database backed up to $BACKUP_DIR/database.sql" + fi + + # Backup storage + if [[ -d storage ]]; then + print_status "Backing up storage directory..." + tar -czf "$BACKUP_DIR/storage.tar.gz" storage/ + print_success "Storage backed up to $BACKUP_DIR/storage.tar.gz" + fi + + # Backup environment + if [[ -f $ENV_FILE ]]; then + cp $ENV_FILE "$BACKUP_DIR/env.backup" + print_success "Environment backed up to $BACKUP_DIR/env.backup" + fi + + print_success "Backup completed in $BACKUP_DIR" +} + +# Function to optimize for production +optimize_production() { + print_status "Optimizing application for production..." + + # Laravel optimizations + docker-compose -f $COMPOSE_FILE exec -T app composer install --optimize-autoloader --no-dev --no-interaction + docker-compose -f $COMPOSE_FILE exec -T app php artisan config:cache + docker-compose -f $COMPOSE_FILE exec -T app php artisan route:cache + docker-compose -f $COMPOSE_FILE exec -T app php artisan view:cache + + # Clean up Docker + docker system prune -f + + print_success "Production optimization completed!" +} + +# Main execution +echo "================================================" +print_status "๐Ÿš€ CKB Production Deployment Script" +print_status "Domain: $DOMAIN" +print_status "Action: $ACTION" +echo "================================================" +echo "" + +# Check prerequisites +check_prerequisites + +case $ACTION in + build) + print_status "Building containers only..." + build_containers + print_success "โœ… Build completed!" + ;; + + deploy) + print_status "Full deployment process..." + backup_before_deploy + setup_production_env + build_containers + deploy_application + optimize_production + print_success "โœ… Deployment completed!" + echo "" + print_status "Next steps:" + echo "1. Setup SSL certificate: ./docker-deploy-prod.sh ssl" + echo "2. Check status: ./docker-deploy-prod.sh status" + ;; + + ssl) + print_status "Setting up SSL certificate..." + setup_ssl + print_success "โœ… SSL setup completed!" + ;; + + status) + show_status + ;; +esac + +echo "" +print_success "โœ… Production deployment script completed!" \ No newline at end of file diff --git a/docker-quick-setup.sh b/docker-quick-setup.sh index 929f71a..cf1ef03 100755 --- a/docker-quick-setup.sh +++ b/docker-quick-setup.sh @@ -62,13 +62,25 @@ check_docker() { # Function to setup environment file setup_env() { if [[ ! -f .env ]]; then - if [[ -f docker/env.example ]]; then - print_status "Setting up environment file..." - cp docker/env.example .env - print_success "Environment file created: .env" + if [[ $ENVIRONMENT == "dev" ]]; then + if [[ -f docker/env.example.local ]]; then + print_status "Setting up local development environment file..." + cp docker/env.example.local .env + print_success "Local environment file created: .env" + else + print_error "Local environment template not found: docker/env.example.local" + exit 1 + fi else - print_error "No environment template found." - exit 1 + if [[ -f docker/env.example.production ]]; then + print_status "Setting up production environment file..." + cp docker/env.example.production .env + print_success "Production environment file created: .env" + print_warning "โš ๏ธ IMPORTANT: Edit .env and change all CHANGE_THIS_* passwords!" + else + print_error "Production environment template not found: docker/env.example.production" + exit 1 + fi fi else print_status "Environment file already exists: .env" diff --git a/docker-setup-env.sh b/docker-setup-env.sh new file mode 100755 index 0000000..5ce3c8f --- /dev/null +++ b/docker-setup-env.sh @@ -0,0 +1,233 @@ +#!/bin/bash + +# Script untuk setup environment file +# Usage: ./docker-setup-env.sh [local|production] + +set -e + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Default environment +ENVIRONMENT="local" + +# Parse arguments +while [[ $# -gt 0 ]]; do + case $1 in + local|dev|development) + ENVIRONMENT="local" + shift + ;; + prod|production) + ENVIRONMENT="production" + shift + ;; + *) + echo "Unknown option $1" + echo "Usage: $0 [local|production]" + exit 1 + ;; + esac +done + +# Function to print colored output +print_status() { + echo -e "${BLUE}[INFO]${NC} $1" +} + +print_success() { + echo -e "${GREEN}[SUCCESS]${NC} $1" +} + +print_warning() { + echo -e "${YELLOW}[WARNING]${NC} $1" +} + +print_error() { + echo -e "${RED}[ERROR]${NC} $1" +} + +# Function to backup existing .env +backup_existing_env() { + if [[ -f .env ]]; then + local backup_name=".env.backup.$(date +%Y%m%d_%H%M%S)" + print_status "Backing up existing .env to $backup_name" + cp .env "$backup_name" + print_success "Backup created: $backup_name" + fi +} + +# Function to setup local environment +setup_local_env() { + print_status "Setting up LOCAL development environment..." + + if [[ -f docker/env.example.local ]]; then + backup_existing_env + cp docker/env.example.local .env + print_success "โœ… Local environment file created!" + echo "" + print_status "Local Development Configuration:" + echo " ๐ŸŒ App URL: http://localhost:8000" + echo " ๐Ÿ—„๏ธ Database: ckb_db (MySQL)" + echo " ๐Ÿ“ง Mail: MailHog (http://localhost:8025)" + echo " ๐Ÿ”ด Redis: Session & Cache" + echo " ๐Ÿ› Debug: Enabled" + echo "" + print_status "Services will be available at:" + echo " - Web App: http://localhost:8000" + echo " - phpMyAdmin: http://localhost:8080" + echo " - MailHog: http://localhost:8025" + echo "" + print_success "Ready for local development! Run: ./docker-quick-setup.sh dev" + else + print_error "Local environment template not found: docker/env.example.local" + exit 1 + fi +} + +# Function to setup production environment +setup_production_env() { + print_status "Setting up PRODUCTION environment..." + + if [[ -f docker/env.example.production ]]; then + backup_existing_env + cp docker/env.example.production .env + print_success "โœ… Production environment file created!" + echo "" + print_warning "๐Ÿšจ SECURITY CONFIGURATION REQUIRED!" + echo "" + print_status "You MUST change these settings in .env file:" + echo " ๐Ÿ” DB_PASSWORD=CHANGE_THIS_SECURE_PASSWORD" + echo " ๐Ÿ” DB_ROOT_PASSWORD=CHANGE_THIS_ROOT_PASSWORD" + echo " ๐Ÿ” REDIS_PASSWORD=CHANGE_THIS_REDIS_PASSWORD" + echo "" + print_status "Optional but recommended configurations:" + echo " ๐Ÿ“ง MAIL_HOST, MAIL_USERNAME, MAIL_PASSWORD" + echo " โ˜๏ธ AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY (for S3)" + echo " ๐Ÿ“ก PUSHER_* settings (for real-time features)" + echo "" + print_status "Production Configuration:" + echo " ๐ŸŒ App URL: https://bengkel.digitaloasis.xyz" + echo " ๐Ÿ—„๏ธ Database: ckb_production (MySQL)" + echo " ๐Ÿ“ง Mail: SMTP (configure in .env)" + echo " ๐Ÿ”ด Redis: Session, Cache & Queue" + echo " ๐Ÿ› Debug: Disabled" + echo " ๐Ÿ”’ SSL: Let's Encrypt" + echo "" + print_warning "Next steps:" + echo "1. Edit .env file and change all CHANGE_THIS_* values" + echo "2. Run: ./docker-deploy-prod.sh deploy" + echo "3. Run: ./docker-deploy-prod.sh ssl" + else + print_error "Production environment template not found: docker/env.example.production" + exit 1 + fi +} + +# Function to show current environment info +show_current_env() { + if [[ -f .env ]]; then + print_status "Current Environment Information:" + echo "" + + # Detect environment type + local app_env=$(grep "^APP_ENV=" .env | cut -d '=' -f2) + local app_url=$(grep "^APP_URL=" .env | cut -d '=' -f2) + local app_debug=$(grep "^APP_DEBUG=" .env | cut -d '=' -f2) + local db_host=$(grep "^DB_HOST=" .env | cut -d '=' -f2) + local db_name=$(grep "^DB_DATABASE=" .env | cut -d '=' -f2) + + echo " Environment: $app_env" + echo " App URL: $app_url" + echo " Debug Mode: $app_debug" + echo " Database Host: $db_host" + echo " Database Name: $db_name" + echo "" + + # Check for security issues in production + if [[ "$app_env" == "production" ]]; then + print_status "Security Check:" + if grep -q "CHANGE_THIS" .env; then + print_error "โŒ Found CHANGE_THIS_* values in production .env!" + print_warning "Please update all CHANGE_THIS_* values with secure passwords." + else + print_success "โœ… No CHANGE_THIS_* values found." + fi + + if [[ "$app_debug" == "true" ]]; then + print_error "โŒ Debug mode is enabled in production!" + print_warning "Set APP_DEBUG=false for production." + else + print_success "โœ… Debug mode is disabled." + fi + fi + else + print_status "No .env file found." + fi +} + +# Function to validate environment file +validate_env() { + if [[ ! -f .env ]]; then + print_error "No .env file found!" + return 1 + fi + + print_status "Validating environment file..." + + # Required variables + local required_vars=("APP_NAME" "APP_ENV" "APP_URL" "DB_HOST" "DB_DATABASE" "DB_USERNAME" "DB_PASSWORD") + local missing_vars=() + + for var in "${required_vars[@]}"; do + if ! grep -q "^${var}=" .env; then + missing_vars+=("$var") + fi + done + + if [[ ${#missing_vars[@]} -gt 0 ]]; then + print_error "Missing required environment variables:" + for var in "${missing_vars[@]}"; do + echo " - $var" + done + return 1 + fi + + print_success "โœ… Environment file validation passed!" + return 0 +} + +# Main execution +echo "================================================" +print_status "๐Ÿ”ง CKB Environment Setup Helper" +print_status "Target Environment: $ENVIRONMENT" +echo "================================================" +echo "" + +case $ENVIRONMENT in + local) + setup_local_env + ;; + production) + setup_production_env + ;; +esac + +echo "" +print_status "Environment file setup completed!" +echo "" + +# Show current environment info +show_current_env + +echo "" +print_status "Available commands:" +echo " - Show current env: ./docker-setup-env.sh" +echo " - Setup local: ./docker-setup-env.sh local" +echo " - Setup production: ./docker-setup-env.sh production" +echo " - Quick local setup: ./docker-quick-setup.sh dev" +echo " - Production deploy: ./docker-deploy-prod.sh deploy" \ No newline at end of file diff --git a/docker-ssl-setup.sh b/docker-ssl-setup.sh new file mode 100755 index 0000000..efd02d3 --- /dev/null +++ b/docker-ssl-setup.sh @@ -0,0 +1,283 @@ +#!/bin/bash + +# Script untuk setup SSL certificate dengan Let's Encrypt untuk domain bengkel.digitaloasis.xyz +# Usage: ./docker-ssl-setup.sh + +set -e + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Configuration +DOMAIN="bengkel.digitaloasis.xyz" +WWW_DOMAIN="www.bengkel.digitaloasis.xyz" +EMAIL="admin@digitaloasis.xyz" +COMPOSE_FILE="docker-compose.prod.yml" + +# Function to print colored output +print_status() { + echo -e "${BLUE}[INFO]${NC} $1" +} + +print_success() { + echo -e "${GREEN}[SUCCESS]${NC} $1" +} + +print_warning() { + echo -e "${YELLOW}[WARNING]${NC} $1" +} + +print_error() { + echo -e "${RED}[ERROR]${NC} $1" +} + +# Function to check if Docker is running +check_docker() { + if ! docker info > /dev/null 2>&1; then + print_error "Docker is not running. Please start Docker first." + exit 1 + fi +} + +# Function to check if domain is pointing to this server +check_domain() { + print_status "Checking if domain $DOMAIN is pointing to this server..." + + # Get current server IP + SERVER_IP=$(curl -s ifconfig.me || curl -s icanhazip.com || echo "Unable to detect") + + # Get domain IP + DOMAIN_IP=$(dig +short $DOMAIN | head -n1) + + print_status "Server IP: $SERVER_IP" + print_status "Domain IP: $DOMAIN_IP" + + if [[ "$SERVER_IP" != "$DOMAIN_IP" ]]; then + print_warning "Domain might not be pointing to this server!" + print_warning "Please make sure DNS is configured correctly before proceeding." + read -p "Continue anyway? (y/N): " -n 1 -r + echo "" + if [[ ! $REPLY =~ ^[Yy]$ ]]; then + print_status "SSL setup cancelled." + exit 0 + fi + else + print_success "Domain is correctly pointing to this server!" + fi +} + +# Function to create temporary nginx config for initial certificate +create_temp_nginx() { + print_status "Creating temporary nginx configuration for initial certificate..." + + cat > docker/nginx-temp.conf << 'EOF' +events { + worker_connections 1024; +} + +http { + server { + listen 80; + server_name bengkel.digitaloasis.xyz www.bengkel.digitaloasis.xyz; + + location /.well-known/acme-challenge/ { + root /var/www/certbot; + } + + location / { + return 200 'SSL setup in progress...'; + add_header Content-Type text/plain; + } + } +} +EOF +} + +# Function to start nginx with temporary config +start_temp_nginx() { + print_status "Starting nginx with temporary configuration..." + + # Update docker-compose to use temporary config + sed -i 's|nginx-proxy.conf|nginx-temp.conf|g' $COMPOSE_FILE + + # Start nginx-proxy + docker-compose -f $COMPOSE_FILE up -d nginx-proxy + + # Wait for nginx to be ready + sleep 10 +} + +# Function to obtain SSL certificate +obtain_certificate() { + print_status "Obtaining SSL certificate from Let's Encrypt..." + + # Run certbot + docker-compose -f $COMPOSE_FILE run --rm certbot certonly \ + --webroot \ + --webroot-path=/var/www/certbot \ + --email $EMAIL \ + --agree-tos \ + --no-eff-email \ + --force-renewal \ + -d $DOMAIN \ + -d $WWW_DOMAIN + + if [[ $? -eq 0 ]]; then + print_success "SSL certificate obtained successfully!" + else + print_error "Failed to obtain SSL certificate!" + exit 1 + fi +} + +# Function to setup certificate files +setup_certificate_files() { + print_status "Setting up certificate files for nginx..." + + # Copy certificates to nginx ssl directory + docker run --rm \ + -v ckb_ssl_certificates:/source \ + -v ckb_ssl_certificates:/target \ + alpine sh -c " + mkdir -p /target/live/$DOMAIN + cp -L /source/live/$DOMAIN/fullchain.pem /target/fullchain.pem + cp -L /source/live/$DOMAIN/privkey.pem /target/privkey.pem + chmod 644 /target/fullchain.pem + chmod 600 /target/privkey.pem + " + + print_success "Certificate files setup completed!" +} + +# Function to restore production nginx config +restore_production_config() { + print_status "Restoring production nginx configuration..." + + # Restore original config + sed -i 's|nginx-temp.conf|nginx-proxy.conf|g' $COMPOSE_FILE + + # Restart nginx with SSL configuration + docker-compose -f $COMPOSE_FILE up -d nginx-proxy + + print_success "Production nginx configuration restored!" +} + +# Function to test SSL certificate +test_ssl() { + print_status "Testing SSL certificate..." + + sleep 10 + + # Test HTTPS connection + if curl -s --max-time 10 https://$DOMAIN > /dev/null; then + print_success "HTTPS is working correctly!" + else + print_warning "HTTPS test failed. Please check the configuration." + fi + + # Test certificate validity + if openssl s_client -connect $DOMAIN:443 -servername $DOMAIN < /dev/null 2>/dev/null | openssl x509 -noout -dates; then + print_success "Certificate information retrieved successfully!" + else + print_warning "Could not retrieve certificate information." + fi +} + +# Function to setup certificate renewal +setup_renewal() { + print_status "Setting up automatic certificate renewal..." + + # Create renewal script + cat > docker-ssl-renew.sh << 'EOF' +#!/bin/bash + +# SSL Certificate Renewal Script +# Add this to crontab: 0 12 * * * /path/to/docker-ssl-renew.sh + +docker-compose -f docker-compose.prod.yml run --rm certbot renew --quiet + +# Reload nginx if certificate was renewed +if [[ $? -eq 0 ]]; then + # Copy renewed certificates + docker run --rm \ + -v ckb_ssl_certificates:/source \ + -v ckb_ssl_certificates:/target \ + alpine sh -c " + cp -L /source/live/bengkel.digitaloasis.xyz/fullchain.pem /target/fullchain.pem + cp -L /source/live/bengkel.digitaloasis.xyz/privkey.pem /target/privkey.pem + " + + # Reload nginx + docker-compose -f docker-compose.prod.yml exec nginx-proxy nginx -s reload +fi +EOF + + chmod +x docker-ssl-renew.sh + + print_success "Certificate renewal script created: docker-ssl-renew.sh" + print_status "To setup automatic renewal, add this to crontab:" + echo "0 12 * * * $(pwd)/docker-ssl-renew.sh" +} + +# Function to show final information +show_final_info() { + echo "" + print_success "๐ŸŽ‰ SSL setup completed successfully!" + echo "" + print_status "Your application is now available at:" + echo " ๐ŸŒ https://bengkel.digitaloasis.xyz" + echo " ๐ŸŒ https://www.bengkel.digitaloasis.xyz" + echo "" + print_status "SSL Certificate Information:" + echo " ๐Ÿ“… Domain: $DOMAIN, $WWW_DOMAIN" + echo " ๐Ÿ“ง Email: $EMAIL" + echo " ๐Ÿ”„ Auto-renewal: Setup docker-ssl-renew.sh in crontab" + echo "" + print_status "Useful Commands:" + echo " - Check certificate: openssl s_client -connect $DOMAIN:443 -servername $DOMAIN" + echo " - Renew certificate: ./docker-ssl-renew.sh" + echo " - View logs: docker-compose -f $COMPOSE_FILE logs nginx-proxy" + echo " - Test renewal: docker-compose -f $COMPOSE_FILE run --rm certbot renew --dry-run" +} + +# Main execution +echo "================================================" +print_status "๐Ÿ”’ SSL Certificate Setup for CKB Production" +print_status "Domain: $DOMAIN" +echo "================================================" +echo "" + +# Check prerequisites +check_docker +check_domain + +# Ask for confirmation +print_warning "This will setup SSL certificate for $DOMAIN" +print_status "Make sure your application is not currently running." +read -p "Continue with SSL setup? (y/N): " -n 1 -r +echo "" + +if [[ ! $REPLY =~ ^[Yy]$ ]]; then + print_status "SSL setup cancelled." + exit 0 +fi + +# Execute SSL setup +print_status "Starting SSL certificate setup process..." + +create_temp_nginx +start_temp_nginx +obtain_certificate +setup_certificate_files +restore_production_config +test_ssl +setup_renewal + +# Show final information +show_final_info + +print_success "โœ… SSL setup completed successfully!" \ No newline at end of file diff --git a/docker-start.sh b/docker-start.sh index b1df592..455d834 100755 --- a/docker-start.sh +++ b/docker-start.sh @@ -82,13 +82,25 @@ check_docker() { # Function to setup environment file setup_env() { if [[ ! -f .env ]]; then - if [[ -f docker/env.example ]]; then - print_status "Copying environment file..." - cp docker/env.example .env - print_warning "Please edit .env file to configure your application" + if [[ $ENVIRONMENT == "dev" ]]; then + if [[ -f docker/env.example.local ]]; then + print_status "Copying local environment file..." + cp docker/env.example.local .env + print_success "Local development environment configured" + else + print_error "Local environment template not found: docker/env.example.local" + exit 1 + fi else - print_error "No environment template found. Please create .env file manually." - exit 1 + if [[ -f docker/env.example.production ]]; then + print_status "Copying production environment file..." + cp docker/env.example.production .env + print_warning "โš ๏ธ IMPORTANT: Edit .env and change all CHANGE_THIS_* passwords!" + print_warning "Please configure production settings before continuing" + else + print_error "Production environment template not found: docker/env.example.production" + exit 1 + fi fi fi } diff --git a/docker/env.example b/docker/env.example index a3efcd4..793de5b 100644 --- a/docker/env.example +++ b/docker/env.example @@ -1,42 +1,46 @@ -APP_NAME="CKB Application" -APP_ENV=local +APP_NAME="CKB Bengkel System" +APP_ENV=production APP_KEY= -APP_DEBUG=true -APP_URL=http://localhost:8000 +APP_DEBUG=false +APP_URL=https://bengkel.digitaloasis.xyz LOG_CHANNEL=stack -LOG_LEVEL=debug +LOG_LEVEL=error -# Database Configuration for Docker +# Database Configuration for Production DB_CONNECTION=mysql DB_HOST=db DB_PORT=3306 -DB_DATABASE=ckb_db -DB_USERNAME=root -DB_PASSWORD=root +DB_DATABASE=ckb_production +DB_USERNAME=ckb_user +DB_PASSWORD=secure_password_here +DB_ROOT_PASSWORD=secure_root_password_here -# Redis Configuration for Docker +# Redis Configuration for Production REDIS_HOST=redis -REDIS_PASSWORD=null +REDIS_PASSWORD=secure_redis_password REDIS_PORT=6379 -BROADCAST_DRIVER=log +BROADCAST_DRIVER=redis CACHE_DRIVER=redis FILESYSTEM_DRIVER=local -QUEUE_CONNECTION=sync +QUEUE_CONNECTION=redis SESSION_DRIVER=redis SESSION_LIFETIME=120 -# Mail Configuration for Docker (MailHog) +# Mail Configuration for Production MAIL_MAILER=smtp -MAIL_HOST=mailhog -MAIL_PORT=1025 -MAIL_USERNAME=null -MAIL_PASSWORD=null -MAIL_ENCRYPTION=null -MAIL_FROM_ADDRESS=test@ckb.local +MAIL_HOST=your-smtp-host.com +MAIL_PORT=587 +MAIL_USERNAME=your-email@domain.com +MAIL_PASSWORD=your-email-password +MAIL_ENCRYPTION=tls +MAIL_FROM_ADDRESS=noreply@bengkel.digitaloasis.xyz MAIL_FROM_NAME="${APP_NAME}" +# Trusted Proxies for Production +TRUSTED_PROXIES=* + # AWS (if needed for production) AWS_ACCESS_KEY_ID= AWS_SECRET_ACCESS_KEY= diff --git a/docker/env.example.local b/docker/env.example.local new file mode 100644 index 0000000..0cc0d72 --- /dev/null +++ b/docker/env.example.local @@ -0,0 +1,64 @@ +APP_NAME="CKB Application" +APP_ENV=local +APP_KEY= +APP_DEBUG=true +APP_URL=http://localhost:8000 + +LOG_CHANNEL=stack +LOG_LEVEL=debug + +# Database Configuration for Local Development +DB_CONNECTION=mysql +DB_HOST=db +DB_PORT=3306 +DB_DATABASE=ckb_db +DB_USERNAME=root +DB_PASSWORD=root + +# Redis Configuration for Local Development +REDIS_HOST=redis +REDIS_PASSWORD=null +REDIS_PORT=6379 + +BROADCAST_DRIVER=log +CACHE_DRIVER=redis +FILESYSTEM_DRIVER=local +QUEUE_CONNECTION=sync +SESSION_DRIVER=redis +SESSION_LIFETIME=120 + +# Mail Configuration for Local Development (MailHog) +MAIL_MAILER=smtp +MAIL_HOST=mailhog +MAIL_PORT=1025 +MAIL_USERNAME=null +MAIL_PASSWORD=null +MAIL_ENCRYPTION=null +MAIL_FROM_ADDRESS=test@ckb.local +MAIL_FROM_NAME="${APP_NAME}" + +# AWS (for local testing if needed) +AWS_ACCESS_KEY_ID= +AWS_SECRET_ACCESS_KEY= +AWS_DEFAULT_REGION=us-east-1 +AWS_BUCKET= +AWS_USE_PATH_STYLE_ENDPOINT=false + +# Pusher (for local testing if needed) +PUSHER_APP_ID= +PUSHER_APP_KEY= +PUSHER_APP_SECRET= +PUSHER_HOST= +PUSHER_PORT=443 +PUSHER_SCHEME=https +PUSHER_APP_CLUSTER=mt1 + +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}" + +# Local Development Settings +TELESCOPE_ENABLED=true +DEBUGBAR_ENABLED=true \ No newline at end of file diff --git a/docker/env.example.production b/docker/env.example.production new file mode 100644 index 0000000..71cafc1 --- /dev/null +++ b/docker/env.example.production @@ -0,0 +1,78 @@ +APP_NAME="CKB Bengkel System" +APP_ENV=production +APP_KEY= +APP_DEBUG=false +APP_URL=https://bengkel.digitaloasis.xyz + +LOG_CHANNEL=stack +LOG_LEVEL=error + +# Database Configuration for Production +# IMPORTANT: Change these credentials for security! +DB_CONNECTION=mysql +DB_HOST=db +DB_PORT=3306 +DB_DATABASE=ckb_production +DB_USERNAME=ckb_user +DB_PASSWORD=CHANGE_THIS_SECURE_PASSWORD +DB_ROOT_PASSWORD=CHANGE_THIS_ROOT_PASSWORD + +# Redis Configuration for Production +REDIS_HOST=redis +REDIS_PASSWORD=CHANGE_THIS_REDIS_PASSWORD +REDIS_PORT=6379 + +BROADCAST_DRIVER=redis +CACHE_DRIVER=redis +FILESYSTEM_DRIVER=local +QUEUE_CONNECTION=redis +SESSION_DRIVER=redis +SESSION_LIFETIME=120 + +# Mail Configuration for Production +# Configure with your SMTP provider (Gmail, SendGrid, Mailgun, etc.) +MAIL_MAILER=smtp +MAIL_HOST=smtp.gmail.com +MAIL_PORT=587 +MAIL_USERNAME=your-email@gmail.com +MAIL_PASSWORD=your-app-password +MAIL_ENCRYPTION=tls +MAIL_FROM_ADDRESS=noreply@bengkel.digitaloasis.xyz +MAIL_FROM_NAME="${APP_NAME}" + +# Trusted Proxies for Production (Nginx reverse proxy) +TRUSTED_PROXIES=* + +# AWS Configuration for Production (if using S3 for file storage) +AWS_ACCESS_KEY_ID=your-aws-access-key +AWS_SECRET_ACCESS_KEY=your-aws-secret-key +AWS_DEFAULT_REGION=us-east-1 +AWS_BUCKET=ckb-production-storage +AWS_USE_PATH_STYLE_ENDPOINT=false + +# Pusher Configuration for Production (if using real-time features) +PUSHER_APP_ID=your-pusher-app-id +PUSHER_APP_KEY=your-pusher-key +PUSHER_APP_SECRET=your-pusher-secret +PUSHER_HOST= +PUSHER_PORT=443 +PUSHER_SCHEME=https +PUSHER_APP_CLUSTER=ap1 + +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}" + +# Production Optimization Settings +TELESCOPE_ENABLED=false +DEBUGBAR_ENABLED=false + +# Security Settings +SESSION_SECURE_COOKIE=true +SESSION_SAME_SITE=strict + +# Backup Configuration (optional) +BACKUP_DISK=s3 +BACKUP_NOTIFICATION_MAIL=admin@digitaloasis.xyz \ No newline at end of file diff --git a/docker/nginx-proxy.conf b/docker/nginx-proxy.conf new file mode 100644 index 0000000..193eafa --- /dev/null +++ b/docker/nginx-proxy.conf @@ -0,0 +1,142 @@ +events { + worker_connections 1024; +} + +http { + # Basic settings + sendfile on; + tcp_nopush on; + tcp_nodelay on; + keepalive_timeout 65; + types_hash_max_size 2048; + client_max_body_size 100M; + + # Gzip compression + gzip on; + gzip_vary on; + gzip_min_length 1024; + gzip_types + text/plain + text/css + text/xml + text/javascript + application/javascript + application/xml+rss + application/json + image/svg+xml; + + # MIME types + include /etc/nginx/mime.types; + default_type application/octet-stream; + + # Logging + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + + access_log /var/log/nginx/access.log main; + error_log /var/log/nginx/error.log; + + # Rate limiting + limit_req_zone $binary_remote_addr zone=login:10m rate=10r/m; + limit_req_zone $binary_remote_addr zone=api:10m rate=60r/m; + + # Upstream to Laravel app + upstream app { + server app:80; + } + + # HTTP to HTTPS redirect + server { + listen 80; + server_name bengkel.digitaloasis.xyz www.bengkel.digitaloasis.xyz; + + # Let's Encrypt challenge + location /.well-known/acme-challenge/ { + root /var/www/certbot; + } + + # Redirect all other traffic to HTTPS + location / { + return 301 https://$server_name$request_uri; + } + } + + # HTTPS server configuration + server { + listen 443 ssl http2; + server_name bengkel.digitaloasis.xyz www.bengkel.digitaloasis.xyz; + + # SSL configuration + ssl_certificate /etc/nginx/ssl/fullchain.pem; + ssl_certificate_key /etc/nginx/ssl/privkey.pem; + + # Modern SSL configuration + ssl_protocols TLSv1.2 TLSv1.3; + ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384; + ssl_prefer_server_ciphers off; + ssl_session_cache shared:SSL:10m; + ssl_session_timeout 10m; + + # Security headers + add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; + add_header X-Frame-Options "SAMEORIGIN" always; + add_header X-Content-Type-Options "nosniff" always; + add_header X-XSS-Protection "1; mode=block" always; + add_header Referrer-Policy "strict-origin-when-cross-origin" always; + + # Root directory + root /var/www/html/public; + index index.php index.html; + + # Proxy settings + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Forwarded-Host $server_name; + proxy_set_header X-Forwarded-Port $server_port; + + # Handle static files + location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ { + proxy_pass http://app; + expires 1y; + add_header Cache-Control "public, immutable"; + } + + # Rate limiting for login endpoints + location ~ ^/(login|register|password) { + limit_req zone=login burst=5 nodelay; + proxy_pass http://app; + } + + # Rate limiting for API endpoints + location /api/ { + limit_req zone=api burst=20 nodelay; + proxy_pass http://app; + } + + # Main application + location / { + proxy_pass http://app; + proxy_read_timeout 300; + proxy_connect_timeout 300; + proxy_send_timeout 300; + } + + # Health check endpoint + location /health { + access_log off; + proxy_pass http://app; + } + + # Block access to sensitive files + location ~ /\. { + deny all; + } + + location ~ ^/(storage|bootstrap/cache) { + deny all; + } + } +} \ No newline at end of file