From 0b917b0ea3d142377df213f0d6fb48dc81563e40 Mon Sep 17 00:00:00 2001 From: Administrator Date: Sun, 9 Nov 2025 03:55:48 +0100 Subject: [PATCH] feat(deployment): add production Docker deployment with auto-restart and on-boot startup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add comprehensive production deployment infrastructure with Docker auto-restart and systemd on-boot startup capabilities. Changes: - Add deploy-production-docker.sh: Automated deployment script with Docker validation - Add install-systemd-service.sh: Systemd service installer for auto-start on boot - Add scripts/mev-bot.service: Systemd service definition for MEV bot - Update docker-compose.yml: Enable logs volume mount and metrics port - Update PRODUCTION_QUICKSTART.md: Simplified deployment documentation Features: - Docker auto-restart on failure (restart: always policy) - Systemd auto-start on system boot - Persistent logs via volume mount - Health checks and resource limits - Comprehensive deployment validation - Easy-to-use installation scripts Usage: ./scripts/deploy-production-docker.sh # Deploy with Docker sudo ./scripts/install-systemd-service.sh # Enable auto-start on boot 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- PRODUCTION_QUICKSTART.md | 285 ++++++++++++++++++++++++++++ docker-compose.yml | 5 +- scripts/deploy-production-docker.sh | 192 +++++++++++++++++++ scripts/install-systemd-service.sh | 149 +++++++++++++++ scripts/mev-bot.service | 24 +++ 5 files changed, 653 insertions(+), 2 deletions(-) create mode 100644 PRODUCTION_QUICKSTART.md create mode 100755 scripts/deploy-production-docker.sh create mode 100755 scripts/install-systemd-service.sh create mode 100644 scripts/mev-bot.service diff --git a/PRODUCTION_QUICKSTART.md b/PRODUCTION_QUICKSTART.md new file mode 100644 index 0000000..e429799 --- /dev/null +++ b/PRODUCTION_QUICKSTART.md @@ -0,0 +1,285 @@ +# MEV Bot - Production Quick Start + +This guide will help you deploy the MEV Bot in production with Docker, auto-restart, and on-boot capabilities. + +## Prerequisites + +- Docker and Docker Compose installed +- Git repository cloned +- Root/sudo access (for systemd auto-start on boot) + +## Quick Deployment + +### Option 1: One-Step Deployment (Recommended) + +```bash +# Run the simplified deployment script +./scripts/deploy-production-docker.sh +``` + +This script will: +1. Verify Docker and Docker Compose are installed +2. Create/verify `.env` file from `.env.production` or `.env.example` +3. Build the Docker image +4. Start the container with auto-restart (`restart: always`) +5. Provide instructions for systemd auto-start on boot + +**For auto-start on boot (requires sudo):** +```bash +sudo ./scripts/install-systemd-service.sh +``` + +### Option 2: Manual Deployment + +```bash +# 1. Create environment file +cp .env.production .env # or use .env.example +nano .env # Edit with your configuration if needed + +# 2. Build and start with auto-restart +docker compose up -d + +# 3. Setup auto-start on boot (optional) +sudo ./scripts/install-systemd-service.sh +``` + +## Configuration + +Edit `.env` file with your settings: + +```bash +# Required: Update with your RPC endpoint +ARBITRUM_RPC_ENDPOINT=https://arbitrum-rpc.publicnode.com + +# Optional: Adjust log level +LOG_LEVEL=info + +# Optional: Change port +PORT=8080 +``` + +## Verify Deployment + +```bash +# Check container status +docker compose ps + +# View logs +docker compose logs -f mev-bot + +# Check health +curl http://localhost:8080/health + +# View systemd status (if configured) +sudo systemctl status mev-bot +``` + +## Production Features + +The production deployment includes: + +- **Auto-Restart**: Container restarts automatically on failure (`restart: always`) +- **Auto-Start on Boot**: Systemd service starts container on system boot +- **Health Checks**: Automatic health monitoring every 30 seconds +- **Resource Limits**: CPU and memory limits to prevent resource exhaustion +- **Security Hardening**: Runs as non-root user with minimal privileges +- **Read-Only Config**: Configuration mounted as read-only + +## Managing the Bot + +### Docker Compose Commands + +```bash +# View logs (follow mode) +docker compose logs -f mev-bot + +# Restart +docker compose restart mev-bot + +# Stop +docker compose down + +# Update and restart +git pull origin master +docker compose up -d --build + +# View container stats +docker stats mev-bot-production +``` + +### Systemd Commands (if configured) + +```bash +# Check status +sudo systemctl status mev-bot + +# Restart +sudo systemctl restart mev-bot + +# Stop +sudo systemctl stop mev-bot + +# View logs +journalctl -u mev-bot -f + +# Disable auto-start +sudo systemctl disable mev-bot +``` + +## Monitoring + +### Container Logs +```bash +# Live logs +docker compose logs -f mev-bot + +# Last 100 lines +docker compose logs --tail=100 mev-bot + +# Logs since 1 hour ago +docker compose logs --since 1h mev-bot +``` + +### Health Check +```bash +# Simple health check +curl http://localhost:8080/health + +# Expected response: {"status": "ok"} or similar +``` + +### Resource Usage +```bash +# Real-time stats +docker stats mev-bot-production + +# Shows: CPU %, Memory, Network I/O, Block I/O +``` + +## Troubleshooting + +### Container won't start +```bash +# Check logs for errors +docker compose logs mev-bot + +# Verify .env file exists and is configured +cat .env + +# Check if port is already in use +sudo netstat -tulpn | grep 8080 +``` + +### Auto-start not working +```bash +# Verify systemd service is enabled +sudo systemctl is-enabled mev-bot + +# Check service status +sudo systemctl status mev-bot + +# View systemd logs +journalctl -u mev-bot -n 50 +``` + +### High resource usage +```bash +# Check current usage +docker stats mev-bot-production + +# Adjust limits in docker-compose.yml: +# deploy.resources.limits.cpus +# deploy.resources.limits.memory +``` + +## Updating the Bot + +### Manual Updates +```bash +# Pull latest code +git pull origin master + +# Rebuild and restart +docker compose up -d --build + +# Or using systemd +sudo systemctl reload mev-bot +``` + +### Automatic Updates (Recommended) + +Setup auto-updates to automatically pull, rebuild, and restart when master branch changes: + +```bash +# Enable auto-updates +sudo ./scripts/setup-auto-update.sh +``` + +This enables: +- ✅ Auto-rebuild after manual `git pull` +- ✅ Periodic update checks every 5 minutes +- ✅ Automatic pull, rebuild, and restart +- ✅ Detailed logging of all updates + +**Manage auto-updates:** +```bash +# Check auto-update status +sudo systemctl status mev-bot-auto-update.timer + +# View auto-update logs +tail -f logs/auto-update.log + +# Disable auto-updates +sudo systemctl stop mev-bot-auto-update.timer + +# Enable auto-updates +sudo systemctl start mev-bot-auto-update.timer +``` + +For complete auto-update documentation, see [AUTO_UPDATE_GUIDE.md](AUTO_UPDATE_GUIDE.md) + +## Security Best Practices + +1. **Never commit `.env` file** - It's in `.gitignore` +2. **Use strong RPC credentials** - Keep API keys secure +3. **Restrict network access** - Use firewall rules +4. **Monitor logs regularly** - Check for suspicious activity +5. **Keep system updated** - Update Docker and dependencies + +## Support + +For detailed deployment options, monitoring, and advanced configuration, see: +- [DEPLOYMENT_GUIDE.md](docs/DEPLOYMENT_GUIDE.md) - Comprehensive deployment guide +- [README.md](README.md) - Project overview + +## Quick Command Reference + +```bash +# Deploy +sudo ./scripts/deploy-production.sh +sudo ./scripts/setup-auto-update.sh # Add auto-updates + +# Status +docker compose ps +sudo systemctl status mev-bot +sudo systemctl status mev-bot-auto-update.timer # Auto-update status + +# Logs +docker compose logs -f mev-bot +journalctl -u mev-bot -f +tail -f logs/auto-update.log # Auto-update logs + +# Restart +docker compose restart mev-bot +sudo systemctl restart mev-bot + +# Stop +docker compose down +sudo systemctl stop mev-bot + +# Update (Manual) +git pull && docker compose up -d --build + +# Update (Auto - happens automatically) +./scripts/auto-update.sh # Trigger manual update check +``` diff --git a/docker-compose.yml b/docker-compose.yml index 3ecd276..48a16dd 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -11,8 +11,8 @@ services: volumes: # Mount only the config file for production - ./config/config.production.yaml:/app/config/config.yaml:ro - # Optional: mount a directory for logs if needed - # - ./logs:/app/logs + # Mount logs directory for persistent logs + - ./logs:/app/logs environment: - LOG_LEVEL=${LOG_LEVEL:-info} - ARBITRUM_RPC_ENDPOINT=${ARBITRUM_RPC_ENDPOINT:-https://arbitrum-rpc.publicnode.com} @@ -21,6 +21,7 @@ services: - .env ports: - "${PORT:-8080}:8080" + - "${METRICS_PORT:-9090}:9090" command: ["start"] # Health check to ensure the bot is running properly healthcheck: diff --git a/scripts/deploy-production-docker.sh b/scripts/deploy-production-docker.sh new file mode 100755 index 0000000..4ee75bb --- /dev/null +++ b/scripts/deploy-production-docker.sh @@ -0,0 +1,192 @@ +#!/usr/bin/env bash + +# Production Docker Deployment Script for MEV Bot (Master Repo) +# This script deploys the MEV bot with Docker auto-restart and systemd on-boot startup +# Optimized for production use with the master repository + +set -euo pipefail + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +PURPLE='\033[0;35m' +CYAN='\033[0;36m' +NC='\033[0m' # No Color + +# Script information +echo -e "${PURPLE}🚀 MEV Bot Production Docker Deployment${NC}" +echo -e "${PURPLE}========================================${NC}" +echo "" + +# Check if running from project root +if [ ! -f "go.mod" ]; then + echo -e "${RED}❌ Error: This script must be run from the project root directory${NC}" + exit 1 +fi + +# Check if Docker is available +if ! command -v docker &> /dev/null; then + echo -e "${RED}❌ Error: Docker is not installed${NC}" + echo -e "${YELLOW}Please install Docker first: https://docs.docker.com/get-docker/${NC}" + exit 1 +fi + +# Check if Docker Compose is available +if ! docker compose version &> /dev/null; then + echo -e "${RED}❌ Error: Docker Compose is not available${NC}" + echo -e "${YELLOW}Please install Docker Compose: https://docs.docker.com/compose/install/${NC}" + exit 1 +fi + +echo -e "${GREEN}✅ Docker and Docker Compose are available${NC}" + +# Check/Create .env file +echo -e "${BLUE}🔧 Checking environment configuration...${NC}" + +if [ ! -f ".env" ]; then + if [ -f ".env.production" ]; then + echo -e "${YELLOW}âš ī¸ .env file not found, copying from .env.production${NC}" + cp .env.production .env + echo -e "${GREEN}✅ Created .env from .env.production${NC}" + elif [ -f ".env.example" ]; then + echo -e "${YELLOW}âš ī¸ .env file not found, copying from .env.example${NC}" + cp .env.example .env + echo -e "${YELLOW}âš ī¸ Please edit .env file with your configuration before running again${NC}" + echo -e "${YELLOW} Required: ARBITRUM_RPC_ENDPOINT, ARBITRUM_WS_ENDPOINT${NC}" + exit 1 + else + echo -e "${RED}❌ Error: No .env or .env.example file found${NC}" + exit 1 + fi +else + echo -e "${GREEN}✅ .env file exists${NC}" +fi + +# Verify critical environment variables +echo -e "${BLUE}🔍 Verifying environment variables...${NC}" +source .env + +MISSING_VARS=() + +if [ -z "${ARBITRUM_RPC_ENDPOINT:-}" ]; then + MISSING_VARS+=("ARBITRUM_RPC_ENDPOINT") +fi + +if [ -z "${ARBITRUM_WS_ENDPOINT:-}" ]; then + MISSING_VARS+=("ARBITRUM_WS_ENDPOINT") +fi + +if [ ${#MISSING_VARS[@]} -ne 0 ]; then + echo -e "${RED}❌ Error: Missing required environment variables in .env:${NC}" + for var in "${MISSING_VARS[@]}"; do + echo -e "${RED} - $var${NC}" + done + exit 1 +fi + +echo -e "${GREEN}✅ Required environment variables are set${NC}" + +# Create required directories +echo -e "${BLUE}📁 Creating required directories...${NC}" +mkdir -p logs config data + +# Stop any existing containers +echo -e "${BLUE}âšī¸ Stopping any existing containers...${NC}" +docker compose down 2>/dev/null || true + +# Build the Docker image +echo -e "${BLUE}🔨 Building Docker image...${NC}" +docker compose build + +if [ $? -ne 0 ]; then + echo -e "${RED}❌ Error: Failed to build Docker image${NC}" + exit 1 +fi + +echo -e "${GREEN}✅ Docker image built successfully${NC}" + +# Start the container +echo -e "${BLUE}🚀 Starting MEV Bot container...${NC}" +docker compose up -d + +if [ $? -ne 0 ]; then + echo -e "${RED}❌ Error: Failed to start container${NC}" + exit 1 +fi + +echo -e "${GREEN}✅ MEV Bot container started successfully${NC}" + +# Wait for container to be healthy +echo -e "${BLUE}âŗ Waiting for container to be ready...${NC}" +sleep 5 + +# Check container status +CONTAINER_STATUS=$(docker compose ps --format json 2>/dev/null | grep -o '"State":"[^"]*"' | cut -d'"' -f4 || echo "unknown") + +if [ "$CONTAINER_STATUS" = "running" ]; then + echo -e "${GREEN}✅ Container is running${NC}" +else + echo -e "${YELLOW}âš ī¸ Container status: $CONTAINER_STATUS${NC}" +fi + +# Setup systemd service for auto-start on boot +echo "" +echo -e "${BLUE}🔧 Setting up systemd service for auto-start on boot...${NC}" + +if [ "$EUID" -ne 0 ]; then + echo -e "${YELLOW}âš ī¸ Systemd setup requires root privileges${NC}" + echo -e "${YELLOW} Run the following commands to enable auto-start on boot:${NC}" + echo "" + echo -e "${CYAN} sudo cp scripts/mev-bot.service /etc/systemd/system/${NC}" + echo -e "${CYAN} sudo systemctl daemon-reload${NC}" + echo -e "${CYAN} sudo systemctl enable mev-bot.service${NC}" + echo -e "${CYAN} sudo systemctl start mev-bot.service${NC}" + echo "" +else + # Running as root, set up systemd service + cp scripts/mev-bot.service /etc/systemd/system/ + systemctl daemon-reload + systemctl enable mev-bot.service + systemctl start mev-bot.service + + echo -e "${GREEN}✅ Systemd service installed and enabled${NC}" +fi + +# Display deployment summary +echo "" +echo -e "${GREEN}╔════════════════════════════════════════════════════════════╗${NC}" +echo -e "${GREEN}║ 🎉 MEV Bot Production Deployment Complete! ║${NC}" +echo -e "${GREEN}╚════════════════════════════════════════════════════════════╝${NC}" +echo "" +echo -e "${BLUE}📊 Container Information:${NC}" +echo -e " Container: mev-bot-production" +echo -e " Status: $CONTAINER_STATUS" +echo -e " Restart Policy: Always (auto-restart on failure)" +echo "" +echo -e "${BLUE}📝 View Logs:${NC}" +echo -e " ${CYAN}docker compose logs -f mev-bot${NC}" +echo "" +echo -e "${BLUE}🔍 Container Status:${NC}" +echo -e " ${CYAN}docker compose ps${NC}" +echo "" +echo -e "${BLUE}🔄 Restart Container:${NC}" +echo -e " ${CYAN}docker compose restart mev-bot${NC}" +echo "" +echo -e "${BLUE}âšī¸ Stop Container:${NC}" +echo -e " ${CYAN}docker compose down${NC}" +echo "" +echo -e "${BLUE}🔧 Systemd Commands (if installed):${NC}" +echo -e " ${CYAN}sudo systemctl status mev-bot${NC} # Check status" +echo -e " ${CYAN}sudo systemctl restart mev-bot${NC} # Restart service" +echo -e " ${CYAN}sudo systemctl stop mev-bot${NC} # Stop service" +echo -e " ${CYAN}journalctl -u mev-bot -f${NC} # View systemd logs" +echo "" +echo -e "${YELLOW}âš ī¸ Production Deployment Notes:${NC}" +echo -e " - Container will auto-restart on failure (restart: always)" +echo -e " - Install systemd service for auto-start on system boot" +echo -e " - Monitor logs regularly for any issues" +echo -e " - Keep your .env file secure and never commit it" +echo "" +echo -e "${CYAN}🚀 MEV Bot is now running and monitoring Arbitrum for opportunities${NC}" diff --git a/scripts/install-systemd-service.sh b/scripts/install-systemd-service.sh new file mode 100755 index 0000000..bed0c11 --- /dev/null +++ b/scripts/install-systemd-service.sh @@ -0,0 +1,149 @@ +#!/usr/bin/env bash + +# Systemd Service Installation Script for MEV Bot +# Installs and enables MEV Bot to auto-start on system boot + +set -euo pipefail + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +CYAN='\033[0;36m' +NC='\033[0m' # No Color + +echo -e "${BLUE}🔧 MEV Bot Systemd Service Installation${NC}" +echo -e "${BLUE}========================================${NC}" +echo "" + +# Check if running as root +if [ "$EUID" -ne 0 ]; then + echo -e "${RED}❌ Error: This script must be run as root or with sudo${NC}" + echo -e "${YELLOW}Usage: sudo $0${NC}" + exit 1 +fi + +# Get the directory where the script is located +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" + +echo -e "${BLUE}📁 Project root: ${PROJECT_ROOT}${NC}" + +# Check if Docker is installed +if ! command -v docker &> /dev/null; then + echo -e "${RED}❌ Error: Docker is not installed${NC}" + exit 1 +fi + +# Check if docker-compose.yml exists +if [ ! -f "$PROJECT_ROOT/docker-compose.yml" ]; then + echo -e "${RED}❌ Error: docker-compose.yml not found in $PROJECT_ROOT${NC}" + exit 1 +fi + +echo -e "${GREEN}✅ Docker and docker-compose.yml found${NC}" + +# Create systemd service file with actual project path +echo -e "${BLUE}📝 Creating systemd service file...${NC}" + +SERVICE_FILE="/etc/systemd/system/mev-bot.service" + +cat > "$SERVICE_FILE" << EOF +[Unit] +Description=MEV Bot Production Service +Requires=docker.service +After=docker.service network-online.target +Wants=network-online.target + +[Service] +Type=oneshot +RemainAfterExit=yes +WorkingDirectory=$PROJECT_ROOT +ExecStartPre=/usr/bin/docker compose pull --quiet +ExecStart=/usr/bin/docker compose up -d +ExecStop=/usr/bin/docker compose down +ExecReload=/usr/bin/docker compose restart +TimeoutStartSec=0 +Restart=on-failure +RestartSec=10s + +# Security settings +User=root +Group=docker + +[Install] +WantedBy=multi-user.target +EOF + +echo -e "${GREEN}✅ Service file created at $SERVICE_FILE${NC}" + +# Reload systemd daemon +echo -e "${BLUE}🔄 Reloading systemd daemon...${NC}" +systemctl daemon-reload + +# Enable the service +echo -e "${BLUE}✅ Enabling MEV Bot service...${NC}" +systemctl enable mev-bot.service + +echo -e "${GREEN}✅ MEV Bot service enabled for auto-start on boot${NC}" + +# Ask if user wants to start the service now +echo "" +read -p "Do you want to start the MEV Bot service now? (y/n) " -n 1 -r +echo "" + +if [[ $REPLY =~ ^[Yy]$ ]]; then + echo -e "${BLUE}🚀 Starting MEV Bot service...${NC}" + systemctl start mev-bot.service + + # Wait a moment for service to start + sleep 3 + + # Check status + if systemctl is-active --quiet mev-bot.service; then + echo -e "${GREEN}✅ MEV Bot service is running${NC}" + else + echo -e "${YELLOW}âš ī¸ Service may not be running properly${NC}" + echo -e "${YELLOW} Check status with: sudo systemctl status mev-bot${NC}" + fi +fi + +# Display usage information +echo "" +echo -e "${GREEN}╔════════════════════════════════════════════════════════════╗${NC}" +echo -e "${GREEN}║ 🎉 Systemd Service Installation Complete! ║${NC}" +echo -e "${GREEN}╚════════════════════════════════════════════════════════════╝${NC}" +echo "" +echo -e "${BLUE}📋 Systemd Service Commands:${NC}" +echo "" +echo -e " ${CYAN}sudo systemctl status mev-bot${NC}" +echo -e " └─ Check service status" +echo "" +echo -e " ${CYAN}sudo systemctl start mev-bot${NC}" +echo -e " └─ Start the service" +echo "" +echo -e " ${CYAN}sudo systemctl stop mev-bot${NC}" +echo -e " └─ Stop the service" +echo "" +echo -e " ${CYAN}sudo systemctl restart mev-bot${NC}" +echo -e " └─ Restart the service" +echo "" +echo -e " ${CYAN}sudo systemctl reload mev-bot${NC}" +echo -e " └─ Reload (restart container)" +echo "" +echo -e " ${CYAN}journalctl -u mev-bot -f${NC}" +echo -e " └─ View service logs (follow mode)" +echo "" +echo -e " ${CYAN}sudo systemctl disable mev-bot${NC}" +echo -e " └─ Disable auto-start on boot" +echo "" +echo -e "${BLUE}📊 Docker Commands:${NC}" +echo "" +echo -e " ${CYAN}docker compose logs -f mev-bot${NC}" +echo -e " └─ View container logs" +echo "" +echo -e " ${CYAN}docker compose ps${NC}" +echo -e " └─ Check container status" +echo "" +echo -e "${GREEN}✅ MEV Bot will now auto-start on system boot${NC}" diff --git a/scripts/mev-bot.service b/scripts/mev-bot.service new file mode 100644 index 0000000..f4de095 --- /dev/null +++ b/scripts/mev-bot.service @@ -0,0 +1,24 @@ +[Unit] +Description=MEV Bot Production Service +Requires=docker.service +After=docker.service network-online.target +Wants=network-online.target + +[Service] +Type=oneshot +RemainAfterExit=yes +WorkingDirectory=/docker/mev-beta +ExecStartPre=/usr/bin/docker compose pull --quiet +ExecStart=/usr/bin/docker compose up -d +ExecStop=/usr/bin/docker compose down +ExecReload=/usr/bin/docker compose restart +TimeoutStartSec=0 +Restart=on-failure +RestartSec=10s + +# Security settings +User=root +Group=docker + +[Install] +WantedBy=multi-user.target