This commit is contained in:
uprightbass360
2025-09-30 04:30:03 -04:00
parent 0f07bd34a4
commit c21b364faf
29 changed files with 373 additions and 4143 deletions

98
.env
View File

@@ -1,98 +0,0 @@
# ==============================================
# AZEROTHCORE DATABASE LAYER ENVIRONMENT - LOCAL TESTING
# ==============================================
# Environment variables for local Docker testing
# ==============================================
# DATABASE CREDENTIALS (REQUIRED)
# ==============================================
MYSQL_ROOT_PASSWORD=azerothcore123
# Database connection settings
MYSQL_HOST=ac-mysql
MYSQL_PORT=3306
MYSQL_USER=root
MYSQL_ROOT_HOST=%
# Database names
DB_AUTH_NAME=acore_auth
DB_WORLD_NAME=acore_world
DB_CHARACTERS_NAME=acore_characters
# Database wait settings - Conservative for local testing
DB_WAIT_RETRIES=30
DB_WAIT_SLEEP=3
# ==============================================
# DOCKER IMAGES (REQUIRED)
# ==============================================
# Database layer images
AC_DB_IMPORT_IMAGE=acore/ac-wotlk-db-import:14.0.0-dev
MYSQL_IMAGE=mysql:8.0
ALPINE_IMAGE=alpine:latest
# ==============================================
# IMAGE PULL POLICY (REQUIRED)
# ==============================================
IMAGE_PULL_POLICY=if_not_present
# ==============================================
# MYSQL CONFIGURATION (REQUIRED)
# ==============================================
# MySQL server settings
MYSQL_CHARACTER_SET=utf8mb4
MYSQL_COLLATION=utf8mb4_unicode_ci
MYSQL_MAX_CONNECTIONS=100
MYSQL_INNODB_BUFFER_POOL_SIZE=128M
MYSQL_INNODB_LOG_FILE_SIZE=32M
# MySQL health check settings - Local testing values
MYSQL_HEALTHCHECK_INTERVAL=10s
MYSQL_HEALTHCHECK_TIMEOUT=5s
MYSQL_HEALTHCHECK_RETRIES=10
MYSQL_HEALTHCHECK_START_PERIOD=30s
# ==============================================
# NETWORK CONFIGURATION (REQUIRED)
# ==============================================
# External database port
DOCKER_DB_EXTERNAL_PORT=64306
# ==============================================
# DEPLOYMENT CONFIGURATION (REQUIRED)
# ==============================================
# Storage configuration for local testing
STORAGE_PATH=./local-data
# ==============================================
# CONTAINER NAMES (REQUIRED)
# ==============================================
# Database layer container names
CONTAINER_MYSQL=ac-mysql
CONTAINER_DB_INIT=ac-db-init
CONTAINER_DB_IMPORT=ac-db-import
CONTAINER_BACKUP=ac-backup
# ==============================================
# NETWORK SETTINGS (REQUIRED)
# ==============================================
NETWORK_NAME=azerothcore
NETWORK_SUBNET=172.20.0.0/16
NETWORK_GATEWAY=172.20.0.1
# ==============================================
# BACKUP CONFIGURATION (REQUIRED)
# ==============================================
# Host volume paths for backup
HOST_BACKUP_PATH=./backups
HOST_BACKUP_SCRIPTS_PATH=./backup-scripts
# Backup settings
BACKUP_CRON_SCHEDULE=0 3 * * *
BACKUP_RETENTION_DAYS=7
# ==============================================
# SERVER CONFIGURATION (REQUIRED)
# ==============================================
# Timezone
TZ=UTC

174
.env-core
View File

@@ -1,174 +0,0 @@
# ==============================================
# AZEROTHCORE DOCKER ENVIRONMENT CONFIGURATION
# ==============================================
# REQUIRED: All values must be set - no defaults in compose
# ==============================================
# DATABASE CREDENTIALS (REQUIRED)
# ==============================================
MYSQL_ROOT_PASSWORD=azerothcore123
# Database connection settings
MYSQL_HOST=ac-mysql
MYSQL_PORT=3306
MYSQL_USER=root
MYSQL_ROOT_HOST=%
# Database names
DB_AUTH_NAME=acore_auth
DB_WORLD_NAME=acore_world
DB_CHARACTERS_NAME=acore_characters
# Database wait settings
DB_WAIT_RETRIES=30
DB_WAIT_SLEEP=5
# ==============================================
# DOCKER IMAGES (REQUIRED)
# ==============================================
# AzerothCore images
AC_DB_IMPORT_IMAGE=acore/ac-wotlk-db-import:14.0.0-dev
AC_AUTHSERVER_IMAGE=acore/ac-wotlk-authserver:14.0.0-dev
AC_WORLDSERVER_IMAGE=acore/ac-wotlk-worldserver:14.0.0-dev
AC_ELUNA_IMAGE=acore/eluna-ts:master
# Base images
MYSQL_IMAGE=mysql:8.0
ALPINE_IMAGE=alpine:latest
ALPINE_GIT_IMAGE=alpine/git:latest
# ==============================================
# IMAGE PULL POLICY (REQUIRED)
# ==============================================
# Control when Docker pulls images
# Options: always, never, missing, if_not_present
# - always: Always pull the latest image (slower, ensures latest)
# - never: Never pull, use only local images (fastest, may fail if image missing)
# - missing/if_not_present: Only pull if image doesn't exist locally (recommended)
IMAGE_PULL_POLICY=if_not_present
# ==============================================
# DEPLOYMENT OPTIMIZATION (REQUIRED)
# ==============================================
# Skip client data download if data already exists (speeds up deployment)
SKIP_CLIENT_DATA_IF_EXISTS=true
# Parallel container startup (reduces deployment time)
ENABLE_PARALLEL_STARTUP=true
# ==============================================
# MYSQL CONFIGURATION (REQUIRED)
# ==============================================
# MySQL server settings
MYSQL_CHARACTER_SET=utf8mb4
MYSQL_COLLATION=utf8mb4_unicode_ci
MYSQL_MAX_CONNECTIONS=1000
MYSQL_INNODB_BUFFER_POOL_SIZE=256M
MYSQL_INNODB_LOG_FILE_SIZE=64M
# MySQL health check settings
MYSQL_HEALTHCHECK_INTERVAL=15s
MYSQL_HEALTHCHECK_TIMEOUT=10s
MYSQL_HEALTHCHECK_RETRIES=20
MYSQL_HEALTHCHECK_START_PERIOD=60s
# ==============================================
# CONTAINER HEALTH CHECKS (REQUIRED)
# ==============================================
# Auth server health check
AUTH_HEALTHCHECK_INTERVAL=30s
AUTH_HEALTHCHECK_TIMEOUT=10s
AUTH_HEALTHCHECK_RETRIES=3
AUTH_HEALTHCHECK_START_PERIOD=60s
# World server health check
WORLD_HEALTHCHECK_INTERVAL=30s
WORLD_HEALTHCHECK_TIMEOUT=10s
WORLD_HEALTHCHECK_RETRIES=3
WORLD_HEALTHCHECK_START_PERIOD=120s
# ==============================================
# NETWORK CONFIGURATION (REQUIRED)
# ==============================================
# External ports - must be specified
DOCKER_DB_EXTERNAL_PORT=64306
DOCKER_AUTH_EXTERNAL_PORT=3784
DOCKER_WORLD_EXTERNAL_PORT=8215
DOCKER_SOAP_EXTERNAL_PORT=7778
# Internal ports (container side)
AUTH_PORT=3724
WORLD_PORT=8085
SOAP_PORT=7878
# ==============================================
# PATHS (REQUIRED)
# ==============================================
# Host volume paths (for bind mounts if not using named volumes)
HOST_BACKUP_PATH=./backups
HOST_BACKUP_SCRIPTS_PATH=./backup-scripts
# ==============================================
# DEPLOYMENT CONFIGURATION (REQUIRED)
# ==============================================
# Deployment mode: local (development) or portainer (production)
DEPLOYMENT_MODE=local
# Storage configuration for Portainer NFS deployments
# Leave empty for local development with named volumes
STORAGE_PATH=./local-data
# ==============================================
# CONTAINER NAMES (REQUIRED)
# ==============================================
# Core service container names
CONTAINER_MYSQL_INIT=ac-mysql-init
CONTAINER_MYSQL=ac-mysql
CONTAINER_DB_INIT=ac-db-init
CONTAINER_DB_IMPORT=ac-db-import
CONTAINER_AUTHSERVER=ac-authserver
CONTAINER_WORLDSERVER=ac-worldserver
CONTAINER_CLIENT_DATA=ac-client-data
CONTAINER_ELUNA=ac-eluna
CONTAINER_MODULES=ac-modules
CONTAINER_BACKUP=ac-backup
# ==============================================
# NETWORK SETTINGS (REQUIRED)
# ==============================================
NETWORK_NAME=azerothcore
NETWORK_SUBNET=172.20.0.0/16
NETWORK_GATEWAY=172.20.0.1
# ==============================================
# SERVER CONFIGURATION (REQUIRED)
# ==============================================
# Timezone
TZ=UTC
# ==============================================
# BACKUP CONFIGURATION (REQUIRED)
# ==============================================
# Cron schedule
BACKUP_CRON_SCHEDULE=0 3 * * *
# Retention
BACKUP_RETENTION_DAYS=7
# ==============================================
# CUSTOM MODULE SETTINGS
# ==============================================
# Playerbot settings
PLAYERBOT_ENABLED=1
PLAYERBOT_MAX_BOTS=40
# Module Management (1 = enabled, 0 = disabled)
MODULE_PLAYERBOTS=1
MODULE_AOE_LOOT=0
MODULE_LEARN_SPELLS=0
MODULE_FIREWORKS=0
MODULE_INDIVIDUAL_PROGRESSION=0
# ==============================================
# END OF CONFIGURATION
# ==============================================

View File

@@ -1,98 +0,0 @@
# ==============================================
# AZEROTHCORE DATABASE LAYER ENVIRONMENT
# ==============================================
# Environment variables for MySQL, database init, import, and backup
# ==============================================
# DATABASE CREDENTIALS (REQUIRED)
# ==============================================
MYSQL_ROOT_PASSWORD=azerothcore123
# Database connection settings
MYSQL_HOST=ac-mysql
MYSQL_PORT=3306
MYSQL_USER=root
MYSQL_ROOT_HOST=%
# Database names
DB_AUTH_NAME=acore_auth
DB_WORLD_NAME=acore_world
DB_CHARACTERS_NAME=acore_characters
# Database wait settings - Increased for Portainer/NFS deployments
DB_WAIT_RETRIES=60
DB_WAIT_SLEEP=10
# ==============================================
# DOCKER IMAGES (REQUIRED)
# ==============================================
# Database layer images
AC_DB_IMPORT_IMAGE=acore/ac-wotlk-db-import:14.0.0-dev
MYSQL_IMAGE=mysql:8.0
ALPINE_IMAGE=alpine:latest
# ==============================================
# IMAGE PULL POLICY (REQUIRED)
# ==============================================
IMAGE_PULL_POLICY=if_not_present
# ==============================================
# MYSQL CONFIGURATION (REQUIRED)
# ==============================================
# MySQL server settings
MYSQL_CHARACTER_SET=utf8mb4
MYSQL_COLLATION=utf8mb4_unicode_ci
MYSQL_MAX_CONNECTIONS=1000
MYSQL_INNODB_BUFFER_POOL_SIZE=256M
MYSQL_INNODB_LOG_FILE_SIZE=64M
# MySQL health check settings - Moderately increased for Portainer/NFS deployments
MYSQL_HEALTHCHECK_INTERVAL=20s
MYSQL_HEALTHCHECK_TIMEOUT=15s
MYSQL_HEALTHCHECK_RETRIES=25
MYSQL_HEALTHCHECK_START_PERIOD=120s
# ==============================================
# NETWORK CONFIGURATION (REQUIRED)
# ==============================================
# External database port
DOCKER_DB_EXTERNAL_PORT=64306
# ==============================================
# DEPLOYMENT CONFIGURATION (REQUIRED)
# ==============================================
# Storage configuration for Portainer NFS deployments
STORAGE_PATH=./local-data
# ==============================================
# CONTAINER NAMES (REQUIRED)
# ==============================================
# Database layer container names
CONTAINER_MYSQL=ac-mysql
CONTAINER_DB_INIT=ac-db-init
CONTAINER_DB_IMPORT=ac-db-import
CONTAINER_BACKUP=ac-backup
# ==============================================
# NETWORK SETTINGS (REQUIRED)
# ==============================================
NETWORK_NAME=azerothcore
NETWORK_SUBNET=172.20.0.0/16
NETWORK_GATEWAY=172.20.0.1
# ==============================================
# BACKUP CONFIGURATION (REQUIRED)
# ==============================================
# Host volume paths for backup
HOST_BACKUP_PATH=./backups
HOST_BACKUP_SCRIPTS_PATH=./backup-scripts
# Backup settings
BACKUP_CRON_SCHEDULE=0 3 * * *
BACKUP_RETENTION_DAYS=7
# ==============================================
# SERVER CONFIGURATION (REQUIRED)
# ==============================================
# Timezone
TZ=UTC

View File

@@ -1,98 +0,0 @@
# ==============================================
# AZEROTHCORE DATABASE LAYER ENVIRONMENT - LOCAL TESTING
# ==============================================
# Environment variables for local Docker testing
# ==============================================
# DATABASE CREDENTIALS (REQUIRED)
# ==============================================
MYSQL_ROOT_PASSWORD=azerothcore123
# Database connection settings
MYSQL_HOST=ac-mysql
MYSQL_PORT=3306
MYSQL_USER=root
MYSQL_ROOT_HOST=%
# Database names
DB_AUTH_NAME=acore_auth
DB_WORLD_NAME=acore_world
DB_CHARACTERS_NAME=acore_characters
# Database wait settings - Conservative for local testing
DB_WAIT_RETRIES=30
DB_WAIT_SLEEP=3
# ==============================================
# DOCKER IMAGES (REQUIRED)
# ==============================================
# Database layer images
AC_DB_IMPORT_IMAGE=acore/ac-wotlk-db-import:14.0.0-dev
MYSQL_IMAGE=mysql:8.0
ALPINE_IMAGE=alpine:latest
# ==============================================
# IMAGE PULL POLICY (REQUIRED)
# ==============================================
IMAGE_PULL_POLICY=if_not_present
# ==============================================
# MYSQL CONFIGURATION (REQUIRED)
# ==============================================
# MySQL server settings
MYSQL_CHARACTER_SET=utf8mb4
MYSQL_COLLATION=utf8mb4_unicode_ci
MYSQL_MAX_CONNECTIONS=100
MYSQL_INNODB_BUFFER_POOL_SIZE=128M
MYSQL_INNODB_LOG_FILE_SIZE=32M
# MySQL health check settings - Local testing values
MYSQL_HEALTHCHECK_INTERVAL=10s
MYSQL_HEALTHCHECK_TIMEOUT=5s
MYSQL_HEALTHCHECK_RETRIES=10
MYSQL_HEALTHCHECK_START_PERIOD=30s
# ==============================================
# NETWORK CONFIGURATION (REQUIRED)
# ==============================================
# External database port
DOCKER_DB_EXTERNAL_PORT=64306
# ==============================================
# DEPLOYMENT CONFIGURATION (REQUIRED)
# ==============================================
# Storage configuration for local testing
STORAGE_PATH=./local-data
# ==============================================
# CONTAINER NAMES (REQUIRED)
# ==============================================
# Database layer container names
CONTAINER_MYSQL=ac-mysql
CONTAINER_DB_INIT=ac-db-init
CONTAINER_DB_IMPORT=ac-db-import
CONTAINER_BACKUP=ac-backup
# ==============================================
# NETWORK SETTINGS (REQUIRED)
# ==============================================
NETWORK_NAME=azerothcore
NETWORK_SUBNET=172.20.0.0/16
NETWORK_GATEWAY=172.20.0.1
# ==============================================
# BACKUP CONFIGURATION (REQUIRED)
# ==============================================
# Host volume paths for backup
HOST_BACKUP_PATH=./backups
HOST_BACKUP_SCRIPTS_PATH=./backup-scripts
# Backup settings
BACKUP_CRON_SCHEDULE=0 3 * * *
BACKUP_RETENTION_DAYS=7
# ==============================================
# SERVER CONFIGURATION (REQUIRED)
# ==============================================
# Timezone
TZ=UTC

View File

@@ -1,200 +0,0 @@
# AzerothCore Portainer Deployment Guide
## 🚀 **Quick Start for Portainer**
This guide will help you deploy AzerothCore in Portainer using your existing NFS storage structure.
### **📁 Files Needed:**
- `docker-compose.yml` - Main docker-compose stack file
- `.env` - Environment variables (set DEPLOYMENT_MODE=portainer)
- `backup-scripts/` Storage directory of backup and restoration scripts
---
## **📋 Step 1: Pre-Deployment Setup**
### **1.1 Prepare Storage Directories**
These directories will be created by the compose file:
```bash
# Main AzerothCore directory structure
${STORAGE_PATH_CONTAINERS}/azerothcore/
├── mysql/ # Database files
├── mysql-config/ # MySQL configuration
├── data/ # Game client data (15GB+)
├── config/ # Server configuration
├── logs/ # Server logs
├── modules/ # Playerbot modules
├── backups/ # Database backups
├── backup-scripts/ # Backup scripts
├── grafana/ # Grafana data
├── grafana-config/ # Grafana configuration
├── influxdb/ # InfluxDB data
├── cms/ # CMS data
└── keira3/ # Keira3 data
```
### **1.2 Copy Backup Scripts**
```bash
# Copy your existing backup scripts to NFS storage
cp -r ./backup-scripts/ ${STORAGE_PATH_CONTAINERS}/azerothcore/
```
---
## **📋 Step 2: Portainer Stack Deployment**
### **2.1 Create New Stack in Portainer**
1. Navigate to Portainer → Stacks → Add Stack
2. Name: `azerothcore`
3. Build method: Web editor
### **2.2 Copy Stack Configuration**
Copy the contents of `docker-compose.yml` into the web editor.
### **2.3 Configure Environment Variables**
In the Environment variables section, add all variables from `portainer-env-template.txt`:
**⚠️ CRITICAL: Update these values for your environment:**
- `STORAGE_PATH_CONTAINERS=/nfs/containers` (your actual NFS path)
- `EXTERNAL_IP=192.168.1.100` (your server's public IP)
- Port numbers (ensure no conflicts with existing services)
- Database passwords
- Web interface credentials
---
## **📋 Step 3: Network Configuration**
### **3.1 Port Mappings**
The stack uses these external ports (configurable):
- **3784**: Authentication server
- **8215**: World server
- **64306**: MySQL database
- **7778**: SOAP interface (if enabled)
- **8081**: PHPMyAdmin
- **3001**: Grafana
- **8087**: InfluxDB
- **4201**: Keira3 database editor
- **8001**: CMS web interface
### **3.2 Firewall Rules**
Ensure your firewall allows:
- Ports 3784 and 8215 for game clients
- Web interface ports for management access
---
## **📋 Step 4: Deployment Process**
### **4.1 Initial Deployment**
1. Click "Deploy the stack"
2. Monitor the deployment in Portainer logs
3. Services will start in this order:
- MySQL database
- Database initialization
- Authentication server
- Client data download (15GB - may take 30+ minutes)
- World server
- Web interfaces
### **4.2 Monitor Progress**
Watch these services for successful startup:
- `ac-mysql`: Database ready
- `ac-client-data`: Game data download complete
- `ac-authserver`: Authentication ready
- `ac-worldserver`: World server operational
---
## **📋 Step 5: Post-Deployment Verification**
### **5.1 Service Health Checks**
All services include health checks. In Portainer, verify:
- ✅ All containers showing "healthy" status
- ✅ No containers in "restarting" state
### **5.2 Web Interface Access**
Test access to management interfaces:
- **PHPMyAdmin**: `http://your-server:8081`
- **Grafana**: `http://your-server:3001` (admin/acore123)
- **Keira3**: `http://your-server:4201`
- **CMS**: `http://your-server:8001`
### **5.3 Game Server Testing**
1. Check worldserver logs for "AzerothCore ready" message
2. Test client connection to your server IP on port 3784
3. Verify realm list shows your server
---
## **🔧 Maintenance & Operations**
### **Backup Management**
- Automated backups run at 3 AM daily (configurable)
- Backups stored in `${STORAGE_PATH_CONTAINERS}/azerothcore/backups/`
- Retention: 7 days (configurable)
### **Log Access**
- Server logs: `${STORAGE_PATH_CONTAINERS}/azerothcore/logs/`
- Container logs: Available in Portainer → Container → Logs
### **Configuration Updates**
- Server config: `${STORAGE_PATH_CONTAINERS}/azerothcore/config/`
- Restart containers after config changes
---
## **🚨 Troubleshooting**
### **Common Issues:**
**1. Client Data Download Fails**
- Check internet connectivity
- Verify storage permissions
- Monitor `ac-client-data` container logs
**2. Database Connection Errors**
- Verify MySQL container is healthy
- Check database credentials
- Ensure network connectivity between containers
**3. Port Conflicts**
- Update port mappings in environment variables
- Restart stack after port changes
**4. Storage Permission Issues**
- Verify NFS mount permissions
- Check container user permissions
- Ensure storage paths exist
### **Log Locations:**
- Portainer: Container logs in web interface
- Server logs: `${STORAGE_PATH_CONTAINERS}/azerothcore/logs/`
- Database logs: MySQL container logs in Portainer
---
## **📈 Monitoring & Metrics**
The stack includes comprehensive monitoring:
- **Grafana Dashboard**: Real-time server metrics
- **InfluxDB**: Metrics storage
- **Built-in Health Checks**: Automatic container monitoring
- **Backup Status**: Automated backup verification
Access monitoring at: `http://your-server:3001`
---
## **🔐 Security Notes**
- Change default passwords before deployment
- Restrict web interface access to management networks
- Use strong database passwords
- Regular security updates for containers
- Monitor access logs
---
**✅ Your AzerothCore server is now ready for production use in Portainer!**

View File

@@ -1,178 +0,0 @@
# AzerothCore Staged Deployment Guide
## 🚀 Three-Layer Deployment Strategy
The AzerothCore setup has been split into three logical layers for faster, more reliable deployments:
1. **Database Layer** - MySQL, database initialization, import, and backup
2. **Core Services Layer** - Authentication server, world server, and client data
3. **Optional Services Layer** - Modules and monitoring services
## 📋 Deployment Order
### **Stage 1: Database Layer** ⭐ **DEPLOY FIRST**
```bash
File: docker-compose-azerothcore-database.yml
Env: .env-database
```
**Services:**
- `ac-mysql-init` - Fixes NFS permissions
- `ac-mysql` - MySQL database server
- `ac-db-init` - Creates AzerothCore databases
- `ac-db-import` - Imports database schema and data
- `ac-backup` - Automated database backups
**Expected Time:** 5-10 minutes
### **Stage 2: Core Services Layer** ⭐ **DEPLOY SECOND**
```bash
File: docker-compose-azerothcore-services.yml
Env: .env-services
```
**Services:**
- `ac-client-data` - Downloads 15GB game data (cached after first run)
- `ac-authserver` - Authentication server
- `ac-worldserver` - Game world server with Playerbots
**Expected Time:** 15-20 minutes (first run), 3-5 minutes (subsequent)
### **Stage 3: Optional Services Layer** ⭐ **DEPLOY THIRD**
```bash
File: docker-compose-azerothcore-optional.yml
Env: .env-optional
```
**Services:**
- `ac-eluna` - Lua scripting engine
- `ac-modules` - Module management and installation
**Expected Time:** 2-3 minutes
## 🛠️ Portainer Deployment Steps
### **Step 1: Deploy Database Layer**
1. **Create Stack in Portainer:**
- Name: `azerothcore-database`
- Repository: Select your repository
- Compose file: `docker-compose-azerothcore-database.yml`
- Environment file: `.env-database`
2. **Wait for Completion:**
- Watch logs for "Database import complete!"
- Verify MySQL health check is green
- Should complete in 5-10 minutes
### **Step 2: Deploy Core Services Layer**
1. **Create Stack in Portainer:**
- Name: `azerothcore-services`
- Repository: Select your repository
- Compose file: `docker-compose-azerothcore-services.yml`
- Environment file: `.env-services`
2. **Wait for Completion:**
- Watch for "Game data setup complete!"
- Verify auth and world servers are healthy
- First run: 15-20 minutes, subsequent: 3-5 minutes
### **Step 3: Deploy Optional Services Layer**
1. **Create Stack in Portainer:**
- Name: `azerothcore-optional`
- Repository: Select your repository
- Compose file: `docker-compose-azerothcore-optional.yml`
- Environment file: `.env-optional`
2. **Wait for Completion:**
- Should complete quickly (2-3 minutes)
## ✅ Verification Steps
### **After Database Layer:**
```bash
# Check MySQL is running
docker exec ac-mysql mysql -u root -pazerothcore123 -e "SHOW DATABASES;"
# Expected output should include:
# - acore_auth
# - acore_world
# - acore_characters
```
### **After Core Services:**
```bash
# Check auth server
docker logs ac-authserver | tail -10
# Check world server
docker logs ac-worldserver | tail -10
# Look for "AzerothCore ready..." message
```
### **After Optional Services:**
```bash
# Check modules
docker exec ac-modules ls -la /modules
# Should show mod-playerbots directory
```
## 🔧 Configuration Notes
### **Cross-Layer Dependencies:**
- All layers share the same **network**: `azerothcore`
- All layers use the same **storage path**: `/nfs/containers/azerothcore`
- Services layer connects to database via **external_links**
### **Environment Variable Consistency:**
- Database credentials must match across all layers
- Container names must be consistent for external linking
- Network name must be identical
### **Image Pull Optimization:**
All layers use `IMAGE_PULL_POLICY=if_not_present` for fast deployment.
## 🚨 Troubleshooting
### **Database Layer Issues:**
- **MySQL won't start**: Check NFS permissions and storage path
- **Database import fails**: Check container logs for database connection errors
- **Backup fails**: Verify backup scripts directory exists
### **Core Services Issues:**
- **Auth server can't connect**: Verify database layer is healthy first
- **Client data download timeout**: Check internet connection, may take 30+ minutes
- **World server fails**: Ensure client data completed successfully
### **Optional Services Issues:**
- **Modules won't install**: Check git connectivity and storage permissions
- **Eluna won't start**: Verify world server is running first
## 🎯 Benefits of Staged Deployment
1. **Faster Individual Deployments** - Each layer deploys in 2-10 minutes vs 20-30 minutes
2. **Better Error Isolation** - Problems are contained to specific layers
3. **Selective Updates** - Update only the layer that changed
4. **Reduced Portainer Timeouts** - No more 504 Gateway Timeout errors
5. **Easier Debugging** - Clear separation of concerns
## 📊 Deployment Time Comparison
| Method | First Deploy | Update Deploy | Risk |
|--------|--------------|---------------|------|
| **Monolithic** | 20-30 min | 15-20 min | High timeout risk |
| **Staged** | 10-15 min total | 3-8 min per layer | Low timeout risk |
## 🔄 Update Strategy
To update a specific layer:
1. Stop only that layer's stack
2. Update the compose file or environment variables
3. Redeploy just that layer
4. Other layers continue running uninterrupted
This approach provides much better reliability and faster deployment times!

View File

@@ -1,190 +0,0 @@
# Unused Environment Variables Documentation
This document lists all environment variables that were removed from `.env-core` because they are not used by the current Docker Compose setup.
**Total removed**: 117 variables (72% of original configuration)
## 🗄️ Database Configuration (Not Used in Docker Compose)
```bash
AC_LOG_LEVEL_IMPORT=1
AC_LOG_LEVEL_AUTH=1
AC_LOG_LEVEL_WORLD=2
AC_UPDATES_ENABLE_DATABASES_IMPORT=7
AC_UPDATES_ENABLE_DATABASES_SERVERS=0
AC_UPDATES_AUTO_SETUP=1
AC_LOGGER_ROOT_CONFIG=1,Console
AC_LOGGER_SERVER_CONFIG=1,Console
AC_APPENDER_CONSOLE_CONFIG=1,2,0
AC_CLOSE_IDLE_CONNECTIONS=false
```
## 🌐 Network & Connection Settings (Not Used in Docker Compose)
```bash
EXTERNAL_IP=127.0.0.1
BIND_IP=0.0.0.0
SOAP_IP=0.0.0.0
RA_PORT=3443
AC_BIND_IP=0.0.0.0
AC_SOAP_PORT=7878
AC_PROCESS_PRIORITY=0
```
## 📁 Path Configuration (Not Used in Docker Compose)
```bash
AC_DATA_DIR=/azerothcore/data
AC_LOGS_DIR=/azerothcore/logs
AC_CONFIG_DIR=/azerothcore/env/dist/etc
AC_MODULES_DIR=/azerothcore/modules
AC_BIN_DIR=/azerothcore/env/dist/bin
HOST_DATA_PATH=./data
HOST_DB_PATH=/srv/azerothcore/database
HOST_LOGS_PATH=/srv/azerothcore/logs
HOST_CONFIG_PATH=/srv/azerothcore/config
```
## 💾 Volume Names (Not Used in Docker Compose)
```bash
VOLUME_DB_DATA=ac_mysql_data
VOLUME_WORLD_DATA=ac_data
VOLUME_CONFIG=ac_config
VOLUME_LOGS=ac_logs
VOLUME_BACKUP=ac_backup
```
## 📥 Client Data Settings (Not Used in Docker Compose)
```bash
CLIENT_DATA_REPO=wowgaming/client-data
CLIENT_DATA_FALLBACK_VERSION=v16
CLIENT_DATA_REQUIRED_DIRS=maps vmaps mmaps dbc
```
## 🎮 Game Server Configuration (Potentially Used by AzerothCore)
```bash
GAME_TYPE=0
REALM_ID=1
REALM_NAME=AzerothCore
REALM_ZONE=1
REALM_FLAGS=0
REALM_TIMEZONE=1
REALM_ALLOWED_SECURITY_LEVEL=0
REALM_POPULATION=0
REALM_GAMEBUILD=12340
```
## ⚡ Performance Settings (Not Used in Docker Compose)
```bash
PROCESS_PRIORITY=0
USE_PROCESSORS=0
COMPRESSION=1
MAX_CONNECTIONS=1000
MAX_PLAYERS=100
MAX_OVERSPEED_PINGS=2
INNODB_BUFFER_POOL_SIZE=256M
INNODB_LOG_FILE_SIZE=64M
SOCKET_TIMEOUT_TIME=900000
SESSION_ADD_DELAY=10000
GRID_CLEANUP_DELAY=300000
MAP_UPDATE_INTERVAL=100
```
## 🔄 Update Settings (Not Used in Docker Compose)
```bash
UPDATES_ENABLE_DATABASES=7
UPDATES_AUTO_SETUP=1
UPDATES_REDUNDANCY=2
UPDATES_ARCHIVED_REDUNDANCY=0
UPDATES_ALLOW_REHASH=1
UPDATES_CLEAN_DEAD_REF_MAX_COUNT=3
```
## 📝 Logging Configuration (Not Used in Docker Compose)
```bash
LOG_LEVEL=1
LOG_FILE=
LOG_TIMESTAMP=0
LOG_FILE_LEVEL=0
DB_ERROR_LOG_FILE=DBErrors.log
CHAR_LOG_FILE=
GM_LOG_FILE=
RA_LOG_FILE=
SQL_DRIVER_LOG_FILE=
SQL_DRIVER_QUERY_LOGGING=0
```
## 🔧 Feature Flags (Potentially Used by AzerothCore)
```bash
CONSOLE_ENABLE=1
SOAP_ENABLED=0
RA_ENABLE=0
RA_IP=127.0.0.1
RA_MIN_LEVEL=3
CLOSE_IDLE_CONNECTIONS=false
SKIP_BATTLEGROUND_RELOCATE_CHECK=0
```
## 💰 Backup Configuration (Not Used in Docker Compose)
```bash
BACKUP_FILE_PREFIX=acore_backup
```
## 🔒 Security Settings (Potentially Used by AzerothCore)
```bash
WRONG_PASS_MAX_COUNT=3
WRONG_PASS_BAN_TIME=600
WRONG_PASS_BAN_TYPE=0
BAN_EXPIRY_CHECK_INTERVAL=60
```
## 📈 Game Rates (Potentially Used by AzerothCore)
```bash
RATE_HEALTH=1
RATE_MANA=1
RATE_XP_KILL=1
RATE_XP_QUEST=1
RATE_XP_EXPLORE=1
RATE_DROP_MONEY=1
RATE_DROP_ITEMS=1
RATE_HONOR=1
RATE_REPUTATION=1
RATE_TALENT=1
```
## 👤 Character Settings (Potentially Used by AzerothCore)
```bash
CHARACTERS_PER_ACCOUNT=50
CHARACTERS_PER_REALM=10
HEROIC_CHARACTERS_PER_REALM=1
START_PLAYER_LEVEL=1
START_HEROIC_PLAYER_LEVEL=55
START_PLAYER_MONEY=0
START_HEROIC_PLAYER_MONEY=2000
MAX_PLAYER_LEVEL=80
MIN_DUAL_SPEC_LEVEL=40
```
## 🗺️ VMAP/MMAP Settings (Potentially Used by AzerothCore)
```bash
VMAP_ENABLE_LOS=1
VMAP_ENABLE_HEIGHT=1
VMAP_PET_LOS=1
VMAP_ENABLE_INDOOR_CHECK=1
MMAP_ENABLE_PATH_FINDING=0
```
## 🔌 Module Settings (Not Used in Docker Compose)
```bash
ELUNA_ENABLED=1
```
---
## Notes
**Categories marked "Potentially Used by AzerothCore"** may be used by the AzerothCore server configuration files (worldserver.conf, authserver.conf) even though they're not referenced in the Docker Compose file. These might be substituted into configuration files during container startup.
**Categories marked "Not Used in Docker Compose"** are definitely not used by the current Docker setup and can be safely removed.
If you need to restore any of these variables in the future, they can be found in this documentation file.
**Removal Date**: September 29, 2025
**Reason**: Environment cleanup - variables not referenced in docker-compose-azerothcore-core.yml

View File

@@ -1,203 +0,0 @@
# AzerothCore Web Interface Testing Checklist
## 🧪 **Local Testing Results - Current Status**
Based on the latest docker-compose run, here's the status and testing checklist for all web interfaces:
---
## **✅ WORKING WEB INTERFACES**
### **1. PHPMyAdmin - Database Management**
- **URL**: http://localhost:8081
- **Status**: ✅ **OPERATIONAL**
- **Container**: `ac-phpmyadmin` - Up and running
- **Credentials**:
- Server: `ac-mysql`
- Username: `root`
- Password: `azerothcore123`
#### **Testing Checklist:**
- [ ] Access PHPMyAdmin interface
- [ ] Login with root credentials
- [ ] Verify database connectivity
- [ ] Check `acore_auth` database tables
- [ ] Check `acore_world` database tables
- [ ] Check `acore_characters` database tables
- [ ] Test query execution
- [ ] Verify import/export functionality
---
### **2. Grafana - Monitoring Dashboard**
- **URL**: http://localhost:3001
- **Status**: ✅ **OPERATIONAL**
- **Container**: `ac-grafana` - Up and running
- **Credentials**:
- Username: `admin`
- Password: `acore123`
#### **Testing Checklist:**
- [ ] Access Grafana login page
- [ ] Login with admin credentials
- [ ] Check dashboard configuration
- [ ] Verify plugin installation (grafana-piechart-panel)
- [ ] Test data source connections (if configured)
- [ ] Create test dashboard
- [ ] Verify user management settings
- [ ] Test alerting features (if configured)
---
### **3. InfluxDB - Metrics Database**
- **URL**: http://localhost:8087
- **Status**: ✅ **OPERATIONAL**
- **Container**: `ac-influxdb` - Up and running
- **Credentials**:
- Username: `acore`
- Password: `acore123`
- Organization: `azerothcore`
- Bucket: `metrics`
- Token: `acore-monitoring-token-12345`
#### **Testing Checklist:**
- [ ] Access InfluxDB web interface
- [ ] Login with admin credentials
- [ ] Verify organization setup
- [ ] Check metrics bucket creation
- [ ] Test data exploration
- [ ] Verify API token functionality
- [ ] Test data ingestion (if configured)
- [ ] Check retention policies
---
## **❌ PROBLEMATIC WEB INTERFACES**
### **4. Keira3 - Database Editor**
- **URL**: http://localhost:4201 (when working)
- **Status**: ❌ **SYNTAX ERRORS** - Restarting loop
- **Container**: `ac-keira3` - Shell syntax errors
- **Issue**: `sh: syntax error: EOF in backquote substitution`
#### **Problems Identified:**
- Multi-line shell command syntax issues in docker-compose
- Backquote substitution errors
- Container failing to start properly
#### **Testing Checklist (when fixed):**
- [ ] Access Keira3 interface
- [ ] Connect to AzerothCore database
- [ ] Test world database editing
- [ ] Verify creature data editing
- [ ] Test quest data modification
- [ ] Check item database editing
- [ ] Verify SQL query execution
- [ ] Test data export/import
---
### **5. CMS - Admin Dashboard**
- **URL**: http://localhost:8001 (when working)
- **Status**: ❌ **SYNTAX ERRORS** - Restarting loop
- **Container**: `ac-cms` - Shell redirection errors
- **Issue**: `sh: syntax error: unexpected redirection`
#### **Problems Identified:**
- Multi-line shell command syntax issues in docker-compose
- Shell redirection errors in heredoc
- Nginx configuration issues
#### **Testing Checklist (when fixed):**
- [ ] Access CMS login page
- [ ] Login with admin credentials
- [ ] Test user account management
- [ ] Verify realm status display
- [ ] Check player statistics
- [ ] Test admin commands interface
- [ ] Verify security settings
- [ ] Test responsive design
---
## **✅ FULLY OPERATIONAL SERVICES**
### **6. AzerothCore Servers**
- **Auth Server**: ✅ **FULLY OPERATIONAL** - Ready for client connections
- **World Server**: ✅ **FULLY OPERATIONAL** - AzerothCore ready for players
- **Database Import**: ✅ **COMPLETED** - All databases successfully imported
- **Client Data**: ✅ **LOADED** - 3.1GB game data extracted and available
### **7. Game Server Status**
- **Server IP**: Configure clients to connect to your server IP
- **Auth Port**: 3784 (External port for client authentication)
- **World Port**: 8215 (External port for world server)
- **Client Version**: World of Warcraft 3.3.5a (12340)
- **Status**: **🎉 READY FOR PLAYERS! 🎉**
### **⚠️ PARTIALLY WORKING SERVICES**
### **8. Backup Service**
- **Container**: `ac-backup` - ❌ Restarting
- **Issue**: Cron/backup script configuration problems
- **Schedule**: Automated daily backups at 3:00 AM
### **9. Eluna Scripting**
- **Container**: `ac-eluna` - ❌ Restarting
- **Issue**: Eluna server startup problems
---
## **🔧 REMAINING TASKS FOR FULL FUNCTIONALITY**
### **Priority 1: Web Interface Fixes (Optional)**
1. **Fix Keira3 shell command syntax** in `acore-full.yml`
2. **Fix CMS shell command syntax** in `acore-full.yml`
3. **Resolve heredoc and redirection issues**
### **Priority 2: Service Configuration (Optional)**
1. **Fix backup service cron configuration**
2. **Configure Eluna service properly**
3. **Add proper health checks for backup service**
### **✅ COMPLETED TASKS**
1.**Database import completion** - All databases imported successfully
2.**Logger configuration** - Worldserver logging configured properly
3.**Client data dependencies** - 3.1GB game data loaded successfully
4.**Worldserver file storage** - Logs and data properly mounted to host directories
---
## **🌐 CURRENT ACCESSIBLE WEB INTERFACES**
For **immediate testing**, these interfaces are accessible:
| Service | URL | Status | Purpose |
|---------|-----|--------|---------|
| **PHPMyAdmin** | http://localhost:8081 | ✅ Working | Database management |
| **Grafana** | http://localhost:3001 | ✅ Working | Monitoring dashboards |
| **InfluxDB** | http://localhost:8087 | ✅ Working | Metrics storage |
| **Keira3** | http://localhost:4201 | ❌ Broken | Database editor |
| **CMS** | http://localhost:8001 | ❌ Broken | Admin dashboard |
---
## **📊 TESTING PRIORITY ORDER**
1. **Start with PHPMyAdmin** - Verify database structure and data
2. **Test Grafana** - Check monitoring setup and dashboards
3. **Verify InfluxDB** - Ensure metrics collection is possible
4. **Fix and test Keira3** - Critical for world database editing
5. **Fix and test CMS** - Important for player management
---
## **🚀 NEXT STEPS**
1. **Test the 3 working web interfaces immediately**
2. **Fix syntax errors in docker-compose file**
3. **Wait for database import to complete**
4. **Test AzerothCore server startup**
5. **Verify end-to-end functionality**
**The core monitoring and database management interfaces are working and ready for testing!**

View File

@@ -1,456 +0,0 @@
#!/bin/bash
# ==============================================
# AzerothCore Complete Stack Deployment Script
# ==============================================
# Deploys AzerothCore services in proper order with monitoring
# Designed for Debian systems with Docker/Docker Compose
set -euo pipefail
# Configuration
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" &> /dev/null && pwd)"
LOG_DIR="$SCRIPT_DIR/deployment-logs"
LOG_FILE="$LOG_DIR/deployment-$(date +%Y%m%d_%H%M%S).log"
PID_FILE="/var/run/azerothcore-deploy.pid"
# Ensure log directory exists
mkdir -p "$LOG_DIR"
# Deployment layers in order
COMPOSE_LAYERS=(
"database"
"services"
"optional"
"tools"
)
# Service monitoring timeouts (seconds)
declare -A SERVICE_TIMEOUTS=(
["ac-mysql"]=120
["ac-db-init"]=60
["ac-db-import"]=1800
["ac-client-data"]=2400
["ac-authserver"]=180
["ac-worldserver"]=300
["ac-backup"]=60
["ac-mysql-persist"]=60
)
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
PURPLE='\033[0;35m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color
# Logging functions
log() {
local level="$1"
shift
local message="$*"
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
case "$level" in
"INFO") echo -e "${CYAN}[INFO]${NC} $message" ;;
"WARN") echo -e "${YELLOW}[WARN]${NC} $message" ;;
"ERROR") echo -e "${RED}[ERROR]${NC} $message" ;;
"SUCCESS") echo -e "${GREEN}[SUCCESS]${NC} $message" ;;
"DEBUG") echo -e "${PURPLE}[DEBUG]${NC} $message" ;;
esac
echo "[$timestamp] [$level] $message" >> "$LOG_FILE"
}
# Error handling
cleanup() {
log "INFO" "Cleaning up..."
rm -f "$PID_FILE"
if [[ ${#BACKGROUND_PIDS[@]} -gt 0 ]]; then
log "INFO" "Stopping background monitoring processes..."
for pid in "${BACKGROUND_PIDS[@]}"; do
kill "$pid" 2>/dev/null || true
done
fi
}
trap cleanup EXIT
error_exit() {
log "ERROR" "$1"
cleanup
exit 1
}
# Array to track background processes
BACKGROUND_PIDS=()
# Check prerequisites
check_prerequisites() {
log "INFO" "Checking prerequisites..."
# Check if running as root for system service setup
if [[ "$DEPLOY_MODE" == "system" ]] && [[ $EUID -ne 0 ]]; then
error_exit "System deployment mode requires root privileges"
fi
# Check Docker
if ! command -v docker &> /dev/null; then
error_exit "Docker is not installed"
fi
if ! docker info &> /dev/null; then
error_exit "Docker daemon is not running"
fi
# Check Docker Compose
if ! command -v docker-compose &> /dev/null; then
error_exit "Docker Compose is not installed"
fi
# Check compose files exist
for layer in "${COMPOSE_LAYERS[@]}"; do
local compose_file="docker-compose-azerothcore-${layer}.yml"
if [[ ! -f "$SCRIPT_DIR/$compose_file" ]]; then
error_exit "Missing compose file: $compose_file"
fi
done
log "SUCCESS" "Prerequisites check passed"
}
# Setup environment
setup_environment() {
log "INFO" "Setting up deployment environment..."
# Create log directory
mkdir -p "$LOG_DIR"
# Create data directories
mkdir -p "$SCRIPT_DIR/local-data/mysql-data"
mkdir -p "$SCRIPT_DIR/local-data/config"
mkdir -p "$SCRIPT_DIR/backups"
# Set up environment file
if [[ ! -f "$SCRIPT_DIR/.env" ]]; then
if [[ -f "$SCRIPT_DIR/.env-database-local" ]]; then
log "INFO" "Using local database environment configuration"
cp "$SCRIPT_DIR/.env-database-local" "$SCRIPT_DIR/.env"
else
error_exit "No environment configuration found"
fi
fi
# Store PID for system service management
echo $$ > "$PID_FILE"
log "SUCCESS" "Environment setup complete"
}
# Monitor container health
monitor_container() {
local container_name="$1"
local timeout="${2:-300}"
local start_time=$(date +%s)
log "INFO" "Monitoring $container_name (timeout: ${timeout}s)..."
while [[ $(($(date +%s) - start_time)) -lt $timeout ]]; do
if docker ps --filter "name=$container_name" --format "{{.Names}}" | grep -q "^${container_name}$"; then
local status=$(docker ps --filter "name=$container_name" --format "{{.Status}}")
# Check if container is healthy
if echo "$status" | grep -q "healthy"; then
log "SUCCESS" "$container_name is healthy"
return 0
fi
# Check if container exited
if echo "$status" | grep -q "Exited"; then
local exit_code=$(docker ps -a --filter "name=$container_name" --format "{{.Status}}" | grep -o "Exited ([0-9]*)" | grep -o "[0-9]*")
if [[ "$exit_code" == "0" ]]; then
log "SUCCESS" "$container_name completed successfully"
return 0
else
log "ERROR" "$container_name failed (exit code: $exit_code)"
log "DEBUG" "Container logs:"
docker logs "$container_name" 2>&1 | tail -20 | while read line; do
log "DEBUG" " $line"
done
return 1
fi
fi
# Show periodic status updates
if [[ $(( ($(date +%s) - start_time) % 30 )) -eq 0 ]]; then
log "INFO" "$container_name status: $status"
# Show last few log lines
docker logs "$container_name" --tail 3 2>&1 | while read line; do
log "DEBUG" " [$container_name] $line"
done
fi
else
log "WARN" "Waiting for $container_name to start..."
fi
sleep 5
done
log "ERROR" "Timeout waiting for $container_name after ${timeout}s"
return 1
}
# Deploy a specific layer
deploy_layer() {
local layer="$1"
local compose_file="docker-compose-azerothcore-${layer}.yml"
log "INFO" "Deploying layer: $layer"
# Start the layer
if ! docker-compose -f "$compose_file" up -d; then
error_exit "Failed to start $layer layer"
fi
# Get services in this layer
local services=$(docker-compose -f "$compose_file" config --services)
# Monitor each service
for service in $services; do
local container_name="$service"
local timeout="${SERVICE_TIMEOUTS[$container_name]:-300}"
if ! monitor_container "$container_name" "$timeout"; then
error_exit "Service $container_name failed to start properly"
fi
done
log "SUCCESS" "Layer $layer deployed successfully"
}
# Monitor running services
monitor_services() {
log "INFO" "Starting continuous service monitoring..."
while true; do
local unhealthy_services=()
# Check all running containers
for container in $(docker ps --format "{{.Names}}" | grep "^ac-"); do
local status=$(docker ps --filter "name=$container" --format "{{.Status}}")
if echo "$status" | grep -q "unhealthy\|Restarting\|Exited"; then
unhealthy_services+=("$container")
log "WARN" "Unhealthy service detected: $container ($status)"
fi
done
# Report status
if [[ ${#unhealthy_services[@]} -eq 0 ]]; then
log "INFO" "All services healthy ($(docker ps --filter "name=ac-" --format "{{.Names}}" | wc -l) running)"
else
log "WARN" "Unhealthy services: ${unhealthy_services[*]}"
fi
sleep 60
done
}
# Get deployment status
get_status() {
log "INFO" "Current deployment status:"
for layer in "${COMPOSE_LAYERS[@]}"; do
local compose_file="docker-compose-azerothcore-${layer}.yml"
if [[ -f "$compose_file" ]]; then
echo -e "\n${BLUE}=== $layer Layer ===${NC}"
docker-compose -f "$compose_file" ps 2>/dev/null || echo "Layer not deployed"
fi
done
echo -e "\n${BLUE}=== Resource Usage ===${NC}"
docker stats --no-stream --format "table {{.Container}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.NetIO}}" $(docker ps --filter "name=ac-" --format "{{.Names}}" 2>/dev/null || echo "none") 2>/dev/null || echo "No containers running"
}
# Stop all services
stop_all() {
log "INFO" "Stopping all AzerothCore services..."
# Stop in reverse order
for ((i=${#COMPOSE_LAYERS[@]}-1; i>=0; i--)); do
local layer="${COMPOSE_LAYERS[i]}"
local compose_file="docker-compose-azerothcore-${layer}.yml"
if [[ -f "$compose_file" ]]; then
log "INFO" "Stopping $layer layer..."
docker-compose -f "$compose_file" down 2>/dev/null || true
fi
done
log "SUCCESS" "All services stopped"
}
# Install system service
install_system_service() {
log "INFO" "Installing AzerothCore as system service..."
cat > /etc/systemd/system/azerothcore.service << EOF
[Unit]
Description=AzerothCore WoW Server
After=docker.service
Requires=docker.service
StartLimitIntervalSec=0
[Service]
Type=forking
User=root
WorkingDirectory=$SCRIPT_DIR
ExecStart=$SCRIPT_DIR/azerothcore-deploy.sh start
ExecStop=$SCRIPT_DIR/azerothcore-deploy.sh stop
ExecReload=$SCRIPT_DIR/azerothcore-deploy.sh restart
PIDFile=$PID_FILE
Restart=always
RestartSec=30
TimeoutStartSec=1800
TimeoutStopSec=300
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable azerothcore
log "SUCCESS" "AzerothCore system service installed"
log "INFO" "Use 'systemctl start azerothcore' to start the service"
log "INFO" "Use 'systemctl status azerothcore' to check status"
}
# Main deployment function
main_deploy() {
log "INFO" "Starting AzerothCore deployment..."
check_prerequisites
setup_environment
# Deploy each layer in sequence
for layer in "${COMPOSE_LAYERS[@]}"; do
deploy_layer "$layer"
# Brief pause between layers
sleep 10
done
log "SUCCESS" "AzerothCore deployment completed successfully!"
# Show final status
get_status
# Start background monitoring if not in daemon mode
if [[ "$MONITOR_MODE" == "continuous" ]]; then
monitor_services &
BACKGROUND_PIDS+=($!)
log "INFO" "Background monitoring started (PID: $!)"
# Keep script running
wait
fi
}
# Usage information
usage() {
cat << EOF
Usage: $0 [COMMAND] [OPTIONS]
COMMANDS:
start Deploy AzerothCore stack
stop Stop all AzerothCore services
restart Restart AzerothCore stack
status Show current deployment status
logs [service] Show logs for service (or all services)
install-service Install as system service (requires root)
OPTIONS:
--monitor Enable continuous monitoring
--system System deployment mode (requires root)
--help Show this help message
Examples:
$0 start --monitor # Deploy with continuous monitoring
$0 status # Show current status
$0 logs ac-worldserver # Show worldserver logs
$0 install-service # Install as system service
Environment Variables:
DEPLOY_MODE=system # Enable system mode
MONITOR_MODE=continuous # Enable monitoring
EOF
}
# Parse command line arguments
COMMAND="${1:-start}"
DEPLOY_MODE="${DEPLOY_MODE:-local}"
MONITOR_MODE="${MONITOR_MODE:-single}"
shift || true
while [[ $# -gt 0 ]]; do
case $1 in
--monitor)
MONITOR_MODE="continuous"
shift
;;
--system)
DEPLOY_MODE="system"
shift
;;
--help)
usage
exit 0
;;
*)
break
;;
esac
done
# Execute command
case "$COMMAND" in
"start")
main_deploy
;;
"stop")
stop_all
;;
"restart")
stop_all
sleep 5
main_deploy
;;
"status")
get_status
;;
"logs")
service_name="${1:-}"
if [[ -n "$service_name" ]]; then
docker logs "$service_name" --follow
else
log "INFO" "Available services:"
docker ps --filter "name=ac-" --format "{{.Names}}" || echo "No services running"
fi
;;
"install-service")
install_system_service
;;
"help"|"--help")
usage
exit 0
;;
*)
echo "Unknown command: $COMMAND"
usage
exit 1
;;
esac

