Skip to content

Instantly share code, notes, and snippets.

@digitaldrreamer
Created November 6, 2025 13:53
Show Gist options
  • Select an option

  • Save digitaldrreamer/8b6aede713d12668840a49a135d62e99 to your computer and use it in GitHub Desktop.

Select an option

Save digitaldrreamer/8b6aede713d12668840a49a135d62e99 to your computer and use it in GitHub Desktop.
test
#!/bin/bash
# ============================================
# WAHA Plus Complete Production Deployment
# Version: 2.0.1 - Corrected and Verified
# ============================================
set -euo pipefail
# Colors for output
## CORRECTED ##: Removed extra backslash from all color code definitions.
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
MAGENTA='\033[0;35m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color
# State tracking
STATE_FILE="/tmp/waha_deployment_state.json"
ROLLBACK_DIR="/tmp/waha_rollback_$(date +%s)"
LOG_FILE="/var/log/waha_deployment_$(date +%Y%m%d_%H%M%S).log"
REPORT_FILE="/root/waha-deployment-report-$(date +%Y%m%d_%H%M%S).md"
# Deployment tracking
# Generate deployment ID (with fallback if uuidgen not available)
if command -v uuidgen &> /dev/null; then
DEPLOYMENT_ID=$(uuidgen)
else
# Fallback: use timestamp + random number
DEPLOYMENT_ID="deploy-$(date +%s)-$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 8 | head -n 1)"
fi
START_TIME=$(date +%s)
STAGE_RESULTS=()
ERRORS_ENCOUNTERED=()
WARNINGS_ENCOUNTERED=()
SUCCESS_MESSAGES=()
# Configuration variables (will be populated by user input)
WAHA_DOMAIN=""
MONITOR_DOMAIN=""
SSL_EMAIL=""
VPS_IP=""
WAHA_API_KEY=""
DASHBOARD_USER=""
DASHBOARD_PASS=""
SWAGGER_USER=""
SWAGGER_PASS=""
R2_BUCKET=""
R2_ACCESS_KEY=""
R2_SECRET_KEY=""
R2_ENDPOINT=""
DOCKER_USER=""
DOCKER_PASS=""
POSTGRES_PASSWORD=""
BACKUP_KEY=""
BESZEL_KEY=""
# ============================================
# Utility Functions
# ============================================
log() {
local message="$1"
echo -e "${GREEN}[$(date +'%Y-%m-%d %H:%M:%S')]${NC} $message" | tee -a "$LOG_FILE"
SUCCESS_MESSAGES+=("$(date +'%H:%M:%S') - $message")
}
error() {
local message="$1"
echo -e "${RED}[ERROR]${NC} $message" | tee -a "$LOG_FILE"
ERRORS_ENCOUNTERED+=("$(date +'%H:%M:%S') - $message")
}
warn() {
local message="$1"
echo -e "${YELLOW}[WARN]${NC} $message" | tee -a "$LOG_FILE"
WARNINGS_ENCOUNTERED+=("$(date +'%H:%M:%S') - $message")
}
info() {
local message="$1"
echo -e "${BLUE}[INFO]${NC} $message" | tee -a "$LOG_FILE"
}
# Save deployment state
save_state() {
local step=$1
local status=$2
local details="${3:-}"
cat > "$STATE_FILE" <<EOF
{
"deployment_id": "$DEPLOYMENT_ID",
"step": "$step",
"status": "$status",
"details": "$details",
"timestamp": "$(date -Iseconds)"
}
EOF
# Track stage results for report
STAGE_RESULTS+=("| $step | $status | $(date +'%H:%M:%S') | $details |")
}
# Create rollback point
create_rollback_point() {
local description=$1
local backup_path="$ROLLBACK_DIR/$(date +%s)_${description}"
mkdir -p "$backup_path"
echo "$backup_path"
}
# Generate deployment report
generate_report() {
local status=$1
local end_time=$(date +%s)
local duration=$((end_time - START_TIME))
local hours=$((duration / 3600))
local minutes=$(( (duration % 3600) / 60 ))
local seconds=$((duration % 60))
cat > "$REPORT_FILE" <<EOFREPORT
# WAHA Plus Deployment Report
**Deployment ID:** \`$DEPLOYMENT_ID\`
**Date:** $(date +'%Y-%m-%d %H:%M:%S')
**Duration:** ${hours}h ${minutes}m ${seconds}s
**Overall Status:** **$status**
---
## 📋 Deployment Configuration
| Parameter | Value |
|-----------|-------|
| **VPS IP** | \`$VPS_IP\` |
| **WAHA Domain** | \`$WAHA_DOMAIN\` |
| **Monitor Domain** | \`$MONITOR_DOMAIN\` |
| **SSL Email** | \`$SSL_EMAIL\` |
| **R2 Bucket** | \`$R2_BUCKET\` |
| **Docker User** | \`$DOCKER_USER\` |
| **Dashboard User** | \`$DASHBOARD_USER\` |
| **Swagger User** | \`$SWAGGER_USER\` |
---
## 📊 Stage Execution Summary
| Stage | Status | Time | Details |
|-------|--------|------|---------|
$(printf '%s\n' "${STAGE_RESULTS[@]}")
---
## ✅ Success Messages
$(if [ ${#SUCCESS_MESSAGES[@]} -gt 0 ]; then
for msg in "${SUCCESS_MESSAGES[@]}"; do
echo "- ✓ $msg"
done
else
echo "*No success messages recorded*"
fi)
---
## ⚠️ Warnings
$(if [ ${#WARNINGS_ENCOUNTERED[@]} -gt 0 ]; then
for warning in "${WARNINGS_ENCOUNTERED[@]}"; do
echo "- ⚠️ $warning"
done
else
echo "*No warnings encountered*"
fi)
---
## ❌ Errors
$(if [ ${#ERRORS_ENCOUNTERED[@]} -gt 0 ]; then
for error_msg in "${ERRORS_ENCOUNTERED[@]}"; do
echo "- ❌ $error_msg"
done
else
echo "*No errors encountered*"
fi)
---
## 🔐 Service Access Information
$(if [ "$status" = "SUCCESS" ]; then
cat <<EOF
### WAHA Dashboard
- **URL:** https://$WAHA_DOMAIN/dashboard
- **Username:** \`$DASHBOARD_USER\`
- **Password:** \`$DASHBOARD_PASS\`
### API Documentation (Swagger)
- **URL:** https://$WAHA_DOMAIN/
- **Username:** \`$SWAGGER_USER\`
- **Password:** \`$SWAGGER_PASS\`
### API Access
- **Endpoint:** https://$WAHA_DOMAIN/api/
- **API Key:** \`$WAHA_API_KEY\`
### Monitoring Dashboard
- **URL:** https://$MONITOR_DOMAIN
- **Note:** Create admin account on first visit
### Health Check Endpoint
- **URL:** https://$WAHA_DOMAIN/health
EOF
else
echo "*Deployment did not complete successfully - no service URLs available*"
fi)
---
## 🛠️ Useful Commands
\`\`\`bash
# View logs
cd /root/waha-production && docker-compose logs -f
# Check container status
cd /root/waha-production && docker-compose ps
# Run health check
/root/health-check.sh
# Manual backup
/root/backup-waha.sh
# View full deployment log
cat $LOG_FILE
# View credentials
cat /root/waha-credentials.txt
\`\`\`
---
## 📁 Important File Locations
| File | Path |
|------|------|
| **Deployment Log** | \`$LOG_FILE\` |
| **Credentials** | \`/root/waha-credentials.txt\` |
| **Docker Compose** | \`/root/waha-production/docker-compose.yml\` |
| **Environment Config** | \`/root/waha-production/.env\` |
| **Nginx Config** | \`/root/waha-production/nginx/nginx.conf\` |
| **Backup Script** | \`/root/backup-waha.sh\` |
| **Health Check Script** | \`/root/health-check.sh\` |
---
## 🔄 Next Steps
$(if [ "$status" = "SUCCESS" ]; then
cat <<EOF
1. ✅ Access the WAHA Dashboard at https://$WAHA_DOMAIN/dashboard
2. ✅ Set up Beszel monitoring at https://$MONITOR_DOMAIN
3. ✅ Create your first WhatsApp session
4. ✅ Configure webhooks for your application
5. ✅ Test the API using the Swagger documentation
6. ✅ Review backup schedule (daily at 2 AM)
7. ✅ Monitor SSL certificate renewal (automatic)
EOF
else
cat <<EOF
1. ❌ Review the errors above
2. ❌ Check the deployment log: \`cat $LOG_FILE\`
3. ❌ Fix any DNS or configuration issues
4. ❌ Re-run the deployment script
5. ❌ Contact support if issues persist
EOF
fi)
---
## 📚 Documentation & Support
- **WAHA Documentation:** https://waha.devlike.pro/
- **API Reference:** https://waha.devlike.pro/docs/api/
- **Docker Hub:** https://hub.docker.com/r/devlikeapro/waha-plus
- **Deployment Report:** This file (\`$REPORT_FILE\`)
---
*Generated by WAHA Plus Automated Deployment Script v2.0.1*
*Report generated at: $(date +'%Y-%m-%d %H:%M:%S %Z')*
EOFREPORT
# Display report location
echo -e "\n${CYAN}════════════════════════════════════════════════════${NC}"
echo -e "${CYAN}📄 Deployment Report Generated${NC}"
echo -e "${CYAN}════════════════════════════════════════════════════${NC}"
echo -e "${GREEN}Report saved to: ${YELLOW}$REPORT_FILE${NC}"
echo -e "${GREEN}View report: ${YELLOW}cat $REPORT_FILE${NC}"
echo -e "${GREEN}Download via SCP: ${YELLOW}scp root@$VPS_IP:$REPORT_FILE ./${NC}"
echo -e "${CYAN}════════════════════════════════════════════════════${NC}\n"
}
# Rollback function
rollback() {
error "Deployment failed. Initiating rollback..."
# Stop any running containers
if [ -d "/root/waha-production" ]; then
cd /root/waha-production
docker-compose down 2>/dev/null || true
fi
# Restore from rollback directory
if [ -d "$ROLLBACK_DIR" ]; then
log "Rolling back changes..."
warn "Manual cleanup may be required. Check: $ROLLBACK_DIR"
fi
# Generate failure report
generate_report "FAILED"
exit 1
}
# Trap errors
trap rollback ERR
# Check if running as root
check_root() {
if [ "$EUID" -ne 0 ]; then
error "This script must be run as root"
exit 1
fi
}
# Install essential packages early
ensure_essential_packages() {
echo -e "${BLUE}[INFO]${NC} Checking essential packages..."
# Check and install essential packages if missing
local packages_to_install=""
# Check each essential command
if ! command -v uuidgen &> /dev/null; then
packages_to_install="$packages_to_install uuid-runtime"
fi
if ! command -v dig &> /dev/null; then
packages_to_install="$packages_to_install dnsutils"
fi
if ! command -v lsof &> /dev/null; then
packages_to_install="$packages_to_install lsof"
fi
if ! command -v jq &> /dev/null; then
packages_to_install="$packages_to_install jq"
fi
if [ -n "$packages_to_install" ]; then
echo -e "${BLUE}[INFO]${NC} Installing essential packages: $packages_to_install"
apt-get update
apt-get install -y $packages_to_install
fi
echo -e "${GREEN}[INFO]${NC} Essential packages ready"
}
# Check port availability
check_ports() {
log "Checking port availability..."
for port in 80 443; do
if lsof -i :$port &>/dev/null; then
error "Port $port is already in use"
log "Processes using port $port:"
lsof -i :$port
return 1
fi
done
log "✓ Ports 80 and 443 are available"
return 0
}
# Validate prerequisites
validate_prerequisites() {
log "Validating prerequisites..."
# Check OS
if ! grep -q -E "(Ubuntu|Debian)" /etc/os-release; then
error "This script requires Ubuntu or Debian"
exit 1
fi
# Check internet connectivity
if ! ping -c 1 8.8.8.8 &> /dev/null; then
error "No internet connectivity"
exit 1
fi
# Check minimum resources
local total_mem=$(free -m | awk '/^Mem:/{print $2}')
if [ "$total_mem" -lt 3800 ]; then
warn "System has less than 4GB RAM. Performance may be affected."
fi
local free_space=$(df / | awk 'NR==2 {print int($4/1048576)}')
if [ "$free_space" -lt 20 ]; then
error "Less than 20GB free disk space available"
exit 1
fi
log "Prerequisites validated"
}
# Validate configuration
validate_configuration() {
log "Validating configuration..."
# Check domain format
if ! echo "$WAHA_DOMAIN" | grep -qE '^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?(\.[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?)*$'; then
error "Invalid domain format: $WAHA_DOMAIN"
return 1
fi
# Check email format
if ! echo "$SSL_EMAIL" | grep -qE '^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}$'; then
error "Invalid email format: $SSL_EMAIL"
return 1
fi
# Check R2 endpoint format
if ! echo "$R2_ENDPOINT" | grep -qE '^https://'; then
error "R2 endpoint must start with https://"
return 1
fi
# Test Docker credentials
info "Validating Docker Hub credentials..."
if ! echo "$DOCKER_PASS" | docker login -u "$DOCKER_USER" --password-stdin &>/dev/null; then
error "Invalid Docker Hub credentials"
return 1
fi
docker logout
log "✓ Configuration validated"
return 0
}
# ============================================
# User Input Collection
# ============================================
collect_inputs() {
log "Collecting deployment configuration..."
echo -e "\n${BLUE}═══════════════════════════════════════════════════${NC}"
echo -e "${BLUE} WAHA Plus Deployment Configuration Wizard ${NC}"
echo -e "${BLUE}═══════════════════════════════════════════════════${NC}\n"
# Domain configuration
echo -e "${CYAN}━━━ Domain Configuration ━━━${NC}"
read -p "Enter WAHA domain (e.g., 1.instance.myseller.africa): " WAHA_DOMAIN
read -p "Enter monitoring domain (e.g., monitoring.1.instance.myseller.africa): " MONITOR_DOMAIN
read -p "Enter your email for SSL certificates: " SSL_EMAIL
# Get VPS IP
VPS_IP=$(curl -s ifconfig.me)
info "Detected VPS IP: $VPS_IP"
read -p "Is this correct? (y/n): " confirm
if [ "$confirm" != "y" ]; then
read -p "Enter correct VPS IP: " VPS_IP
fi
echo -e "\n${CYAN}━━━ WAHA Credentials ━━━${NC}"
# WAHA credentials
read -p "Enter WAHA API key [auto-generate]: " WAHA_API_KEY
WAHA_API_KEY=${WAHA_API_KEY:-$(uuidgen)}
read -p "Enter dashboard username [alakori]: " DASHBOARD_USER
DASHBOARD_USER=${DASHBOARD_USER:-alakori}
read -sp "Enter dashboard password [auto-generate]: " DASHBOARD_PASS
DASHBOARD_PASS=${DASHBOARD_PASS:-$(openssl rand -hex 16)}
echo
read -p "Enter Swagger username [shakosimi]: " SWAGGER_USER
SWAGGER_USER=${SWAGGER_USER:-shakosimi}
read -sp "Enter Swagger password [auto-generate]: " SWAGGER_PASS
SWAGGER_PASS=${SWAGGER_PASS:-$(openssl rand -hex 16)}
echo
echo -e "\n${CYAN}━━━ Cloudflare R2 Configuration ━━━${NC}"
read -p "Enter R2 bucket name: " R2_BUCKET
read -p "Enter R2 access key ID: " R2_ACCESS_KEY
read -sp "Enter R2 secret access key: " R2_SECRET_KEY
echo
read -p "Enter R2 endpoint URL: " R2_ENDPOINT
echo -e "\n${CYAN}━━━ Docker Hub Credentials ━━━${NC}"
read -p "Enter Docker Hub username [devlikeapro]: " DOCKER_USER
DOCKER_USER=${DOCKER_USER:-devlikeapro}
read -sp "Enter Docker Hub password/token: " DOCKER_PASS
echo
# Generate secure passwords
POSTGRES_PASSWORD=$(openssl rand -hex 24)
BACKUP_KEY=$(openssl rand -hex 32)
BESZEL_KEY=$(openssl rand -hex 16)
# Summary
echo -e "\n${GREEN}═══════════════════════════════════════════════════${NC}"
echo -e "${GREEN} Configuration Summary ${NC}"
echo -e "${GREEN}═══════════════════════════════════════════════════${NC}"
echo -e "${YELLOW}WAHA Domain:${NC} $WAHA_DOMAIN"
echo -e "${YELLOW}Monitor Domain:${NC} $MONITOR_DOMAIN"
echo -e "${YELLOW}VPS IP:${NC} $VPS_IP"
echo -e "${YELLOW}SSL Email:${NC} $SSL_EMAIL"
echo -e "${YELLOW}Dashboard User:${NC} $DASHBOARD_USER"
echo -e "${YELLOW}Swagger User:${NC} $SWAGGER_USER"
echo -e "${YELLOW}R2 Bucket:${NC} $R2_BUCKET"
echo -e "${GREEN}═══════════════════════════════════════════════════${NC}"
echo ""
## CORRECTED ##: Quoted the string inside echo -e to prevent syntax errors.
## Removed unnecessary backslashes around parentheses.
read -p "$(echo -e "${CYAN}Proceed with deployment? (y/n): ${NC}")" confirm
if [ "$confirm" != "y" ]; then
log "Deployment cancelled by user"
generate_report "CANCELLED"
exit 0
fi
}
# ============================================
# Stage 1: Server Preparation
# ============================================
stage_1_server_prep() {
log "Stage 1: Server Preparation"
save_state "stage_1" "in_progress" "Installing dependencies"
# Backup point
BACKUP_1=$(create_rollback_point "pre_install")
# Update system
log "Updating system packages..."
apt-get update && apt-get upgrade -y
# Install Docker if not present
if ! command -v docker &> /dev/null; then
log "Installing Docker..."
curl -fsSL https://get.docker.com -o get-docker.sh
sh get-docker.sh
rm get-docker.sh
else
log "Docker already installed"
fi
# Install Docker Compose if not present
if ! command -v docker-compose &> /dev/null; then
log "Installing Docker Compose..."
curl -SL https://github.com/docker/compose/releases/latest/download/docker-compose-linux-x86_64 \
-o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
else
log "Docker Compose already installed"
fi
# Install Certbot
if ! command -v certbot &> /dev/null; then
log "Installing Certbot..."
apt-get install certbot python3-certbot-nginx -y
else
log "Certbot already installed"
fi
# Install utilities (fixed netcat issue)
log "Installing utilities..."
apt-get install -y \
tree \
htop \
curl \
wget \
jq \
netcat-openbsd \
python3 \
python3-pip \
uuid-runtime \
dnsutils \
lsof
# Configure firewall
log "Configuring firewall..."
ufw --force enable
ufw allow 22/tcp
ufw allow 80/tcp
ufw allow 443/tcp
# Stop conflicting services
log "Stopping conflicting services..."
systemctl stop nginx 2>/dev/null || true
systemctl stop apache2 2>/dev/null || true
systemctl disable nginx 2>/dev/null || true
systemctl disable apache2 2>/dev/null || true
# Verify port 80 is free
if ! check_ports; then
error "Required ports are not available"
exit 1
fi
save_state "stage_1" "completed" "All dependencies installed"
log "Stage 1 completed successfully"
}
# ============================================
# Stage 2: DNS Verification
# ============================================
stage_2_dns_verification() {
log "Stage 2: DNS Verification"
save_state "stage_2" "in_progress" "Checking DNS propagation"
# Function to check DNS with retries
check_dns() {
local domain=$1
local max_retries=5
local retry_delay=30
for i in $(seq 1 $max_retries); do
local resolved_ip=$(dig +short "$domain" | head -1)
if [ "$resolved_ip" = "$VPS_IP" ]; then
log "✓ DNS for $domain correctly points to $VPS_IP"
return 0
else
warn "Attempt $i/$max_retries: DNS for $domain shows '$resolved_ip', expected '$VPS_IP'"
if [ $i -lt $max_retries ]; then
info "Waiting ${retry_delay}s before retry..."
sleep $retry_delay
fi
fi
done
return 1
}
if ! check_dns "$WAHA_DOMAIN"; then
error "DNS verification failed for $WAHA_DOMAIN after multiple attempts"
echo "Please ensure your DNS A record for '$WAHA_DOMAIN' points to: $VPS_IP"
exit 1
fi
if ! check_dns "$MONITOR_DOMAIN"; then
error "DNS verification failed for $MONITOR_DOMAIN"
exit 1
fi
save_state "stage_2" "completed" "DNS verified for both domains"
log "Stage 2 completed successfully"
}
# ============================================
# Stage 3: Project Structure
# ============================================
stage_3_project_structure() {
log "Stage 3: Project Structure Setup"
save_state "stage_3" "in_progress" "Creating directories and configuration"
cd /root
# Backup existing installation
if [ -d "waha-production" ]; then
warn "Existing installation found. Creating backup..."
mv waha-production "waha-production.backup.$(date +%s)"
fi
# Create directory structure
log "Creating directory structure..."
mkdir -p waha-production/{nginx,certbot/www,postgres_data,beszel_data}
cd waha-production
# Create .env file
log "Creating environment configuration..."
cat > .env <<EOF
# ============================================
# WAHA PLUS CONFIGURATION
# Generated: $(date)
# Deployment ID: $DEPLOYMENT_ID
# ============================================
# --- Core Authentication ---
WAHA_API_KEY=$WAHA_API_KEY
WAHA_DASHBOARD_USERNAME=$DASHBOARD_USER
WAHA_DASHBOARD_PASSWORD=$DASHBOARD_PASS
WHATSAPP_SWAGGER_USERNAME=$SWAGGER_USER
WHATSAPP_SWAGGER_PASSWORD=$SWAGGER_PASS
# --- Server Configuration ---
WAHA_BASE_URL=https://$WAHA_DOMAIN
WHATSAPP_API_HOSTNAME=$WAHA_DOMAIN
# --- Domain Configuration ---
WAHA_DOMAIN=$WAHA_DOMAIN
MONITOR_DOMAIN=$MONITOR_DOMAIN
# --- SSL Configuration ---
SSL_EMAIL=$SSL_EMAIL
# --- Timezone ---
TZ=Africa/Lagos
# --- Logging Configuration ---
WAHA_LOG_FORMAT=JSON
WAHA_LOG_LEVEL=info
WAHA_HTTP_LOG_LEVEL=warn
# --- Engine Configuration ---
WHATSAPP_DEFAULT_ENGINE=WEBJS
# --- Session Management ---
WAHA_AUTO_START_DELAY_SECONDS=5
WHATSAPP_RESTART_ALL_SESSIONS=False
# --- PostgreSQL Database Configuration ---
POSTGRES_USER=waha
POSTGRES_PASSWORD=$POSTGRES_PASSWORD
POSTGRES_DB=waha
POSTGRES_HOST=postgres
POSTGRES_PORT=5432
# PostgreSQL connection string for WAHA
DATABASE_URL=postgresql://waha:$POSTGRES_PASSWORD@postgres:5432/waha
# --- Cloudflare R2 Storage Configuration ---
WAHA_S3_ENABLED=true
WAHA_S3_REGION=auto
WAHA_S3_BUCKET=$R2_BUCKET
WAHA_S3_ACCESS_KEY_ID=$R2_ACCESS_KEY
WAHA_S3_SECRET_ACCESS_KEY=$R2_SECRET_KEY
WAHA_S3_ENDPOINT=$R2_ENDPOINT
WAHA_S3_FORCE_PATH_STYLE=true
# --- Storage Settings ---
WHATSAPP_FILES_FOLDER=/tmp/waha-media
WHATSAPP_FILES_LIFETIME=0
WHATSAPP_DOWNLOAD_MEDIA=true
# --- Health Check Thresholds ---
WHATSAPP_HEALTH_MEDIA_FILES_THRESHOLD_MB=500
WHATSAPP_HEALTH_SESSIONS_FILES_THRESHOLD_MB=500
# --- Beszel Monitoring ---
BESZEL_AGENT_KEY=$BESZEL_KEY
# --- Backup Configuration ---
BACKUP_ENCRYPTION_KEY=$BACKUP_KEY
EOF
chmod 600 .env
save_state "stage_3" "completed" "Project structure created"
log "Stage 3 completed successfully"
}
# ============================================
# Stage 4: Docker Compose Configuration
# ============================================
stage_4_docker_compose() {
log "Stage 4: Docker Compose Configuration"
save_state "stage_4" "in_progress" "Creating docker-compose.yml"
cd /root/waha-production
cat > docker-compose.yml <<'EOFCOMPOSE'
services:
postgres:
image: postgres:16-alpine
container_name: waha-postgres
restart: unless-stopped
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
PGDATA: /var/lib/postgresql/data/pgdata
volumes:
- ./postgres_data:/var/lib/postgresql/data
networks:
- waha-network
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
interval: 10s
timeout: 5s
retries: 5
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
deploy:
resources:
limits:
memory: 512M
cpus: '0.5'
nginx:
image: nginx:alpine
container_name: nginx-proxy
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
- ./certbot/conf:/etc/letsencrypt:ro
- ./certbot/www:/var/www/certbot:ro
depends_on:
- waha
- beszel
networks:
- waha-network
command: "/bin/sh -c 'while :; do sleep 6h & wait $${!}; nginx -s reload; done & nginx -g \"daemon off;\"'"
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
deploy:
resources:
limits:
memory: 256M
cpus: '0.25'
certbot:
image: certbot/certbot
container_name: certbot
restart: unless-stopped
volumes:
- ./certbot/conf:/etc/letsencrypt
- ./certbot/www:/var/www/certbot
entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew --webroot --webroot-path=/var/www/certbot; sleep 12h & wait $${!}; done;'"
logging:
driver: "json-file"
options:
max-size: "5m"
max-file: "2"
waha:
image: devlikeapro/waha-plus:latest
container_name: waha-plus
restart: unless-stopped
depends_on:
postgres:
condition: service_healthy
environment:
- WAHA_API_KEY=${WAHA_API_KEY}
- WAHA_DASHBOARD_USERNAME=${WAHA_DASHBOARD_USERNAME}
- WAHA_DASHBOARD_PASSWORD=${WAHA_DASHBOARD_PASSWORD}
- WHATSAPP_SWAGGER_USERNAME=${WHATSAPP_SWAGGER_USERNAME}
- WHATSAPP_SWAGGER_PASSWORD=${WHATSAPP_SWAGGER_PASSWORD}
- WAHA_BASE_URL=${WAHA_BASE_URL}
- WHATSAPP_API_HOSTNAME=${WHATSAPP_API_HOSTNAME}
- TZ=${TZ}
- WAHA_LOG_FORMAT=${WAHA_LOG_FORMAT}
- WAHA_LOG_LEVEL=${WAHA_LOG_LEVEL}
- WAHA_HTTP_LOG_LEVEL=${WAHA_HTTP_LOG_LEVEL}
- WHATSAPP_DEFAULT_ENGINE=${WHATSAPP_DEFAULT_ENGINE}
- WAHA_AUTO_START_DELAY_SECONDS=${WAHA_AUTO_START_DELAY_SECONDS}
- WHATSAPP_RESTART_ALL_SESSIONS=${WHATSAPP_RESTART_ALL_SESSIONS}
- DATABASE_URL=${DATABASE_URL}
- WAHA_S3_ENABLED=${WAHA_S3_ENABLED}
- WAHA_S3_REGION=${WAHA_S3_REGION}
- WAHA_S3_BUCKET=${WAHA_S3_BUCKET}
- WAHA_S3_ACCESS_KEY_ID=${WAHA_S3_ACCESS_KEY_ID}
- WAHA_S3_SECRET_ACCESS_KEY=${WAHA_S3_SECRET_ACCESS_KEY}
- WAHA_S3_ENDPOINT=${WAHA_S3_ENDPOINT}
- WAHA_S3_FORCE_PATH_STYLE=${WAHA_S3_FORCE_PATH_STYLE}
- WHATSAPP_FILES_FOLDER=${WHATSAPP_FILES_FOLDER}
- WHATSAPP_FILES_LIFETIME=${WHATSAPP_FILES_LIFETIME}
- WHATSAPP_DOWNLOAD_MEDIA=${WHATSAPP_DOWNLOAD_MEDIA}
- WHATSAPP_HEALTH_MEDIA_FILES_THRESHOLD_MB=${WHATSAPP_HEALTH_MEDIA_FILES_THRESHOLD_MB}
- WHATSAPP_HEALTH_SESSIONS_FILES_THRESHOLD_MB=${WHATSAPP_HEALTH_SESSIONS_FILES_THRESHOLD_MB}
networks:
- waha-network
healthcheck:
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:3000/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
logging:
driver: "json-file"
options:
max-size: "50m"
max-file: "5"
deploy:
resources:
limits:
memory: 4G
cpus: '2.0'
beszel:
image: henrygd/beszel
container_name: beszel
restart: unless-stopped
volumes:
- ./beszel_data:/beszel_data
networks:
- waha-network
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
deploy:
resources:
limits:
memory: 256M
cpus: '0.25'
beszel-agent:
image: henrygd/beszel-agent
container_name: beszel-agent
restart: unless-stopped
network_mode: host
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
environment:
- KEY=${BESZEL_AGENT_KEY}
- PORT=45876
logging:
driver: "json-file"
options:
max-size: "5m"
max-file: "2"
networks:
waha-network:
driver: bridge
EOFCOMPOSE
save_state "stage_4" "completed" "Docker Compose configured"
log "Stage 4 completed successfully"
}
# ============================================
# Stage 5: Nginx Configuration
# ============================================
stage_5_nginx_config() {
log "Stage 5: Nginx Configuration"
save_state "stage_5" "in_progress" "Creating Nginx configuration"
cd /root/waha-production
# Temporary HTTP-only config for SSL setup
cat > nginx/nginx.conf <<EOFNGINX
events {
worker_connections 1024;
}
http {
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
client_max_body_size 50M;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
server {
listen 80;
server_name $WAHA_DOMAIN $MONITOR_DOMAIN;
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
location / {
return 200 'Server ready for SSL setup!\n';
add_header Content-Type text/plain;
}
}
}
EOFNGINX
save_state "stage_5" "completed" "Nginx configured for SSL setup"
log "Stage 5 completed successfully"
}
# ============================================
# Stage 6: Initial Deployment for SSL
# ============================================
stage_6_ssl_prep() {
log "Stage 6: SSL Preparation Deployment"
save_state "stage_6" "in_progress" "Preparing for SSL certificates"
cd /root/waha-production
# Docker login
log "Authenticating with Docker Hub..."
echo "$DOCKER_PASS" | docker login -u "$DOCKER_USER" --password-stdin
# Pull images
log "Pulling Docker images..."
docker-compose pull
# Logout
docker logout
# Start only Nginx and Certbot
log "Starting Nginx and Certbot..."
docker-compose up -d nginx certbot
# Wait for Nginx to be ready
info "Waiting 10 seconds for Nginx to start..."
sleep 10
# Verify HTTP access
if ! curl -f "http://$WAHA_DOMAIN"; then
error "Cannot access $WAHA_DOMAIN via HTTP. Check DNS and firewall."
exit 1
fi
save_state "stage_6" "completed" "SSL preparation complete"
log "Stage 6 completed successfully"
}
# ============================================
# Stage 7: SSL Certificate Acquisition
# ============================================
stage_7_ssl_certificates() {
log "Stage 7: SSL Certificate Acquisition"
save_state "stage_7" "in_progress" "Requesting SSL certificates"
# Request certificate for WAHA domain
log "Requesting SSL certificate for $WAHA_DOMAIN..."
certbot certonly \
--webroot \
--webroot-path /root/waha-production/certbot/www \
-d "$WAHA_DOMAIN" \
--email "$SSL_EMAIL" \
--agree-tos \
--no-eff-email \
--non-interactive
# Request certificate for monitoring domain
log "Requesting SSL certificate for $MONITOR_DOMAIN..."
certbot certonly \
--webroot \
--webroot-path /root/waha-production/certbot/www \
-d "$MONITOR_DOMAIN" \
--email "$SSL_EMAIL" \
--agree-tos \
--no-eff-email \
--non-interactive
# Copy certificates to Docker volume
log "Copying certificates to Docker volume..."
mkdir -p /root/waha-production/certbot/conf/live
cp -rL /etc/letsencrypt/live/* /root/waha-production/certbot/conf/live/
cp -rL /etc/letsencrypt/archive /root/waha-production/certbot/conf/
cp -r /etc/letsencrypt/renewal /root/waha-production/certbot/conf/ 2>/dev/null || true
# Set permissions
chown -R root:root /root/waha-production/certbot/conf
chmod -R 755 /root/waha-production/certbot/conf
chmod 600 /root/waha-production/certbot/conf/live/*/privkey.pem
# Verify certificates exist
if [ ! -f "/root/waha-production/certbot/conf/live/$WAHA_DOMAIN/fullchain.pem" ]; then
error "SSL certificate not found for $WAHA_DOMAIN"
exit 1
fi
if [ ! -f "/root/waha-production/certbot/conf/live/$MONITOR_DOMAIN/fullchain.pem" ]; then
error "SSL certificate not found for $MONITOR_DOMAIN"
exit 1
fi
save_state "stage_7" "completed" "SSL certificates acquired"
log "Stage 7 completed successfully"
}
# ============================================
# Stage 8: Production Nginx Configuration
# ============================================
stage_8_nginx_production() {
log "Stage 8: Production Nginx Configuration"
save_state "stage_8" "in_progress" "Configuring production Nginx"
cd /root/waha-production
# Backup temporary config
cp nginx/nginx.conf nginx/nginx.conf.temp
# Create production config
cat > nginx/nginx.conf <<EOFNGINXPROD
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
client_max_body_size 50M;
server_tokens off;
log_format main '\$remote_addr - \$remote_user [\$time_local] "\$request" '
'\$status \$body_bytes_sent "\$http_referer" '
'"\$http_user_agent" "\$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
error_log /var/log/nginx/error.log warn;
gzip on;
gzip_vary on;
gzip_comp_level 6;
gzip_types text/plain text/css application/json application/javascript
text/xml application/xml application/xml+rss text/javascript;
gzip_proxied any;
gzip_min_length 1000;
limit_req_zone \$binary_remote_addr zone=api_limit:10m rate=10r/s;
limit_req_status 429;
server {
listen 80;
server_name $WAHA_DOMAIN $MONITOR_DOMAIN;
location /.well-known/acme-challenge/ {
root /var/www/certbot;
try_files \$uri =404;
}
location / {
return 301 https://\$host\$request_uri;
}
}
server {
listen 443 ssl http2;
server_name $WAHA_DOMAIN;
ssl_certificate /etc/letsencrypt/live/$WAHA_DOMAIN/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/$WAHA_DOMAIN/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
location /api/ {
limit_req zone=api_limit burst=20 nodelay;
proxy_pass http://waha:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade \$http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host \$host;
proxy_cache_bypass \$http_upgrade;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto \$scheme;
proxy_connect_timeout 300s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
proxy_buffering off;
proxy_request_buffering off;
}
location / {
proxy_pass http://waha:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade \$http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host \$host;
proxy_cache_bypass \$http_upgrade;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto \$scheme;
proxy_connect_timeout 300s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
proxy_buffering off;
}
}
server {
listen 443 ssl http2;
server_name $MONITOR_DOMAIN;
ssl_certificate /etc/letsencrypt/live/$MONITOR_DOMAIN/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/$MONITOR_DOMAIN/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;
ssl_session_cache shared:SSL:10m;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
location / {
proxy_pass http://beszel:8090;
proxy_http_version 1.1;
proxy_set_header Upgrade \$http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host \$host;
proxy_cache_bypass \$http_upgrade;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto \$scheme;
}
}
}
EOFNGINXPROD
save_state "stage_8" "completed" "Production Nginx configured"
log "Stage 8 completed successfully"
}
# ============================================
# Stage 9: Full Stack Deployment
# ============================================
stage_9_full_deployment() {
log "Stage 9: Full Stack Deployment"
save_state "stage_9" "in_progress" "Deploying all services"
cd /root/waha-production
# Validate docker-compose
log "Validating Docker Compose configuration..."
docker-compose config > /dev/null
# Stop previous containers
log "Stopping previous containers..."
docker-compose down
# Start all services
log "Starting all services..."
docker-compose up -d
# Wait for services to be ready
log "Waiting up to 90 seconds for services to initialize..."
sleep 30
# Check container status
if ! docker-compose ps | grep -q "Up"; then
error "Some containers failed to start"
docker-compose logs
exit 1
fi
# Wait for WAHA health check
log "Waiting for WAHA to be ready..."
sleep 60
# Test endpoints
log "Testing HTTPS endpoints..."
if ! curl --silent --fail --insecure "https://$WAHA_DOMAIN/health" &> /dev/null; then
warn "WAHA health endpoint not responding yet, checking logs..."
docker-compose logs waha | tail -50
fi
save_state "stage_9" "completed" "All services deployed"
log "Stage 9 completed successfully"
}
# ============================================
# Stage 10: SSL Renewal Setup
# ============================================
stage_10_ssl_renewal() {
log "Stage 10: SSL Renewal Setup"
save_state "stage_10" "in_progress" "Configuring SSL renewal"
# Create renewal hook
mkdir -p /etc/letsencrypt/renewal-hooks/deploy
cat > /etc/letsencrypt/renewal-hooks/deploy/01-docker-reload.sh <<'EOFRENEWAL'
#!/bin/bash
set -e
WAHA_DIR="/root/waha-production"
LOG_FILE="/var/log/ssl-renewal.log"
log_message() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}
log_message "=== Certificate Renewal Hook Started ==="
if [ ! -d "$WAHA_DIR" ]; then
log_message "WAHA directory $WAHA_DIR not found. Aborting."
exit 1
fi
log_message "Copying renewed certificates..."
cp -rL /etc/letsencrypt/live/* "$WAHA_DIR/certbot/conf/live/"
cp -rL /etc/letsencrypt/archive "$WAHA_DIR/certbot/conf/"
cp -r /etc/letsencrypt/renewal "$WAHA_DIR/certbot/conf/" 2>/dev/null || true
log_message "Setting permissions..."
chown -R root:root "$WAHA_DIR/certbot/conf"
chmod -R 755 "$WAHA_DIR/certbot/conf"
chmod 600 "$WAHA_DIR/certbot/conf/live/*/privkey.pem"
log_message "Reloading Nginx proxy..."
if docker ps --format '{{.Names}}' | grep -q '^nginx-proxy$'; then
docker exec nginx-proxy nginx -s reload
log_message "Nginx reloaded successfully."
else
log_message "Nginx container 'nginx-proxy' not found or not running."
fi
log_message "=== Certificate Renewal Hook Completed ==="
EOFRENEWAL
chmod +x /etc/letsencrypt/renewal-hooks/deploy/01-docker-reload.sh
# Test renewal
log "Testing SSL renewal (dry run)..."
certbot renew --dry-run
# Enable certbot timer
systemctl enable certbot.timer
systemctl start certbot.timer
save_state "stage_10" "completed" "SSL renewal configured"
log "Stage 10 completed successfully"
}
# ============================================
# Stage 11: Backup Scripts
# ============================================
stage_11_backup_scripts() {
log "Stage 11: Backup Scripts Setup"
save_state "stage_11" "in_progress" "Creating backup scripts"
# Create backup script
cat > /root/backup-waha.sh <<'EOFBACKUP'
#!/bin/bash
set -e
BACKUP_DIR="/root/waha-backups"
WAHA_DIR="/root/waha-production"
DATE=$(date +%Y%m%d-%H%M%S)
RETENTION_DAYS=7
LOG_FILE="/var/log/waha-backup.log"
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}
mkdir -p "$BACKUP_DIR"
log "=== WAHA Backup Started ==="
if [ ! -f "$WAHA_DIR/docker-compose.yml" ]; then
log "Error: docker-compose.yml not found in $WAHA_DIR. Aborting."
exit 1
fi
log "Backing up PostgreSQL database..."
docker-compose -f "$WAHA_DIR/docker-compose.yml" exec -T postgres \
pg_dump -U waha -d waha > "$BACKUP_DIR/postgres-$DATE.sql"
log "Backing up configuration files..."
tar -czf "$BACKUP_DIR/waha-config-$DATE.tar.gz" \
-C "$WAHA_DIR" .env docker-compose.yml nginx/nginx.conf
log "Backing up Beszel data..."
tar -czf "$BACKUP_DIR/beszel-data-$DATE.tar.gz" \
-C "$WAHA_DIR" beszel_data
log "Backing up SSL certificates..."
tar -czf "$BACKUP_DIR/ssl-certs-$DATE.tar.gz" \
-C /etc/letsencrypt live archive renewal
log "Cleaning up old backups (older than $RETENTION_DAYS days)..."
find "$BACKUP_DIR" -name "*.tar.gz" -mtime +$RETENTION_DAYS -delete
find "$BACKUP_DIR" -name "*.sql" -mtime +$RETENTION_DAYS -delete
log "=== Backup Completed Successfully ==="
EOFBACKUP
chmod +x /root/backup-waha.sh
# Schedule daily backups
(crontab -l 2>/dev/null; echo "0 2 * * * /root/backup-waha.sh") | crontab -
save_state "stage_11" "completed" "Backup system configured"
log "Stage 11 completed successfully"
}
# ============================================
# Stage 12: Health Check Script
# ============================================
stage_12_health_check() {
log "Stage 12: Health Check Setup"
save_state "stage_12" "in_progress" "Creating health check script"
cat > /root/health-check.sh <<EOFHEALTH
#!/bin/bash
echo "=== WAHA Health Check - \$(date) ==="
echo ""
COMPOSE_FILE="/root/waha-production/docker-compose.yml"
if [ ! -f "\$COMPOSE_FILE" ]; then
echo "Error: docker-compose.yml not found at \$COMPOSE_FILE"
exit 1
fi
echo "--- Container Status ---"
docker-compose -f "\$COMPOSE_FILE" ps
echo ""
echo "--- WAHA Health API ---"
curl --insecure -s https://$WAHA_DOMAIN/health | jq . || echo "Health check API call failed"
echo ""
echo "--- Disk Usage for Project Directory ---"
df -h /root/waha-production/
echo ""
echo "--- Docker Resource Usage ---"
docker stats --no-stream --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}"
EOFHEALTH
chmod +x /root/health-check.sh
save_state "stage_12" "completed" "Health monitoring configured"
log "Stage 12 completed successfully"
}
# ============================================
# Final Verification
# ============================================
final_verification() {
log "Performing final verification..."
cd /root/waha-production
# Check all containers are running
if ! docker-compose ps | grep -E "(waha-postgres|nginx-proxy|waha-plus|beszel)" | grep -q "Up"; then
error "Not all critical containers are running"
docker-compose ps
return 1
fi
# Test WAHA health
if curl --insecure -s "https://$WAHA_DOMAIN/health" | grep -q "ok"; then
log "✓ WAHA health check passed"
else
warn "WAHA health check failed - service may still be initializing"
fi
# Test monitoring
if curl --insecure -s "https://$MONITOR_DOMAIN" &> /dev/null; then
log "✓ Beszel monitoring accessible"
else
warn "Beszel monitoring not accessible"
fi
log "Final verification completed"
return 0
}
# ============================================
# Main Deployment Flow
# ============================================
main() {
echo -e "${MAGENTA}"
cat << "EOF"
╔═══════════════════════════════════════════════════════════╗
║ WAHA Plus Complete Production Deployment ║
║ with PostgreSQL + R2 + SSL + Monitoring ║
║ Version 2.0.1 (Verified) ║
╚═══════════════════════════════════════════════════════════╝
EOF
echo -e "${NC}"
# Pre-flight checks
check_root
ensure_essential_packages
validate_prerequisites
# Collect configuration
collect_inputs
# Validate configuration
if ! validate_configuration; then
error "Configuration validation failed"
generate_report "VALIDATION_FAILED"
exit 1
fi
# Execute deployment stages
stage_1_server_prep
stage_2_dns_verification
stage_3_project_structure
stage_4_docker_compose
stage_5_nginx_config
stage_6_ssl_prep
stage_7_ssl_certificates
stage_8_nginx_production
stage_9_full_deployment
stage_10_ssl_renewal
stage_11_backup_scripts
stage_12_health_check
# Final verification
if final_verification; then
DEPLOYMENT_STATUS="SUCCESS"
else
DEPLOYMENT_STATUS="PARTIAL_SUCCESS"
fi
# Generate success report
generate_report "$DEPLOYMENT_STATUS"
# Save credentials
cat > /root/waha-credentials.txt <<EOFCREDS
WAHA Plus Deployment Credentials
Generated: $(date)
Deployment ID: $DEPLOYMENT_ID
=== URLs ===
WAHA Dashboard: https://$WAHA_DOMAIN/dashboard
API Documentation: https://$WAHA_DOMAIN/
Monitoring: https://$MONITOR_DOMAIN
=== WAHA Credentials ===
Dashboard Username: $DASHBOARD_USER
Dashboard Password: $DASHBOARD_PASS
Swagger Username: $SWAGGER_USER
Swagger Password: $SWAGGER_PASS
API Key: $WAHA_API_KEY
=== Database ===
PostgreSQL Password: $POSTGRES_PASSWORD
Database URL: postgresql://waha:$POSTGRES_PASSWORD@postgres:5432/waha
=== Backup Key ===
Encryption Key: $BACKUP_KEY
KEEP THIS FILE SECURE!
EOFCREDS
chmod 600 /root/waha-credentials.txt
# Success message
echo -e "\n${GREEN}╔═══════════════════════════════════════════════════╗${NC}"
echo -e "${GREEN}║ DEPLOYMENT COMPLETED SUCCESSFULLY! ║${NC}"
echo -e "${GREEN}╚═══════════════════════════════════════════════════╝${NC}\n"
echo -e "${BLUE}Your WAHA Plus installation is ready!${NC}\n"
echo -e "📱 WAHA Dashboard: ${GREEN}https://$WAHA_DOMAIN/dashboard${NC}"
echo -e " Username: ${YELLOW}$DASHBOARD_USER${NC}"
echo -e " Password: ${YELLOW}$DASHBOARD_PASS${NC}"
echo -e ""
echo -e "📊 API Documentation: ${GREEN}https://$WAHA_DOMAIN/${NC}"
echo -e " Username: ${YELLOW}$SWAGGER_USER${NC}"
echo -e " Password: ${YELLOW}$SWAGGER_PASS${NC}"
echo -e ""
echo -e "📈 Monitoring: ${GREEN}https://$MONITOR_DOMAIN${NC}"
echo -e " (Create admin account on first visit)"
echo -e ""
echo -e "🔑 API Key: ${YELLOW}$WAHA_API_KEY${NC}"
echo -e ""
echo -e "${BLUE}Useful commands:${NC}"
echo -e " Health check: ${YELLOW}/root/health-check.sh${NC}"
echo -e " Backup: ${YELLOW}/root/backup-waha.sh${NC}"
echo -e " View logs: ${YELLOW}cd /root/waha-production && docker-compose logs -f${NC}"
echo -e " View report: ${YELLOW}cat $REPORT_FILE${NC}"
echo -e ""
echo -e "${GREEN}✨ Happy automating with WAHA Plus! ✨${NC}\n"
}
# Run main deployment
main "$@"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment