diff --git a/README.md b/README.md index 6c2ecf1..0785f39 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,379 @@ -X-Real-IP: "$remote_addr" -X-Forwarded-For: "$proxy_add_x_forwarded_for" -X-Forwarded-Proto: "$scheme" -X-Forwarded-Host: "$host" +# Wallarm Deployment System +A comprehensive solution for deploying Wallarm filtering nodes on virtual machines or bare metal servers. This system provides automated deployment, preflight checks, and management of Wallarm security nodes with support for multiple instances on the same server. +## Features + +- **Automated Preflight Checks** - Validates system readiness, network connectivity, and resource availability +- **Smart Artifact Management** - GitLab-first approach with local fallback support +- **Multiple Node Support** - Deploy multiple Wallarm instances on the same VM with unique port configurations +- **Interactive Configuration** - User-friendly prompts for cloud region, ports, tokens, and upstream applications +- **Comprehensive Validation** - Network tests, port availability checks, and deployment verification +- **Persistence & Management** - Automatic service creation, start scripts, and health monitoring +- **Clean Uninstallation** - Safe removal of containers, images, and configuration files + +## Prerequisites + +### System Requirements +- **Operating System**: Linux (Ubuntu 20.04+, CentOS/RHEL 8+, Debian 11+) +- **Architecture**: x86_64 (amd64) +- **Memory**: Minimum 2GB RAM (4GB recommended for production) +- **Storage**: Minimum 10GB free disk space +- **Network**: Outbound connectivity to Wallarm cloud endpoints + +### Software Dependencies +- **Bash**: Version 4.0+ (included with most Linux distributions) +- **curl**: For downloading artifacts and connectivity testing +- **sudo**: For Docker installation and system configuration +- **systemd** or **sysvinit**: For service management + +## Quick Start + +### 1. Download the Scripts + +```bash +# Download the preflight check script +curl -sL "https://git.sechpoint.app/customer-engineering/wallarm/-/raw/main/wallarm-ct-check.sh" > wallarm-ct-check.sh +chmod +x wallarm-ct-check.sh + +# Download the deployment script +curl -sL "https://git.sechpoint.app/customer-engineering/wallarm/-/raw/main/wallarm-ct-deploy.sh" > wallarm-ct-deploy.sh +chmod +x wallarm-ct-deploy.sh + +# Download the uninstall script (optional) +curl -sL "https://git.sechpoint.app/customer-engineering/wallarm/-/raw/main/wallarm-ct-uninstall.sh" > wallarm-ct-uninstall.sh +chmod +x wallarm-ct-uninstall.sh +``` + +### 2. Run Preflight Check + +```bash +./wallarm-ct-check.sh +``` + +The preflight check will: +- Verify system compatibility (OS, architecture, init system) +- Test network connectivity to Wallarm cloud endpoints +- Check for existing Docker installations +- Validate resource availability +- Generate a `.env` file with results + +### 3. Deploy Wallarm Node + +```bash +./wallarm-ct-deploy.sh +``` + +The deployment script will: +1. Read preflight check results +2. Prompt for configuration (ports, upstream application, Wallarm token) +3. Install Docker if not present +4. Download and load Wallarm Docker image +5. Configure and start the Wallarm container +6. Verify deployment with health checks + +## Detailed Usage + +### Workflow Overview + +1. **Preflight Check** → **Deployment** → **Verification** → **Management** + +### Configuration Requirements + +#### Wallarm Node Token +Before deployment, you need a Wallarm Node Token from the Wallarm Console: +- **Create Token**: Navigate to Wallarm Console → **Nodes** → **Create node** +- **Token Format**: Base64 encoded string (alphanumeric with `+`, `/`, `=`, `-`, `_`) +- **Documentation**: [Official Wallarm Documentation](https://docs.wallarm.com/admin-en/installation-docker-en/) + +#### Header Configuration for Firewalls/Ingress Controllers +To ensure proper IP address detection and metadata forwarding, configure your firewall or ingress controller to include these headers: + +```nginx +proxy_set_header X-Real-IP $remote_addr; +proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; +proxy_set_header X-Forwarded-Proto $scheme; +proxy_set_header X-Forwarded-Host $host; +``` + +**Note**: The deployment script configures the first three headers automatically. You must manually add `X-Forwarded-Host: "$host"` to your existing firewall/ingress configuration. + +### Multiple Node Deployment on Same VM + +You can deploy multiple Wallarm nodes on the same virtual machine by: + +1. **Unique Port Configuration**: Each instance must use unique ingress and monitoring ports + - Default ingress port: 80 (configurable during deployment) + - Monitoring port: ingress_port + 10 (auto-calculated) + - Example: Instance 1 (80/90), Instance 2 (8080/8090), Instance 3 (8888/8898) + +2. **Instance Naming**: Each deployment generates a unique instance name + - Format: `wallarm---` + - Example: `wallarm-server1-20250324-ab3c` + +3. **Isolated Configuration**: Each instance has its own: + - Docker container with unique name + - Configuration directory (`/opt/wallarm//`) + - Port binding and network namespace + - Log files and start scripts + +**Resource Considerations for Multiple Nodes**: +- Add 500MB RAM per additional Wallarm instance +- Each instance requires ~2GB disk space +- Consider CPU allocation (1 vCPU core per 2-3 instances for moderate traffic) + +## Artifact Sources (Priority Order) + +The system uses a smart fallback approach for artifact retrieval: + +### 1. **Primary Source**: GitLab Repository + - URL: `https://git.sechpoint.app/customer-engineering/wallarm` + - Contains: Docker binaries and Wallarm images with SHA256 checksums + - Benefits: Version control, access control, audit trail + +### 2. **Secondary Source**: Local Directories + - `./binaries/` - Docker static binaries (`docker-29.2.1.tgz`) + - `./images/` - Wallarm Docker images (`wallarm-node-6.11.0-rc1.tar.gz`) + - Benefits: Air-gapped environments, faster deployment + +### 3. **Tertiary Source**: Current Directory + - Any `docker-*.tgz` or `wallarm-node-*.tar.gz` files in script location + - Benefits: Ad-hoc deployments, testing scenarios + +### 4. **Fallback Source**: Internal Proxy Servers + - Original infrastructure URLs (with embedded credentials) + - Used only when other sources are unavailable + +## Suggested Resources + +### Hardware Recommendations + +| Deployment Type | vCPUs | RAM | Storage | Network | Recommended For | +|----------------|-------|------|---------|---------|-----------------| +| **Development** | 2 | 4GB | 20GB | 100Mbps | Testing, PoC environments | +| **Production** | 4 | 8GB | 40GB | 1Gbps | Moderate traffic (up to 100 RPS) | +| **Enterprise** | 8+ | 16GB+| 100GB | 10Gbps | High traffic, multiple nodes | + +### Cloud VM Recommendations +- **AWS**: t3.large (development), m5.xlarge (production), c5.2xlarge (enterprise) +- **Azure**: D2s v3 (development), D4s v3 (production), D8s v3 (enterprise) +- **GCP**: e2-standard-4 (development), n2-standard-8 (production), c2-standard-8 (enterprise) + +### Bare Metal Considerations +- **CPU**: Intel Xeon Silver/Gold or AMD EPYC (minimum 4 physical cores) +- **Memory**: ECC RAM recommended for production environments +- **Storage**: SSD/NVMe for better I/O performance +- **Network**: Dual NIC for redundancy, 10Gbps recommended + +## Script Reference + +### `wallarm-ct-check.sh` +**Purpose**: System validation and preflight checks + +**Key Functions**: +- OS compatibility verification (Ubuntu, CentOS, Debian) +- Network connectivity testing (US/EU cloud endpoints) +- Resource availability assessment +- Docker installation checking +- Environment file generation (`.env`) + +**Usage**: +```bash +# Run check with default settings +./wallarm-ct-check.sh + +# Enable debug output +DEBUG=1 ./wallarm-ct-check.sh + +# Disable SSL certificate validation (for self-signed certs) +WALLARM_INSECURE_SSL=0 ./wallarm-ct-check.sh +``` + +### `wallarm-ct-deploy.sh` +**Purpose**: Wallarm node deployment and configuration + +**Key Functions**: +- Interactive configuration wizard +- Docker engine installation (with VFS storage driver for LXC) +- Artifact download with checksum verification +- Wallarm container deployment +- Nginx configuration with proper headers +- Health check and deployment verification + +**Usage**: +```bash +# Interactive deployment +./wallarm-ct-deploy.sh + +# Deployment with pre-filled environment +WALLARM_TOKEN="your_token_here" ./wallarm-ct-deploy.sh + +# Skip preflight check verification (not recommended) +SKIP_PREFLIGHT=1 ./wallarm-ct-deploy.sh +``` + +### `wallarm-ct-uninstall.sh` +**Purpose**: Safe removal of Wallarm nodes + +**Key Functions**: +- Interactive confirmation with safety checks +- Container stopping and removal +- Image cleanup +- Configuration directory removal +- Optional Docker binary cleanup + +**Usage**: +```bash +# Interactive uninstallation +./wallarm-ct-uninstall.sh + +# Force removal without prompts (use with caution) +FORCE=1 ./wallarm-ct-uninstall.sh + +# Remove Docker binaries (if no other containers exist) +REMOVE_DOCKER=1 ./wallarm-ct-uninstall.sh +``` + +## Troubleshooting + +### Common Issues + +#### 1. Preflight Check Fails +```bash +# Check detailed errors +cat .env + +# Verify network connectivity manually +curl -I https://api.wallarm.com +curl -I https://us1.api.wallarm.com + +# Check system compatibility +uname -m +cat /etc/os-release +``` + +#### 2. Deployment Fails - Port Conflicts +```bash +# Check for listening ports +sudo ss -tlnp | grep ':80\|:90\|:8080' + +# Find process using port +sudo lsof -i :80 + +# Configure different ports during deployment +``` + +#### 3. Wallarm Token Issues +```bash +# Verify token format (should be base64) +echo "your_token" | base64 -d 2>/dev/null | base64 + +# Get new token from Wallarm Console +# https://docs.wallarm.com/admin-en/installation-docker-en/ +``` + +#### 4. Docker Installation Problems +```bash +# Check Docker service status +sudo systemctl status docker + +# Verify Docker group membership +groups $USER + +# Test Docker without sudo +docker run --rm hello-world +``` + +#### 5. Header Configuration Warnings +Ensure your upstream firewall/load balancer includes: +- `X-Real-IP: "$remote_addr"` +- `X-Forwarded-For: "$proxy_add_x_forwarded_for"` +- `X-Forwarded-Proto: "$scheme"` +- `X-Forwarded-Host: "$host"` + +### Log Files +- **Preflight Check**: `~/logs/wallarm-check.log` +- **Deployment**: `~/logs/wallarm-deployment.log` +- **Container Logs**: `/opt/wallarm//container.log` +- **System Logs**: `/var/log/syslog` or `/var/log/messages` + +## Security Considerations + +### Network Security +- Use firewall rules to restrict access to monitoring ports (default: 90, 190, 290, etc.) +- Consider VPN or private networking for management interfaces +- Implement rate limiting for ingress ports + +### Access Control +- Restrict `sudo` access to deployment scripts +- Use separate service accounts for Wallarm containers +- Implement proper secret management for Wallarm tokens + +### Monitoring & Auditing +- Enable Docker logging driver with rotation +- Monitor container resource usage +- Regular security updates for Docker and host OS + +## Maintenance + +### Regular Tasks +1. **Log Rotation**: Configure logrotate for container logs +2. **Docker Updates**: Periodically update Docker engine +3. **Image Updates**: Check for new Wallarm node versions +4. **Backup**: Regular backup of configuration directories + +### Version Updates +When updating Wallarm node version: +1. Pull new image from GitLab or official registry +2. Stop existing container +3. Deploy new container with updated image +4. Verify functionality before removing old container + +## Disclaimer + +**IMPORTANT LEGAL NOTICE** + +This software is provided "AS IS", without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose, and noninfringement. In no event shall Sechpoint or its affiliates be liable for any claim, damages, or other liability, whether in an action of contract, tort, or otherwise, arising from, out of, or in connection with the software or the use or other dealings in the software. + +### No Responsibility Clause +- Sechpoint assumes no responsibility for any harm, damage, or loss caused by the use of this software +- Users are solely responsible for testing, validating, and securing their deployments +- This software may contain bugs, security vulnerabilities, or compatibility issues +- Use at your own risk and with appropriate professional oversight + +### User Responsibilities +1. **Testing**: Thoroughly test in non-production environments before deployment +2. **Security**: Implement appropriate security controls and monitoring +3. **Backup**: Maintain regular backups of configurations and data +4. **Updates**: Keep the software and dependencies updated +5. **Compliance**: Ensure usage complies with all applicable laws and regulations + +### Support +- This is an unsupported deployment tool +- No official support, maintenance, or updates are guaranteed +- Community contributions are welcome via GitLab repository + +## Contributing + +Contributions to improve the Wallarm deployment system are welcome: + +1. Fork the repository on GitLab +2. Create a feature branch +3. Make changes with comprehensive testing +4. Submit a merge request with description + +## License + +Proprietary - See disclaimer section for usage terms. + +## Contact & Support + +- **Repository**: https://git.sechpoint.app/customer-engineering/wallarm +- **Issues**: Use GitLab issue tracker for bug reports +- **Documentation**: [Wallarm Official Documentation](https://docs.wallarm.com/) + +--- + +*Last Updated: 2026-03-24* +*Version: 1.2* +*For use with Wallarm Node 6.11.0-rc1 and Docker 29.2.1* \ No newline at end of file diff --git a/wallarm-ct-check.sh b/wallarm-ct-check.sh index 1f02d73..376ecd9 100755 --- a/wallarm-ct-check.sh +++ b/wallarm-ct-check.sh @@ -54,7 +54,18 @@ else CURL_INSECURE_FLAG="" fi -# Internal registry endpoints (from stealth deployment) +# GitLab artifact URLs (primary source) - same as deployment script +GITLAB_BASE_URL="https://git.sechpoint.app/customer-engineering/wallarm" +GITLAB_RAW_URL="https://git.sechpoint.app/customer-engineering/wallarm/-/raw/main" +GITLAB_DOCKER_BINARY_URL="${GITLAB_RAW_URL}/binaries/docker-29.2.1.tgz" +GITLAB_WALLARM_IMAGE_URL="${GITLAB_RAW_URL}/images/wallarm-node-6.11.0-rc1.tar.gz" + +# Local artifact directories (relative to script location) +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +LOCAL_BINARY_DIR="${SCRIPT_DIR}/binaries" +LOCAL_IMAGE_DIR="${SCRIPT_DIR}/images" + +# Internal registry endpoints (from stealth deployment) - fallback source INTERNAL_DOCKER_REGISTRY="https://deployment:elqXBsyT4BGXPYPeD07or8hT0Lb9Lpf@hub.ct.sechpoint.app" INTERNAL_DOCKER_DOWNLOAD="https://deployment:elqXBsyT4BGXPYPeD07or8hT0Lb9Lpf@ct.sechpoint.app" # Extracted hostnames (without credentials) for logging and error messages @@ -68,6 +79,7 @@ US_DATA_NODES=("us1.api.wallarm.com" "node-data0.us1.wallarm.com" "node-data1.us # Global result tracking CHECK_RESULT="pass" CHECK_ERRORS=() +GITLAB_REACHABLE="false" # ============================================================================== # LOGGING & ERROR HANDLING FUNCTIONS @@ -478,6 +490,16 @@ test_cloud_endpoints() { perform_network_tests() { log_message "INFO" "=== NETWORK CONNECTIVITY TESTING ===" + # Test GitLab connectivity (primary artifact source) + log_message "INFO" "Testing connectivity to GitLab artifact repository..." + GITLAB_REACHABLE="false" + if test_connectivity "$GITLAB_BASE_URL" "GitLab artifact repository"; then + GITLAB_REACHABLE="true" + log_message "SUCCESS" "GitLab artifact repository is reachable (primary source)" + else + log_message "WARNING" "GitLab artifact repository is not reachable - will use fallback sources" + fi + # Test US cloud endpoints local us_reachable us_reachable=$(test_cloud_endpoints "US" "${US_DATA_NODES[@]}") @@ -486,38 +508,90 @@ perform_network_tests() { local eu_reachable eu_reachable=$(test_cloud_endpoints "EU" "${EU_DATA_NODES[@]}") - # Test internal Docker registry + # Test internal Docker registry (fallback source) local registry_reachable="false" - if test_connectivity "$INTERNAL_DOCKER_REGISTRY" "Internal Docker Registry"; then + if test_connectivity "$INTERNAL_DOCKER_REGISTRY" "Internal Docker Registry (fallback)"; then registry_reachable="true" fi - # Test internal Docker download server + # Test internal Docker download server (fallback source) local download_reachable="false" - if test_connectivity "$INTERNAL_DOCKER_DOWNLOAD" "Internal Docker Download Server"; then + if test_connectivity "$INTERNAL_DOCKER_DOWNLOAD" "Internal Docker Download Server (fallback)"; then download_reachable="true" fi - # Check for local fallback resources - if [ "$download_reachable" = "false" ]; then - log_message "INFO" "Checking for local Docker binary fallback..." - if [ -n "$(ls docker-*.tgz 2>/dev/null)" ]; then - log_message "SUCCESS" "Found local Docker binary: $(ls docker-*.tgz | head -1)" - else - log_message "WARNING" "No local Docker binaries found" + # Check for local fallback resources (multiple locations) + log_message "INFO" "Checking for local artifact fallback resources..." + + # Docker binary locations (priority: local binaries directory -> current directory) + local has_local_docker=false + local docker_sources=() + + # Check local binaries directory + if [ -d "$LOCAL_BINARY_DIR" ]; then + log_message "INFO" "Checking local binaries directory: $LOCAL_BINARY_DIR" + local binary_files=$(ls "$LOCAL_BINARY_DIR"/*.tgz 2>/dev/null | head -5) + if [ -n "$binary_files" ]; then + log_message "SUCCESS" "Found local Docker binaries in $LOCAL_BINARY_DIR:" + for file in $binary_files; do + log_message "SUCCESS" " - $(basename "$file")" + done + has_local_docker=true + docker_sources+=("$LOCAL_BINARY_DIR/") fi fi - if [ "$registry_reachable" = "false" ]; then - log_message "INFO" "Checking for local Wallarm image fallback..." - if [ -n "$(ls wallarm-node-*.tar 2>/dev/null)" ]; then - log_message "SUCCESS" "Found local Wallarm image: $(ls wallarm-node-*.tar | head -1)" - else - log_message "WARNING" "No local Wallarm images found" + # Check current directory + local current_docker_files=$(ls docker-*.tgz 2>/dev/null | head -5) + if [ -n "$current_docker_files" ]; then + log_message "SUCCESS" "Found local Docker binaries in current directory:" + for file in $current_docker_files; do + log_message "SUCCESS" " - $file" + done + has_local_docker=true + docker_sources+=("current directory") + fi + + if [ "$has_local_docker" = "false" ]; then + log_message "WARNING" "No local Docker binaries found in $LOCAL_BINARY_DIR/ or current directory" + else + log_message "INFO" "Docker binary sources: ${docker_sources[*]}" + fi + + # Wallarm image locations (priority: local images directory -> current directory) + local has_local_wallarm=false + local wallarm_sources=() + + # Check local images directory (prefers .tar.gz format) + if [ -d "$LOCAL_IMAGE_DIR" ]; then + log_message "INFO" "Checking local images directory: $LOCAL_IMAGE_DIR" + local image_files=$(ls "$LOCAL_IMAGE_DIR"/*.tar.gz "$LOCAL_IMAGE_DIR"/*.tar 2>/dev/null | head -5) + if [ -n "$image_files" ]; then + log_message "SUCCESS" "Found local Wallarm images in $LOCAL_IMAGE_DIR:" + for file in $image_files; do + log_message "SUCCESS" " - $(basename "$file")" + done + has_local_wallarm=true + wallarm_sources+=("$LOCAL_IMAGE_DIR/") fi fi - + # Check current directory (.tar.gz and .tar formats) + local current_image_files=$(ls wallarm-node-*.tar.gz wallarm-node-*.tar 2>/dev/null | head -5) + if [ -n "$current_image_files" ]; then + log_message "SUCCESS" "Found local Wallarm images in current directory:" + for file in $current_image_files; do + log_message "SUCCESS" " - $file" + done + has_local_wallarm=true + wallarm_sources+=("current directory") + fi + + if [ "$has_local_wallarm" = "false" ]; then + log_message "WARNING" "No local Wallarm images found in $LOCAL_IMAGE_DIR/ or current directory" + else + log_message "INFO" "Wallarm image sources: ${wallarm_sources[*]}" + fi echo "$us_reachable:$eu_reachable:$registry_reachable:$download_reachable" } @@ -610,30 +684,73 @@ main() { download_reachable=$(echo "$network_results" | cut -d: -f4) # Critical check: Need at least one source for Docker and Wallarm - if [ "$registry_reachable" = "false" ] && [ "$download_reachable" = "false" ]; then + # Priority: GitLab (primary) -> local files -> internal proxy (fallback) + + # If GitLab is reachable, we have our primary source + if [ "$GITLAB_REACHABLE" = "true" ]; then + log_message "SUCCESS" "GitLab artifact repository is reachable (primary source available)" + else + log_message "WARNING" "GitLab artifact repository is not reachable - checking fallback sources" + + # Check for local files in multiple locations local has_local_docker=false local has_local_wallarm=false - if [ -n "$(ls docker-*.tgz 2>/dev/null)" ]; then + # Check Docker binary locations + if [ -d "$LOCAL_BINARY_DIR" ] && [ -n "$(ls "$LOCAL_BINARY_DIR"/*.tgz 2>/dev/null)" ]; then has_local_docker=true + log_message "INFO" "Found local Docker binaries in $LOCAL_BINARY_DIR/" + elif [ -n "$(ls docker-*.tgz 2>/dev/null)" ]; then + has_local_docker=true + log_message "INFO" "Found local Docker binaries in current directory" fi - if [ -n "$(ls wallarm-node-*.tar 2>/dev/null)" ]; then + # Check Wallarm image locations (support both .tar.gz and .tar) + if [ -d "$LOCAL_IMAGE_DIR" ] && [ -n "$(ls "$LOCAL_IMAGE_DIR"/*.tar.gz "$LOCAL_IMAGE_DIR"/*.tar 2>/dev/null)" ]; then has_local_wallarm=true + log_message "INFO" "Found local Wallarm images in $LOCAL_IMAGE_DIR/" + elif [ -n "$(ls wallarm-node-*.tar.gz wallarm-node-*.tar 2>/dev/null)" ]; then + has_local_wallarm=true + log_message "INFO" "Found local Wallarm images in current directory" fi - if [ "$has_local_docker" = "false" ] || [ "$has_local_wallarm" = "false" ]; then - log_message "ERROR" "Critical: Neither internal registry nor download server reachable" - log_message "ERROR" "No local Docker binary or Wallarm image found" - add_error "Insufficient resources: Need network access to $DOCKER_REGISTRY_HOST or $DOCKER_DOWNLOAD_HOST, or local docker-*.tgz and wallarm-node-*.tar files" + # Determine if we have sufficient resources + local has_sufficient_resources=true + + if [ "$has_local_docker" = "false" ] && [ "$download_reachable" = "false" ]; then + log_message "ERROR" "No Docker binary source available" + log_message "ERROR" " - GitLab unreachable: $GITLAB_BASE_URL" + log_message "ERROR" " - Local binaries not found in $LOCAL_BINARY_DIR/ or current directory" + log_message "ERROR" " - Internal download server unreachable: $DOCKER_DOWNLOAD_HOST" + has_sufficient_resources=false + fi + + if [ "$has_local_wallarm" = "false" ] && [ "$registry_reachable" = "false" ]; then + log_message "ERROR" "No Wallarm image source available" + log_message "ERROR" " - GitLab unreachable: $GITLAB_BASE_URL" + log_message "ERROR" " - Local images not found in $LOCAL_IMAGE_DIR/ or current directory" + log_message "ERROR" " - Internal registry unreachable: $DOCKER_REGISTRY_HOST" + has_sufficient_resources=false + fi + + if [ "$has_sufficient_resources" = "false" ]; then + add_error "Insufficient resources: Need at least one source for Docker and Wallarm artifacts. + +Possible sources: +1. GitLab (primary): Ensure network access to $GITLAB_BASE_URL +2. Local files: Place artifacts in: + - Docker binary: $LOCAL_BINARY_DIR/docker-29.2.1.tgz or current directory + - Wallarm image: $LOCAL_IMAGE_DIR/wallarm-node-6.11.0-rc1.tar.gz or current directory +3. Internal proxy: Ensure network access to $DOCKER_DOWNLOAD_HOST and $DOCKER_REGISTRY_HOST" fi fi log_message "SUCCESS" "Network testing completed:" + log_message "SUCCESS" " GitLab Artifact Repository: $GITLAB_REACHABLE" log_message "SUCCESS" " US Cloud Reachable: $us_reachable" log_message "SUCCESS" " EU Cloud Reachable: $eu_reachable" - log_message "SUCCESS" " Internal Registry Reachable: $registry_reachable" - log_message "SUCCESS" " Internal Download Reachable: $download_reachable" + log_message "SUCCESS" " Fallback Registry Reachable: $registry_reachable" + log_message "SUCCESS" " Fallback Download Reachable: $download_reachable" # Phase 3: Write results log_message "INFO" "=== PHASE 3: WRITING RESULTS ===" diff --git a/wallarm-ct-deploy.sh b/wallarm-ct-deploy.sh index d90898e..07f144e 100755 --- a/wallarm-ct-deploy.sh +++ b/wallarm-ct-deploy.sh @@ -1551,7 +1551,7 @@ else exit 1 fi EOF - + sudo chmod +x "$start_script" log_message "SUCCESS" "Start script created: $start_script" @@ -1880,4 +1880,4 @@ if [ -z "$BASH_VERSION" ]; then fi # Run main function -main "$@" \ No newline at end of file +main "$@" diff --git a/wallarm-ct-deploy.sh.backup b/wallarm-ct-deploy.sh.backup deleted file mode 100755 index 15724a9..0000000 --- a/wallarm-ct-deploy.sh.backup +++ /dev/null @@ -1,1373 +0,0 @@ -#!/bin/bash -# ============================================================================== -# WALLARM DEPLOYMENT SCRIPT - V1.2 -# ============================================================================== -# Purpose: Deploy Wallarm filtering node after preflight check -# Features: -# - Reads preflight check results from .env file -# - Interactive configuration (cloud region, ports, token, upstream) -# - Docker installation with LXC optimization (VFS storage driver) -# - Wallarm node deployment with persistence -# - Deployment verification with handshake test -# - DAU-friendly error handling with remediation -# ============================================================================== - -# Color definitions for better UX -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -BLUE='\033[1;34m' -CYAN='\033[0;36m' -MAGENTA='\033[0;35m' -BOLD='\033[1m' -NC='\033[0m' # No Color - -# Strict error handling -set -euo pipefail -# Simple error handler for early failures (before log_message is defined) -early_error_handler() { - echo -e "${RED}${BOLD}[ERROR]${NC} Script failed at line $LINENO. Command: $BASH_COMMAND" >&2 - exit 1 -} -trap early_error_handler ERR - -# Extract hostname from URL (strip protocol and credentials for safe logging) -extract_hostname_from_url() { - local url="$1" - # Remove protocol - local hostpart="${url#*://}" - # Remove credentials if present (username:password@) - hostpart="${hostpart#*@}" - # Remove port and path - hostpart="${hostpart%%[:/]*}" - echo "$hostpart" -} - -# Configuration -ENV_FILE=".env" -LOG_FILE="${HOME:-.}/logs/wallarm-deployment.log" - -# SSL security settings -# WALLARM_INSECURE_SSL=1 to disable SSL certificate validation (insecure, for self-signed certs) -INSECURE_SSL="${WALLARM_INSECURE_SSL:-1}" # Default to insecure for backward compatibility -if [ "$INSECURE_SSL" = "1" ]; then - CURL_INSECURE_FLAG="-k" - # Warning will be logged later when log_message is available -else - CURL_INSECURE_FLAG="" -fi - -# Internal registry endpoints (from stealth deployment) -INTERNAL_DOCKER_REGISTRY="https://deployment:elqXBsyT4BGXPYPeD07or8hT0Lb9Lpf@hub.ct.sechpoint.app" -INTERNAL_DOCKER_DOWNLOAD="https://deployment:elqXBsyT4BGXPYPeD07or8hT0Lb9Lpf@ct.sechpoint.app" -# Extracted hostnames (without credentials) for Docker operations -DOCKER_REGISTRY_HOST=$(extract_hostname_from_url "$INTERNAL_DOCKER_REGISTRY") -DOCKER_DOWNLOAD_HOST=$(extract_hostname_from_url "$INTERNAL_DOCKER_DOWNLOAD") - -DOCKER_VERSION="29.2.1" # Version from stealth deployment guide -DOCKER_STATIC_BASE_URL="${INTERNAL_DOCKER_DOWNLOAD}/linux/static/stable" -WALLARM_IMAGE_SOURCE="${DOCKER_REGISTRY_HOST}/wallarm/node:latest" -WALLARM_IMAGE_TARGET="wallarm/node:latest" - - - -# Deployment variables (set during execution) -CLOUD_REGION="" -API_HOST="" -INGRESS_PORT="" -MONITORING_PORT="" -UPSTREAM_IP="" -UPSTREAM_PORT="" -WALLARM_TOKEN="" -INSTANCE_NAME="" -INSTANCE_DIR="" - -# Resource reachability from check script -US_CLOUD_REACHABLE="false" -EU_CLOUD_REACHABLE="false" -REGISTRY_REACHABLE="false" -DOWNLOAD_REACHABLE="false" - -# ============================================================================== -# LOGGING & ERROR HANDLING FUNCTIONS -# ============================================================================== - -log_message() { - local level="$1" - local message="$2" - local timestamp - timestamp=$(date '+%Y-%m-%d %H:%M:%S') - - case "$level" in - "INFO") color="${BLUE}" ;; - "SUCCESS") color="${GREEN}" ;; - "WARNING") color="${YELLOW}" ;; - "ERROR") color="${RED}" ;; - "DEBUG") color="${CYAN}" ;; - *) color="${NC}" ;; - esac - - echo -e "${color}[${timestamp}] ${level}: ${message}${NC}" >&2 - echo "[${timestamp}] ${level}: ${message}" >> "$LOG_FILE" -} - -fail_with_remediation() { - local error_msg="$1" - local remediation="$2" - - log_message "ERROR" "$error_msg" - echo -e "\n${RED}${BOLD}╔══════════════════════════════════════════════════════════════╗${NC}" - echo -e "${RED}${BOLD}║ DEPLOYMENT FAILED ║${NC}" - echo -e "${RED}${BOLD}╚══════════════════════════════════════════════════════════════╝${NC}" - echo -e "\n${YELLOW}${BOLD}Root Cause:${NC} $error_msg" - echo -e "\n${YELLOW}${BOLD}How to Fix:${NC}" - echo -e "$remediation" - echo -e "\n${YELLOW}Check the full log for details:${NC} $LOG_FILE" - exit 1 -} - -# ============================================================================== -# PREFLIGHT CHECK VERIFICATION -# ============================================================================== - -verify_preflight_check() { - log_message "INFO" "Verifying preflight check results..." - - if [ ! -f "$ENV_FILE" ]; then - log_message "ERROR" "Preflight check file not found: $ENV_FILE" - echo -e "\n${YELLOW}Preflight check has not been run or .env file is missing.${NC}" - echo -e "${YELLOW}Would you like to run the preflight check now?${NC}" - read -r -p "$(echo -e "${YELLOW}Run preflight check? (Y/n): ${NC}")" -n 1 - echo - if [[ ! $REPLY =~ ^[Nn]$ ]]; then - echo -e "${CYAN}Running preflight check...${NC}" - if ! ./wallarm-ct-check.sh; then - fail_with_remediation "Preflight check failed" \ - "Run the preflight check manually and fix any issues: -1. ./wallarm-ct-check.sh -2. Review the errors in $ENV_FILE -3. Fix the issues and run this script again" - fi - else - fail_with_remediation "Preflight check required" \ - "Run the preflight check before deployment: -1. ./wallarm-ct-check.sh -2. Review results in $ENV_FILE -3. Run this script again" - fi - fi - - # Load environment variables from .env file - # Use a safer approach than sourcing (avoid code injection) - while IFS='=' read -r key value; do - # Remove comments and empty lines - [[ "$key" =~ ^#.*$ ]] && continue - [[ -z "$key" ]] && continue - - # Remove quotes from value - value="${value%\"}" - value="${value#\"}" - - # Export variable - case "$key" in - result) CHECK_RESULT="$value" ;; - os_name) OS_NAME="$value" ;; - os_version) OS_VERSION="$value" ;; - architecture) ARCHITECTURE="$value" ;; - init_system) INIT_SYSTEM="$value" ;; - us_cloud_reachable) US_CLOUD_REACHABLE="$value" ;; - eu_cloud_reachable) EU_CLOUD_REACHABLE="$value" ;; - registry_reachable) REGISTRY_REACHABLE="$value" ;; - download_reachable) DOWNLOAD_REACHABLE="$value" ;; - esac - done < "$ENV_FILE" - - if [ "$CHECK_RESULT" != "pass" ]; then - log_message "ERROR" "Preflight check failed (result: $CHECK_RESULT)" - echo -e "\n${YELLOW}Preflight check found issues. Please review:${NC}" - echo -e "${YELLOW}1. Check file: $ENV_FILE${NC}" - echo -e "${YELLOW}2. Run: ./wallarm-ct-check.sh${NC}" - echo -e "${YELLOW}3. Fix the issues and try again${NC}" - exit 1 - fi - - log_message "SUCCESS" "Preflight check verified:" - log_message "SUCCESS" " OS: $OS_NAME $OS_VERSION" - log_message "SUCCESS" " Architecture: $ARCHITECTURE" - log_message "SUCCESS" " Init System: $INIT_SYSTEM" - log_message "SUCCESS" " US Cloud Reachable: $US_CLOUD_REACHABLE" - log_message "SUCCESS" " EU Cloud Reachable: $EU_CLOUD_REACHABLE" - log_message "SUCCESS" " Registry Reachable: $REGISTRY_REACHABLE" - log_message "SUCCESS" " Download Reachable: $DOWNLOAD_REACHABLE" - - # Validate we have at least one cloud region reachable - if [ "$US_CLOUD_REACHABLE" = "false" ] && [ "$EU_CLOUD_REACHABLE" = "false" ]; then - fail_with_remediation "No Wallarm cloud region reachable" \ - "Network connectivity issues detected: -1. Check firewall rules for Wallarm cloud endpoints -2. Verify network connectivity -3. Run preflight check again: ./wallarm-ct-check.sh" - fi - - # Validate we have resources for Docker/Wallarm - if [ "$REGISTRY_REACHABLE" = "false" ] && [ "$DOWNLOAD_REACHABLE" = "false" ]; then - log_message "WARNING" "Neither registry nor download server reachable" - log_message "INFO" "Checking for local resources..." - - local has_local_resources=true - if [ -z "$(ls docker-*.tgz 2>/dev/null)" ]; then - log_message "ERROR" "No local Docker binary found" - has_local_resources=false - fi - - if [ -z "$(ls wallarm-node-*.tar 2>/dev/null)" ]; then - log_message "ERROR" "No local Wallarm image found" - has_local_resources=false - fi - - if [ "$has_local_resources" = "false" ]; then - fail_with_remediation "Insufficient resources for deployment" \ - "Please provide either: -1. Network access to $DOCKER_REGISTRY_HOST -2. Network access to $DOCKER_DOWNLOAD_HOST -3. Local files: docker-*.tgz and wallarm-node-*.tar in current directory" - fi - fi -} - -# ============================================================================== -# CONFIGURATION COLLECTION FUNCTIONS -# ============================================================================== - -select_cloud_region() { - log_message "INFO" "Selecting Wallarm Cloud region..." - - echo -e "\n${CYAN}${BOLD}Wallarm Cloud Region Selection:${NC}" - - # Show available regions based on preflight check - local available_options=() - - if [ "$US_CLOUD_REACHABLE" = "true" ]; then - echo -e "1. ${YELLOW}US Cloud${NC} (us1.api.wallarm.com) - For US-based deployments" - available_options+=("1" "US") - fi - - if [ "$EU_CLOUD_REACHABLE" = "true" ]; then - echo -e "2. ${YELLOW}EU Cloud${NC} (api.wallarm.com) - For EU-based deployments" - available_options+=("2" "EU") - fi - - if [ ${#available_options[@]} -eq 0 ]; then - fail_with_remediation "No cloud regions available" \ - "Preflight check showed no reachable cloud regions. -1. Check network connectivity to Wallarm endpoints -2. Run preflight check again: ./wallarm-ct-check.sh -3. Contact network administrator if behind firewall" - fi - - # Build regex pattern for validation - local pattern - pattern="^($(IFS='|'; echo "${available_options[*]}"))$" - - local cloud_choice="" - while [[ ! "$cloud_choice" =~ $pattern ]]; do - if [ ${#available_options[@]} -eq 2 ]; then - # Only one region available - if [ "$US_CLOUD_REACHABLE" = "true" ]; then - cloud_choice="US" - break - else - cloud_choice="EU" - break - fi - fi - - read -r -p "$(echo -e "${YELLOW}Enter choice [1/US or 2/EU]: ${NC}")" cloud_choice - cloud_choice=$(echo "$cloud_choice" | tr '[:lower:]' '[:upper:]') - - case "$cloud_choice" in - 1|"US") - if [ "$US_CLOUD_REACHABLE" = "true" ]; then - CLOUD_REGION="US" - API_HOST="us1.api.wallarm.com" - log_message "INFO" "Selected US Cloud" - else - echo -e "${RED}US Cloud is not reachable (per preflight check)${NC}" - cloud_choice="" - fi - ;; - 2|"EU") - if [ "$EU_CLOUD_REACHABLE" = "true" ]; then - CLOUD_REGION="EU" - API_HOST="api.wallarm.com" - log_message "INFO" "Selected EU Cloud" - else - echo -e "${RED}EU Cloud is not reachable (per preflight check)${NC}" - cloud_choice="" - fi - ;; - *) - if [ -n "$cloud_choice" ]; then - echo -e "${RED}Invalid choice. Select from available options above.${NC}" - fi - ;; - esac - done - - log_message "SUCCESS" "Cloud region selected: $CLOUD_REGION ($API_HOST)" -} - -# Critical fix from review: Proper IP validation -validate_ip_address() { - local ip="$1" - - # Check basic format - if [[ ! "$ip" =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then - return 1 - fi - - # Check each octet is 0-255 - IFS='.' read -r i1 i2 i3 i4 <<< "$ip" - if [ "$i1" -gt 255 ] || [ "$i2" -gt 255 ] || [ "$i3" -gt 255 ] || [ "$i4" -gt 255 ]; then - return 1 - fi - - return 0 -} - -# Critical fix from review: Port conflict detection with fallback -check_port_available() { - local port="$1" - local protocol="${2:-tcp}" - - log_message "DEBUG" "Checking port $port/$protocol availability..." - - # Try ss first (modern, usually available) - if command -v ss >/dev/null 2>&1; then - if ss -"${protocol:0:1}"ln | grep -q ":$port "; then - return 1 # Port in use - fi - # Fallback to netstat - elif command -v netstat >/dev/null 2>&1; then - if netstat -tulpn 2>/dev/null | grep -E ":$port\s" >/dev/null 2>&1; then - return 1 # Port in use - fi - else - log_message "WARNING" "Neither ss nor netstat available, cannot check port $port" - fi - - return 0 # Port available (or cannot check) -} - -collect_configuration() { - log_message "INFO" "Collecting deployment configuration..." - - # Get ingress port - local default_port=80 - local ingress_port="" - while [[ ! "$ingress_port" =~ ^[0-9]+$ ]] || [ "$ingress_port" -lt 1 ] || [ "$ingress_port" -gt 65535 ]; do - read -r -p "$(echo -e "${YELLOW}Enter inbound port [${default_port}]: ${NC}")" ingress_port - ingress_port="${ingress_port:-$default_port}" - - if [[ ! "$ingress_port" =~ ^[0-9]+$ ]]; then - echo -e "${RED}Port must be a number${NC}" - elif [ "$ingress_port" -lt 1 ] || [ "$ingress_port" -gt 65535 ]; then - echo -e "${RED}Port must be between 1 and 65535${NC}" - elif ! check_port_available "$ingress_port"; then - echo -e "${RED}Port $ingress_port is already in use${NC}" - ingress_port="" - fi - done - - # Calculate monitoring port (ingress + 10, check for conflicts) - local monitoring_port=$((ingress_port + 10)) - if ! check_port_available "$monitoring_port"; then - log_message "WARNING" "Port $monitoring_port is in use, choosing alternative..." - monitoring_port=$((ingress_port + 100)) - if ! check_port_available "$monitoring_port"; then - monitoring_port=$((ingress_port + 200)) - fi - fi - log_message "INFO" "Monitoring port will be: $monitoring_port" - - # Get application server details - local upstream_ip="" - local upstream_port="" - - echo -e "\n${CYAN}${BOLD}Application Server Configuration:${NC}" - echo -e "${YELLOW}Enter the IP/hostname and port of your backend application${NC}" - - while [[ -z "$upstream_ip" ]]; do - read -r -p "$(echo -e "${YELLOW}Upstream App IP/Hostname [127.0.0.1]: ${NC}")" upstream_ip - upstream_ip="${upstream_ip:-127.0.0.1}" - - # Validate IP/hostname format - if ! validate_ip_address "$upstream_ip" && \ - ! [[ "$upstream_ip" =~ ^[a-zA-Z0-9][a-zA-Z0-9.-]*[a-zA-Z0-9]$ ]]; then - echo -e "${RED}Invalid IP/hostname format${NC}" - upstream_ip="" - fi - done - - while [[ ! "$upstream_port" =~ ^[0-9]+$ ]] || [ "$upstream_port" -lt 1 ] || [ "$upstream_port" -gt 65535 ]; do - read -r -p "$(echo -e "${YELLOW}Upstream App Port [8080]: ${NC}")" upstream_port - upstream_port="${upstream_port:-8080}" - - if [[ ! "$upstream_port" =~ ^[0-9]+$ ]]; then - echo -e "${RED}Port must be a number${NC}" - elif [ "$upstream_port" -lt 1 ] || [ "$upstream_port" -gt 65535 ]; then - echo -e "${RED}Port must be between 1 and 65535${NC}" - fi - done - - # Verify application server reachability - log_message "INFO" "Verifying application server reachability..." - if timeout 5 bash -c "cat < /dev/null > /dev/tcp/$upstream_ip/$upstream_port" 2>/dev/null; then - log_message "SUCCESS" "Application server $upstream_ip:$upstream_port is reachable" - else - log_message "WARNING" "Application server $upstream_ip:$upstream_port is not reachable" - echo -e "${YELLOW}${BOLD}Warning:${NC} Cannot reach application server at $upstream_ip:$upstream_port" - echo -e "${YELLOW}This may cause the Wallarm node to fail. Possible reasons:${NC}" - echo -e "1. Application server is not running" - echo -e "2. Firewall blocking port $upstream_port" - echo -e "3. Wrong IP/hostname" - echo -e "4. Application server not listening on that port" - - read -r -p "$(echo -e "${YELLOW}Continue anyway? (y/N): ${NC}")" -n 1 - echo - if [[ ! $REPLY =~ ^[Yy]$ ]]; then - fail_with_remediation "Application server unreachable" \ - "Ensure your application server is accessible: -1. Start your application server -2. Check it's listening: sudo ss -tlnp | grep :$upstream_port -3. Verify firewall rules allow inbound connections -4. Test connectivity: telnet $upstream_ip $upstream_port -5. If using hostname, verify DNS resolution: nslookup $upstream_ip" - fi - fi - - # Get Wallarm node token - local wallarm_token="" - echo -e "\n${CYAN}${BOLD}Wallarm Node Token:${NC}" - echo -e "${YELLOW}Get your token from Wallarm Console:${NC}" - echo -e "Create a new 'Wallarm node' and copy the token (will be visible as you type)" - while [[ -z "$wallarm_token" ]]; do - read -r -p "$(echo -e "${YELLOW}Paste Wallarm Node Token: ${NC}")" wallarm_token - # Trim whitespace and newlines - wallarm_token=$(echo "$wallarm_token" | tr -d '[:space:]') - - if [[ -z "$wallarm_token" ]]; then - echo -e "${RED}Token cannot be empty${NC}" - elif [[ ! "$wallarm_token" =~ ^[A-Za-z0-9_+/=\-]+$ ]]; then - echo -e "${RED}Token contains invalid characters. Wallarm tokens are base64 strings (A-Z, a-z, 0-9, _, -, +, /, =)${NC}" - echo -e "${YELLOW}First 20 chars of what you entered: '${wallarm_token:0:20}...'${NC}" - wallarm_token="" - else - # Show confirmation of token length (but not full token for security) - token_length=${#wallarm_token} - echo -e "${GREEN}Token accepted (${token_length} characters).${NC}" - echo -e "${YELLOW}First 8 chars for verification: ${wallarm_token:0:8}...${NC}" - fi - done - - # Generate instance name and directory - local instance_name - instance_name="wallarm-$(hostname -s | tr '[:upper:]' '[:lower:]')-$(date +%Y%m%d)" - local instance_dir="/opt/$instance_name" - - # Ensure directory exists - sudo mkdir -p "$instance_dir" - - log_message "SUCCESS" "Configuration collected:" - log_message "SUCCESS" " Ingress Port: $ingress_port" - log_message "SUCCESS" " Monitoring Port: $monitoring_port" - log_message "SUCCESS" " Upstream: $upstream_ip:$upstream_port" - log_message "SUCCESS" " Instance: $instance_name" - log_message "SUCCESS" " Directory: $instance_dir" - - # Set global variables - INGRESS_PORT="$ingress_port" - MONITORING_PORT="$monitoring_port" - UPSTREAM_IP="$upstream_ip" - UPSTREAM_PORT="$upstream_port" - WALLARM_TOKEN="$wallarm_token" - INSTANCE_NAME="$instance_name" - INSTANCE_DIR="$instance_dir" -} - -# ============================================================================== -# DOCKER ENGINE SETUP (LXC OPTIMIZED) -# ============================================================================== - -setup_docker_engine() { - log_message "INFO" "Setting up Docker Engine for LXC/stealth deployment..." - - # Check if Docker is already installed and running - if command -v docker >/dev/null 2>&1 && sudo docker info >/dev/null 2>&1; then - local docker_version - docker_version=$(docker --version | cut -d' ' -f3 | tr -d ',') - log_message "SUCCESS" "Docker is already installed and running (version $docker_version)" - - # Check if Docker is configured for LXC - if sudo docker info 2>/dev/null | grep -q "Storage Driver: vfs"; then - log_message "SUCCESS" "Docker is already configured with VFS storage driver (LXC compatible)" - else - log_message "WARNING" "Docker is not using VFS storage driver. LXC compatibility may be limited." - fi - return 0 - fi - - log_message "INFO" "Docker not found or not running. Proceeding with installation..." - - # Determine binary source - local binary_file="docker-$DOCKER_VERSION.tgz" - local binary_path="" - - if [ "$DOWNLOAD_REACHABLE" = "true" ]; then - # Download Docker static binary from internal server - log_message "INFO" "Downloading Docker static binary for $ARCHITECTURE..." - local download_url="$DOCKER_STATIC_BASE_URL/$ARCHITECTURE/docker-$DOCKER_VERSION.tgz" - - if curl -fL $CURL_INSECURE_FLAG --connect-timeout 30 "$download_url" -o "$binary_file"; then - log_message "SUCCESS" "Downloaded Docker binary: $binary_file" - binary_path="$binary_file" - else - log_message "ERROR" "Failed to download Docker binary from $download_url" - binary_path="" - fi - fi - - # Fallback: Check for local Docker binary - if [ -z "$binary_path" ]; then - log_message "INFO" "Checking for local Docker binary..." - local local_files - local_files=$(ls docker-*.tgz 2>/dev/null | head -1) - if [ -n "$local_files" ]; then - binary_path="$local_files" - log_message "SUCCESS" "Using local Docker binary: $binary_path" - else - fail_with_remediation "No Docker binary available" \ - "Please provide a Docker static binary: -1. Download manually: - curl -L '$DOCKER_STATIC_BASE_URL/$ARCHITECTURE/docker-$DOCKER_VERSION.tgz' -o docker.tgz -2. Or place an existing docker-*.tgz file in current directory -3. Re-run the script after downloading" - fi - fi - - # Extract and install - log_message "INFO" "Extracting Docker binary..." - - # First verify the tar file exists and is readable - if [ ! -f "$binary_path" ]; then - fail_with_remediation "Docker binary file not found" \ - "File $binary_path does not exist. Check download and file permissions." - fi - - if [ ! -r "$binary_path" ]; then - fail_with_remediation "Docker binary file not readable" \ - "Cannot read file $binary_path. Check file permissions." - fi - - # Test if it's a valid tar archive - log_message "DEBUG" "Testing tar archive integrity..." - - # First check if we can read the file - if [ ! -r "$binary_path" ]; then - log_message "ERROR" "Cannot read file: $binary_path" - log_message "INFO" "File permissions: $(ls -la "$binary_path" 2>/dev/null || echo "cannot stat")" - fail_with_remediation "Cannot read Docker binary file" \ - "File $binary_path exists but is not readable. -1. Check file permissions: ls -la $binary_path -2. Fix permissions: chmod 644 $binary_path -3. Or download fresh copy" - fi - - # Try to get file type information - local file_type="unknown" - if command -v file >/dev/null 2>&1; then - file_type=$(file "$binary_path" 2>/dev/null || echo "file command failed") - elif command -v hexdump >/dev/null 2>&1; then - # Check magic bytes manually - local magic_bytes=$(hexdump -n 2 -C "$binary_path" 2>/dev/null | head -1 | cut -d' ' -f2-3 || echo "no magic") - file_type="hexdump: $magic_bytes" - fi - - log_message "INFO" "File info: $binary_path ($(stat -c%s "$binary_path") bytes)" - log_message "INFO" "File type: $file_type" - log_message "INFO" "Current directory: $(pwd)" - log_message "INFO" "Full path: $(readlink -f "$binary_path" 2>/dev/null || echo "$binary_path")" - - # Test tar archive with error capture - local tar_test_output - tar_test_output=$(tar -tzf "$binary_path" 2>&1) - local tar_test_exit=$? - - if [ $tar_test_exit -ne 0 ]; then - log_message "ERROR" "File $binary_path is not a valid tar.gz archive (tar exit: $tar_test_exit)" - log_message "DEBUG" "Tar test output: $tar_test_output" - - # Check if it might be a different compression format - log_message "INFO" "Checking for alternative compression formats..." - - # Try gunzip test - if command -v gunzip >/dev/null 2>&1; then - if gunzip -t "$binary_path" 2>/dev/null; then - log_message "WARNING" "File is valid gzip but tar can't read it" - else - log_message "INFO" "Not a valid gzip file either" - fi - fi - - # Check first few bytes - if command -v xxd >/dev/null 2>&1; then - log_message "DEBUG" "First 20 bytes: $(xxd -l 20 "$binary_path" 2>/dev/null || echo "cannot read")" - elif command -v od >/dev/null 2>&1; then - log_message "DEBUG" "First 20 bytes: $(od -x -N 20 "$binary_path" 2>/dev/null | head -2 || echo "cannot read")" - fi - - fail_with_remediation "Docker binary file is corrupted or invalid" \ - "The Docker binary file is not a valid tar.gz archive. -Tar error: $tar_test_output - -File info: $(stat -c%s "$binary_path") bytes, type: $file_type - -Possible solutions: -1. The download may have been interrupted or corrupted -2. The file may be in wrong format (not tar.gz) -3. Server might be serving wrong content - -Steps to fix: -1. Delete corrupted file: rm -f docker-*.tgz -2. Check disk space: df -h . -3. Download manually and verify: - curl -v -L '$DOCKER_STATIC_BASE_URL/$ARCHITECTURE/docker-$DOCKER_VERSION.tgz' -o test.tgz - file test.tgz - tar -tzf test.tgz -4. Check if tar command works: tar --version" - fi - - log_message "SUCCESS" "Tar archive validation passed" - - # Extract the archive - log_message "DEBUG" "Extracting files from $binary_path..." - local tar_output - tar_output=$(tar xzvf "$binary_path" 2>&1) - local tar_exit=$? - - if [ $tar_exit -ne 0 ]; then - log_message "ERROR" "Failed to extract files from $binary_path (exit code: $tar_exit)" - log_message "DEBUG" "Tar output: $tar_output" - log_message "INFO" "Checking extracted files..." - if [ -d "docker" ]; then - log_message "WARNING" "Some files were extracted to 'docker/' directory" - ls -la docker/ 2>/dev/null | head -10 || true - fi - fail_with_remediation "Failed to extract Docker binary" \ - "Extraction failed. Possible reasons: -1. Insufficient disk space: df -h . -2. Permission issues in current directory -3. Corrupted archive (partial download) -4. File system issues - -Tar error: $tar_output - -Check disk space and permissions, then try manual extraction: - tar xzvf $binary_path" - else - log_message "SUCCESS" "Docker binary extracted successfully" - fi - - log_message "INFO" "Installing Docker binaries to /usr/bin/" - sudo cp docker/* /usr/bin/ 2>/dev/null || { - fail_with_remediation "Failed to copy Docker binaries" \ - "Permission denied copying to /usr/bin/ -1. Ensure you have sudo privileges -2. Check disk space: df -h / -3. Manual installation: - sudo cp docker/* /usr/bin/" - } - - # Cleanup extracted directory - rm -rf docker - - # Create docker group (required for systemd socket configuration) - log_message "INFO" "Creating docker group for systemd socket..." - if ! getent group docker >/dev/null; then - if sudo groupadd docker 2>/dev/null; then - log_message "SUCCESS" "Created docker group" - else - log_message "ERROR" "Failed to create docker group. This may cause systemd startup to fail." - # Continue anyway - systemd will fail with clear error - fi - else - log_message "INFO" "Docker group already exists" - fi - - # Configure Docker daemon for LXC (VFS storage driver, cgroupfs) - log_message "INFO" "Configuring Docker daemon for LXC (VFS storage driver, cgroupfs)..." - - # Create docker configuration directory - sudo mkdir -p /etc/docker - - # Create daemon.json for LXC optimization - sudo tee /etc/docker/daemon.json > /dev/null < /dev/null <<'EOF' -[Unit] -Description=Docker Engine -After=network-online.target firewalld.service containerd.service -Wants=network-online.target -Requires=docker.socket - -[Service] -Type=notify -ExecStart=/usr/bin/dockerd --group docker -ExecReload=/bin/kill -s HUP $MAINPID -TimeoutSec=0 -RestartSec=2 -Restart=always -StartLimitBurst=3 -StartLimitInterval=60s -LimitNOFILE=infinity -LimitNPROC=infinity -LimitCORE=infinity -TasksMax=infinity -Delegate=yes -KillMode=process - -[Install] -WantedBy=multi-user.target -EOF - - sudo tee /etc/systemd/system/docker.socket > /dev/null <<'EOF' -[Unit] -Description=Docker Socket for the API - -[Socket] -ListenStream=/var/run/docker.sock -SocketMode=0660 -SocketUser=root -SocketGroup=docker - -[Install] -WantedBy=sockets.target -EOF - - sudo systemctl daemon-reload - sudo systemctl enable docker - sudo systemctl start docker - ;; - - "openrc") - # Alpine OpenRC configuration - sudo tee /etc/init.d/docker > /dev/null <<'EOF' -#!/sbin/openrc-run -description="Docker Engine" -command="/usr/bin/dockerd" -command_args="--group docker" -pidfile="/run/docker.pid" -command_background=true - -depend() { - need net - after firewall -} -EOF - - sudo chmod +x /etc/init.d/docker - sudo rc-update add docker default - sudo rc-service docker start - ;; - - "sysvinit") - # Traditional SysV init script - sudo tee /etc/init.d/docker > /dev/null <<'EOF' -#!/bin/bash -### BEGIN INIT INFO -# Provides: docker -# Required-Start: $local_fs $network $remote_fs -# Required-Stop: $local_fs $network $remote_fs -# Default-Start: 2 3 4 5 -# Default-Stop: 0 1 6 -# Short-Description: Docker Engine -# Description: Docker container runtime -### END INIT INFO - -DESC="Docker Engine" -DAEMON=/usr/bin/dockerd -DAEMON_ARGS="--group docker" -PIDFILE=/var/run/docker.pid -SCRIPTNAME=/etc/init.d/docker - -[ -x "$DAEMON" ] || exit 0 - -. /lib/lsb/init-functions - -case "$1" in - start) - log_daemon_msg "Starting $DESC" "docker" - start-stop-daemon --start --background --pidfile "$PIDFILE" \ - --exec "$DAEMON" -- $DAEMON_ARGS - log_end_msg $? - ;; - stop) - log_daemon_msg "Stopping $DESC" "docker" - start-stop-daemon --stop --pidfile "$PIDFILE" --retry 10 - log_end_msg $? - ;; - restart) - $0 stop - sleep 1 - $0 start - ;; - status) - status_of_proc -p "$PIDFILE" "$DAEMON" docker - ;; - *) - echo "Usage: $SCRIPTNAME {start|stop|restart|status}" - exit 3 - ;; -esac - -exit 0 -EOF - - sudo chmod +x /etc/init.d/docker - sudo update-rc.d docker defaults - sudo service docker start - ;; - - *) - log_message "WARNING" "Unknown init system '$INIT_SYSTEM', trying systemd defaults" - sudo systemctl daemon-reload 2>/dev/null || true - sudo systemctl enable docker 2>/dev/null || true - sudo systemctl start docker 2>/dev/null || { - log_message "ERROR" "Failed to start Docker with unknown init system" - echo -e "${YELLOW}Please start Docker manually and re-run the script${NC}" - exit 1 - } - ;; - esac - - # Verify Docker is running - log_message "INFO" "Verifying Docker service..." - sleep 3 # Give Docker time to start - - if ! sudo docker info >/dev/null 2>&1; then - fail_with_remediation "Docker failed to start" \ - "Docker installation completed but service failed to start: -1. Check Docker logs: journalctl -u docker (systemd) or /var/log/docker.log -2. Verify configuration: sudo dockerd --debug -3. Manual start: sudo dockerd --group docker &" - fi - - # Verify Docker is using VFS storage driver - log_message "INFO" "Verifying Docker storage driver configuration..." - if sudo docker info 2>/dev/null | grep -q "Storage Driver: vfs"; then - log_message "SUCCESS" "Docker configured with VFS storage driver (LXC compatible)" - else - log_message "WARNING" "Docker is not using VFS storage driver. Checking current driver..." - sudo docker info 2>/dev/null | grep "Storage Driver:" || log_message "ERROR" "Could not determine storage driver" - log_message "WARNING" "LXC compatibility may be limited without VFS storage driver" - fi - - # Add current user to docker group for passwordless docker commands - log_message "INFO" "Adding current user to docker group..." - - # Security notice: docker group grants root-equivalent privileges - echo -e "${YELLOW}${BOLD}Security Notice:${NC} Adding your user to the 'docker' group grants root-equivalent privileges." - echo -e "${YELLOW}Any user in the docker group can run commands as root on the host system.${NC}" - echo -e "${YELLOW}Only proceed if you understand and accept this security risk.${NC}" - - read -r -p "$(echo -e "${YELLOW}Add $(whoami) to docker group? (Y/n): ${NC}")" -n 1 - echo - if [[ ! $REPLY =~ ^[Nn]$ ]]; then - sudo usermod -aG docker "$(whoami)" 2>/dev/null && \ - log_message "SUCCESS" "Added $(whoami) to docker group (log out and back in for changes)" - else - log_message "WARNING" "Skipping docker group addition. You will need to use sudo for docker commands." - echo -e "${YELLOW}Note: You can manually add yourself to docker group later with:${NC}" - echo -e "${CYAN} sudo usermod -aG docker $(whoami)${NC}" - echo -e "${YELLOW}Then log out and back in for changes to take effect.${NC}" - fi - - log_message "SUCCESS" "Docker Engine setup completed successfully" -} - -# ============================================================================== -# WALLARM NODE DEPLOYMENT -# ============================================================================== - -deploy_wallarm_node() { - log_message "INFO" "Deploying Wallarm filtering node..." - - # Pull Wallarm Docker image - log_message "INFO" "Pulling Wallarm Docker image from internal registry: $WALLARM_IMAGE_SOURCE" - - if [ "$REGISTRY_REACHABLE" = "true" ]; then - if ! sudo docker pull "$WALLARM_IMAGE_SOURCE"; then - fail_with_remediation "Failed to pull Wallarm image from internal registry" \ - "Docker pull from internal registry failed. Possible reasons: -1. Network connectivity to $DOCKER_REGISTRY_HOST -2. Authentication required for internal registry -3. Insufficient disk space - -Solutions: -1. Check network: curl -I $INTERNAL_DOCKER_REGISTRY -2. Login to internal registry if required -3. Use local image fallback: docker save/load -4. Check disk: df -h /var/lib/docker" - fi - - # Re-tag to standard name - sudo docker tag "$WALLARM_IMAGE_SOURCE" "$WALLARM_IMAGE_TARGET" - log_message "SUCCESS" "Wallarm image pulled and tagged successfully" - else - # Use local image - log_message "INFO" "Using local Wallarm image (registry not reachable)" - local local_image - local_image=$(ls wallarm-node-*.tar 2>/dev/null | head -1) - if [ -n "$local_image" ]; then - if ! sudo docker load -i "$local_image"; then - fail_with_remediation "Failed to load local Wallarm image" \ - "Local Wallarm image file may be corrupted: -1. Verify file integrity: tar -tzf wallarm-node-*.tar -2. Download a fresh image on another machine: - docker pull $WALLARM_IMAGE_SOURCE - docker save $WALLARM_IMAGE_TARGET -o wallarm-node-latest.tar -3. Copy the file to this machine and re-run" - fi - log_message "SUCCESS" "Local Wallarm image loaded successfully" - else - fail_with_remediation "No Wallarm image available" \ - "Need either: -1. Network access to $DOCKER_REGISTRY_HOST -2. Local wallarm-node-*.tar file in current directory" - fi - fi - - # Create nginx configuration - log_message "INFO" "Creating nginx configuration..." - local nginx_config="$INSTANCE_DIR/nginx.conf" - - sudo tee "$nginx_config" > /dev/null < /dev/null <> "\$LOG_FILE" - -# Stop existing container if running -sudo docker stop "\$CONTAINER_NAME" 2>/dev/null || true -sudo docker rm "\$CONTAINER_NAME" 2>/dev/null || true - -# Start new container -sudo docker run -d \\ - --name "\$CONTAINER_NAME" \\ - --restart always \\ - --network host \\ - -p $INGRESS_PORT:80 \\ - -p $MONITORING_PORT:90 \\ - -e WALLARM_API_TOKEN="$WALLARM_TOKEN" \\ - -e WALLARM_API_HOST="$API_HOST" \\ - -e NGINX_BACKEND="$UPSTREAM_IP:$UPSTREAM_PORT" \\ - -e WALLARM_MODE="monitoring" \\ - -v "\$NGINX_CONFIG:/etc/nginx/http.d/default.conf:ro" \\ - $WALLARM_IMAGE_TARGET - -echo "\$(date) - Container started with ID: \$(sudo docker ps -q -f name=\$CONTAINER_NAME)" >> "\$LOG_FILE" - -# Verify container is running -sleep 3 -if sudo docker ps | grep -q "\$CONTAINER_NAME"; then - echo "\$(date) - Verification: Container is running" >> "\$LOG_FILE" - echo "Wallarm node \$CONTAINER_NAME started successfully" -else - echo "\$(date) - ERROR: Container failed to start" >> "\$LOG_FILE" - sudo docker logs "\$CONTAINER_NAME" >> "\$LOG_FILE" 2>&1 - exit 1 -fi -EOF - - sudo chmod +x "$start_script" - log_message "SUCCESS" "Start script created: $start_script" - - # Create init system service for automatic startup - log_message "INFO" "Creating service for automatic startup (init system: $INIT_SYSTEM)..." - - case "$INIT_SYSTEM" in - "systemd") - local service_file="/etc/systemd/system/wallarm-$INSTANCE_NAME.service" - sudo tee "$service_file" > /dev/null </dev/null || \ - log_message "WARNING" "Failed to enable systemd service (may already exist)" - ;; - - "openrc") - local service_file="/etc/init.d/wallarm-$INSTANCE_NAME" - sudo tee "$service_file" > /dev/null </dev/null || true - docker rm $INSTANCE_NAME 2>/dev/null || true - eend \$? -} -EOF - sudo chmod +x "$service_file" - sudo rc-update add "wallarm-$INSTANCE_NAME" default 2>/dev/null || \ - log_message "WARNING" "Failed to add OpenRC service (may already exist)" - ;; - - "sysvinit") - local service_file="/etc/init.d/wallarm-$INSTANCE_NAME" - sudo tee "$service_file" > /dev/null </dev/null || true - docker rm $INSTANCE_NAME 2>/dev/null || true - log_end_msg \$? - ;; - restart) - \$0 stop - sleep 2 - \$0 start - ;; - status) - if docker ps | grep -q "$INSTANCE_NAME"; then - echo "$INSTANCE_NAME is running" - exit 0 - else - echo "$INSTANCE_NAME is not running" - exit 1 - fi - ;; - *) - echo "Usage: \$0 {start|stop|restart|status}" - exit 3 - ;; -esac - -exit 0 -EOF - sudo chmod +x "$service_file" - sudo update-rc.d "wallarm-$INSTANCE_NAME" defaults 2>/dev/null || \ - log_message "WARNING" "Failed to add SysV init service (may already exist)" - ;; - - *) - log_message "WARNING" "Unknown init system, not creating service (manual start via $start_script)" - ;; - esac - - # Start the Wallarm node - log_message "INFO" "Starting Wallarm filtering node..." - if ! sudo "$start_script"; then - fail_with_remediation "Failed to start Wallarm node" \ - "Container failed to start. Check: -1. Docker logs: sudo docker logs $INSTANCE_NAME -2. Port conflicts: sudo ss -tlnp | grep ':$INGRESS_PORT\|:$MONITORING_PORT' -3. Docker status: sudo docker info -4. Manual start attempt: sudo $start_script" - fi - - log_message "SUCCESS" "Wallarm filtering node deployed successfully" - log_message "SUCCESS" " Container: $INSTANCE_NAME" - log_message "SUCCESS" " Ingress Port: $INGRESS_PORT" - log_message "SUCCESS" " Monitoring Port: $MONITORING_PORT" - log_message "SUCCESS" " Upstream: $UPSTREAM_IP:$UPSTREAM_PORT" - log_message "SUCCESS" " Config Directory: $INSTANCE_DIR" -} - -# ============================================================================== -# DEPLOYMENT VERIFICATION -# ============================================================================== - -verify_deployment() { - log_message "INFO" "Verifying Wallarm deployment..." - - # Check if container is running - log_message "INFO" "Checking if container is running..." - if ! sudo docker ps | grep -q "$INSTANCE_NAME"; then - fail_with_remediation "Wallarm container is not running" \ - "Container failed to start or crashed: -1. Check container logs: sudo docker logs $INSTANCE_NAME -2. Check Docker service: sudo systemctl status docker (or equivalent) -3. Manual start: sudo $INSTANCE_DIR/start.sh" - fi - log_message "SUCCESS" "Container is running" - - # Test ingress port - log_message "INFO" "Testing ingress port $INGRESS_PORT..." - if ! check_port_available "$INGRESS_PORT"; then - log_message "SUCCESS" "Ingress port $INGRESS_PORT is in use (as expected)" - else - log_message "WARNING" "Ingress port $INGRESS_PORT appears available (container may not be listening)" - fi - - # Test monitoring port - log_message "INFO" "Testing monitoring port $MONITORING_PORT..." - if ! check_port_available "$MONITORING_PORT"; then - log_message "SUCCESS" "Monitoring port $MONITORING_PORT is in use (as expected)" - else - log_message "WARNING" "Monitoring port $MONITORING_PORT appears available" - fi - - # Test health check endpoint - log_message "INFO" "Testing health check endpoint..." - local health_check_url="http://localhost:$INGRESS_PORT/health" - if curl -sf --connect-timeout 5 "$health_check_url" >/dev/null 2>&1; then - log_message "SUCCESS" "Health check endpoint responsive" - else - log_message "WARNING" "Health check endpoint not responsive (may need time to start)" - sleep 5 - if curl -sf --connect-timeout 5 "$health_check_url" >/dev/null 2>&1; then - log_message "SUCCESS" "Health check endpoint now responsive" - else - log_message "WARNING" "Health check endpoint still not responsive (check nginx config)" - fi - fi - - # Test handshake through filtering node - log_message "INFO" "Testing handshake through filtering node to upstream..." - local test_url="http://localhost:$INGRESS_PORT/" - if curl -sfI --connect-timeout 10 "$test_url" >/dev/null 2>&1; then - log_message "SUCCESS" "Handshake successful: filtering node can reach upstream" - else - log_message "WARNING" "Handshake failed (upstream may not be responding)" - log_message "INFO" "Checking if upstream is directly reachable..." - if timeout 5 bash -c "cat < /dev/null > /dev/tcp/$UPSTREAM_IP/$UPSTREAM_PORT" 2>/dev/null; then - log_message "ERROR" "Upstream is reachable but filtering node cannot proxy" - echo -e "${YELLOW}Possible nginx configuration issue. Check:${NC}" - echo -e "1. Container logs: sudo docker logs $INSTANCE_NAME" - echo -e "2. Nginx config: sudo docker exec $INSTANCE_NAME cat /etc/nginx/http.d/default.conf" - else - log_message "WARNING" "Upstream server is not reachable (as previously warned)" - fi - fi - - # Check Wallarm cloud synchronization - log_message "INFO" "Checking Wallarm cloud synchronization (this may take 30 seconds)..." - echo -e "${YELLOW}Note: Full synchronization with Wallarm cloud may take several minutes.${NC}" - echo -e "${YELLOW}You can check sync status in Wallarm Console.${NC}" - - # Quick test: check container logs for synchronization messages - if sudo docker logs "$INSTANCE_NAME" 2>&1 | tail -20 | grep -i "sync\|connected\|token" >/dev/null 2>&1; then - log_message "SUCCESS" "Wallarm node appears to be communicating with cloud" - else - log_message "WARNING" "No cloud synchronization messages in logs yet (may need time)" - fi - - log_message "SUCCESS" "Deployment verification completed" - echo -e "\n${GREEN}${BOLD}Verification Summary:${NC}" - echo -e " ${GREEN}✓${NC} Container running: $INSTANCE_NAME" - echo -e " ${GREEN}✓${NC} Ingress port: $INGRESS_PORT" - echo -e " ${GREEN}✓${NC} Monitoring port: $MONITORING_PORT" - echo -e " ${GREEN}✓${NC} Upstream: $UPSTREAM_IP:$UPSTREAM_PORT" - echo -e " ${GREEN}✓${NC} Cloud region: $CLOUD_REGION ($API_HOST)" -} - -# ============================================================================== -# MAIN FUNCTION -# ============================================================================== - -main() { - clear - echo -e "${BLUE}${BOLD}" - echo "╔══════════════════════════════════════════════════════════════╗" - echo "║ WALLARM DEPLOYMENT SCRIPT - V1.2 ║" - echo "║ LXC-Optimized Filtering Node Deployment ║" - echo "╚══════════════════════════════════════════════════════════════╝${NC}" - echo -e "\n${YELLOW}Starting deployment at: $(date)${NC}" - - # Initialize logging - # Create logs directory if it doesn't exist - local log_dir="${HOME:-.}/logs" - if [ ! -d "$log_dir" ]; then - if ! mkdir -p "$log_dir"; then - echo -e "${YELLOW}Cannot create log directory $log_dir, falling back to current directory...${NC}" - log_dir="." - fi - fi - - LOG_FILE="$log_dir/wallarm-deployment.log" - if ! : > "$LOG_FILE"; then - echo -e "${RED}Cannot create log file at $LOG_FILE${NC}" - echo -e "${YELLOW}Falling back to current directory...${NC}" - LOG_FILE="./wallarm-deployment.log" - : > "$LOG_FILE" 2>/dev/null || true - fi - if ! chmod 644 "$LOG_FILE" 2>/dev/null; then - echo -e "${YELLOW}Warning: Could not set permissions on log file${NC}" - fi - - log_message "INFO" "=== Wallarm Deployment Started ===" - - # SSL security warning - if [ "$INSECURE_SSL" = "1" ]; then - log_message "WARNING" "SSL certificate validation is DISABLED (insecure). Set WALLARM_INSECURE_SSL=0 to enable validation." - fi - - # Phase 1: Verify preflight check - log_message "INFO" "=== PHASE 1: PREFLIGHT CHECK VERIFICATION ===" - verify_preflight_check - - # Phase 2: Configuration collection - log_message "INFO" "=== PHASE 2: CONFIGURATION COLLECTION ===" - select_cloud_region - collect_configuration - - # Phase 3: Docker engine setup (LXC optimized) - log_message "INFO" "=== PHASE 3: DOCKER ENGINE SETUP (LXC OPTIMIZED) ===" - setup_docker_engine - - # Phase 4: Deployment - log_message "INFO" "=== PHASE 4: DEPLOYMENT ===" - deploy_wallarm_node - - # Phase 5: Verification - log_message "INFO" "=== PHASE 5: VERIFICATION ===" - verify_deployment - - # Success message - log_message "SUCCESS" "=== WALLARM DEPLOYMENT COMPLETED SUCCESSFULLY ===" - echo -e "\n${GREEN}${BOLD}╔══════════════════════════════════════════════════════════════╗${NC}" - echo -e "${GREEN}${BOLD}║ WALLARM FILTERING NODE DEPLOYMENT SUCCESSFUL ║${NC}" - echo -e "${GREEN}${BOLD}╚══════════════════════════════════════════════════════════════╝${NC}" - echo -e "\n${CYAN}The Wallarm filtering node is now active and protecting your application.${NC}" - echo -e "${YELLOW}Full deployment log: $LOG_FILE${NC}" - echo -e "${YELLOW}Instance directory: $INSTANCE_DIR${NC}" - echo -e "\n${GREEN}To stop the node:${NC} sudo docker stop $INSTANCE_NAME" - echo -e "${GREEN}To restart:${NC} sudo $INSTANCE_DIR/start.sh" - echo -e "${GREEN}To view logs:${NC} sudo docker logs -f $INSTANCE_NAME" - echo -e "\n${MAGENTA}${BOLD}Deployment completed successfully!${NC}" - echo -e "\n${YELLOW}Important next steps:${NC}" - echo -e "1. Monitor sync status in Wallarm Console" - echo -e "2. Test attack detection with safe test: curl http://localhost:$INGRESS_PORT/?wallarm_test=1" - echo -e "3. Review logs periodically: sudo docker logs --tail 50 $INSTANCE_NAME" -} - -# ============================================================================== -# SCRIPT EXECUTION -# ============================================================================== - -# Ensure we're in bash -if [ -z "$BASH_VERSION" ]; then - echo "Error: This script must be run with bash" >&2 - exit 1 -fi - -# Run main function -main "$@" \ No newline at end of file