View File

@@ -1,330 +0,0 @@
#!/bin/bash
# ==============================================
# AzerothCore Advanced Monitoring Script
# ==============================================
# Real-time monitoring with alerts and health checks
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" &> /dev/null && pwd)"
LOG_DIR="$SCRIPT_DIR/monitoring-logs"
ALERT_LOG="$LOG_DIR/alerts-$(date +%Y%m%d).log"
METRICS_LOG="$LOG_DIR/metrics-$(date +%Y%m%d).log"
WEB_DIR="$SCRIPT_DIR/monitoring-web"
# Create directories
mkdir -p "$LOG_DIR" "$WEB_DIR"
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
# Monitoring configuration
declare -A EXPECTED_SERVICES=(
["ac-mysql"]="MySQL Database"
["ac-authserver"]="Authentication Server"
["ac-worldserver"]="World Server"
["ac-backup"]="Backup Service"
)
declare -A HEALTH_THRESHOLDS=(
["cpu_warn"]=80
["cpu_critical"]=95
["memory_warn"]=80
["memory_critical"]=95
["disk_warn"]=85
["disk_critical"]=95
)
# Alert functions
send_alert() {
local level="$1"
local service="$2"
local message="$3"
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
case "$level" in
"CRITICAL") echo -e "${RED}[CRITICAL]${NC} $service: $message" ;;
"WARNING") echo -e "${YELLOW}[WARNING]${NC} $service: $message" ;;
"INFO") echo -e "${BLUE}[INFO]${NC} $service: $message" ;;
"OK") echo -e "${GREEN}[OK]${NC} $service: $message" ;;
esac
echo "[$timestamp] [$level] $service: $message" >> "$ALERT_LOG"
}
# Get container stats
get_container_stats() {
local container="$1"
if ! docker ps --filter "name=$container" --format "{{.Names}}" | grep -q "^${container}$"; then
echo "status=missing"
return 1
fi
local stats=$(docker stats --no-stream --format "{{.CPUPerc}},{{.MemPerc}},{{.MemUsage}},{{.NetIO}},{{.BlockIO}}" "$container" 2>/dev/null || echo "0.00%,0.00%,0B / 0B,0B / 0B,0B / 0B")
echo "status=running,$stats"
}
# Monitor service health
check_service_health() {
local service="$1"
local description="${EXPECTED_SERVICES[$service]}"
local stats=$(get_container_stats "$service")
if [[ "$stats" == "status=missing" ]]; then
send_alert "CRITICAL" "$service" "$description is not running"
return 1
fi
# Parse stats
IFS=',' read -r status cpu_percent mem_percent mem_usage net_io block_io <<< "$stats"
# Remove % signs for comparison
local cpu_num=$(echo "$cpu_percent" | sed 's/%//')
local mem_num=$(echo "$mem_percent" | sed 's/%//')
# Convert to integers for comparison
cpu_num=$(printf "%.0f" "$cpu_num" 2>/dev/null || echo "0")
mem_num=$(printf "%.0f" "$mem_num" 2>/dev/null || echo "0")
# Check thresholds
if [[ $cpu_num -gt ${HEALTH_THRESHOLDS["cpu_critical"]} ]]; then
send_alert "CRITICAL" "$service" "CPU usage critical: ${cpu_percent}"
elif [[ $cpu_num -gt ${HEALTH_THRESHOLDS["cpu_warn"]} ]]; then
send_alert "WARNING" "$service" "CPU usage high: ${cpu_percent}"
fi
if [[ $mem_num -gt ${HEALTH_THRESHOLDS["memory_critical"]} ]]; then
send_alert "CRITICAL" "$service" "Memory usage critical: ${mem_percent}"
elif [[ $mem_num -gt ${HEALTH_THRESHOLDS["memory_warn"]} ]]; then
send_alert "WARNING" "$service" "Memory usage high: ${mem_percent}"
fi
# Log metrics
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
echo "$timestamp,$service,$cpu_percent,$mem_percent,$mem_usage,$net_io,$block_io" >> "$METRICS_LOG"
return 0
}
# Check database connectivity
check_database_health() {
if docker run --rm --network azerothcore mysql:8.0 \
mysql -h ac-mysql -uroot -p"${MYSQL_ROOT_PASSWORD:-azerothcore123}" \
-e "SELECT 1;" &>/dev/null; then
send_alert "OK" "database" "Database connectivity verified"
return 0
else
send_alert "CRITICAL" "database" "Database connectivity failed"
return 1
fi
}
# Check game server ports
check_game_ports() {
local auth_port="3784"
local world_port="8215"
# Check auth server port
if timeout 5 bash -c "</dev/tcp/localhost/$auth_port" 2>/dev/null; then
send_alert "OK" "authserver" "Port $auth_port responding"
else
send_alert "WARNING" "authserver" "Port $auth_port not responding"
fi
# Check world server port
if timeout 5 bash -c "</dev/tcp/localhost/$world_port" 2>/dev/null; then
send_alert "OK" "worldserver" "Port $world_port responding"
else
send_alert "WARNING" "worldserver" "Port $world_port not responding"
fi
}
# Generate HTML status page
generate_web_status() {
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
local uptime=$(uptime -p 2>/dev/null || echo "Unknown")
cat > "$WEB_DIR/index.html" << EOF
<!DOCTYPE html>
<html>
<head>
<title>AzerothCore Status</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="refresh" content="30">
<style>
body { font-family: Arial, sans-serif; margin: 20px; background: #f5f5f5; }
.container { max-width: 1200px; margin: 0 auto; background: white; padding: 20px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }
.header { text-align: center; margin-bottom: 30px; }
.status-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 20px; }
.service-card { border: 1px solid #ddd; border-radius: 8px; padding: 15px; }
.service-running { border-left: 4px solid #4CAF50; }
.service-warning { border-left: 4px solid #FF9800; }
.service-critical { border-left: 4px solid #F44336; }
.service-missing { border-left: 4px solid #9E9E9E; }
.metric { display: flex; justify-content: space-between; margin: 5px 0; }
.timestamp { text-align: center; color: #666; margin-top: 20px; }
table { width: 100%; border-collapse: collapse; margin: 10px 0; }
th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
th { background-color: #f2f2f2; }
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>🏰 AzerothCore Server Status</h1>
<p>System Uptime: $uptime</p>
</div>
<div class="status-grid">
EOF
# Add service status cards
for service in "${!EXPECTED_SERVICES[@]}"; do
local description="${EXPECTED_SERVICES[$service]}"
local stats=$(get_container_stats "$service")
local css_class="service-missing"
local status_text="Not Running"
if [[ "$stats" != "status=missing" ]]; then
IFS=',' read -r status cpu_percent mem_percent mem_usage net_io block_io <<< "$stats"
css_class="service-running"
status_text="Running"
# Check for warnings
local cpu_num=$(echo "$cpu_percent" | sed 's/%//' | cut -d. -f1)
local mem_num=$(echo "$mem_percent" | sed 's/%//' | cut -d. -f1)
if [[ ${cpu_num:-0} -gt ${HEALTH_THRESHOLDS["cpu_warn"]} ]] || [[ ${mem_num:-0} -gt ${HEALTH_THRESHOLDS["memory_warn"]} ]]; then
css_class="service-warning"
status_text="Warning"
fi
fi
cat >> "$WEB_DIR/index.html" << EOF
<div class="service-card $css_class">
<h3>$description</h3>
<div class="metric"><strong>Service:</strong> <span>$service</span></div>
<div class="metric"><strong>Status:</strong> <span>$status_text</span></div>
EOF
if [[ "$stats" != "status=missing" ]]; then
cat >> "$WEB_DIR/index.html" << EOF
<div class="metric"><strong>CPU:</strong> <span>$cpu_percent</span></div>
<div class="metric"><strong>Memory:</strong> <span>$mem_percent</span></div>
<div class="metric"><strong>Memory Usage:</strong> <span>$mem_usage</span></div>
<div class="metric"><strong>Network I/O:</strong> <span>$net_io</span></div>
EOF
fi
cat >> "$WEB_DIR/index.html" << EOF
</div>
EOF
done
# Add recent alerts
cat >> "$WEB_DIR/index.html" << EOF
</div>
<h2>Recent Alerts</h2>
<table>
<tr><th>Time</th><th>Level</th><th>Service</th><th>Message</th></tr>
EOF
if [[ -f "$ALERT_LOG" ]]; then
tail -10 "$ALERT_LOG" | while IFS= read -r line; do
if [[ -n "$line" ]]; then
# Parse log line: [timestamp] [level] service: message
local timestamp=$(echo "$line" | sed -n 's/\[\([^]]*\)\].*/\1/p')
local level=$(echo "$line" | sed -n 's/.*\[\([^]]*\)\] [^:]*:.*/\1/p')
local service=$(echo "$line" | sed -n 's/.*\] \([^:]*\):.*/\1/p')
local message=$(echo "$line" | sed -n 's/.*: \(.*\)/\1/p')
cat >> "$WEB_DIR/index.html" << EOF
<tr><td>$timestamp</td><td>$level</td><td>$service</td><td>$message</td></tr>
EOF
fi
done
fi
cat >> "$WEB_DIR/index.html" << EOF
</table>
<div class="timestamp">
Last updated: $timestamp
</div>
</div>
</body>
</html>
EOF
}
# Main monitoring loop
main_monitor() {
echo "Starting AzerothCore monitoring..."
echo "Logs: $LOG_DIR"
echo "Web status: $WEB_DIR/index.html"
echo "Press Ctrl+C to stop"
while true; do
echo -e "\n$(date '+%Y-%m-%d %H:%M:%S') - Running health checks..."
# Check each service
for service in "${!EXPECTED_SERVICES[@]}"; do
check_service_health "$service"
done
# Additional health checks
check_database_health
check_game_ports
# Generate web status
generate_web_status
# System resource check
local disk_usage=$(df / | awk 'NR==2 {print $5}' | sed 's/%//')
if [[ ${disk_usage:-0} -gt ${HEALTH_THRESHOLDS["disk_critical"]} ]]; then
send_alert "CRITICAL" "system" "Disk usage critical: ${disk_usage}%"
elif [[ ${disk_usage:-0} -gt ${HEALTH_THRESHOLDS["disk_warn"]} ]]; then
send_alert "WARNING" "system" "Disk usage high: ${disk_usage}%"
fi
sleep 30
done
}
# Command handling
case "${1:-monitor}" in
"monitor")
main_monitor
;;
"status")
generate_web_status
echo "Status page generated: $WEB_DIR/index.html"
;;
"alerts")
if [[ -f "$ALERT_LOG" ]]; then
tail -n 20 "$ALERT_LOG"
else
echo "No alerts found"
fi
;;
"metrics")
if [[ -f "$METRICS_LOG" ]]; then
tail -n 20 "$METRICS_LOG"
else
echo "No metrics found"
fi
;;
*)
echo "Usage: $0 [monitor|status|alerts|metrics]"
exit 1
;;
esac

View File

@@ -1 +0,0 @@
[2025-09-29 22:13:35] [INFO] Cleaning up...

View File

@@ -1,3 +0,0 @@
[2025-09-29 22:13:48] [INFO] Cleaning up...
[2025-09-29 22:13:48] [INFO] Current deployment status:
[2025-09-29 22:13:49] [INFO] Cleaning up...

View File

@@ -1,525 +0,0 @@
# ==============================================
# AZEROTHCORE UNIFIED DOCKER COMPOSE
# ==============================================
# Compatible with both local development and Portainer deployment
# Set DEPLOYMENT_MODE=local|portainer in .env file
services:
# Step 0: Fix MySQL volume permissions
ac-mysql-init:
image: ${ALPINE_IMAGE}
pull_policy: ${IMAGE_PULL_POLICY}
container_name: ${CONTAINER_MYSQL_INIT}
user: "0:0"
volumes:
- ${STORAGE_PATH}/mysql:/mysql-data
command:
- sh
- -c
- |
echo "🔧 Initializing MySQL data directory permissions..."
# Create the directory structure
mkdir -p /mysql-data
# Set broad permissions to ensure MySQL can access
chmod 777 /mysql-data
# Create a marker file to indicate initialization is complete
touch /mysql-data/.permissions-fixed
echo "✅ MySQL data directory permissions initialized"
restart: "no"
networks:
- azerothcore
# Step 1: Standard MySQL database
ac-mysql:
image: ${MYSQL_IMAGE}
pull_policy: ${IMAGE_PULL_POLICY}
container_name: ${CONTAINER_MYSQL}
user: "0:0" # Run as root to handle NFS permissions
depends_on:
- ac-mysql-init
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_ROOT_HOST: '${MYSQL_ROOT_HOST}'
MYSQL_ALLOW_EMPTY_PASSWORD: no
ports:
- "${DOCKER_DB_EXTERNAL_PORT}:${MYSQL_PORT}"
volumes:
- ${STORAGE_PATH}/mysql:/var/lib/mysql
command:
- mysqld
- --default-authentication-plugin=mysql_native_password
- --character-set-server=${MYSQL_CHARACTER_SET}
- --collation-server=${MYSQL_COLLATION}
- --max_connections=${MYSQL_MAX_CONNECTIONS}
- --innodb-buffer-pool-size=${MYSQL_INNODB_BUFFER_POOL_SIZE}
- --innodb-log-file-size=${MYSQL_INNODB_LOG_FILE_SIZE}
- --user=root
restart: unless-stopped
healthcheck:
test: ["CMD", "sh", "-c", "mysqladmin ping -h localhost -u ${MYSQL_USER} -p${MYSQL_ROOT_PASSWORD} --silent || exit 1"]
interval: ${MYSQL_HEALTHCHECK_INTERVAL}
timeout: ${MYSQL_HEALTHCHECK_TIMEOUT}
retries: ${MYSQL_HEALTHCHECK_RETRIES}
start_period: ${MYSQL_HEALTHCHECK_START_PERIOD}
networks:
- azerothcore
# Step 2: Initialize databases
ac-db-init:
image: ${MYSQL_IMAGE}
pull_policy: ${IMAGE_PULL_POLICY}
container_name: ${CONTAINER_DB_INIT}
depends_on:
ac-mysql:
condition: service_healthy
networks:
- azerothcore
environment:
MYSQL_PWD: ${MYSQL_ROOT_PASSWORD}
command:
- sh
- -c
- |
echo "🔧 Waiting for MySQL to be ready..."
# Wait for MySQL to be responsive
for i in $(seq 1 ${DB_WAIT_RETRIES}); do
if mysql -h ${MYSQL_HOST} -u${MYSQL_USER} -p${MYSQL_ROOT_PASSWORD} -e "SELECT 1;" >/dev/null 2>&1; then
echo "✅ MySQL is responsive"
break
fi
echo "⏳ Waiting for MySQL... attempt $i/${DB_WAIT_RETRIES}"
sleep ${DB_WAIT_SLEEP}
done
echo "🗄️ Creating AzerothCore databases..."
mysql -h ${MYSQL_HOST} -u${MYSQL_USER} -p${MYSQL_ROOT_PASSWORD} -e "
CREATE DATABASE IF NOT EXISTS ${DB_AUTH_NAME} DEFAULT CHARACTER SET ${MYSQL_CHARACTER_SET} COLLATE ${MYSQL_COLLATION};
CREATE DATABASE IF NOT EXISTS ${DB_WORLD_NAME} DEFAULT CHARACTER SET ${MYSQL_CHARACTER_SET} COLLATE ${MYSQL_COLLATION};
CREATE DATABASE IF NOT EXISTS ${DB_CHARACTERS_NAME} DEFAULT CHARACTER SET ${MYSQL_CHARACTER_SET} COLLATE ${MYSQL_COLLATION};
SHOW DATABASES;
" || {
echo "❌ Failed to create databases"
exit 1
}
echo "✅ Databases created successfully!"
restart: "no"
# Step 3: Import AzerothCore database schema and data
ac-db-import:
image: ${AC_DB_IMPORT_IMAGE}
pull_policy: ${IMAGE_PULL_POLICY}
container_name: ${CONTAINER_DB_IMPORT}
user: "0:0" # Run as root to handle NFS permissions
depends_on:
- ac-db-init
networks:
- azerothcore
volumes:
- ${STORAGE_PATH}/config:/azerothcore/env/dist/etc
environment:
AC_DATA_DIR: "/azerothcore/data"
AC_LOGS_DIR: "/azerothcore/logs"
AC_LOGIN_DATABASE_INFO: "${CONTAINER_MYSQL};${MYSQL_PORT};${MYSQL_USER};${MYSQL_ROOT_PASSWORD};${DB_AUTH_NAME}"
AC_WORLD_DATABASE_INFO: "${CONTAINER_MYSQL};${MYSQL_PORT};${MYSQL_USER};${MYSQL_ROOT_PASSWORD};${DB_WORLD_NAME}"
AC_CHARACTER_DATABASE_INFO: "${CONTAINER_MYSQL};${MYSQL_PORT};${MYSQL_USER};${MYSQL_ROOT_PASSWORD};${DB_CHARACTERS_NAME}"
AC_CLOSE_IDLE_CONNECTIONS: "false"
AC_UPDATES_ENABLE_DATABASES: "7"
AC_UPDATES_AUTO_SETUP: "1"
AC_LOG_LEVEL: "1"
AC_LOGGER_ROOT_CONFIG: "1,Console"
AC_LOGGER_SERVER_CONFIG: "1,Console"
AC_APPENDER_CONSOLE_CONFIG: "1,2,0"
entrypoint: ["/bin/bash", "-c"]
command:
- |
echo 'Waiting for databases to be ready...'
sleep 10
echo 'Creating config file for dbimport...'
mkdir -p /azerothcore/env/dist/etc
cat > /azerothcore/env/dist/etc/dbimport.conf <<EOF
LoginDatabaseInfo = "${CONTAINER_MYSQL};${MYSQL_PORT};${MYSQL_USER};${MYSQL_ROOT_PASSWORD};${DB_AUTH_NAME}"
WorldDatabaseInfo = "${CONTAINER_MYSQL};${MYSQL_PORT};${MYSQL_USER};${MYSQL_ROOT_PASSWORD};${DB_WORLD_NAME}"
CharacterDatabaseInfo = "${CONTAINER_MYSQL};${MYSQL_PORT};${MYSQL_USER};${MYSQL_ROOT_PASSWORD};${DB_CHARACTERS_NAME}"
Updates.EnableDatabases = 7
Updates.AutoSetup = 1
EOF
echo 'Running database import...'
cd /azerothcore/env/dist/bin
./dbimport
echo 'Database import complete!'
restart: "no"
# Step 4: Auth server
ac-authserver:
image: ${AC_AUTHSERVER_IMAGE}
pull_policy: ${IMAGE_PULL_POLICY}
container_name: ${CONTAINER_AUTHSERVER}
user: "0:0" # Run as root to handle NFS permissions
depends_on:
- ac-db-import
environment:
AC_LOGIN_DATABASE_INFO: "${CONTAINER_MYSQL};${MYSQL_PORT};${MYSQL_USER};${MYSQL_ROOT_PASSWORD};${DB_AUTH_NAME}"
AC_UPDATES_ENABLE_DATABASES: "0"
AC_BIND_IP: "0.0.0.0"
AC_LOG_LEVEL: "1"
AC_LOGGER_ROOT_CONFIG: "1,Console"
AC_LOGGER_SERVER_CONFIG: "1,Console"
AC_APPENDER_CONSOLE_CONFIG: "1,2,0"
ports:
- "${DOCKER_AUTH_EXTERNAL_PORT}:${AUTH_PORT}"
restart: unless-stopped
networks:
- azerothcore
volumes:
- ${STORAGE_PATH}/config:/azerothcore/env/dist/etc
cap_add:
- SYS_NICE
healthcheck:
test: ["CMD", "sh", "-c", "ps aux | grep '[a]uthserver' | grep -v grep || exit 1"]
interval: ${AUTH_HEALTHCHECK_INTERVAL}
timeout: ${AUTH_HEALTHCHECK_TIMEOUT}
retries: ${AUTH_HEALTHCHECK_RETRIES}
start_period: ${AUTH_HEALTHCHECK_START_PERIOD}
# Client Data Download Service
ac-client-data:
image: ${ALPINE_IMAGE}
pull_policy: ${IMAGE_PULL_POLICY}
container_name: ${CONTAINER_CLIENT_DATA}
user: "0:0" # Run as root to handle NFS permissions
volumes:
- ${STORAGE_PATH}/data:/azerothcore/data
- ${STORAGE_PATH}/cache:/cache
working_dir: /tmp
command:
- sh
- -c
- |
apk add --no-cache curl unzip wget ca-certificates p7zip jq
# Create cache directory if it doesn't exist
mkdir -p /cache
# Check if game data already exists
if [ -d '/azerothcore/data/maps' ] && [ -d '/azerothcore/data/vmaps' ] && [ -d '/azerothcore/data/mmaps' ] && [ -d '/azerothcore/data/dbc' ]; then
echo '✅ Game data already exists, verifying integrity...'
# Quick verification of required directories
MISSING_DIRS=""
for dir in maps vmaps mmaps dbc; do
if [ ! -d "/azerothcore/data/$$dir" ] || [ -z "$$(ls -A /azerothcore/data/$$dir 2>/dev/null)" ]; then
MISSING_DIRS="$$MISSING_DIRS $$dir"
fi
done
if [ -z "$$MISSING_DIRS" ]; then
echo '✅ All game data directories verified, startup complete!'
exit 0
else
echo "⚠️ Missing or empty directories:$$MISSING_DIRS"
echo "🔄 Re-extracting game data..."
fi
fi
echo '🚀 Starting AzerothCore game data setup...'
# Get the latest release info from wowgaming/client-data
echo '📡 Fetching latest client data release info...'
RELEASE_INFO=$$(wget -qO- https://api.github.com/repos/wowgaming/client-data/releases/latest 2>/dev/null)
if [ -n "$$RELEASE_INFO" ]; then
LATEST_URL=$$(echo "$$RELEASE_INFO" | grep '"browser_download_url":' | grep '\.zip' | cut -d'"' -f4 | head -1)
LATEST_TAG=$$(echo "$$RELEASE_INFO" | grep '"tag_name":' | cut -d'"' -f4)
LATEST_SIZE=$$(echo "$$RELEASE_INFO" | grep '"size":' | head -1 | grep -o '[0-9]*')
fi
if [ -z "$$LATEST_URL" ]; then
echo '❌ Could not fetch latest release URL'
echo '📥 Using fallback: direct download from v16 release'
LATEST_URL='https://github.com/wowgaming/client-data/releases/download/v16/data.zip'
LATEST_TAG='v16'
LATEST_SIZE='0'
fi
echo "📍 Latest release: $$LATEST_TAG"
echo "📥 Download URL: $$LATEST_URL"
# Cache file paths
CACHE_FILE="/cache/client-data-$$LATEST_TAG.zip"
VERSION_FILE="/cache/client-data-version.txt"
# Check if we have a cached version
if [ -f "$$CACHE_FILE" ] && [ -f "$$VERSION_FILE" ]; then
CACHED_VERSION=$$(cat "$$VERSION_FILE" 2>/dev/null)
if [ "$$CACHED_VERSION" = "$$LATEST_TAG" ]; then
echo "✅ Found cached client data version $$LATEST_TAG"
echo "📊 Cached file size: $$(ls -lh "$$CACHE_FILE" | awk '{print $$5}')"
# Verify cache file integrity
if unzip -t "$$CACHE_FILE" > /dev/null 2>&1; then
echo "✅ Cache file integrity verified"
echo "⚡ Using cached download - skipping download phase"
cp "$$CACHE_FILE" data.zip
else
echo "⚠️ Cache file corrupted, will re-download"
rm -f "$$CACHE_FILE" "$$VERSION_FILE"
fi
else
echo "📦 Cache version ($$CACHED_VERSION) differs from latest ($$LATEST_TAG)"
echo "🗑️ Removing old cache"
rm -f /cache/client-data-*.zip "$$VERSION_FILE"
fi
fi
# Download if we don't have a valid cached file
if [ ! -f "data.zip" ]; then
echo "📥 Downloading client data (~15GB, may take 10-30 minutes)..."
echo "📍 Source: $$LATEST_URL"
# Download with progress indication
wget --progress=bar:force -O "$$CACHE_FILE.tmp" "$$LATEST_URL" || {
echo '❌ wget failed, trying curl...'
curl -L --progress-bar -o "$$CACHE_FILE.tmp" "$$LATEST_URL" || {
echo '❌ All download methods failed'
rm -f "$$CACHE_FILE.tmp"
exit 1
}
}
# Verify download integrity
if unzip -t "$$CACHE_FILE.tmp" > /dev/null 2>&1; then
mv "$$CACHE_FILE.tmp" "$$CACHE_FILE"
echo "$$LATEST_TAG" > "$$VERSION_FILE"
echo '✅ Download completed and verified'
echo "📊 File size: $$(ls -lh "$$CACHE_FILE" | awk '{print $$5}')"
cp "$$CACHE_FILE" data.zip
else
echo '❌ Downloaded file is corrupted'
rm -f "$$CACHE_FILE.tmp"
exit 1
fi
fi
echo '📂 Extracting client data (this may take 10-15 minutes)...'
echo '⏳ Please wait while extracting...'
# Clear existing data if extraction failed previously
rm -rf /azerothcore/data/maps /azerothcore/data/vmaps /azerothcore/data/mmaps /azerothcore/data/dbc
unzip -q data.zip -d /azerothcore/data/ || {
echo '❌ Extraction failed'
rm -f data.zip
exit 1
}
# Clean up temporary extraction file (keep cached version)
rm -f data.zip
echo '✅ Client data extraction complete!'
echo '📁 Verifying extracted directories:'
# Verify required directories exist and have content
ALL_GOOD=true
for dir in maps vmaps mmaps dbc; do
if [ -d "/azerothcore/data/$$dir" ] && [ -n "$$(ls -A /azerothcore/data/$$dir 2>/dev/null)" ]; then
DIR_SIZE=$$(du -sh /azerothcore/data/$$dir 2>/dev/null | cut -f1)
echo "✅ $$dir directory: OK ($$DIR_SIZE)"
else
echo "❌ $$dir directory: MISSING or EMPTY"
ALL_GOOD=false
fi
done
if [ "$$ALL_GOOD" = "true" ]; then
echo '🎉 Game data setup complete! AzerothCore worldserver can now start.'
echo "💾 Cached version $$LATEST_TAG for future use"
else
echo '❌ Some directories are missing or empty'
exit 1
fi
restart: "no"
networks:
- azerothcore
# Step 5: World server with Playerbots support
ac-worldserver:
image: ${AC_WORLDSERVER_IMAGE}
pull_policy: ${IMAGE_PULL_POLICY}
container_name: ${CONTAINER_WORLDSERVER}
user: "0:0" # Run as root to handle NFS permissions
stdin_open: true
tty: true
depends_on:
- ac-authserver
- ac-client-data
environment:
AC_LOGIN_DATABASE_INFO: "${CONTAINER_MYSQL};${MYSQL_PORT};${MYSQL_USER};${MYSQL_ROOT_PASSWORD};${DB_AUTH_NAME}"
AC_WORLD_DATABASE_INFO: "${CONTAINER_MYSQL};${MYSQL_PORT};${MYSQL_USER};${MYSQL_ROOT_PASSWORD};${DB_WORLD_NAME}"
AC_CHARACTER_DATABASE_INFO: "${CONTAINER_MYSQL};${MYSQL_PORT};${MYSQL_USER};${MYSQL_ROOT_PASSWORD};${DB_CHARACTERS_NAME}"
AC_UPDATES_ENABLE_DATABASES: "0"
AC_BIND_IP: "0.0.0.0"
AC_DATA_DIR: "/azerothcore/data"
AC_SOAP_PORT: "7878"
AC_PROCESS_PRIORITY: "0"
PLAYERBOT_ENABLED: "${PLAYERBOT_ENABLED}"
PLAYERBOT_MAX_BOTS: "${PLAYERBOT_MAX_BOTS}"
# Logger configuration - Use config file defaults with proper log level
AC_LOG_LEVEL: "2"
ports:
- "${DOCKER_WORLD_EXTERNAL_PORT}:${WORLD_PORT}"
- "${DOCKER_SOAP_EXTERNAL_PORT}:${SOAP_PORT}"
volumes:
- ${STORAGE_PATH}/data:/azerothcore/data
- ${STORAGE_PATH}/config:/azerothcore/env/dist/etc
- ${STORAGE_PATH}/logs:/azerothcore/logs
- ${STORAGE_PATH}/modules:/azerothcore/modules
restart: unless-stopped
networks:
- azerothcore
cap_add:
- SYS_NICE
healthcheck:
test: ["CMD", "sh", "-c", "ps aux | grep '[w]orldserver' | grep -v grep || exit 1"]
interval: ${WORLD_HEALTHCHECK_INTERVAL}
timeout: ${WORLD_HEALTHCHECK_TIMEOUT}
retries: ${WORLD_HEALTHCHECK_RETRIES}
start_period: ${WORLD_HEALTHCHECK_START_PERIOD}
# Optional: Eluna Lua Engine
ac-eluna:
image: ${AC_ELUNA_IMAGE}
pull_policy: ${IMAGE_PULL_POLICY}
container_name: ${CONTAINER_ELUNA}
depends_on:
- ac-worldserver
restart: unless-stopped
networks:
- azerothcore
# Module Management Service
ac-modules:
image: ${ALPINE_GIT_IMAGE}
pull_policy: ${IMAGE_PULL_POLICY}
container_name: ${CONTAINER_MODULES}
user: "0:0" # Run as root to handle NFS permissions
volumes:
- ${STORAGE_PATH}/modules:/modules
environment:
- MODULE_PLAYERBOTS=${MODULE_PLAYERBOTS}
- MODULE_AOE_LOOT=${MODULE_AOE_LOOT}
- MODULE_LEARN_SPELLS=${MODULE_LEARN_SPELLS}
- MODULE_FIREWORKS=${MODULE_FIREWORKS}
- MODULE_INDIVIDUAL_PROGRESSION=${MODULE_INDIVIDUAL_PROGRESSION}
- DEPLOYMENT_MODE=${DEPLOYMENT_MODE}
entrypoint: ["/bin/sh", "-c"]
command:
- |
echo 'Initializing module management...'
cd /modules
if [ "$DEPLOYMENT_MODE" = "portainer" ]; then
echo 'Simple module setup for Portainer deployment...'
mkdir -p mod-playerbots
echo '✅ Playerbot module directory created'
else
echo 'Advanced module setup for local development...'
# Install Playerbots if enabled
if [ "$MODULE_PLAYERBOTS" = "1" ] && [ ! -d "mod-playerbots" ]; then
echo 'Installing mod-playerbots...'
git clone https://github.com/liyunfan1223/mod-playerbots.git mod-playerbots
fi
# Install AOE Loot if enabled
if [ "$MODULE_AOE_LOOT" = "1" ] && [ ! -d "mod-aoe-loot" ]; then
echo 'Installing mod-aoe-loot...'
git clone https://github.com/azerothcore/mod-aoe-loot.git mod-aoe-loot
fi
# Install Learn Spells if enabled
if [ "$MODULE_LEARN_SPELLS" = "1" ] && [ ! -d "mod-learn-spells" ]; then
echo 'Installing mod-learn-spells...'
git clone https://github.com/azerothcore/mod-learn-spells.git mod-learn-spells
fi
# Install Fireworks on Level if enabled
if [ "$MODULE_FIREWORKS" = "1" ] && [ ! -d "mod-fireworks-on-level" ]; then
echo 'Installing mod-fireworks-on-level...'
git clone https://github.com/azerothcore/mod-fireworks-on-level.git mod-fireworks-on-level
fi
# Install Individual Progression if enabled
if [ "$MODULE_INDIVIDUAL_PROGRESSION" = "1" ] && [ ! -d "mod-individual-progression" ]; then
echo 'Installing mod-individual-progression...'
git clone https://github.com/azerothcore/mod-individual-progression.git mod-individual-progression
fi
fi
echo 'Module management complete. Keeping container alive...'
tail -f /dev/null
restart: "no"
networks:
- azerothcore
# Automated Backup System
ac-backup:
image: ${MYSQL_IMAGE}
pull_policy: ${IMAGE_PULL_POLICY}
container_name: ${CONTAINER_BACKUP}
depends_on:
ac-mysql:
condition: service_healthy
environment:
MYSQL_HOST: ${CONTAINER_MYSQL}
MYSQL_PORT: ${MYSQL_PORT}
MYSQL_USER: ${MYSQL_USER}
MYSQL_PASSWORD: ${MYSQL_ROOT_PASSWORD}
BACKUP_RETENTION_DAYS: ${BACKUP_RETENTION_DAYS}
BACKUP_CRON_SCHEDULE: ${BACKUP_CRON_SCHEDULE}
TZ: ${TZ}
volumes:
- ${HOST_BACKUP_PATH}:/backups
- ${HOST_BACKUP_SCRIPTS_PATH}:/scripts
working_dir: /scripts
command:
- /bin/bash
- -c
- |
apt-get update && apt-get install -y cron
chmod +x /scripts/*.sh 2>/dev/null || echo 'No scripts to make executable'
touch /var/log/backup.log
echo "$$BACKUP_CRON_SCHEDULE /scripts/backup.sh >> /var/log/backup.log 2>&1" | crontab -
echo "Starting backup service with schedule: $$BACKUP_CRON_SCHEDULE"
echo "Backup retention: $$BACKUP_RETENTION_DAYS days"
echo "Scripts location: /scripts"
echo "Backup location: /backups"
if [ -f "/scripts/backup.sh" ]; then
echo "Running initial backup..."
/scripts/backup.sh >> /var/log/backup.log 2>&1
else
echo "No backup script found at /scripts/backup.sh"
fi
echo "Starting cron daemon..."
/etc/init.d/cron start
tail -f /var/log/backup.log
restart: unless-stopped
networks:
- azerothcore
networks:
azerothcore:
driver: bridge
name: ${NETWORK_NAME}
ipam:
config:
- subnet: ${NETWORK_SUBNET}
gateway: ${NETWORK_GATEWAY}

View File

@@ -0,0 +1,76 @@
# AZEROTHCORE DATABASE LAYER ENVIRONMENT
# SERVER CONFIGURATION
# Timezone
TZ=UTC
# DATABASE CREDENTIALS
MYSQL_ROOT_PASSWORD=azerothcore123
# Database connection settings
MYSQL_HOST=ac-mysql
MYSQL_PORT=3306
MYSQL_USER=root
MYSQL_ROOT_HOST=%
MYSQL_PASSWORD=${MYSQL_ROOT_PASSWORD}
# Database names
DB_AUTH_NAME=acore_auth
DB_WORLD_NAME=acore_world
DB_CHARACTERS_NAME=acore_characters
# Database wait settings - Increased for Portainer/NFS deployments
DB_WAIT_RETRIES=60
DB_WAIT_SLEEP=10
# Database layer images
AC_DB_IMPORT_IMAGE=acore/ac-wotlk-db-import:14.0.0-dev
MYSQL_IMAGE=mysql:8.0
ALPINE_IMAGE=alpine:latest
# IMAGE PULL POLICY
IMAGE_PULL_POLICY=if_not_present
# MYSQL CONFIGURATION
# MySQL server settings
MYSQL_CHARACTER_SET=utf8mb4
MYSQL_COLLATION=utf8mb4_unicode_ci
MYSQL_MAX_CONNECTIONS=1000
MYSQL_INNODB_BUFFER_POOL_SIZE=256M
MYSQL_INNODB_LOG_FILE_SIZE=64M
# MySQL health check settings - Moderately increased for Portainer/NFS deployments
MYSQL_HEALTHCHECK_INTERVAL=20s
MYSQL_HEALTHCHECK_TIMEOUT=15s
MYSQL_HEALTHCHECK_RETRIES=25
MYSQL_HEALTHCHECK_START_PERIOD=120s
# NETWORK CONFIGURATION
# External database port
DOCKER_DB_EXTERNAL_PORT=64306
# DEPLOYMENT CONFIGURATION
# Storage configuration for Portainer NFS deployments
STORAGE_PATH=/nfs/containers/azerothcore
# CONTAINER NAMES
# Database layer container names
CONTAINER_MYSQL=ac-mysql
CONTAINER_DB_INIT=ac-db-init
CONTAINER_DB_IMPORT=ac-db-import
CONTAINER_BACKUP=ac-backup
# NETWORK SETTINGS
NETWORK_NAME=azerothcore
NETWORK_SUBNET=172.20.0.0/16
NETWORK_GATEWAY=172.20.0.1
# BACKUP CONFIGURATION
# Host volume paths for backup
HOST_BACKUP_PATH=./backups
HOST_BACKUP_SCRIPTS_PATH=./backup-scripts
# Backup settings
BACKUP_CRON_SCHEDULE=0 3 * * *
BACKUP_RETENTION_DAYS=7

View File

@@ -1,11 +1,11 @@
# ============================================== # ==============================================
# AZEROTHCORE DATABASE LAYER # AZEROTHCORE DATABASE LAYER - PORTAINER VERSION (CLEAN)
# ============================================== # ==============================================
# MySQL database, initialization, import, and backup services # Modified for better Portainer compatibility
# Deploy this layer FIRST before core services # Removed redundant ac-mysql-persist service
services: services:
# Step 1: MySQL database with NFS-compatible approach # Step 1: MySQL database
ac-mysql: ac-mysql:
image: ${MYSQL_IMAGE} image: ${MYSQL_IMAGE}
pull_policy: ${IMAGE_PULL_POLICY} pull_policy: ${IMAGE_PULL_POLICY}
@@ -18,9 +18,7 @@ services:
ports: ports:
- "${DOCKER_DB_EXTERNAL_PORT}:${MYSQL_PORT}" - "${DOCKER_DB_EXTERNAL_PORT}:${MYSQL_PORT}"
volumes: volumes:
# Use bind mount for persistent data
- ${STORAGE_PATH}/mysql-data:/var/lib/mysql-persistent - ${STORAGE_PATH}/mysql-data:/var/lib/mysql-persistent
# Use tmpfs for MySQL runtime with different path
- type: tmpfs - type: tmpfs
target: /var/lib/mysql-runtime target: /var/lib/mysql-runtime
tmpfs: tmpfs:
@@ -29,21 +27,16 @@ services:
command: command:
- | - |
echo "🔧 Starting MySQL with NFS-compatible setup..." echo "🔧 Starting MySQL with NFS-compatible setup..."
# Ensure runtime directory permissions
echo "📁 Setting up MySQL runtime directory..."
mkdir -p /var/lib/mysql-runtime mkdir -p /var/lib/mysql-runtime
chown -R mysql:mysql /var/lib/mysql-runtime chown -R mysql:mysql /var/lib/mysql-runtime
chmod 755 /var/lib/mysql-runtime chmod 755 /var/lib/mysql-runtime
# Check if we have a SQL backup to restore
if [ -f "/var/lib/mysql-persistent/backup.sql" ]; then if [ -f "/var/lib/mysql-persistent/backup.sql" ]; then
echo "📦 SQL backup found, will restore after MySQL starts..." echo "📦 SQL backup found, will restore after MySQL starts..."
else else
echo "🆕 No backup found, will initialize fresh MySQL..." echo "🆕 No backup found, will initialize fresh MySQL..."
fi fi
# Start MySQL with custom data directory
echo "🚀 Starting MySQL server with custom datadir..." echo "🚀 Starting MySQL server with custom datadir..."
exec docker-entrypoint.sh mysqld \ exec docker-entrypoint.sh mysqld \
--datadir=/var/lib/mysql-runtime \ --datadir=/var/lib/mysql-runtime \
@@ -63,14 +56,98 @@ services:
networks: networks:
- azerothcore - azerothcore
# Step 2: Initialize databases and restore data # Step 2: Backup service
ac-backup:
image: ${MYSQL_IMAGE}
pull_policy: ${IMAGE_PULL_POLICY}
container_name: ${CONTAINER_BACKUP}
environment:
MYSQL_HOST: ${CONTAINER_MYSQL}
MYSQL_PORT: ${MYSQL_PORT}
MYSQL_USER: ${MYSQL_USER}
MYSQL_PASSWORD: ${MYSQL_ROOT_PASSWORD}
BACKUP_RETENTION_DAYS: ${BACKUP_RETENTION_DAYS}
BACKUP_CRON_SCHEDULE: ${BACKUP_CRON_SCHEDULE}
TZ: ${TZ}
volumes:
- ${HOST_BACKUP_PATH}:/backups
- ${HOST_BACKUP_SCRIPTS_PATH}:/scripts
working_dir: /scripts
command:
- /bin/bash
- -c
- |
echo "🔧 Starting simple backup service..."
# Create backup function
run_backup() {
echo "💾 [$(date)] Starting database backup..."
# Wait for MySQL to be available
for i in $(seq 1 10); do
if mysqldump -h ${CONTAINER_MYSQL} -u ${MYSQL_USER} -p${MYSQL_PASSWORD} --version >/dev/null 2>&1; then
echo "✅ MySQL connection available"
break
fi
echo "⏳ Waiting for MySQL... attempt $$i/10"
sleep 5
done
# Create backup directory
BACKUP_DIR="/backups/$(date +%Y%m%d_%H%M%S)"
mkdir -p "$$BACKUP_DIR"
# Backup all databases
echo "📦 Backing up databases to $$BACKUP_DIR"
mysqldump -h ${CONTAINER_MYSQL} -u ${MYSQL_USER} -p${MYSQL_PASSWORD} \
--all-databases --single-transaction --routines --triggers \
> "$$BACKUP_DIR/full_backup.sql" 2>/dev/null
if [ -f "$$BACKUP_DIR/full_backup.sql" ]; then
echo "✅ [$(date)] Backup completed: $$BACKUP_DIR/full_backup.sql"
# Cleanup old backups
echo "🧹 Cleaning up backups older than ${BACKUP_RETENTION_DAYS} days..."
find /backups -type d -name "????????_??????" -mtime +${BACKUP_RETENTION_DAYS} -exec rm -rf {} + 2>/dev/null || true
echo "📊 Current backup status:"
ls -la /backups/ 2>/dev/null || echo "No backups directory"
else
echo "❌ [$(date)] Backup failed"
fi
}
echo "Starting backup service with schedule: ${BACKUP_CRON_SCHEDULE}"
echo "Backup retention: ${BACKUP_RETENTION_DAYS} days"
# Wait for MySQL to be ready, then run initial backup
sleep 30
run_backup
# Simple cron-like scheduler (runs backup at 3 AM daily)
while true; do
current_hour=$(date +%H)
current_minute=$(date +%M)
# Check if it's 3:00 AM (matching default cron schedule)
if [ "$$current_hour" = "03" ] && [ "$$current_minute" = "00" ]; then
run_backup
# Sleep for 2 minutes to avoid running multiple times
sleep 120
else
# Sleep for 1 minute before checking again
sleep 60
fi
done
restart: unless-stopped
networks:
- azerothcore
# Step 3: Database initialization (one-time setup)
ac-db-init: ac-db-init:
image: ${MYSQL_IMAGE} image: ${MYSQL_IMAGE}
pull_policy: ${IMAGE_PULL_POLICY} pull_policy: ${IMAGE_PULL_POLICY}
container_name: ${CONTAINER_DB_INIT} container_name: ${CONTAINER_DB_INIT}
depends_on:
ac-mysql:
condition: service_healthy
volumes: volumes:
- ${STORAGE_PATH}/mysql-data:/var/lib/mysql-persistent - ${STORAGE_PATH}/mysql-data:/var/lib/mysql-persistent
networks: networks:
@@ -83,13 +160,13 @@ services:
- | - |
echo "🔧 Waiting for MySQL to be ready..." echo "🔧 Waiting for MySQL to be ready..."
# Wait for MySQL to be responsive # Wait for MySQL to be responsive with longer timeout
for i in $(seq 1 ${DB_WAIT_RETRIES}); do for i in $(seq 1 ${DB_WAIT_RETRIES}); do
if mysql -h ${MYSQL_HOST} -u${MYSQL_USER} -p${MYSQL_ROOT_PASSWORD} -e "SELECT 1;" >/dev/null 2>&1; then if mysql -h ${MYSQL_HOST} -u${MYSQL_USER} -p${MYSQL_ROOT_PASSWORD} -e "SELECT 1;" >/dev/null 2>&1; then
echo "✅ MySQL is responsive" echo "✅ MySQL is responsive"
break break
fi fi
echo "⏳ Waiting for MySQL... attempt $i/${DB_WAIT_RETRIES}" echo "⏳ Waiting for MySQL... attempt $$i/${DB_WAIT_RETRIES}"
sleep ${DB_WAIT_SLEEP} sleep ${DB_WAIT_SLEEP}
done done
@@ -114,14 +191,12 @@ services:
echo "✅ Databases ready!" echo "✅ Databases ready!"
restart: "no" restart: "no"
# Step 3: Import AzerothCore database schema and data # Step 4: Database import (one-time setup - run after db-init)
ac-db-import: ac-db-import:
image: ${AC_DB_IMPORT_IMAGE} image: ${AC_DB_IMPORT_IMAGE}
pull_policy: ${IMAGE_PULL_POLICY} pull_policy: ${IMAGE_PULL_POLICY}
container_name: ${CONTAINER_DB_IMPORT} container_name: ${CONTAINER_DB_IMPORT}
user: "0:0" # Run as root to handle NFS permissions user: "0:0"
depends_on:
- ac-db-init
networks: networks:
- azerothcore - azerothcore
volumes: volumes:
@@ -143,7 +218,16 @@ services:
command: command:
- | - |
echo 'Waiting for databases to be ready...' echo 'Waiting for databases to be ready...'
sleep 10
# Wait for databases to exist with longer timeout
for i in $(seq 1 120); do
if mysql -h ${CONTAINER_MYSQL} -u${MYSQL_USER} -p${MYSQL_ROOT_PASSWORD} -e "USE ${DB_AUTH_NAME}; USE ${DB_WORLD_NAME}; USE ${DB_CHARACTERS_NAME};" >/dev/null 2>&1; then
echo "✅ All databases accessible"
break
fi
echo "⏳ Waiting for databases... attempt $$i/120"
sleep 5
done
echo 'Creating config file for dbimport...' echo 'Creating config file for dbimport...'
mkdir -p /azerothcore/env/dist/etc mkdir -p /azerothcore/env/dist/etc
@@ -162,100 +246,6 @@ services:
echo 'Database import complete!' echo 'Database import complete!'
restart: "no" restart: "no"
# MySQL Data Persistence Service
ac-mysql-persist:
image: ${MYSQL_IMAGE}
pull_policy: ${IMAGE_PULL_POLICY}
container_name: ac-mysql-persist
depends_on:
ac-mysql:
condition: service_healthy
environment:
MYSQL_HOST: ${CONTAINER_MYSQL}
MYSQL_PORT: ${MYSQL_PORT}
MYSQL_USER: ${MYSQL_USER}
MYSQL_PASSWORD: ${MYSQL_ROOT_PASSWORD}
TZ: ${TZ}
volumes:
- ${STORAGE_PATH}/mysql-data:/var/lib/mysql-persistent
command:
- /bin/bash
- -c
- |
echo "🔄 Starting MySQL persistence service..."
# Create persistent directory
mkdir -p /var/lib/mysql-persistent
# Function to backup MySQL data
backup_mysql_data() {
echo "💾 Backing up MySQL data to persistent storage..."
# Create SQL dump for safety
mysqldump -h ${CONTAINER_MYSQL} -u ${MYSQL_USER} -p${MYSQL_PASSWORD} --all-databases \
--single-transaction --routines --triggers > /var/lib/mysql-persistent/backup.sql 2>/dev/null || true
echo "✅ MySQL data backup completed"
}
# Initial backup
sleep 30 # Wait for MySQL to be fully ready
backup_mysql_data
# Schedule periodic backups every 30 minutes
while true; do
sleep 1800 # 30 minutes
backup_mysql_data
done
restart: unless-stopped
networks:
- azerothcore
# Automated Backup System
ac-backup:
image: ${MYSQL_IMAGE}
pull_policy: ${IMAGE_PULL_POLICY}
container_name: ${CONTAINER_BACKUP}
depends_on:
ac-mysql:
condition: service_healthy
environment:
MYSQL_HOST: ${CONTAINER_MYSQL}
MYSQL_PORT: ${MYSQL_PORT}
MYSQL_USER: ${MYSQL_USER}
MYSQL_PASSWORD: ${MYSQL_ROOT_PASSWORD}
BACKUP_RETENTION_DAYS: ${BACKUP_RETENTION_DAYS}
BACKUP_CRON_SCHEDULE: ${BACKUP_CRON_SCHEDULE}
TZ: ${TZ}
volumes:
- ${HOST_BACKUP_PATH}:/backups
- ${HOST_BACKUP_SCRIPTS_PATH}:/scripts
working_dir: /scripts
command:
- /bin/bash
- -c
- |
apt-get update && apt-get install -y cron
chmod +x /scripts/*.sh 2>/dev/null || echo 'No scripts to make executable'
touch /var/log/backup.log
echo "$$BACKUP_CRON_SCHEDULE /scripts/backup.sh >> /var/log/backup.log 2>&1" | crontab -
echo "Starting backup service with schedule: $$BACKUP_CRON_SCHEDULE"
echo "Backup retention: $$BACKUP_RETENTION_DAYS days"
echo "Scripts location: /scripts"
echo "Backup location: /backups"
if [ -f "/scripts/backup.sh" ]; then
echo "Running initial backup..."
/scripts/backup.sh >> /var/log/backup.log 2>&1
else
echo "No backup script found at /scripts/backup.sh"
fi
echo "Starting cron daemon..."
/etc/init.d/cron start
tail -f /var/log/backup.log
restart: unless-stopped
networks:
- azerothcore
networks: networks:
azerothcore: azerothcore:
driver: bridge driver: bridge

View File

@@ -1,7 +1,7 @@
# ============================================== # ==============================================
# AZEROTHCORE CORE SERVICES ENVIRONMENT # AZEROTHCORE SERVICES ENVIRONMENT (COMBINED)
# ============================================== # ==============================================
# Environment variables for auth server, world server, and client data # Environment variables for auth server, world server, client data, modules, and optional services
# ============================================== # ==============================================
# DATABASE CONNECTION (REQUIRED) # DATABASE CONNECTION (REQUIRED)
@@ -25,6 +25,10 @@ AC_AUTHSERVER_IMAGE=acore/ac-wotlk-authserver:14.0.0-dev
AC_WORLDSERVER_IMAGE=acore/ac-wotlk-worldserver:14.0.0-dev AC_WORLDSERVER_IMAGE=acore/ac-wotlk-worldserver:14.0.0-dev
ALPINE_IMAGE=alpine:latest ALPINE_IMAGE=alpine:latest
# Optional service images (from combined optional layer)
AC_ELUNA_IMAGE=acore/eluna-ts:master
ALPINE_GIT_IMAGE=alpine/git:latest
# ============================================== # ==============================================
# IMAGE PULL POLICY (REQUIRED) # IMAGE PULL POLICY (REQUIRED)
# ============================================== # ==============================================
@@ -62,7 +66,7 @@ SOAP_PORT=7878
# DEPLOYMENT CONFIGURATION (REQUIRED) # DEPLOYMENT CONFIGURATION (REQUIRED)
# ============================================== # ==============================================
# Storage configuration (must match database layer) # Storage configuration (must match database layer)
STORAGE_PATH=./local-data STORAGE_PATH=/nfs/containers/azerothcore
# ============================================== # ==============================================
# CONTAINER NAMES (REQUIRED) # CONTAINER NAMES (REQUIRED)
@@ -87,3 +91,20 @@ NETWORK_NAME=azerothcore
# Playerbot settings # Playerbot settings
PLAYERBOT_ENABLED=1 PLAYERBOT_ENABLED=1
PLAYERBOT_MAX_BOTS=40 PLAYERBOT_MAX_BOTS=40
# Module configuration
MODULE_PLAYERBOTS=1
MODULE_AOE_LOOT=0
MODULE_LEARN_SPELLS=0
MODULE_FIREWORKS=0
MODULE_INDIVIDUAL_PROGRESSION=0
# Deployment mode
DEPLOYMENT_MODE=portainer
# ==============================================
# ADDITIONAL CONTAINER NAMES (OPTIONAL)
# ==============================================
# Optional service container names
CONTAINER_ELUNA=ac-eluna
CONTAINER_MODULES=ac-modules

View File

@@ -1,7 +1,7 @@
# ============================================== # ==============================================
# AZEROTHCORE CORE SERVICES LAYER # AZEROTHCORE SERVICES LAYER (COMBINED)
# ============================================== # ==============================================
# Authentication server, world server, and client data # Authentication server, world server, client data, modules, and optional services
# Deploy this layer AFTER the database layer is running # Deploy this layer AFTER the database layer is running
services: services:
@@ -10,7 +10,7 @@ services:
image: ${ALPINE_IMAGE} image: ${ALPINE_IMAGE}
pull_policy: ${IMAGE_PULL_POLICY} pull_policy: ${IMAGE_PULL_POLICY}
container_name: ${CONTAINER_CLIENT_DATA} container_name: ${CONTAINER_CLIENT_DATA}
user: "0:0" # Run as root to handle NFS permissions user: "0:0" # Run as root to install packages
volumes: volumes:
- ${STORAGE_PATH}/data:/azerothcore/data - ${STORAGE_PATH}/data:/azerothcore/data
- ${STORAGE_PATH}/cache:/cache - ${STORAGE_PATH}/cache:/cache
@@ -21,30 +21,12 @@ services:
- | - |
apk add --no-cache curl unzip wget ca-certificates p7zip jq apk add --no-cache curl unzip wget ca-certificates p7zip jq
# Fix ownership of mount points to match NFS
chown -R 1001:1001 /azerothcore/data /cache
# Create cache directory if it doesn't exist # Create cache directory if it doesn't exist
mkdir -p /cache mkdir -p /cache
# Check if game data already exists
if [ -d '/azerothcore/data/maps' ] && [ -d '/azerothcore/data/vmaps' ] && [ -d '/azerothcore/data/mmaps' ] && [ -d '/azerothcore/data/dbc' ]; then
echo '✅ Game data already exists, verifying integrity...'
# Quick verification of required directories
MISSING_DIRS=""
for dir in maps vmaps mmaps dbc; do
if [ ! -d "/azerothcore/data/$$dir" ] || [ -z "$$(ls -A /azerothcore/data/$$dir 2>/dev/null)" ]; then
MISSING_DIRS="$$MISSING_DIRS $$dir"
fi
done
if [ -z "$$MISSING_DIRS" ]; then
echo '✅ All game data directories verified, startup complete!'
exit 0
else
echo "⚠️ Missing or empty directories:$$MISSING_DIRS"
echo "🔄 Re-extracting game data..."
fi
fi
echo '🚀 Starting AzerothCore game data setup...' echo '🚀 Starting AzerothCore game data setup...'
# Get the latest release info from wowgaming/client-data # Get the latest release info from wowgaming/client-data
@@ -100,8 +82,9 @@ services:
echo "📥 Downloading client data (~15GB, may take 10-30 minutes)..." echo "📥 Downloading client data (~15GB, may take 10-30 minutes)..."
echo "📍 Source: $$LATEST_URL" echo "📍 Source: $$LATEST_URL"
# Download with progress indication # Download with clean progress indication
wget --progress=bar:force -O "$$CACHE_FILE.tmp" "$$LATEST_URL" || { echo "📥 Starting download..."
wget --progress=dot:giga -O "$$CACHE_FILE.tmp" "$$LATEST_URL" 2>&1 | sed 's/^/📊 /' || {
echo '❌ wget failed, trying curl...' echo '❌ wget failed, trying curl...'
curl -L --progress-bar -o "$$CACHE_FILE.tmp" "$$LATEST_URL" || { curl -L --progress-bar -o "$$CACHE_FILE.tmp" "$$LATEST_URL" || {
echo '❌ All download methods failed' echo '❌ All download methods failed'
@@ -130,11 +113,57 @@ services:
# Clear existing data if extraction failed previously # Clear existing data if extraction failed previously
rm -rf /azerothcore/data/maps /azerothcore/data/vmaps /azerothcore/data/mmaps /azerothcore/data/dbc rm -rf /azerothcore/data/maps /azerothcore/data/vmaps /azerothcore/data/mmaps /azerothcore/data/dbc
unzip -q data.zip -d /azerothcore/data/ || { # Extract with detailed progress tracking
echo '🔄 Starting extraction with progress monitoring...'
# Start extraction in background with overwrite
unzip -o -q data.zip -d /azerothcore/data/ &
UNZIP_PID=$!
LAST_CHECK_TIME=0
# Monitor progress with directory size checks
while kill -0 "$$UNZIP_PID" 2>/dev/null; do
CURRENT_TIME=$$(date +%s)
if [ $$((CURRENT_TIME - LAST_CHECK_TIME)) -ge 30 ]; then
LAST_CHECK_TIME=$$CURRENT_TIME
# Check what's been extracted so far
PROGRESS_MSG="📊 Progress at $$(date '+%H:%M:%S'):"
if [ -d "/azerothcore/data/dbc" ] && [ -n "$$(ls -A /azerothcore/data/dbc 2>/dev/null)" ]; then
DBC_SIZE=$$(du -sh /azerothcore/data/dbc 2>/dev/null | cut -f1)
PROGRESS_MSG="$$PROGRESS_MSG DBC($$DBC_SIZE)"
fi
if [ -d "/azerothcore/data/maps" ] && [ -n "$$(ls -A /azerothcore/data/maps 2>/dev/null)" ]; then
MAPS_SIZE=$$(du -sh /azerothcore/data/maps 2>/dev/null | cut -f1)
PROGRESS_MSG="$$PROGRESS_MSG Maps($$MAPS_SIZE)"
fi
if [ -d "/azerothcore/data/vmaps" ] && [ -n "$$(ls -A /azerothcore/data/vmaps 2>/dev/null)" ]; then
VMAPS_SIZE=$$(du -sh /azerothcore/data/vmaps 2>/dev/null | cut -f1)
PROGRESS_MSG="$$PROGRESS_MSG VMaps($$VMAPS_SIZE)"
fi
if [ -d "/azerothcore/data/mmaps" ] && [ -n "$$(ls -A /azerothcore/data/mmaps 2>/dev/null)" ]; then
MMAPS_SIZE=$$(du -sh /azerothcore/data/mmaps 2>/dev/null | cut -f1)
PROGRESS_MSG="$$PROGRESS_MSG MMaps($$MMAPS_SIZE)"
fi
echo "$$PROGRESS_MSG"
fi
sleep 5
done
wait "$$UNZIP_PID"
UNZIP_EXIT_CODE=$?
if [ $$UNZIP_EXIT_CODE -ne 0 ]; then
echo '❌ Extraction failed' echo '❌ Extraction failed'
rm -f data.zip rm -f data.zip
exit 1 exit 1
} fi
# Clean up temporary extraction file (keep cached version) # Clean up temporary extraction file (keep cached version)
rm -f data.zip rm -f data.zip
@@ -171,8 +200,6 @@ services:
pull_policy: ${IMAGE_PULL_POLICY} pull_policy: ${IMAGE_PULL_POLICY}
container_name: ${CONTAINER_AUTHSERVER} container_name: ${CONTAINER_AUTHSERVER}
user: "0:0" # Run as root to handle NFS permissions user: "0:0" # Run as root to handle NFS permissions
external_links:
- ${CONTAINER_MYSQL}:${CONTAINER_MYSQL}
environment: environment:
AC_LOGIN_DATABASE_INFO: "${CONTAINER_MYSQL};${MYSQL_PORT};${MYSQL_USER};${MYSQL_ROOT_PASSWORD};${DB_AUTH_NAME}" AC_LOGIN_DATABASE_INFO: "${CONTAINER_MYSQL};${MYSQL_PORT};${MYSQL_USER};${MYSQL_ROOT_PASSWORD};${DB_AUTH_NAME}"
AC_UPDATES_ENABLE_DATABASES: "0" AC_UPDATES_ENABLE_DATABASES: "0"
@@ -208,8 +235,6 @@ services:
depends_on: depends_on:
- ac-authserver - ac-authserver
- ac-client-data - ac-client-data
external_links:
- ${CONTAINER_MYSQL}:${CONTAINER_MYSQL}
environment: environment:
AC_LOGIN_DATABASE_INFO: "${CONTAINER_MYSQL};${MYSQL_PORT};${MYSQL_USER};${MYSQL_ROOT_PASSWORD};${DB_AUTH_NAME}" AC_LOGIN_DATABASE_INFO: "${CONTAINER_MYSQL};${MYSQL_PORT};${MYSQL_USER};${MYSQL_ROOT_PASSWORD};${DB_AUTH_NAME}"
AC_WORLD_DATABASE_INFO: "${CONTAINER_MYSQL};${MYSQL_PORT};${MYSQL_USER};${MYSQL_ROOT_PASSWORD};${DB_WORLD_NAME}" AC_WORLD_DATABASE_INFO: "${CONTAINER_MYSQL};${MYSQL_PORT};${MYSQL_USER};${MYSQL_ROOT_PASSWORD};${DB_WORLD_NAME}"
@@ -243,6 +268,80 @@ services:
retries: ${WORLD_HEALTHCHECK_RETRIES} retries: ${WORLD_HEALTHCHECK_RETRIES}
start_period: ${WORLD_HEALTHCHECK_START_PERIOD} start_period: ${WORLD_HEALTHCHECK_START_PERIOD}
# Optional: Eluna Lua Engine
ac-eluna:
image: ${AC_ELUNA_IMAGE}
pull_policy: ${IMAGE_PULL_POLICY}
container_name: ${CONTAINER_ELUNA}
user: "0:0" # Run as root to handle NFS permissions
restart: unless-stopped
networks:
- azerothcore
# Module Management Service
ac-modules:
image: ${ALPINE_GIT_IMAGE}
pull_policy: ${IMAGE_PULL_POLICY}
container_name: ${CONTAINER_MODULES}
user: "0:0" # Run as root to handle NFS permissions
volumes:
- ${STORAGE_PATH}/modules:/modules
environment:
- MODULE_PLAYERBOTS=${MODULE_PLAYERBOTS}
- MODULE_AOE_LOOT=${MODULE_AOE_LOOT}
- MODULE_LEARN_SPELLS=${MODULE_LEARN_SPELLS}
- MODULE_FIREWORKS=${MODULE_FIREWORKS}
- MODULE_INDIVIDUAL_PROGRESSION=${MODULE_INDIVIDUAL_PROGRESSION}
- DEPLOYMENT_MODE=${DEPLOYMENT_MODE}
entrypoint: ["/bin/sh", "-c"]
command:
- |
echo 'Initializing module management...'
cd /modules
if [ "$DEPLOYMENT_MODE" = "portainer" ]; then
echo 'Simple module setup for Portainer deployment...'
mkdir -p mod-playerbots
echo '✅ Playerbot module directory created'
else
echo 'Advanced module setup for local development...'
# Install Playerbots if enabled
if [ "$MODULE_PLAYERBOTS" = "1" ] && [ ! -d "mod-playerbots" ]; then
echo 'Installing mod-playerbots...'
git clone https://github.com/liyunfan1223/mod-playerbots.git mod-playerbots
fi
# Install AOE Loot if enabled
if [ "$MODULE_AOE_LOOT" = "1" ] && [ ! -d "mod-aoe-loot" ]; then
echo 'Installing mod-aoe-loot...'
git clone https://github.com/azerothcore/mod-aoe-loot.git mod-aoe-loot
fi
# Install Learn Spells if enabled
if [ "$MODULE_LEARN_SPELLS" = "1" ] && [ ! -d "mod-learn-spells" ]; then
echo 'Installing mod-learn-spells...'
git clone https://github.com/azerothcore/mod-learn-spells.git mod-learn-spells
fi
# Install Fireworks on Level if enabled
if [ "$MODULE_FIREWORKS" = "1" ] && [ ! -d "mod-fireworks-on-level" ]; then
echo 'Installing mod-fireworks-on-level...'
git clone https://github.com/azerothcore/mod-fireworks-on-level.git mod-fireworks-on-level
fi
# Install Individual Progression if enabled
if [ "$MODULE_INDIVIDUAL_PROGRESSION" = "1" ] && [ ! -d "mod-individual-progression" ]; then
echo 'Installing mod-individual-progression...'
git clone https://github.com/azerothcore/mod-individual-progression.git mod-individual-progression
fi
fi
echo 'Module management complete. Keeping container alive...'
tail -f /dev/null
restart: "no"
networks:
- azerothcore
networks: networks:
azerothcore: azerothcore:
external: true external: true

View File

@@ -11,9 +11,9 @@
DOCKER_DB_ROOT_PASSWORD=azerothcore123 DOCKER_DB_ROOT_PASSWORD=azerothcore123
# Database connection for tools (connects to core stack) # Database connection for tools (connects to core stack)
# Use host.docker.internal for Docker Desktop or actual server IP # Connect directly to ac-mysql container on azerothcore network
MYSQL_HOST=host.docker.internal MYSQL_HOST=ac-mysql
MYSQL_PORT=64306 MYSQL_PORT=3306
# ============================================== # ==============================================
# TOOL STORAGE PATHS (REQUIRED) # TOOL STORAGE PATHS (REQUIRED)
@@ -32,8 +32,8 @@ TOOLS_NETWORK_GATEWAY=172.21.0.1
# WEB INTERFACE PORTS (REQUIRED) # WEB INTERFACE PORTS (REQUIRED)
# ============================================== # ==============================================
# PHPMyAdmin settings # PHPMyAdmin settings
PMA_HOST=host.docker.internal PMA_HOST=ac-mysql
PMA_PORT=64306 PMA_PORT=3306
PMA_USER=root PMA_USER=root
PMA_EXTERNAL_PORT=8081 PMA_EXTERNAL_PORT=8081
PMA_ARBITRARY=1 PMA_ARBITRARY=1
@@ -44,15 +44,15 @@ PMA_MAX_EXECUTION_TIME=600
# Keira3 Database Editor settings # Keira3 Database Editor settings
KEIRA3_EXTERNAL_PORT=4201 KEIRA3_EXTERNAL_PORT=4201
KEIRA_DATABASE_HOST=host.docker.internal KEIRA_DATABASE_HOST=ac-mysql
KEIRA_DATABASE_PORT=64306 KEIRA_DATABASE_PORT=3306
# Grafana settings # Grafana settings
GF_EXTERNAL_PORT=3001 GF_EXTERNAL_PORT=3001
GF_SECURITY_ADMIN_USER=admin GF_SECURITY_ADMIN_USER=admin
GF_SECURITY_ADMIN_PASSWORD=acore123 GF_SECURITY_ADMIN_PASSWORD=acore123
GF_SERVER_ROOT_URL=http://localhost:3001 GF_SERVER_ROOT_URL=http://localhost:3001
GF_INSTALL_PLUGINS=grafana-piechart-panel GF_PLUGINS_PREINSTALL=grafana-piechart-panel
# Security settings # Security settings
GF_SECURITY_DISABLE_INITIAL_ADMIN_CREATION=false GF_SECURITY_DISABLE_INITIAL_ADMIN_CREATION=false
GF_SECURITY_SECRET_KEY= GF_SECURITY_SECRET_KEY=

View File

@@ -10,8 +10,8 @@ services:
image: phpmyadmin/phpmyadmin:latest image: phpmyadmin/phpmyadmin:latest
container_name: ac-phpmyadmin container_name: ac-phpmyadmin
environment: environment:
PMA_HOST: ${PMA_HOST:-host.docker.internal} PMA_HOST: ${PMA_HOST:-ac-mysql}
PMA_PORT: ${PMA_PORT:-64306} PMA_PORT: ${PMA_PORT:-3306}
PMA_USER: ${PMA_USER:-root} PMA_USER: ${PMA_USER:-root}
PMA_PASSWORD: ${DOCKER_DB_ROOT_PASSWORD:-password} PMA_PASSWORD: ${DOCKER_DB_ROOT_PASSWORD:-password}
MYSQL_ROOT_PASSWORD: ${DOCKER_DB_ROOT_PASSWORD:-password} MYSQL_ROOT_PASSWORD: ${DOCKER_DB_ROOT_PASSWORD:-password}
@@ -24,7 +24,7 @@ services:
- "${PMA_EXTERNAL_PORT:-8081}:80" - "${PMA_EXTERNAL_PORT:-8081}:80"
restart: unless-stopped restart: unless-stopped
networks: networks:
- azerothcore-tools - azerothcore
# Keira3 Database Editor (Production Ready) # Keira3 Database Editor (Production Ready)
ac-keira3: ac-keira3:
@@ -35,8 +35,8 @@ services:
- NODE_ENV=production - NODE_ENV=production
- KEIRA_PORT=8080 - KEIRA_PORT=8080
- KEIRA_HOST=0.0.0.0 - KEIRA_HOST=0.0.0.0
- KEIRA_DATABASE_HOST=${KEIRA_DATABASE_HOST:-host.docker.internal} - KEIRA_DATABASE_HOST=${KEIRA_DATABASE_HOST:-ac-mysql}
- KEIRA_DATABASE_PORT=${KEIRA_DATABASE_PORT:-64306} - KEIRA_DATABASE_PORT=${KEIRA_DATABASE_PORT:-3306}
- KEIRA_DATABASE_USER=root - KEIRA_DATABASE_USER=root
- KEIRA_DATABASE_PASSWORD=${DOCKER_DB_ROOT_PASSWORD:-password} - KEIRA_DATABASE_PASSWORD=${DOCKER_DB_ROOT_PASSWORD:-password}
- KEIRA_DATABASE_NAME=acore_world - KEIRA_DATABASE_NAME=acore_world
@@ -64,7 +64,7 @@ services:
security_opt: security_opt:
- no-new-privileges:true - no-new-privileges:true
networks: networks:
- azerothcore-tools - azerothcore
# InfluxDB for Monitoring # InfluxDB for Monitoring
ac-influxdb: ac-influxdb:
@@ -85,18 +85,19 @@ services:
- ${STORAGE_PATH_TOOLS:-./volumes-tools}/azerothcore/influxdb:/var/lib/influxdb2 - ${STORAGE_PATH_TOOLS:-./volumes-tools}/azerothcore/influxdb:/var/lib/influxdb2
restart: unless-stopped restart: unless-stopped
networks: networks:
- azerothcore-tools - azerothcore
# Grafana Monitoring Dashboard # Grafana Monitoring Dashboard
ac-grafana: ac-grafana:
image: grafana/grafana:latest image: grafana/grafana:latest
container_name: ac-grafana container_name: ac-grafana
user: "0:0" # Run as root to handle NFS permissions
depends_on: depends_on:
- ac-influxdb - ac-influxdb
environment: environment:
GF_SECURITY_ADMIN_USER: ${GF_SECURITY_ADMIN_USER:-admin} GF_SECURITY_ADMIN_USER: ${GF_SECURITY_ADMIN_USER:-admin}
GF_SECURITY_ADMIN_PASSWORD: ${GF_SECURITY_ADMIN_PASSWORD:-acore123} GF_SECURITY_ADMIN_PASSWORD: ${GF_SECURITY_ADMIN_PASSWORD:-acore123}
GF_INSTALL_PLUGINS: ${GF_INSTALL_PLUGINS:-grafana-piechart-panel} GF_INSTALL_PLUGINS: ${GF_PLUGINS_PREINSTALL:-grafana-piechart-panel}
GF_SERVER_ROOT_URL: ${GF_SERVER_ROOT_URL:-http://localhost:3001} GF_SERVER_ROOT_URL: ${GF_SERVER_ROOT_URL:-http://localhost:3001}
GF_SECURITY_DISABLE_INITIAL_ADMIN_CREATION: ${GF_SECURITY_DISABLE_INITIAL_ADMIN_CREATION:-false} GF_SECURITY_DISABLE_INITIAL_ADMIN_CREATION: ${GF_SECURITY_DISABLE_INITIAL_ADMIN_CREATION:-false}
GF_SECURITY_SECRET_KEY: ${GF_SECURITY_SECRET_KEY:-} GF_SECURITY_SECRET_KEY: ${GF_SECURITY_SECRET_KEY:-}
@@ -110,16 +111,24 @@ services:
- "${GF_EXTERNAL_PORT:-3001}:3000" - "${GF_EXTERNAL_PORT:-3001}:3000"
volumes: volumes:
- ${STORAGE_PATH_TOOLS:-./volumes-tools}/azerothcore/grafana:/var/lib/grafana - ${STORAGE_PATH_TOOLS:-./volumes-tools}/azerothcore/grafana:/var/lib/grafana
- ${STORAGE_PATH_TOOLS:-./volumes-tools}/azerothcore/grafana-config:/etc/grafana entrypoint: ["/bin/bash", "-c"]
command:
- |
echo "🔧 Setting up Grafana permissions..."
# Create directories with proper ownership
mkdir -p /var/lib/grafana
chown -R 472:472 /var/lib/grafana
chmod -R 755 /var/lib/grafana
echo "🚀 Starting Grafana server..."
exec su -s /bin/bash grafana -c "/run.sh"
restart: unless-stopped restart: unless-stopped
networks: networks:
- azerothcore-tools - azerothcore
networks: networks:
azerothcore-tools:
driver: bridge azerothcore:
name: ${TOOLS_NETWORK_NAME:-azerothcore-tools} external: true
ipam: name: azerothcore
config:
- subnet: ${TOOLS_NETWORK_SUBNET:-172.21.0.0/16}
gateway: ${TOOLS_NETWORK_GATEWAY:-172.21.0.1}

View File

@@ -1,442 +0,0 @@
#!/bin/bash
# ==============================================
# AzerothCore System Service Installer
# ==============================================
# Configures AzerothCore to start automatically on Debian systems
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" &> /dev/null && pwd)"
SERVICE_USER="${SERVICE_USER:-azerothcore}"
INSTALL_DIR="${INSTALL_DIR:-/opt/azerothcore}"
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
log() {
local level="$1"
shift
local message="$*"
case "$level" in
"INFO") echo -e "${BLUE}[INFO]${NC} $message" ;;
"WARN") echo -e "${YELLOW}[WARN]${NC} $message" ;;
"ERROR") echo -e "${RED}[ERROR]${NC} $message" ;;
"SUCCESS") echo -e "${GREEN}[SUCCESS]${NC} $message" ;;
esac
}
error_exit() {
log "ERROR" "$1"
exit 1
}
# Check if running as root
check_root() {
if [[ $EUID -ne 0 ]]; then
error_exit "This script must be run as root. Use: sudo $0"
fi
}
# Check prerequisites
check_prerequisites() {
log "INFO" "Checking prerequisites..."
# Check if Docker is installed
if ! command -v docker &> /dev/null; then
error_exit "Docker is not installed. Please install Docker first."
fi
# Check if Docker Compose is installed
if ! command -v docker-compose &> /dev/null; then
error_exit "Docker Compose is not installed. Please install Docker Compose first."
fi
# Check if systemd is available
if ! command -v systemctl &> /dev/null; then
error_exit "systemd is not available on this system"
fi
log "SUCCESS" "Prerequisites check passed"
}
# Create service user
create_service_user() {
log "INFO" "Creating service user: $SERVICE_USER"
if id "$SERVICE_USER" &>/dev/null; then
log "INFO" "User $SERVICE_USER already exists"
else
useradd --system --no-create-home --shell /bin/false --group docker "$SERVICE_USER"
log "SUCCESS" "Created user: $SERVICE_USER"
fi
# Add user to docker group
usermod -aG docker "$SERVICE_USER" || true
}
# Install application
install_application() {
log "INFO" "Installing AzerothCore to $INSTALL_DIR"
# Create install directory
mkdir -p "$INSTALL_DIR"
# Copy application files
cp -r "$SCRIPT_DIR"/* "$INSTALL_DIR/"
# Set ownership
chown -R "$SERVICE_USER:$SERVICE_USER" "$INSTALL_DIR"
# Set permissions
chmod +x "$INSTALL_DIR"/*.sh
log "SUCCESS" "Application installed to $INSTALL_DIR"
}
# Create systemd service files
create_systemd_services() {
log "INFO" "Creating systemd service files..."
# Main AzerothCore service
cat > /etc/systemd/system/azerothcore.service << EOF
[Unit]
Description=AzerothCore World of Warcraft Server
Documentation=https://www.azerothcore.org/
After=docker.service network.target
Requires=docker.service
StartLimitIntervalSec=0
[Service]
Type=forking
User=$SERVICE_USER
Group=$SERVICE_USER
WorkingDirectory=$INSTALL_DIR
Environment=DEPLOY_MODE=system
Environment=MONITOR_MODE=single
ExecStartPre=/usr/bin/docker system prune -f --volumes
ExecStart=$INSTALL_DIR/azerothcore-deploy.sh start
ExecStop=$INSTALL_DIR/azerothcore-deploy.sh stop
ExecReload=/bin/kill -HUP \$MAINPID
PIDFile=/var/run/azerothcore-deploy.pid
Restart=always
RestartSec=30
TimeoutStartSec=1800
TimeoutStopSec=300
KillMode=mixed
KillSignal=SIGTERM
# Resource limits
LimitNOFILE=65536
LimitMEMLOCK=infinity
# Security settings
NoNewPrivileges=yes
ProtectSystem=strict
ProtectHome=yes
ReadWritePaths=$INSTALL_DIR /var/run /tmp
PrivateTmp=yes
[Install]
WantedBy=multi-user.target
EOF
# AzerothCore monitoring service
cat > /etc/systemd/system/azerothcore-monitor.service << EOF
[Unit]
Description=AzerothCore Monitoring Service
After=azerothcore.service
Requires=azerothcore.service
[Service]
Type=simple
User=$SERVICE_USER
Group=$SERVICE_USER
WorkingDirectory=$INSTALL_DIR
Environment=MYSQL_ROOT_PASSWORD=azerothcore123
ExecStart=$INSTALL_DIR/azerothcore-monitor.sh monitor
Restart=always
RestartSec=10
StandardOutput=journal
StandardError=journal
# Security settings
NoNewPrivileges=yes
ProtectSystem=strict
ProtectHome=yes
ReadWritePaths=$INSTALL_DIR
PrivateTmp=yes
[Install]
WantedBy=multi-user.target
EOF
# Web status service (simple HTTP server)
cat > /etc/systemd/system/azerothcore-web.service << EOF
[Unit]
Description=AzerothCore Web Status Server
After=azerothcore-monitor.service
Requires=azerothcore-monitor.service
[Service]
Type=simple
User=$SERVICE_USER
Group=$SERVICE_USER
WorkingDirectory=$INSTALL_DIR/monitoring-web
ExecStart=/usr/bin/python3 -m http.server 8080
Restart=always
RestartSec=10
StandardOutput=journal
StandardError=journal
# Security settings
NoNewPrivileges=yes
ProtectSystem=strict
ProtectHome=yes
ReadWritePaths=$INSTALL_DIR/monitoring-web
PrivateTmp=yes
[Install]
WantedBy=multi-user.target
EOF
log "SUCCESS" "Systemd service files created"
}
# Create startup configuration
create_startup_config() {
log "INFO" "Creating startup configuration..."
# Create environment file
cat > "$INSTALL_DIR/.env-production" << EOF
# Production Environment Configuration
DEPLOYMENT_MODE=production
STORAGE_PATH=$INSTALL_DIR/data
HOST_BACKUP_PATH=$INSTALL_DIR/backups
HOST_BACKUP_SCRIPTS_PATH=$INSTALL_DIR/backup-scripts
# Database configuration
MYSQL_ROOT_PASSWORD=azerothcore123
DB_WAIT_RETRIES=60
DB_WAIT_SLEEP=10
# MySQL health check settings (for slower systems)
MYSQL_HEALTHCHECK_INTERVAL=20s
MYSQL_HEALTHCHECK_TIMEOUT=15s
MYSQL_HEALTHCHECK_RETRIES=25
MYSQL_HEALTHCHECK_START_PERIOD=120s
# Performance settings
MYSQL_MAX_CONNECTIONS=200
MYSQL_INNODB_BUFFER_POOL_SIZE=512M
MYSQL_INNODB_LOG_FILE_SIZE=128M
# Security settings
PLAYERBOT_MAX_BOTS=20
MODULE_PLAYERBOTS=1
EOF
# Set default environment
if [[ ! -f "$INSTALL_DIR/.env" ]]; then
cp "$INSTALL_DIR/.env-production" "$INSTALL_DIR/.env"
fi
# Create data directories
mkdir -p "$INSTALL_DIR/data/mysql-data"
mkdir -p "$INSTALL_DIR/data/config"
mkdir -p "$INSTALL_DIR/backups"
mkdir -p "$INSTALL_DIR/monitoring-logs"
mkdir -p "$INSTALL_DIR/deployment-logs"
# Set ownership
chown -R "$SERVICE_USER:$SERVICE_USER" "$INSTALL_DIR"
log "SUCCESS" "Startup configuration created"
}
# Configure logrotate
configure_logrotate() {
log "INFO" "Configuring log rotation..."
cat > /etc/logrotate.d/azerothcore << EOF
$INSTALL_DIR/deployment-logs/*.log {
daily
rotate 7
compress
delaycompress
missingok
notifempty
copytruncate
su $SERVICE_USER $SERVICE_USER
}
$INSTALL_DIR/monitoring-logs/*.log {
daily
rotate 14
compress
delaycompress
missingok
notifempty
copytruncate
su $SERVICE_USER $SERVICE_USER
}
EOF
log "SUCCESS" "Log rotation configured"
}
# Configure firewall (if ufw is available)
configure_firewall() {
if command -v ufw &> /dev/null; then
log "INFO" "Configuring firewall rules..."
# Game server ports
ufw allow 3784/tcp comment "AzerothCore Auth Server"
ufw allow 8215/tcp comment "AzerothCore World Server"
ufw allow 7778/tcp comment "AzerothCore SOAP"
# Database port (only from localhost)
ufw allow from 127.0.0.1 to any port 64306 comment "AzerothCore MySQL"
# Web status (optional, adjust as needed)
ufw allow 8080/tcp comment "AzerothCore Web Status"
log "SUCCESS" "Firewall rules configured"
else
log "WARN" "UFW not available, skipping firewall configuration"
fi
}
# Enable and start services
enable_services() {
log "INFO" "Enabling and starting services..."
# Reload systemd
systemctl daemon-reload
# Enable services
systemctl enable azerothcore.service
systemctl enable azerothcore-monitor.service
systemctl enable azerothcore-web.service
log "SUCCESS" "Services enabled"
log "INFO" "To start services: systemctl start azerothcore"
log "INFO" "To check status: systemctl status azerothcore"
}
# Create uninstall script
create_uninstall_script() {
cat > "$INSTALL_DIR/uninstall.sh" << 'EOF'
#!/bin/bash
# Uninstall AzerothCore system service
if [[ $EUID -ne 0 ]]; then
echo "This script must be run as root"
exit 1
fi
echo "Stopping services..."
systemctl stop azerothcore-web azerothcore-monitor azerothcore 2>/dev/null || true
echo "Disabling services..."
systemctl disable azerothcore-web azerothcore-monitor azerothcore 2>/dev/null || true
echo "Removing service files..."
rm -f /etc/systemd/system/azerothcore*.service
rm -f /etc/logrotate.d/azerothcore
echo "Reloading systemd..."
systemctl daemon-reload
echo "Removing installation directory..."
read -p "Remove $INSTALL_DIR? [y/N] " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
rm -rf "$INSTALL_DIR"
echo "Installation directory removed"
fi
echo "AzerothCore system service uninstalled"
EOF
chmod +x "$INSTALL_DIR/uninstall.sh"
chown "$SERVICE_USER:$SERVICE_USER" "$INSTALL_DIR/uninstall.sh"
}
# Display installation summary
show_summary() {
log "SUCCESS" "AzerothCore system service installation completed!"
echo
echo "📋 Installation Summary:"
echo " • Install Directory: $INSTALL_DIR"
echo " • Service User: $SERVICE_USER"
echo " • Services: azerothcore, azerothcore-monitor, azerothcore-web"
echo
echo "🚀 Quick Start:"
echo " • Start services: systemctl start azerothcore"
echo " • Check status: systemctl status azerothcore"
echo " • View logs: journalctl -u azerothcore -f"
echo " • Web status: http://localhost:8080"
echo
echo "🔧 Management:"
echo " • Stop services: systemctl stop azerothcore"
echo " • Restart services: systemctl restart azerothcore"
echo " • Disable services: systemctl disable azerothcore"
echo " • Uninstall: $INSTALL_DIR/uninstall.sh"
echo
echo "📁 Important Paths:"
echo " • Configuration: $INSTALL_DIR/.env"
echo " • Data: $INSTALL_DIR/data/"
echo " • Backups: $INSTALL_DIR/backups/"
echo " • Logs: $INSTALL_DIR/deployment-logs/"
echo " • Monitoring: $INSTALL_DIR/monitoring-logs/"
echo
}
# Main installation function
main_install() {
log "INFO" "Starting AzerothCore system service installation..."
check_root
check_prerequisites
create_service_user
install_application
create_systemd_services
create_startup_config
configure_logrotate
configure_firewall
enable_services
create_uninstall_script
show_summary
}
# Command handling
case "${1:-install}" in
"install")
main_install
;;
"uninstall")
if [[ -f "$INSTALL_DIR/uninstall.sh" ]]; then
"$INSTALL_DIR/uninstall.sh"
else
error_exit "Uninstall script not found. Manual removal required."
fi
;;
*)
echo "Usage: $0 [install|uninstall]"
echo
echo "Environment Variables:"
echo " SERVICE_USER=username # Service user (default: azerothcore)"
echo " INSTALL_DIR=path # Install directory (default: /opt/azerothcore)"
echo
echo "Examples:"
echo " sudo $0 install # Standard installation"
echo " sudo SERVICE_USER=wow $0 install # Custom user"
echo " sudo $0 uninstall # Remove installation"
exit 1
;;
esac

View File

@@ -1,5 +0,0 @@
LoginDatabaseInfo = "ac-mysql;3306;root;azerothcore123;acore_auth"
WorldDatabaseInfo = "ac-mysql;3306;root;azerothcore123;acore_world"
CharacterDatabaseInfo = "ac-mysql;3306;root;azerothcore123;acore_characters"
Updates.EnableDatabases = 7
Updates.AutoSetup = 1

View File

@@ -1,65 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<title>AzerothCore Status</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="refresh" content="30">
<style>
body { font-family: Arial, sans-serif; margin: 20px; background: #f5f5f5; }
.container { max-width: 1200px; margin: 0 auto; background: white; padding: 20px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }
.header { text-align: center; margin-bottom: 30px; }
.status-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 20px; }
.service-card { border: 1px solid #ddd; border-radius: 8px; padding: 15px; }
.service-running { border-left: 4px solid #4CAF50; }
.service-warning { border-left: 4px solid #FF9800; }
.service-critical { border-left: 4px solid #F44336; }
.service-missing { border-left: 4px solid #9E9E9E; }
.metric { display: flex; justify-content: space-between; margin: 5px 0; }
.timestamp { text-align: center; color: #666; margin-top: 20px; }
table { width: 100%; border-collapse: collapse; margin: 10px 0; }
th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
th { background-color: #f2f2f2; }
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>🏰 AzerothCore Server Status</h1>
<p>System Uptime: up 1 day, 9 hours, 22 minutes</p>
</div>
<div class="status-grid">
<div class="service-card service-missing">
<h3>Authentication Server</h3>
<div class="metric"><strong>Service:</strong> <span>ac-authserver</span></div>
<div class="metric"><strong>Status:</strong> <span>Not Running</span></div>
</div>
<div class="service-card service-missing">
<h3>MySQL Database</h3>
<div class="metric"><strong>Service:</strong> <span>ac-mysql</span></div>
<div class="metric"><strong>Status:</strong> <span>Not Running</span></div>
</div>
<div class="service-card service-missing">
<h3>Backup Service</h3>
<div class="metric"><strong>Service:</strong> <span>ac-backup</span></div>
<div class="metric"><strong>Status:</strong> <span>Not Running</span></div>
</div>
<div class="service-card service-missing">
<h3>World Server</h3>
<div class="metric"><strong>Service:</strong> <span>ac-worldserver</span></div>
<div class="metric"><strong>Status:</strong> <span>Not Running</span></div>
</div>
</div>
<h2>Recent Alerts</h2>
<table>
<tr><th>Time</th><th>Level</th><th>Service</th><th>Message</th></tr>
</table>
<div class="timestamp">
Last updated: 2025-09-29 22:13:56
</div>
</div>
</body>
</html>

View File

@@ -1,151 +0,0 @@
#!/bin/bash
# Portainer Diagnostics Script for AzerothCore Docker Compose
# Run this on your slower Portainer machine to diagnose timeout issues
echo "==============================================="
echo "AzerothCore Portainer Diagnostics"
echo "==============================================="
echo "Date: $(date)"
echo "Machine: $(hostname)"
echo ""
# System Resources
echo "🖥️ SYSTEM RESOURCES"
echo "-------------------"
echo "CPU Cores: $(nproc)"
echo "Memory: $(free -h | grep '^Mem:' | awk '{print $2 " total, " $7 " available"}')"
echo "Disk Space: $(df -h / | tail -1 | awk '{print $4 " available on " $6}')"
echo "Load Average: $(uptime | awk -F'load average:' '{print $2}')"
echo ""
# Podman Status
echo "🐳 PODMAN STATUS"
echo "----------------"
podman --version
echo "Podman Service Status: $(systemctl is-active podman 2>/dev/null || echo 'Unknown')"
echo "Podman Memory Limit: $(podman system info 2>/dev/null | grep 'memTotal' || echo 'Unable to determine')"
echo ""
# Network Connectivity Tests
echo "🌐 NETWORK CONNECTIVITY"
echo "-----------------------"
echo "Testing GitHub connectivity (for client data download):"
curl -s -w "Response Time: %{time_total}s\n" -o /dev/null https://api.github.com/repos/wowgaming/client-data/releases/latest || echo "❌ GitHub API unreachable"
echo "Testing GitHub download speed (5MB test):"
timeout 30 wget -O /tmp/speed_test.zip https://github.com/wowgaming/client-data/releases/download/v16/data.zip --progress=dot 2>&1 | tail -5 || echo "❌ Download test failed"
rm -f /tmp/speed_test.zip
echo ""
# Check for existing volumes/data
echo "📁 EXISTING DATA CHECK"
echo "---------------------"
VOLUMES_PATH="${STORAGE_PATH_CONTAINERS:-./volumes}"
echo "Checking volumes path: $VOLUMES_PATH"
if [ -d "$VOLUMES_PATH/azerothcore/data" ]; then
echo "✅ Data directory exists"
if [ -d "$VOLUMES_PATH/azerothcore/data/maps" ] && [ -d "$VOLUMES_PATH/azerothcore/data/vmaps" ]; then
echo "✅ Game data appears complete - client download should be skipped"
else
echo "⚠️ Game data incomplete - client download will be required"
fi
else
echo "❌ No existing data - full download required (~15GB)"
fi
if [ -d "$VOLUMES_PATH/azerothcore/mysql" ]; then
echo "✅ MySQL data directory exists"
if [ -f "$VOLUMES_PATH/azerothcore/mysql/acore_world/creature.ibd" ]; then
echo "✅ Database appears populated - import should be skipped"
else
echo "⚠️ Database may need importing"
fi
else
echo "❌ No existing MySQL data - full import required"
fi
echo ""
# Podman Compose Services Status
echo "🔧 PODMAN COMPOSE STATUS"
echo "------------------------"
if [ -f "docker-compose.yml" ]; then
echo "Docker Compose file found"
podman-compose ps 2>/dev/null || echo "Podman Compose not running or not available"
else
echo "❌ docker-compose.yml not found in current directory"
fi
echo ""
# Resource-intensive operation simulation
echo "⏱️ PERFORMANCE TESTS"
echo "--------------------"
echo "Testing disk I/O (1GB file):"
timeout 60 dd if=/dev/zero of=/tmp/test_io bs=1M count=1024 2>&1 | grep -E '(copied|MB/s)' || echo "❌ I/O test failed or too slow"
rm -f /tmp/test_io
echo "Testing compression/extraction speed:"
timeout 30 sh -c 'echo "test data" | gzip > /tmp/test.gz && gunzip /tmp/test.gz && echo "✅ Compression test OK"' || echo "❌ Compression test failed"
rm -f /tmp/test.gz /tmp/test
echo ""
# Memory pressure test
echo "🧠 MEMORY PRESSURE TEST"
echo "-----------------------"
echo "Available memory before test:"
free -h | grep '^Mem:'
echo "Testing memory allocation (512MB):"
timeout 10 sh -c 'python3 -c "import time; data = b\"x\" * (512 * 1024 * 1024); time.sleep(2); print(\"✅ Memory allocation test OK\")"' 2>/dev/null || echo "❌ Memory allocation test failed"
echo "Available memory after test:"
free -h | grep '^Mem:'
echo ""
# Container runtime test
echo "🏃 CONTAINER RUNTIME TEST"
echo "-------------------------"
echo "Testing basic container startup time:"
START_TIME=$(date +%s)
podman run --rm alpine:latest echo "Container startup test" 2>/dev/null || echo "❌ Container startup failed"
END_TIME=$(date +%s)
DURATION=$((END_TIME - START_TIME))
echo "Container startup took: ${DURATION}s"
if [ $DURATION -gt 10 ]; then
echo "⚠️ Container startup is slow (>10s)"
else
echo "✅ Container startup time is acceptable"
fi
echo ""
# Recommendations
echo "💡 RECOMMENDATIONS"
echo "------------------"
# Check if we have enough resources
AVAILABLE_GB=$(df / | tail -1 | awk '{print int($4/1024/1024)}')
MEMORY_GB=$(free -g | grep '^Mem:' | awk '{print $2}')
if [ $AVAILABLE_GB -lt 20 ]; then
echo "⚠️ Low disk space ($AVAILABLE_GB GB available). Need at least 20GB for full setup."
fi
if [ $MEMORY_GB -lt 2 ]; then
echo "⚠️ Low memory ($MEMORY_GB GB). Consider increasing to 4GB+ for better performance."
fi
echo ""
echo "🚀 SUGGESTED PORTAINER DEPLOYMENT STRATEGY:"
echo "1. Pre-download client data on faster machine and copy to Portainer server"
echo "2. Use 'DEPLOYMENT_MODE=portainer' environment variable for simplified setup"
echo "3. Increase Portainer deployment timeouts to 30+ minutes"
echo "4. Deploy services in phases rather than all at once"
echo ""
echo "Diagnostics complete. Save this output for troubleshooting."

View File

@@ -1,135 +0,0 @@
#!/bin/bash
# Real-time monitoring script for Portainer deployment
# Run this DURING deployment to monitor progress and catch issues
echo "==============================================="
echo "AzerothCore Portainer Deployment Monitor"
echo "==============================================="
# Function to monitor container logs
monitor_container() {
local container_name=$1
local max_wait=${2:-300} # Default 5 minutes
local start_time=$(date +%s)
echo "🔍 Monitoring $container_name (max wait: ${max_wait}s)"
while [ $(($(date +%s) - start_time)) -lt $max_wait ]; do
if podman ps --filter "name=$container_name" --format "table {{.Names}}\t{{.Status}}" | grep -q "$container_name"; then
local status=$(podman ps --filter "name=$container_name" --format "{{.Status}}")
echo "[$container_name] Status: $status"
# Show last few log lines
echo "[$container_name] Recent logs:"
podman logs --tail 5 "$container_name" 2>&1 | sed 's/^/ /'
echo ""
# Check if container exited
if echo "$status" | grep -q "Exited"; then
local exit_code=$(podman ps -a --filter "name=$container_name" --format "{{.Status}}" | grep -o "Exited ([0-9]*)" | grep -o "[0-9]*")
if [ "$exit_code" = "0" ]; then
echo "$container_name completed successfully"
return 0
else
echo "$container_name failed (exit code: $exit_code)"
echo "Full error logs:"
podman logs "$container_name" 2>&1 | tail -20 | sed 's/^/ /'
return 1
fi
fi
else
echo "⏳ Waiting for $container_name to start..."
fi
sleep 10
done
echo "⏰ Timeout waiting for $container_name"
return 1
}
# Function to monitor network download progress
monitor_download() {
local container_name="ac-client-data"
echo "📥 Monitoring client data download progress..."
while podman ps --filter "name=$container_name" --format "{{.Names}}" | grep -q "$container_name"; do
# Look for download progress in logs
podman logs "$container_name" 2>&1 | tail -10 | grep -E "(downloading|download|MB|GB|%)" | tail -3 | sed 's/^/ /'
# Check disk usage in data directory
if podman exec "$container_name" ls -la /azerothcore/data/ 2>/dev/null; then
echo " 📁 Current data directory contents:"
podman exec "$container_name" du -sh /azerothcore/data/* 2>/dev/null | sed 's/^/ /' || echo " (empty or not accessible)"
fi
echo "---"
sleep 30
done
}
# Function to check database import progress
monitor_db_import() {
local container_name="ac-db-import"
echo "🗄️ Monitoring database import progress..."
while podman ps --filter "name=$container_name" --format "{{.Names}}" | grep -q "$container_name"; do
echo "[$container_name] Recent activity:"
podman logs "$container_name" 2>&1 | tail -5 | sed 's/^/ /'
# Check database size growth
echo " 📊 Database status:"
podman exec ac-mysql mysql -uroot -p${DOCKER_DB_ROOT_PASSWORD:-password} -e "
SELECT
table_schema as 'Database',
ROUND(SUM(data_length + index_length) / 1024 / 1024, 2) as 'Size (MB)'
FROM information_schema.tables
WHERE table_schema IN ('acore_auth', 'acore_world', 'acore_characters')
GROUP BY table_schema;
" 2>/dev/null | sed 's/^/ /' || echo " Database not accessible yet"
echo "---"
sleep 20
done
}
# Main monitoring loop
echo "🚀 Starting deployment monitoring..."
echo "Press Ctrl+C to stop monitoring"
echo ""
# Load environment variables if .env exists
if [ -f ".env" ]; then
export $(grep -v '^#' .env | xargs)
fi
# Monitor the deployment phases
echo "Phase 1: MySQL startup"
monitor_container "ac-mysql" 120
echo "Phase 2: Database initialization"
monitor_container "ac-db-init" 60
echo "Phase 3: Client data download (this will take longest)"
monitor_download &
DOWNLOAD_PID=$!
monitor_container "ac-client-data" 2400 # 40 minutes max
kill $DOWNLOAD_PID 2>/dev/null
echo "Phase 4: Database import"
monitor_db_import &
IMPORT_PID=$!
monitor_container "ac-db-import" 1800 # 30 minutes max
kill $IMPORT_PID 2>/dev/null
echo "Phase 5: Application servers"
monitor_container "ac-authserver" 120
monitor_container "ac-worldserver" 180
echo ""
echo "🏁 Monitoring complete!"
echo ""
echo "💡 If you see timeouts or failures:"
echo "1. Check 'podman-compose logs [service-name]' for detailed errors"
echo "2. Restart individual failed services with 'podman-compose up [service-name]'"
echo "3. Consider running services one at a time instead of all at once"

View File

@@ -1,248 +0,0 @@
#!/bin/bash
# Quick fixes for common Portainer timeout issues
# Run this script to apply optimizations for slower machines
echo "==============================================="
echo "AzerothCore Portainer Quick Fixes"
echo "==============================================="
# Create optimized .env for Portainer
create_portainer_env() {
echo "📝 Creating Portainer-optimized .env file..."
cat > .env.portainer << 'EOF'
# Portainer Optimized Configuration
DEPLOYMENT_MODE=portainer
# Reduce resource usage
PLAYERBOT_MAX_BOTS=10
MODULE_PLAYERBOTS=1
MODULE_AOE_LOOT=0
MODULE_LEARN_SPELLS=0
MODULE_FIREWORKS=0
MODULE_INDIVIDUAL_PROGRESSION=0
# Database optimizations for slower machines
DOCKER_DB_ROOT_PASSWORD=password
# Monitoring disabled for performance
INFLUXDB_INIT_MODE=disabled
GF_INSTALL_PLUGINS=""
# Backup disabled during initial setup
BACKUP_RETENTION_DAYS=3
BACKUP_CRON_SCHEDULE="0 4 * * 0"
# Network settings
NETWORK_NAME=azerothcore
NETWORK_SUBNET=172.20.0.0/16
# Storage paths
STORAGE_PATH_CONTAINERS=./volumes
# Port configurations
DOCKER_DB_EXTERNAL_PORT=64306
DOCKER_AUTH_EXTERNAL_PORT=3784
DOCKER_WORLD_EXTERNAL_PORT=8215
DOCKER_SOAP_EXTERNAL_PORT=7778
PMA_EXTERNAL_PORT=8081
KEIRA3_EXTERNAL_PORT=4201
INFLUXDB_EXTERNAL_PORT=8087
GF_EXTERNAL_PORT=3001
EOF
echo "✅ Created .env.portainer with optimized settings"
}
# Create minimal docker-compose for phased deployment
create_minimal_compose() {
echo "📝 Creating minimal docker-compose for phased deployment..."
cat > docker-compose.minimal.yml << 'EOF'
# Minimal AzerothCore setup for slow machines - Phase 1: Core services only
services:
ac-mysql:
image: mysql:8.0
container_name: ac-mysql
environment:
MYSQL_ROOT_PASSWORD: ${DOCKER_DB_ROOT_PASSWORD:-password}
MYSQL_ROOT_HOST: '%'
ports:
- "64306:3306"
volumes:
- ./volumes/azerothcore/mysql:/var/lib/mysql
command:
- --default-authentication-plugin=mysql_native_password
- --character-set-server=utf8mb4
- --collation-server=utf8mb4_unicode_ci
- --max_connections=200
- --innodb-buffer-pool-size=128M
- --innodb-log-file-size=32M
restart: unless-stopped
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-uroot", "-p${DOCKER_DB_ROOT_PASSWORD:-password}"]
interval: 30s
timeout: 10s
retries: 5
start_period: 60s
networks:
- azerothcore
ac-db-init:
image: mysql:8.0
container_name: ac-db-init
depends_on:
ac-mysql:
condition: service_healthy
networks:
- azerothcore
environment:
MYSQL_PWD: ${DOCKER_DB_ROOT_PASSWORD:-password}
command:
- sh
- -c
- |
echo "Creating AzerothCore databases..."
mysql -h ac-mysql -uroot -e "
CREATE DATABASE IF NOT EXISTS acore_auth DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE DATABASE IF NOT EXISTS acore_world DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE DATABASE IF NOT EXISTS acore_characters DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
SHOW DATABASES;
" || true
echo "Databases created!"
restart: "no"
networks:
azerothcore:
driver: bridge
EOF
echo "✅ Created docker-compose.minimal.yml for phase 1"
}
# Create data download script for separate execution
create_data_download_script() {
echo "📝 Creating separate client data download script..."
cat > download-client-data.sh << 'EOF'
#!/bin/bash
# Separate client data download - run this independently
echo "🚀 Starting client data download..."
# Create data directory
mkdir -p ./volumes/azerothcore/data
# Check if data already exists
if [ -d './volumes/azerothcore/data/maps' ] && [ -d './volumes/azerothcore/data/vmaps' ]; then
echo '✅ Game data already exists, skipping download'
exit 0
fi
echo '📥 Downloading client data (this may take 30+ minutes on slow connections)...'
# Download with progress and resume capability
wget -c -t 3 --progress=bar:force \
-O ./volumes/azerothcore/data/data.zip \
"https://github.com/wowgaming/client-data/releases/download/v16/data.zip"
if [ $? -eq 0 ]; then
echo '📂 Extracting client data...'
cd ./volumes/azerothcore/data
unzip -q data.zip
rm -f data.zip
echo '✅ Client data download and extraction complete!'
else
echo '❌ Download failed. You may need to:'
echo '1. Run this script again (wget will resume)'
echo '2. Download manually from a faster connection'
echo '3. Copy data from another AzerothCore installation'
fi
EOF
chmod +x download-client-data.sh
echo "✅ Created download-client-data.sh script"
}
# Create deployment instructions
create_deployment_guide() {
echo "📝 Creating deployment guide..."
cat > PORTAINER-DEPLOYMENT.md << 'EOF'
# AzerothCore Portainer Deployment Guide
## For Slow Machines / High Latency Connections
### Phase 1: Pre-setup (Optional but Recommended)
1. Run diagnostics: `bash portainer-diagnostics.sh`
2. Pre-download client data: `bash download-client-data.sh`
### Phase 2: Minimal Core Services
1. Copy `.env.portainer` to `.env`
2. Deploy using `docker-compose.minimal.yml`:
```bash
podman-compose -f docker-compose.minimal.yml up -d
```
### Phase 3: Add Database Import
Once Phase 2 is stable, add the db-import service to your stack.
### Phase 4: Add Application Services
Finally, add authserver and worldserver.
### Phase 5: Add Optional Services
Add monitoring, backup, and management tools last.
## Troubleshooting Tips
### 504 Gateway Timeouts
- These usually mean operations are taking too long, not failing
- Check logs: `podman-compose logs [service-name]`
- Monitor progress: `bash portainer-verify.sh`
### Memory Issues
- Reduce `PLAYERBOT_MAX_BOTS` to 5-10
- Disable monitoring services temporarily
- Deploy one service at a time
### Network Issues
- Pre-download client data on faster connection
- Use local file copies instead of downloads
- Check firewall/proxy settings
### Disk Space Issues
- Need minimum 20GB free space
- Monitor with `df -h`
- Clean up unused Podman images: `podman system prune`
## Service Dependencies
```
MySQL → DB Init → DB Import → Auth Server → World Server
Client Data (parallel)
```
Deploy in this order for best results.
EOF
echo "✅ Created PORTAINER-DEPLOYMENT.md guide"
}
# Main execution
echo "🛠️ Applying Portainer optimizations..."
create_portainer_env
create_minimal_compose
create_data_download_script
create_deployment_guide
echo ""
echo "✅ Portainer optimization complete!"
echo ""
echo "📋 Next Steps:"
echo "1. Run: bash portainer-diagnostics.sh (to check your system)"
echo "2. Run: bash download-client-data.sh (to pre-download game data)"
echo "3. Copy .env.portainer to .env"
echo "4. Deploy with: podman-compose -f docker-compose.minimal.yml up -d"
echo "5. Monitor with: bash portainer-verify.sh"
echo ""
echo "📖 See PORTAINER-DEPLOYMENT.md for detailed instructions"

View File

@@ -1,286 +0,0 @@
#!/bin/bash
# ==============================================
# AzerothCore Deployment Test Script
# ==============================================
# Tests the deployment script functionality
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" &> /dev/null && pwd)"
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
log() {
local level="$1"
shift
local message="$*"
case "$level" in
"INFO") echo -e "${BLUE}[INFO]${NC} $message" ;;
"WARN") echo -e "${YELLOW}[WARN]${NC} $message" ;;
"ERROR") echo -e "${RED}[ERROR]${NC} $message" ;;
"SUCCESS") echo -e "${GREEN}[SUCCESS]${NC} $message" ;;
esac
}
# Test deployment script
test_deployment_script() {
log "INFO" "Testing deployment script functionality..."
# Test help command
if ./azerothcore-deploy.sh --help >/dev/null 2>&1; then
log "SUCCESS" "Help command works"
else
log "ERROR" "Help command failed"
return 1
fi
# Test configuration validation
if ./azerothcore-deploy.sh status >/dev/null 2>&1; then
log "SUCCESS" "Status command works"
else
log "WARN" "Status command failed (expected if no services running)"
fi
log "SUCCESS" "Deployment script tests passed"
}
# Test monitoring script
test_monitoring_script() {
log "INFO" "Testing monitoring script functionality..."
# Test status generation
if ./azerothcore-monitor.sh status >/dev/null 2>&1; then
log "SUCCESS" "Monitoring status generation works"
else
log "ERROR" "Monitoring status generation failed"
return 1
fi
# Check if web directory was created
if [[ -d "monitoring-web" ]] && [[ -f "monitoring-web/index.html" ]]; then
log "SUCCESS" "Web status page generated"
else
log "ERROR" "Web status page not generated"
return 1
fi
log "SUCCESS" "Monitoring script tests passed"
}
# Test database layer deployment
test_database_layer() {
log "INFO" "Testing database layer deployment..."
# Ensure clean state
docker-compose -f docker-compose-azerothcore-database.yml down 2>/dev/null || true
# Test database deployment
log "INFO" "Starting database layer..."
if docker-compose -f docker-compose-azerothcore-database.yml up -d ac-mysql; then
log "SUCCESS" "MySQL started successfully"
# Wait for health check
local timeout=60
local start_time=$(date +%s)
while [[ $(($(date +%s) - start_time)) -lt $timeout ]]; do
if docker ps --filter "name=ac-mysql" --format "{{.Status}}" | grep -q "healthy"; then
log "SUCCESS" "MySQL is healthy"
break
fi
sleep 2
done
# Test database connection
if docker run --rm --network azerothcore mysql:8.0 \
mysql -h ac-mysql -uroot -pazerothcore123 -e "SELECT 1;" &>/dev/null; then
log "SUCCESS" "Database connectivity test passed"
else
log "ERROR" "Database connectivity test failed"
fi
# Cleanup
docker-compose -f docker-compose-azerothcore-database.yml down
log "INFO" "Database layer test cleanup completed"
else
log "ERROR" "MySQL failed to start"
return 1
fi
log "SUCCESS" "Database layer tests passed"
}
# Test environment setup
test_environment() {
log "INFO" "Testing environment setup..."
# Check required files
local required_files=(
"azerothcore-deploy.sh"
"azerothcore-monitor.sh"
"install-system-service.sh"
".env-database-local"
"docker-compose-azerothcore-database.yml"
)
for file in "${required_files[@]}"; do
if [[ -f "$file" ]]; then
log "SUCCESS" "$file exists"
else
log "ERROR" "$file missing"
return 1
fi
done
# Check if scripts are executable
for script in azerothcore-deploy.sh azerothcore-monitor.sh install-system-service.sh; do
if [[ -x "$script" ]]; then
log "SUCCESS" "$script is executable"
else
log "ERROR" "$script is not executable"
return 1
fi
done
log "SUCCESS" "Environment tests passed"
}
# Test Docker requirements
test_docker() {
log "INFO" "Testing Docker requirements..."
# Check Docker
if command -v docker &> /dev/null; then
log "SUCCESS" "Docker is installed"
else
log "ERROR" "Docker is not installed"
return 1
fi
# Check Docker daemon
if docker info &> /dev/null; then
log "SUCCESS" "Docker daemon is running"
else
log "ERROR" "Docker daemon is not running"
return 1
fi
# Check Docker Compose
if command -v docker-compose &> /dev/null; then
log "SUCCESS" "Docker Compose is installed"
else
log "ERROR" "Docker Compose is not installed"
return 1
fi
log "SUCCESS" "Docker tests passed"
}
# Test system service installer (dry run)
test_system_service_installer() {
log "INFO" "Testing system service installer (validation only)..."
# Test script syntax
if bash -n install-system-service.sh; then
log "SUCCESS" "System service installer syntax is valid"
else
log "ERROR" "System service installer has syntax errors"
return 1
fi
# Test help command
if ./install-system-service.sh 2>&1 | grep -q "Usage:"; then
log "SUCCESS" "System service installer help works"
else
log "ERROR" "System service installer help failed"
return 1
fi
log "SUCCESS" "System service installer tests passed"
}
# Run all tests
run_all_tests() {
log "INFO" "Starting comprehensive deployment tests..."
echo
local tests=(
"test_environment"
"test_docker"
"test_deployment_script"
"test_monitoring_script"
"test_system_service_installer"
"test_database_layer"
)
local passed=0
local total=${#tests[@]}
for test in "${tests[@]}"; do
echo "----------------------------------------"
if $test; then
((passed++))
else
log "ERROR" "Test $test failed"
fi
echo
done
echo "========================================"
log "INFO" "Test Results: $passed/$total tests passed"
if [[ $passed -eq $total ]]; then
log "SUCCESS" "All tests passed! 🎉"
log "INFO" "Your AzerothCore deployment is ready"
return 0
else
log "ERROR" "Some tests failed. Please fix issues before deployment."
return 1
fi
}
# Command handling
case "${1:-all}" in
"all")
run_all_tests
;;
"environment")
test_environment
;;
"docker")
test_docker
;;
"deployment")
test_deployment_script
;;
"monitoring")
test_monitoring_script
;;
"database")
test_database_layer
;;
"installer")
test_system_service_installer
;;
*)
echo "Usage: $0 [all|environment|docker|deployment|monitoring|database|installer]"
echo
echo "Tests:"
echo " all Run all tests (default)"
echo " environment Test file structure and permissions"
echo " docker Test Docker installation and daemon"
echo " deployment Test deployment script functionality"
echo " monitoring Test monitoring script functionality"
echo " database Test database layer deployment"
echo " installer Test system service installer"
echo
exit 1
;;
esac

79
todo.md
View File

@@ -1,79 +0,0 @@
# AzerothCore-with-Playerbots-Docker-Setup - Remaining Tasks
## 🎉 **SYSTEM STATUS: OPERATIONAL**
**AzerothCore worldserver is now fully functional and ready for players!**
---
## 📋 **Remaining Minor Tasks**
### **🟡 Medium Priority (Optional Improvements)**
#### 1. Fix Web Interface Syntax Issues
**Affected Services**:
- `ac-keira3`: Totally broken, requires fundamental changes to be run as a docker container
**Status**: Services are functional but could be optimized
**Impact**: Web interfaces work but may have occasional display issues
#### 2. Environment-Specific Network Configuration
**Current State**:
- `EXTERNAL_IP=192.168.1.100` (generic default)
- Realm configured correctly for local access
**Optional**: Update `.env` file with environment-specific external IP for remote client connections
### **🟢 Future Enhancements (Nice to Have)**
#### 3. Advanced Security Hardening
**Potential Improvements**:
- TLS/SSL configuration for web interfaces
- Non-root container execution (currently runs as root for compatibility)
- Network segmentation with custom subnets
- Additional firewall rules
#### 4. Additional Web Features
**Possible Additions**:
- User registration web interface
- Advanced admin dashboard features
- Real-time server statistics display
- Player management tools
---
## ✅ **COMPLETED FIXES**
All major issues have been resolved:
### **🎉 Successfully Fixed:**
- **✅ Logger Configuration**: Worldserver now starts properly without interactive prompts
- **✅ Game Data**: All required files (3.1GB) installed and accessible
- **✅ Database Issues**: Authentication, schema, and population completed
- **✅ Dynamic URLs**: Web interfaces auto-detect external access URLs
- **✅ Port Conflicts**: All external ports updated to avoid development tool collisions
- **✅ Security Settings**: Enhanced security for all web interfaces
### **🌐 Web Interfaces (Updated Ports):**
- **PHPMyAdmin**: http://localhost:8081 (Database Management)
- **Grafana**: http://localhost:3001 (Monitoring Dashboard)
- **InfluxDB**: http://localhost:8087 (Metrics Database)
- **Keira3**: http://localhost:4201 (Database Editor)
- **CMS**: http://localhost:8001 (Admin Dashboard)
### **📊 Final Service Status:**
```
✅ ac-mysql - Database server (healthy)
✅ ac-authserver - Authentication server (stable)
✅ ac-worldserver - 🎉 OPERATIONAL ("AzerothCore ready...")
✅ ac-db-import - Database import (completed successfully)
✅ ac-phpmyadmin - Database management (port 8081)
✅ ac-grafana - Monitoring dashboard (port 3001)
✅ ac-influxdb - Metrics database (port 8087)
✅ ac-modules - Playerbots module (fully integrated - 40 bots)
✅ ac-backup - Automated backups (working)
⚠️ ac-keira3 - Broken
⚠️ ac-eluna - Lua scripting (should be starting now)
```
---
**Last Updated**: September 24, 2025
**Status**: 🎉 **SYSTEM FULLY OPERATIONAL** - Ready for Players!