Merge gitea/main, preserving release v0.2.2 stability and CLI documentation

This commit is contained in:
AITBC System
2026-03-25 12:58:02 +01:00
230 changed files with 2370 additions and 369 deletions

View File

@@ -0,0 +1,36 @@
# AITBC Deployment Configuration Template
# Copy this file to .env.deploy and fill in your actual values
# NEVER commit the actual .env.deploy file with real credentials
# === REQUIRED DEPLOYMENT SETTINGS ===
CONTAINER_NAME="aitbc"
CONTAINER_IP="YOUR_CONTAINER_IP"
PROJECT_DIR="/path/to/your/aitbc"
SSH_ALIAS="your-ssh-alias"
SSH_KEY_PATH="/path/to/your/private/key"
# === OPTIONAL SECURITY SETTINGS ===
# SSH connection timeout (seconds)
SSH_TIMEOUT=30
# Backup settings
CREATE_BACKUP=true
BACKUP_RETENTION_DAYS=7
# Service restart settings
RESTART_SERVICES=true
SERVICE_STARTUP_TIMEOUT=60
# === EXAMPLE VALUES ===
# CONTAINER_NAME="aitbc"
# CONTAINER_IP="192.168.1.100"
# PROJECT_DIR="/home/user/aitbc"
# SSH_ALIAS="user@container-ip"
# SSH_KEY_PATH="/home/user/.ssh/id_rsa"
# === SECURITY NOTES ===
# 1. Never commit this file with real credentials
# 2. Use SSH keys instead of passwords
# 3. Restrict file permissions: chmod 600 .env.deploy
# 4. Use SSH config file for complex connection settings
# 5. Consider using a secrets management system for production

View File

@@ -0,0 +1,24 @@
#!/bin/bash
# Clean up failed deployment and prepare for redeployment
echo "🧹 Cleaning up failed deployment..."
echo "=================================="
# Stop any running services
echo "Stopping services..."
ssh ns3-root "systemctl stop blockchain-node blockchain-rpc nginx 2>/dev/null || true"
# Remove old directories
echo "Removing old directories..."
ssh ns3-root "rm -rf /opt/blockchain-node /opt/blockchain-node-src /opt/blockchain-explorer 2>/dev/null || true"
# Remove systemd services
echo "Removing systemd services..."
ssh ns3-root "systemctl disable blockchain-node blockchain-rpc blockchain-explorer 2>/dev/null || true"
ssh ns3-root "rm -f /etc/systemd/system/blockchain-node.service /etc/systemd/system/blockchain-rpc.service /etc/systemd/system/blockchain-explorer.service 2>/dev/null || true"
ssh ns3-root "systemctl daemon-reload"
echo "✅ Cleanup complete!"
echo ""
echo "You can now run: ./scripts/deploy/deploy-all-remote.sh"

View File

@@ -0,0 +1,109 @@
#!/usr/bin/env python3
"""
Deploy AITBC services to incus container
"""
import subprocess
import time
import sys
def run_command(cmd, container=None):
"""Run command locally or in container"""
if container:
cmd = f"incus exec {container} -- {cmd}"
print(f"Running: {cmd}")
result = subprocess.run(cmd, shell=True, capture_output=True, text=True)
if result.returncode != 0:
print(f"Error: {result.stderr}")
return False
return True
def deploy_to_container():
container = "aitbc"
container_ip = "10.1.223.93"
print("🚀 Deploying AITBC services to container...")
# Stop local services
print("\n📋 Stopping local services...")
subprocess.run("sudo fuser -k 8000/tcp 2>/dev/null || true", shell=True)
subprocess.run("sudo fuser -k 9080/tcp 2>/dev/null || true", shell=True)
subprocess.run("pkill -f 'marketplace-ui' 2>/dev/null || true", shell=True)
subprocess.run("pkill -f 'trade-exchange' 2>/dev/null || true", shell=True)
# Copy project to container
print("\n📁 Copying project to container...")
subprocess.run(f"incus file push -r /home/oib/windsurf/aitbc {container}/home/oib/", shell=True)
# Setup Python environment in container
print("\n🐍 Setting up Python environment...")
run_command("cd /home/oib/aitbc && python3 -m venv .venv", container)
run_command("cd /home/oib/aitbc && source .venv/bin/activate && pip install fastapi uvicorn httpx sqlmodel", container)
# Install dependencies
print("\n📦 Installing dependencies...")
run_command("cd /home/oib/aitbc/apps/coordinator-api && source ../../.venv/bin/activate && pip install -e .", container)
run_command("cd /home/oib/aitbc/apps/blockchain-node && source ../../.venv/bin/activate && pip install -e .", container)
# Create startup script
print("\n🔧 Creating startup script...")
startup_script = """#!/bin/bash
cd /home/oib/aitbc
# Start blockchain node
echo "Starting blockchain node..."
cd apps/blockchain-node
source ../../.venv/bin/activate
python -m uvicorn aitbc_chain.app:app --host 0.0.0.0 --port 9080 &
NODE_PID=$!
# Start coordinator API
echo "Starting coordinator API..."
cd ../coordinator-api
source ../../.venv/bin/activate
python -m uvicorn src.app.main:app --host 0.0.0.0 --port 8000 &
COORD_PID=$!
# Start marketplace UI
echo "Starting marketplace UI..."
cd ../marketplace-ui
python server.py --port 3001 &
MARKET_PID=$!
# Start trade exchange
echo "Starting trade exchange..."
cd ../trade-exchange
python server.py --port 3002 &
EXCHANGE_PID=$!
echo "Services started!"
echo "Blockchain: http://10.1.223.93:9080"
echo "API: http://10.1.223.93:8000"
echo "Marketplace: http://10.1.223.93:3001"
echo "Exchange: http://10.1.223.93:3002"
# Wait for services
wait $NODE_PID $COORD_PID $MARKET_PID $EXCHANGE_PID
"""
# Write startup script to container
with open('/tmp/start_aitbc.sh', 'w') as f:
f.write(startup_script)
subprocess.run("incus file push /tmp/start_aitbc.sh aitbc/home/oib/", shell=True)
run_command("chmod +x /home/oib/start_aitbc.sh", container)
# Start services
print("\n🚀 Starting AITBC services...")
run_command("/home/oib/start_aitbc.sh", container)
print(f"\n✅ Services deployed to container!")
print(f"\n📋 Access URLs:")
print(f" 🌐 Container IP: {container_ip}")
print(f" 📊 Marketplace: http://{container_ip}:3001")
print(f" 💱 Trade Exchange: http://{container_ip}:3002")
print(f" 🔗 API: http://{container_ip}:8000")
print(f" ⛓️ Blockchain: http://{container_ip}:9080")
if __name__ == "__main__":
deploy_to_container()

View File

@@ -0,0 +1,56 @@
#!/bin/bash
# Deploy blockchain node and explorer by building directly on ns3
echo "🚀 AITBC Remote Deployment (Build on Server)"
echo "=========================================="
echo "This will build the blockchain node directly on ns3"
echo "to utilize the gigabit connection instead of uploading."
echo ""
# Copy deployment scripts to server
echo "Copying deployment scripts to ns3..."
scp scripts/deploy/deploy-blockchain-remote.sh ns3-root:/opt/
scp scripts/deploy/deploy-explorer-remote.sh ns3-root:/opt/
# Create directories on server first
echo "Creating directories on ns3..."
ssh ns3-root "mkdir -p /opt/blockchain-node-src /opt/blockchain-node"
# Copy blockchain source code to server (excluding data files)
echo "Copying blockchain source code to ns3..."
rsync -av --exclude='data/' --exclude='*.db' --exclude='__pycache__' --exclude='.venv' apps/blockchain-node/ ns3-root:/opt/blockchain-node-src/
# Execute blockchain deployment
echo ""
echo "Deploying blockchain node..."
ssh ns3-root "cd /opt && cp -r /opt/blockchain-node-src/* /opt/blockchain-node/ && cd /opt/blockchain-node && chmod +x ../deploy-blockchain-remote.sh && ../deploy-blockchain-remote.sh"
# Wait for blockchain to start
echo ""
echo "Waiting 10 seconds for blockchain node to start..."
sleep 10
# Execute explorer deployment on ns3
echo ""
echo "Deploying blockchain explorer..."
ssh ns3-root "cd /opt && ./deploy-explorer-remote.sh"
# Check services
echo ""
echo "Checking service status..."
ssh ns3-root "systemctl status blockchain-node blockchain-rpc nginx --no-pager | grep -E 'Active:|Main PID:'"
echo ""
echo "✅ Deployment complete!"
echo ""
echo "Services:"
echo " - Blockchain Node RPC: http://localhost:8082"
echo " - Blockchain Explorer: http://localhost:3000"
echo ""
echo "External access:"
echo " - Blockchain Node RPC: http://aitbc.keisanki.net:8082"
echo " - Blockchain Explorer: http://aitbc.keisanki.net:3000"
echo ""
echo "The blockchain node will start syncing automatically."
echo "The explorer connects to the local node and displays real-time data."

View File

@@ -0,0 +1,207 @@
#!/bin/bash
# Deploy blockchain node and explorer to incus container
set -e
echo "🚀 Deploying Blockchain Node and Explorer"
echo "========================================"
# Colors
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
print_status() {
echo -e "${GREEN}[INFO]${NC} $1"
}
print_warning() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
# Copy blockchain node to container
print_status "Copying blockchain node to container..."
ssh ns3-root "rm -rf /opt/blockchain-node 2>/dev/null || true"
scp -r apps/blockchain-node ns3-root:/opt/
# Setup blockchain node in container
print_status "Setting up blockchain node..."
ssh ns3-root << 'EOF'
cd /opt/blockchain-node
# Create configuration
cat > .env << EOL
CHAIN_ID=ait-devnet
DB_PATH=./data/chain.db
RPC_BIND_HOST=0.0.0.0
RPC_BIND_PORT=8082
P2P_BIND_HOST=0.0.0.0
P2P_BIND_PORT=7070
PROPOSER_KEY=proposer_key_$(date +%s)
MINT_PER_UNIT=1000
COORDINATOR_RATIO=0.05
GOSSIP_BACKEND=memory
EOL
# Create data directory
mkdir -p data/devnet
# Setup Python environment
python3 -m venv .venv
source .venv/bin/activate
pip install --upgrade pip
pip install -e .
# Generate genesis
export PYTHONPATH="${PWD}/src:${PWD}/scripts:${PYTHONPATH:-}"
python scripts/make_genesis.py --output data/devnet/genesis.json --force
EOF
# Create systemd service for blockchain node
print_status "Creating systemd service for blockchain node..."
ssh ns3-root << 'EOF'
cat > /etc/systemd/system/blockchain-node.service << EOL
[Unit]
Description=AITBC Blockchain Node
After=network.target
[Service]
Type=exec
User=root
WorkingDirectory=/opt/blockchain-node
Environment=PATH=/opt/blockchain-node/.venv/bin:/usr/local/bin:/usr/bin:/bin
Environment=PYTHONPATH=/opt/blockchain-node/src:/opt/blockchain-node/scripts
ExecStart=/opt/blockchain-node/.venv/bin/python3 -m aitbc_chain.main
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
EOL
cat > /etc/systemd/system/blockchain-rpc.service << EOL
[Unit]
Description=AITBC Blockchain RPC API
After=blockchain-node.service
[Service]
Type=exec
User=root
WorkingDirectory=/opt/blockchain-node
Environment=PATH=/opt/blockchain-node/.venv/bin:/usr/local/bin:/usr/bin:/bin
Environment=PYTHONPATH=/opt/blockchain-node/src:/opt/blockchain-node/scripts
ExecStart=/opt/blockchain-node/.venv/bin/python3 -m uvicorn aitbc_chain.app:app --host 0.0.0.0 --port 8082
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
EOL
systemctl daemon-reload
systemctl enable blockchain-node blockchain-rpc
EOF
# Start blockchain node
print_status "Starting blockchain node..."
ssh ns3-root "systemctl start blockchain-node blockchain-rpc"
# Wait for node to start
print_status "Waiting for blockchain node to start..."
sleep 5
# Check status
print_status "Checking blockchain node status..."
ssh ns3-root "systemctl status blockchain-node blockchain-rpc --no-pager | grep -E 'Active:|Main PID:'"
# Copy explorer to container
print_status "Copying blockchain explorer to container..."
ssh ns3-root "rm -rf /opt/blockchain-explorer 2>/dev/null || true"
scp -r apps/blockchain-explorer ns3-root:/opt/
# Setup explorer in container
print_status "Setting up blockchain explorer..."
ssh ns3-root << 'EOF'
cd /opt/blockchain-explorer
# Create Python environment
python3 -m venv .venv
source .venv/bin/activate
pip install --upgrade pip
pip install -r requirements.txt
EOF
# Create systemd service for explorer
print_status "Creating systemd service for blockchain explorer..."
ssh ns3-root << 'EOF'
cat > /etc/systemd/system/blockchain-explorer.service << EOL
[Unit]
Description=AITBC Blockchain Explorer
After=blockchain-rpc.service
[Service]
Type=exec
User=root
WorkingDirectory=/opt/blockchain-explorer
Environment=PATH=/opt/blockchain-explorer/.venv/bin:/usr/local/bin:/usr/bin:/bin
ExecStart=/opt/blockchain-explorer/.venv/bin/python3 main.py
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
EOL
systemctl daemon-reload
systemctl enable blockchain-explorer
EOF
# Start explorer
print_status "Starting blockchain explorer..."
ssh ns3-root "systemctl start blockchain-explorer"
# Wait for explorer to start
print_status "Waiting for explorer to start..."
sleep 3
# Setup port forwarding
print_status "Setting up port forwarding..."
ssh ns3-root << 'EOF'
# Clear existing NAT rules
iptables -t nat -F PREROUTING 2>/dev/null || true
iptables -t nat -F POSTROUTING 2>/dev/null || true
# Add port forwarding for blockchain RPC
iptables -t nat -A PREROUTING -p tcp --dport 8082 -j DNAT --to-destination 192.168.100.10:8082
iptables -t nat -A POSTROUTING -p tcp -d 192.168.100.10 --dport 8082 -j MASQUERADE
# Add port forwarding for explorer
iptables -t nat -A PREROUTING -p tcp --dport 3000 -j DNAT --to-destination 192.168.100.10:3000
iptables -t nat -A POSTROUTING -p tcp -d 192.168.100.10 --dport 3000 -j MASQUERADE
# Save rules
mkdir -p /etc/iptables
iptables-save > /etc/iptables/rules.v4
# Install iptables-persistent for persistence
apt-get update
apt-get install -y iptables-persistent
EOF
# Check all services
print_status "Checking all services..."
ssh ns3-root "systemctl status blockchain-node blockchain-rpc blockchain-explorer --no-pager | grep -E 'Active:|Main PID:'"
print_success "✅ Deployment complete!"
echo ""
echo "Services deployed:"
echo " - Blockchain Node RPC: http://192.168.100.10:8082"
echo " - Blockchain Explorer: http://192.168.100.10:3000"
echo ""
echo "External access:"
echo " - Blockchain Node RPC: http://aitbc.keisanki.net:8082"
echo " - Blockchain Explorer: http://aitbc.keisanki.net:3000"
echo ""
echo "The explorer is connected to the local blockchain node and will display"
echo "real-time blockchain data including blocks and transactions."

View File

@@ -0,0 +1,94 @@
#!/bin/bash
# Deploy blockchain explorer to incus container
set -e
echo "🔍 Deploying Blockchain Explorer"
echo "================================="
# Colors
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
print_status() {
echo -e "${GREEN}[INFO]${NC} $1"
}
print_warning() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
# Copy explorer to container
print_status "Copying blockchain explorer to container..."
ssh ns3-root "rm -rf /opt/blockchain-explorer 2>/dev/null || true"
scp -r apps/blockchain-explorer ns3-root:/opt/
# Setup explorer in container
print_status "Setting up blockchain explorer..."
ssh ns3-root << 'EOF'
cd /opt/blockchain-explorer
# Create Python environment
python3 -m venv .venv
source .venv/bin/activate
pip install --upgrade pip
pip install -r requirements.txt
EOF
# Create systemd service for explorer
print_status "Creating systemd service for blockchain explorer..."
ssh ns3-root << 'EOF'
cat > /etc/systemd/system/blockchain-explorer.service << EOL
[Unit]
Description=AITBC Blockchain Explorer
After=blockchain-rpc.service
[Service]
Type=exec
User=root
WorkingDirectory=/opt/blockchain-explorer
Environment=PATH=/opt/blockchain-explorer/.venv/bin:/usr/local/bin:/usr/bin:/bin
ExecStart=/opt/blockchain-explorer/.venv/bin/python3 main.py
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
EOL
systemctl daemon-reload
systemctl enable blockchain-explorer
EOF
# Start explorer
print_status "Starting blockchain explorer..."
ssh ns3-root "systemctl start blockchain-explorer"
# Wait for explorer to start
print_status "Waiting for explorer to start..."
sleep 3
# Setup port forwarding for explorer
print_status "Setting up port forwarding for explorer..."
ssh ns3-root << 'EOF'
# Add port forwarding for explorer
iptables -t nat -A PREROUTING -p tcp --dport 3000 -j DNAT --to-destination 192.168.100.10:3000
iptables -t nat -A POSTROUTING -p tcp -d 192.168.100.10 --dport 3000 -j MASQUERADE
# Save rules
iptables-save > /etc/iptables/rules.v4
EOF
# Check status
print_status "Checking blockchain explorer status..."
ssh ns3-root "systemctl status blockchain-explorer --no-pager | grep -E 'Active:|Main PID:'"
print_success "✅ Blockchain explorer deployed!"
echo ""
echo "Explorer URL: http://192.168.100.10:3000"
echo "External URL: http://aitbc.keisanki.net:3000"
echo ""
echo "The explorer will automatically connect to the local blockchain node."
echo "You can view blocks, transactions, and chain statistics."

View File

@@ -0,0 +1,157 @@
#!/bin/bash
# Deploy blockchain node directly on ns3 server (build in place)
set -e
echo "🚀 Deploying Blockchain Node on ns3 (Build in Place)"
echo "====================================================="
# Colors
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
print_status() {
echo -e "${GREEN}[INFO]${NC} $1"
}
print_warning() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
# Check if we're on the right server
print_status "Checking server..."
if [ "$(hostname)" != "ns3" ] && [ "$(hostname)" != "aitbc" ]; then
print_warning "This script should be run on ns3 server"
echo "Please run: ssh ns3-root"
echo "Then: cd /opt && ./deploy-blockchain-remote.sh"
exit 1
fi
# Install dependencies if needed
print_status "Installing dependencies..."
apt-get update
apt-get install -y python3 python3-venv python3-pip git curl
# Create directory
print_status "Creating blockchain node directory..."
mkdir -p /opt/blockchain-node
cd /opt/blockchain-node
# Check if source code exists
if [ ! -d "src" ]; then
print_status "Source code not found in /opt/blockchain-node, copying from /opt/blockchain-node-src..."
if [ -d "/opt/blockchain-node-src" ]; then
cp -r /opt/blockchain-node-src/* .
else
print_warning "Source code not found. Please ensure it was copied properly."
exit 1
fi
fi
# Setup Python environment
print_status "Setting up Python environment..."
python3 -m venv .venv
source .venv/bin/activate
pip install --upgrade pip
pip install -e .
# Create configuration with auto-sync
print_status "Creating configuration..."
cat > .env << EOL
CHAIN_ID=ait-devnet
DB_PATH=./data/chain.db
RPC_BIND_HOST=0.0.0.0
RPC_BIND_PORT=8082
P2P_BIND_HOST=0.0.0.0
P2P_BIND_PORT=7070
PROPOSER_KEY=proposer_key_$(date +%s)
MINT_PER_UNIT=1000
COORDINATOR_RATIO=0.05
GOSSIP_BACKEND=memory
EOL
# Create fresh data directory
print_status "Creating fresh data directory..."
rm -rf data
mkdir -p data/devnet
# Generate fresh genesis
print_status "Generating fresh genesis block..."
export PYTHONPATH="${PWD}/src:${PWD}/scripts:${PYTHONPATH:-}"
python scripts/make_genesis.py --output data/devnet/genesis.json --force
# Create systemd service for blockchain node
print_status "Creating systemd services..."
cat > /etc/systemd/system/blockchain-node.service << EOL
[Unit]
Description=AITBC Blockchain Node
After=network.target
[Service]
Type=exec
User=root
WorkingDirectory=/opt/blockchain-node
Environment=PATH=/opt/blockchain-node/.venv/bin:/usr/local/bin:/usr/bin:/bin
Environment=PYTHONPATH=/opt/blockchain-node/src:/opt/blockchain-node/scripts
ExecStart=/opt/blockchain-node/.venv/bin/python3 -m aitbc_chain.main
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
EOL
cat > /etc/systemd/system/blockchain-rpc.service << EOL
[Unit]
Description=AITBC Blockchain RPC API
After=blockchain-node.service
[Service]
Type=exec
User=root
WorkingDirectory=/opt/blockchain-node
Environment=PATH=/opt/blockchain-node/.venv/bin:/usr/local/bin:/usr/bin:/bin
Environment=PYTHONPATH=/opt/blockchain-node/src:/opt/blockchain-node/scripts
ExecStart=/opt/blockchain-node/.venv/bin/python3 -m uvicorn aitbc_chain.app:app --host 0.0.0.0 --port 8082
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
EOL
# Enable and start services
print_status "Starting blockchain node..."
systemctl daemon-reload
systemctl enable blockchain-node blockchain-rpc
systemctl start blockchain-node blockchain-rpc
# Wait for services to start
print_status "Waiting for services to start..."
sleep 5
# Check status
print_status "Checking service status..."
systemctl status blockchain-node blockchain-rpc --no-pager | head -15
# Setup port forwarding if in container
if [ "$(hostname)" = "aitbc" ]; then
print_status "Setting up port forwarding..."
iptables -t nat -A PREROUTING -p tcp --dport 8082 -j DNAT --to-destination 192.168.100.10:8082
iptables -t nat -A POSTROUTING -p tcp -d 192.168.100.10 --dport 8082 -j MASQUERADE
iptables-save > /etc/iptables/rules.v4
fi
print_success "✅ Blockchain node deployed!"
echo ""
if [ "$(hostname)" = "aitbc" ]; then
echo "Node RPC: http://192.168.100.10:8082"
echo "External RPC: http://aitbc.keisanki.net:8082"
else
echo "Node RPC: http://95.216.198.140:8082"
echo "External RPC: http://aitbc.keisanki.net:8082"
fi
echo ""
echo "The node will automatically sync on startup."

View File

@@ -0,0 +1,139 @@
#!/bin/bash
# Deploy blockchain node and explorer to incus container
set -e
echo "🚀 Deploying Blockchain Node and Explorer"
echo "========================================"
# Colors
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
print_status() {
echo -e "${GREEN}[INFO]${NC} $1"
}
print_warning() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
# Copy blockchain node to container
print_status "Copying blockchain node to container..."
ssh ns3-root "rm -rf /opt/blockchain-node 2>/dev/null || true"
scp -r apps/blockchain-node ns3-root:/opt/
# Setup blockchain node in container
print_status "Setting up blockchain node..."
ssh ns3-root << 'EOF'
cd /opt/blockchain-node
# Create configuration
cat > .env << EOL
CHAIN_ID=ait-devnet
DB_PATH=./data/chain.db
RPC_BIND_HOST=0.0.0.0
RPC_BIND_PORT=8082
P2P_BIND_HOST=0.0.0.0
P2P_BIND_PORT=7070
PROPOSER_KEY=proposer_key_$(date +%s)
MINT_PER_UNIT=1000
COORDINATOR_RATIO=0.05
GOSSIP_BACKEND=memory
EOL
# Create data directory
mkdir -p data/devnet
# Setup Python environment
python3 -m venv .venv
source .venv/bin/activate
pip install --upgrade pip
pip install -e .
# Generate genesis
export PYTHONPATH="${PWD}/src:${PWD}/scripts:${PYTHONPATH:-}"
python scripts/make_genesis.py --output data/devnet/genesis.json --force
EOF
# Create systemd service for blockchain node
print_status "Creating systemd service for blockchain node..."
ssh ns3-root << 'EOF'
cat > /etc/systemd/system/blockchain-node.service << EOL
[Unit]
Description=AITBC Blockchain Node
After=network.target
[Service]
Type=exec
User=root
WorkingDirectory=/opt/blockchain-node
Environment=PATH=/opt/blockchain-node/.venv/bin:/usr/local/bin:/usr/bin:/bin
Environment=PYTHONPATH=/opt/blockchain-node/src:/opt/blockchain-node/scripts
ExecStart=/opt/blockchain-node/.venv/bin/python3 -m aitbc_chain.main
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
EOL
cat > /etc/systemd/system/blockchain-rpc.service << EOL
[Unit]
Description=AITBC Blockchain RPC API
After=blockchain-node.service
[Service]
Type=exec
User=root
WorkingDirectory=/opt/blockchain-node
Environment=PATH=/opt/blockchain-node/.venv/bin:/usr/local/bin:/usr/bin:/bin
Environment=PYTHONPATH=/opt/blockchain-node/src:/opt/blockchain-node/scripts
ExecStart=/opt/blockchain-node/.venv/bin/python3 -m uvicorn aitbc_chain.app:app --host 0.0.0.0 --port 8082
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
EOL
systemctl daemon-reload
systemctl enable blockchain-node blockchain-rpc
EOF
# Start blockchain node
print_status "Starting blockchain node..."
ssh ns3-root "systemctl start blockchain-node blockchain-rpc"
# Wait for node to start
print_status "Waiting for blockchain node to start..."
sleep 5
# Check status
print_status "Checking blockchain node status..."
ssh ns3-root "systemctl status blockchain-node blockchain-rpc --no-pager | grep -E 'Active:|Main PID:'"
# Setup port forwarding
print_status "Setting up port forwarding..."
ssh ns3-root << 'EOF'
# Clear existing rules
iptables -t nat -F PREROUTING 2>/dev/null || true
iptables -t nat -F POSTROUTING 2>/dev/null || true
# Add port forwarding for blockchain RPC
iptables -t nat -A PREROUTING -p tcp --dport 8082 -j DNAT --to-destination 192.168.100.10:8082
iptables -t nat -A POSTROUTING -p tcp -d 192.168.100.10 --dport 8082 -j MASQUERADE
# Save rules
mkdir -p /etc/iptables
iptables-save > /etc/iptables/rules.v4
EOF
print_success "✅ Blockchain node deployed!"
echo ""
echo "Node RPC: http://192.168.100.10:8082"
echo "External RPC: http://aitbc.keisanki.net:8082"
echo ""
echo "Next: Deploying blockchain explorer..."

View File

@@ -0,0 +1,316 @@
#!/bin/bash
# Deploy blockchain node and explorer directly on ns3
set -e
echo "🚀 AITBC Direct Deployment on ns3"
echo "================================="
# Colors
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
print_status() {
echo -e "${GREEN}[INFO]${NC} $1"
}
print_warning() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
# Check if we're on ns3
if [ "$(hostname)" != "ns3" ] && [ "$(hostname)" != "aitbc" ]; then
print_warning "This script must be run on ns3 server"
echo "Run: ssh ns3-root"
echo "Then: cd /opt && ./deploy-direct.sh"
exit 1
fi
# Stop existing services
print_status "Stopping existing services..."
systemctl stop blockchain-node blockchain-rpc blockchain-explorer nginx 2>/dev/null || true
# Install dependencies
print_status "Installing dependencies..."
apt-get update
apt-get install -y python3 python3-venv python3-pip git curl nginx
# Deploy blockchain node
print_status "Deploying blockchain node..."
cd /opt
rm -rf blockchain-node
cp -r blockchain-node-src blockchain-node
cd blockchain-node
# Create configuration
print_status "Creating configuration..."
cat > .env << EOL
CHAIN_ID=ait-devnet
DB_PATH=./data/chain.db
RPC_BIND_HOST=0.0.0.0
RPC_BIND_PORT=8082
P2P_BIND_HOST=0.0.0.0
P2P_BIND_PORT=7070
PROPOSER_KEY=proposer_key_$(date +%s)
MINT_PER_UNIT=1000
COORDINATOR_RATIO=0.05
GOSSIP_BACKEND=memory
EOL
# Create fresh data directory
rm -rf data
mkdir -p data/devnet
# Setup Python environment
python3 -m venv .venv
source .venv/bin/activate
pip install --upgrade pip
pip install -e .
# Generate genesis
export PYTHONPATH="${PWD}/src:${PWD}/scripts:${PYTHONPATH:-}"
python scripts/make_genesis.py --output data/devnet/genesis.json --force
# Create systemd services
print_status "Creating systemd services..."
cat > /etc/systemd/system/blockchain-node.service << EOL
[Unit]
Description=AITBC Blockchain Node
After=network.target
[Service]
Type=exec
User=root
WorkingDirectory=/opt/blockchain-node
Environment=PATH=/opt/blockchain-node/.venv/bin:/usr/local/bin:/usr/bin:/bin
Environment=PYTHONPATH=/opt/blockchain-node/src:/opt/blockchain-node/scripts
ExecStart=/opt/blockchain-node/.venv/bin/python3 -m aitbc_chain.main
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
EOL
cat > /etc/systemd/system/blockchain-rpc.service << EOL
[Unit]
Description=AITBC Blockchain RPC API
After=blockchain-node.service
[Service]
Type=exec
User=root
WorkingDirectory=/opt/blockchain-node
Environment=PATH=/opt/blockchain-node/.venv/bin:/usr/local/bin:/usr/bin:/bin
Environment=PYTHONPATH=/opt/blockchain-node/src:/opt/blockchain-node/scripts
ExecStart=/opt/blockchain-node/.venv/bin/python3 -m uvicorn aitbc_chain.app:app --host 0.0.0.0 --port 8082
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
EOL
# Start blockchain services
print_status "Starting blockchain services..."
systemctl daemon-reload
systemctl enable blockchain-node blockchain-rpc
systemctl start blockchain-node blockchain-rpc
# Deploy explorer
print_status "Deploying blockchain explorer..."
cd /opt
rm -rf blockchain-explorer
mkdir -p blockchain-explorer
cd blockchain-explorer
# Create HTML explorer
cat > index.html << 'EOF'
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AITBC Blockchain Explorer</title>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://unpkg.com/lucide@latest"></script>
</head>
<body class="bg-gray-50">
<header class="bg-blue-600 text-white shadow-lg">
<div class="container mx-auto px-4 py-4">
<div class="flex items-center justify-between">
<div class="flex items-center space-x-3">
<i data-lucide="cube" class="w-8 h-8"></i>
<h1 class="text-2xl font-bold">AITBC Blockchain Explorer</h1>
</div>
<button onclick="refreshData()" class="bg-blue-500 hover:bg-blue-400 px-3 py-1 rounded flex items-center space-x-1">
<i data-lucide="refresh-cw" class="w-4 h-4"></i>
<span>Refresh</span>
</button>
</div>
</div>
</header>
<main class="container mx-auto px-4 py-8">
<div class="grid grid-cols-1 md:grid-cols-3 gap-6 mb-8">
<div class="bg-white rounded-lg shadow p-6">
<div class="flex items-center justify-between">
<div>
<p class="text-gray-500 text-sm">Current Height</p>
<p class="text-2xl font-bold" id="chain-height">-</p>
</div>
<i data-lucide="trending-up" class="w-10 h-10 text-green-500"></i>
</div>
</div>
<div class="bg-white rounded-lg shadow p-6">
<div class="flex items-center justify-between">
<div>
<p class="text-gray-500 text-sm">Latest Block</p>
<p class="text-lg font-mono" id="latest-hash">-</p>
</div>
<i data-lucide="hash" class="w-10 h-10 text-blue-500"></i>
</div>
</div>
<div class="bg-white rounded-lg shadow p-6">
<div class="flex items-center justify-between">
<div>
<p class="text-gray-500 text-sm">Node Status</p>
<p class="text-lg font-semibold" id="node-status">-</p>
</div>
<i data-lucide="activity" class="w-10 h-10 text-purple-500"></i>
</div>
</div>
</div>
<div class="bg-white rounded-lg shadow">
<div class="px-6 py-4 border-b">
<h2 class="text-xl font-semibold flex items-center">
<i data-lucide="blocks" class="w-5 h-5 mr-2"></i>
Latest Blocks
</h2>
</div>
<div class="p-6">
<table class="w-full">
<thead>
<tr class="text-left text-gray-500 text-sm">
<th class="pb-3">Height</th>
<th class="pb-3">Hash</th>
<th class="pb-3">Timestamp</th>
<th class="pb-3">Transactions</th>
</tr>
</thead>
<tbody id="blocks-table">
<tr>
<td colspan="4" class="text-center py-8 text-gray-500">
Loading blocks...
</td>
</tr>
</tbody>
</table>
</div>
</div>
</main>
<script>
lucide.createIcons();
const RPC_URL = 'http://localhost:8082';
async function refreshData() {
try {
const response = await fetch(`${RPC_URL}/rpc/head`);
const head = await response.json();
document.getElementById('chain-height').textContent = head.height || '-';
document.getElementById('latest-hash').textContent = head.hash ? head.hash.substring(0, 16) + '...' : '-';
document.getElementById('node-status').innerHTML = '<span class="text-green-500">Online</span>';
// Load last 10 blocks
const tbody = document.getElementById('blocks-table');
tbody.innerHTML = '';
for (let i = 0; i < 10 && head.height - i >= 0; i++) {
const blockResponse = await fetch(`${RPC_URL}/rpc/blocks/${head.height - i}`);
const block = await blockResponse.json();
const row = tbody.insertRow();
row.innerHTML = `
<td class="py-3 font-mono">${block.height}</td>
<td class="py-3 font-mono text-sm">${block.hash ? block.hash.substring(0, 16) + '...' : '-'}</td>
<td class="py-3 text-sm">${new Date(block.timestamp * 1000).toLocaleString()}</td>
<td class="py-3">${block.transactions ? block.transactions.length : 0}</td>
`;
}
} catch (error) {
console.error('Error:', error);
document.getElementById('node-status').innerHTML = '<span class="text-red-500">Error</span>';
}
}
refreshData();
setInterval(refreshData, 30000);
</script>
</body>
</html>
EOF
# Configure nginx
print_status "Configuring nginx..."
cat > /etc/nginx/sites-available/blockchain-explorer << EOL
server {
listen 3000;
server_name _;
root /opt/blockchain-explorer;
index index.html;
location / {
try_files \$uri \$uri/ =404;
}
}
EOL
ln -sf /etc/nginx/sites-available/blockchain-explorer /etc/nginx/sites-enabled/
rm -f /etc/nginx/sites-enabled/default
nginx -t
systemctl reload nginx
# Setup port forwarding if in container
if [ "$(hostname)" = "aitbc" ]; then
print_status "Setting up port forwarding..."
iptables -t nat -F PREROUTING 2>/dev/null || true
iptables -t nat -F POSTROUTING 2>/dev/null || true
iptables -t nat -A PREROUTING -p tcp --dport 8082 -j DNAT --to-destination 192.168.100.10:8082
iptables -t nat -A POSTROUTING -p tcp -d 192.168.100.10 --dport 8082 -j MASQUERADE
iptables -t nat -A PREROUTING -p tcp --dport 3000 -j DNAT --to-destination 192.168.100.10:3000
iptables -t nat -A POSTROUTING -p tcp -d 192.168.100.10 --dport 3000 -j MASQUERADE
iptables-save > /etc/iptables/rules.v4
fi
# Wait for services to start
print_status "Waiting for services to start..."
sleep 5
# Check services
print_status "Checking service status..."
systemctl status blockchain-node blockchain-rpc nginx --no-pager | grep -E 'Active:|Main PID:'
print_success "✅ Deployment complete!"
echo ""
echo "Services:"
if [ "$(hostname)" = "aitbc" ]; then
echo " - Blockchain Node RPC: http://192.168.100.10:8082"
echo " - Blockchain Explorer: http://192.168.100.10:3000"
echo ""
echo "External access:"
echo " - Blockchain Node RPC: http://aitbc.keisanki.net:8082"
echo " - Blockchain Explorer: http://aitbc.keisanki.net:3000"
else
echo " - Blockchain Node RPC: http://localhost:8082"
echo " - Blockchain Explorer: http://localhost:3000"
echo ""
echo "External access:"
echo " - Blockchain Node RPC: http://aitbc.keisanki.net:8082"
echo " - Blockchain Explorer: http://aitbc.keisanki.net:3000"
fi

View File

@@ -0,0 +1,88 @@
#!/bin/bash
# Deploy AITBC services to domain https://aitbc.bubuit.net
set -e
DOMAIN="aitbc.bubuit.net"
CONTAINER="aitbc"
echo "🚀 Deploying AITBC services to https://$DOMAIN"
echo ""
# Colors
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
print_status() {
echo -e "${GREEN}[INFO]${NC} $1"
}
print_warning() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
# Stop local services
print_status "Stopping local services..."
sudo fuser -k 8000/tcp 2>/dev/null || true
sudo fuser -k 9080/tcp 2>/dev/null || true
sudo fuser -k 3001/tcp 2>/dev/null || true
sudo fuser -k 3002/tcp 2>/dev/null || true
# Deploy to container
print_status "Deploying to container..."
python /home/oib/windsurf/aitbc/container-deploy.py
# Copy nginx config to container
print_status "Configuring nginx for domain..."
incus file push /home/oib/windsurf/aitbc/nginx-aitbc.conf $CONTAINER/etc/nginx/sites-available/aitbc
# Enable site
incus exec $CONTAINER -- ln -sf /etc/nginx/sites-available/aitbc /etc/nginx/sites-enabled/
incus exec $CONTAINER -- rm -f /etc/nginx/sites-enabled/default
# Test nginx config
incus exec $CONTAINER -- nginx -t
# Reload nginx
incus exec $CONTAINER -- systemctl reload nginx
# Install SSL certificate (Let's Encrypt)
print_warning "SSL Certificate Setup:"
echo "1. Ensure port 80/443 are forwarded to container IP (10.1.223.93)"
echo "2. Run certbot in container:"
echo " incus exec $CONTAINER -- certbot --nginx -d $DOMAIN"
echo ""
# Update UIs to use correct API endpoints
print_status "Updating API endpoints..."
# Update marketplace API base URL
incus exec $CONTAINER -- sed -i "s|http://127.0.0.1:8000|https://$DOMAIN/api|g" /home/oib/aitbc/apps/marketplace-ui/index.html
# Update exchange API endpoints
incus exec $CONTAINER -- sed -i "s|http://127.0.0.1:8000|https://$DOMAIN/api|g" /home/oib/aitbc/apps/trade-exchange/index.html
incus exec $CONTAINER -- sed -i "s|http://127.0.0.1:9080|https://$DOMAIN/rpc|g" /home/oib/aitbc/apps/trade-exchange/index.html
# Restart services to apply changes
print_status "Restarting services..."
incus exec $CONTAINER -- pkill -f "server.py"
sleep 2
incus exec $CONTAINER -- /home/oib/start_aitbc.sh
echo ""
print_status "✅ Deployment complete!"
echo ""
echo "📋 Service URLs:"
echo " 🌐 Domain: https://$DOMAIN"
echo " 📊 Marketplace: https://$DOMAIN/Marketplace"
echo " 💱 Trade Exchange: https://$DOMAIN/Exchange"
echo " 🔗 API: https://$DOMAIN/api"
echo " ⛓️ Blockchain RPC: https://$DOMAIN/rpc"
echo ""
echo "📝 Next Steps:"
echo "1. Forward ports 80/443 to container IP (10.1.223.93)"
echo "2. Install SSL certificate:"
echo " incus exec $CONTAINER -- certbot --nginx -d $DOMAIN"
echo "3. Test services at the URLs above"

View File

@@ -0,0 +1,74 @@
#!/bin/bash
# Deploy AITBC Trade Exchange to the server
set -e
SERVER="root@10.1.223.93"
EXCHANGE_DIR="/root/aitbc/apps/trade-exchange"
echo "🚀 Deploying AITBC Trade Exchange"
echo "=================================="
echo "Server: $SERVER"
echo ""
# Colors
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
print_status() {
echo -e "${GREEN}[INFO]${NC} $1"
}
print_warning() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
# Test SSH connection
print_status "Testing SSH connection..."
ssh $SERVER "hostname && ip a show eth0 | grep inet"
# Copy updated files
print_status "Copying updated Exchange files..."
scp /home/oib/windsurf/aitbc/apps/trade-exchange/index.html $SERVER:$EXCHANGE_DIR/
scp /home/oib/windsurf/aitbc/apps/trade-exchange/server.py $SERVER:$EXCHANGE_DIR/
# Ensure assets are available
print_status "Ensuring assets directory exists..."
ssh $SERVER "mkdir -p /var/www/aitbc.bubuit.net/assets"
ssh $SERVER "mkdir -p /var/www/aitbc.bubuit.net/assets/css"
ssh $SERVER "mkdir -p /var/www/aitbc.bubuit.net/assets/js"
# Copy assets if they don't exist
print_status "Copying assets if needed..."
if ! ssh $SERVER "test -f /var/www/aitbc.bubuit.net/assets/css/aitbc.css"; then
scp -r /home/oib/windsurf/aitbc/assets/* $SERVER:/var/www/aitbc.bubuit.net/assets/
fi
# Restart the exchange service
print_status "Restarting Trade Exchange service..."
ssh $SERVER "systemctl restart aitbc-exchange"
# Wait for service to start
print_status "Waiting for service to start..."
sleep 5
# Check service status
print_status "Checking service status..."
ssh $SERVER "systemctl status aitbc-exchange --no-pager -l | head -10"
# Test the endpoint
print_status "Testing Exchange endpoint..."
ssh $SERVER "curl -s http://127.0.0.1:3002/ | head -c 100"
echo ""
echo ""
print_status "✅ Exchange deployment complete!"
echo ""
echo "📋 URLs:"
echo " 🌐 IP: http://10.1.223.93/Exchange"
echo " 🔒 Domain: https://aitbc.bubuit.net/Exchange"
echo ""
echo "🔍 To check logs:"
echo " ssh $SERVER 'journalctl -u aitbc-exchange -f'"

View File

@@ -0,0 +1,396 @@
#!/bin/bash
# Deploy blockchain explorer directly on ns3 server
set -e
echo "🔍 Deploying Blockchain Explorer on ns3"
echo "======================================"
# Colors
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
print_status() {
echo -e "${GREEN}[INFO]${NC} $1"
}
print_warning() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
# Check if we're on the right server
if [ "$(hostname)" != "ns3" ] && [ "$(hostname)" != "aitbc" ]; then
print_warning "This script should be run on ns3 server"
exit 1
fi
# Create directory
print_status "Creating blockchain explorer directory..."
mkdir -p /opt/blockchain-explorer
cd /opt/blockchain-explorer
# Create a simple HTML-based explorer (no build needed)
print_status "Creating web-based explorer..."
cat > index.html << 'EOF'
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AITBC Blockchain Explorer</title>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://unpkg.com/lucide@latest"></script>
<style>
.fade-in { animation: fadeIn 0.3s ease-in; }
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
</style>
</head>
<body class="bg-gray-50">
<header class="bg-blue-600 text-white shadow-lg">
<div class="container mx-auto px-4 py-4">
<div class="flex items-center justify-between">
<div class="flex items-center space-x-3">
<i data-lucide="cube" class="w-8 h-8"></i>
<h1 class="text-2xl font-bold">AITBC Blockchain Explorer</h1>
</div>
<div class="flex items-center space-x-4">
<span class="text-sm">Network: <span class="font-mono bg-blue-700 px-2 py-1 rounded">ait-devnet</span></span>
<button onclick="refreshData()" class="bg-blue-500 hover:bg-blue-400 px-3 py-1 rounded flex items-center space-x-1">
<i data-lucide="refresh-cw" class="w-4 h-4"></i>
<span>Refresh</span>
</button>
</div>
</div>
</div>
</header>
<main class="container mx-auto px-4 py-8">
<!-- Chain Stats -->
<div class="grid grid-cols-1 md:grid-cols-3 gap-6 mb-8">
<div class="bg-white rounded-lg shadow p-6">
<div class="flex items-center justify-between">
<div>
<p class="text-gray-500 text-sm">Current Height</p>
<p class="text-2xl font-bold" id="chain-height">-</p>
</div>
<i data-lucide="trending-up" class="w-10 h-10 text-green-500"></i>
</div>
</div>
<div class="bg-white rounded-lg shadow p-6">
<div class="flex items-center justify-between">
<div>
<p class="text-gray-500 text-sm">Latest Block</p>
<p class="text-lg font-mono" id="latest-hash">-</p>
</div>
<i data-lucide="hash" class="w-10 h-10 text-blue-500"></i>
</div>
</div>
<div class="bg-white rounded-lg shadow p-6">
<div class="flex items-center justify-between">
<div>
<p class="text-gray-500 text-sm">Node Status</p>
<p class="text-lg font-semibold" id="node-status">-</p>
</div>
<i data-lucide="activity" class="w-10 h-10 text-purple-500"></i>
</div>
</div>
</div>
<!-- Search -->
<div class="bg-white rounded-lg shadow p-6 mb-8">
<div class="flex space-x-4">
<input type="text" id="search-input" placeholder="Search by block height, hash, or transaction hash"
class="flex-1 px-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500">
<button onclick="search()" class="bg-blue-600 text-white px-6 py-2 rounded-lg hover:bg-blue-700">
Search
</button>
</div>
</div>
<!-- Latest Blocks -->
<div class="bg-white rounded-lg shadow">
<div class="px-6 py-4 border-b">
<h2 class="text-xl font-semibold flex items-center">
<i data-lucide="blocks" class="w-5 h-5 mr-2"></i>
Latest Blocks
</h2>
</div>
<div class="p-6">
<div class="overflow-x-auto">
<table class="w-full">
<thead>
<tr class="text-left text-gray-500 text-sm">
<th class="pb-3">Height</th>
<th class="pb-3">Hash</th>
<th class="pb-3">Timestamp</th>
<th class="pb-3">Transactions</th>
<th class="pb-3">Actions</th>
</tr>
</thead>
<tbody id="blocks-table">
<tr>
<td colspan="5" class="text-center py-8 text-gray-500">
Loading blocks...
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<!-- Block Details Modal -->
<div id="block-modal" class="fixed inset-0 bg-black bg-opacity-50 hidden z-50">
<div class="flex items-center justify-center min-h-screen p-4">
<div class="bg-white rounded-lg max-w-4xl w-full max-h-[90vh] overflow-y-auto">
<div class="p-6 border-b">
<div class="flex justify-between items-center">
<h2 class="text-2xl font-bold">Block Details</h2>
<button onclick="closeModal()" class="text-gray-500 hover:text-gray-700">
<i data-lucide="x" class="w-6 h-6"></i>
</button>
</div>
</div>
<div class="p-6" id="block-details">
<!-- Block details will be loaded here -->
</div>
</div>
</div>
</div>
</main>
<footer class="bg-gray-800 text-white mt-12">
<div class="container mx-auto px-4 py-6 text-center">
<p class="text-sm">AITBC Blockchain Explorer - Connected to node at http://localhost:8082</p>
</div>
</footer>
<script>
// Initialize lucide icons
lucide.createIcons();
// RPC URL - change based on environment
const RPC_URL = window.location.hostname === 'localhost' ?
'http://localhost:8082' :
'http://95.216.198.140:8082';
// Global state
let currentData = {};
// Load initial data
document.addEventListener('DOMContentLoaded', () => {
refreshData();
});
// Refresh all data
async function refreshData() {
try {
await Promise.all([
loadChainStats(),
loadLatestBlocks()
]);
} catch (error) {
console.error('Error refreshing data:', error);
document.getElementById('node-status').innerHTML = '<span class="text-red-500">Error</span>';
}
}
// Load chain statistics
async function loadChainStats() {
const response = await fetch(`${RPC_URL}/rpc/head`);
const data = await response.json();
document.getElementById('chain-height').textContent = data.height || '-';
document.getElementById('latest-hash').textContent = data.hash ? data.hash.substring(0, 16) + '...' : '-';
document.getElementById('node-status').innerHTML = '<span class="text-green-500">Online</span>';
currentData.head = data;
}
// Load latest blocks
async function loadLatestBlocks() {
const tbody = document.getElementById('blocks-table');
tbody.innerHTML = '<tr><td colspan="5" class="text-center py-8 text-gray-500">Loading blocks...</td></tr>';
const head = await fetch(`${RPC_URL}/rpc/head`).then(r => r.json());
const blocks = [];
// Load last 10 blocks
for (let i = 0; i < 10 && head.height - i >= 0; i++) {
const block = await fetch(`${RPC_URL}/rpc/blocks/${head.height - i}`).then(r => r.json());
blocks.push(block);
}
tbody.innerHTML = blocks.map(block => `
<tr class="border-t hover:bg-gray-50">
<td class="py-3 font-mono">${block.height}</td>
<td class="py-3 font-mono text-sm">${block.hash ? block.hash.substring(0, 16) + '...' : '-'}</td>
<td class="py-3 text-sm">${formatTimestamp(block.timestamp)}</td>
<td class="py-3">${block.transactions ? block.transactions.length : 0}</td>
<td class="py-3">
<button onclick="showBlockDetails(${block.height})" class="text-blue-600 hover:text-blue-800">
View Details
</button>
</td>
</tr>
`).join('');
}
// Show block details
async function showBlockDetails(height) {
const block = await fetch(`${RPC_URL}/rpc/blocks/${height}`).then(r => r.json());
const modal = document.getElementById('block-modal');
const details = document.getElementById('block-details');
details.innerHTML = `
<div class="space-y-6">
<div>
<h3 class="text-lg font-semibold mb-2">Block Header</h3>
<div class="bg-gray-50 rounded p-4 space-y-2">
<div class="flex justify-between">
<span class="text-gray-600">Height:</span>
<span class="font-mono">${block.height}</span>
</div>
<div class="flex justify-between">
<span class="text-gray-600">Hash:</span>
<span class="font-mono text-sm">${block.hash || '-'}</span>
</div>
<div class="flex justify-between">
<span class="text-gray-600">Parent Hash:</span>
<span class="font-mono text-sm">${block.parent_hash || '-'}</span>
</div>
<div class="flex justify-between">
<span class="text-gray-600">Timestamp:</span>
<span>${formatTimestamp(block.timestamp)}</span>
</div>
<div class="flex justify-between">
<span class="text-gray-600">Proposer:</span>
<span class="font-mono text-sm">${block.proposer || '-'}</span>
</div>
</div>
</div>
${block.transactions && block.transactions.length > 0 ? `
<div>
<h3 class="text-lg font-semibold mb-2">Transactions (${block.transactions.length})</h3>
<div class="space-y-2">
${block.transactions.map(tx => `
<div class="bg-gray-50 rounded p-4">
<div class="flex justify-between mb-2">
<span class="text-gray-600">Hash:</span>
<span class="font-mono text-sm">${tx.hash || '-'}</span>
</div>
<div class="flex justify-between mb-2">
<span class="text-gray-600">Type:</span>
<span>${tx.type || '-'}</span>
</div>
<div class="flex justify-between mb-2">
<span class="text-gray-600">From:</span>
<span class="font-mono text-sm">${tx.sender || '-'}</span>
</div>
<div class="flex justify-between">
<span class="text-gray-600">Fee:</span>
<span>${tx.fee || '0'}</span>
</div>
</div>
`).join('')}
</div>
</div>
` : '<p class="text-gray-500">No transactions in this block</p>'}
</div>
`;
modal.classList.remove('hidden');
}
// Close modal
function closeModal() {
document.getElementById('block-modal').classList.add('hidden');
}
// Search functionality
async function search() {
const query = document.getElementById('search-input').value.trim();
if (!query) return;
// Try block height first
if (/^\\d+$/.test(query)) {
showBlockDetails(parseInt(query));
return;
}
// TODO: Add transaction hash search
alert('Search by block height is currently supported');
}
// Format timestamp
function formatTimestamp(timestamp) {
if (!timestamp) return '-';
return new Date(timestamp * 1000).toLocaleString();
}
// Auto-refresh every 30 seconds
setInterval(refreshData, 30000);
</script>
</body>
</html>
EOF
# Install a simple web server
print_status "Installing web server..."
apt-get install -y nginx
# Configure nginx to serve the explorer
print_status "Configuring nginx..."
cat > /etc/nginx/sites-available/blockchain-explorer << EOL
server {
listen 3000;
server_name _;
root /opt/blockchain-explorer;
index index.html;
location / {
try_files \$uri \$uri/ =404;
}
# CORS headers for API access
location /rpc/ {
proxy_pass http://localhost:8082;
proxy_set_header Host \$host;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
}
}
EOL
# Enable the site
ln -sf /etc/nginx/sites-available/blockchain-explorer /etc/nginx/sites-enabled/
rm -f /etc/nginx/sites-enabled/default
# Test and reload nginx
nginx -t
systemctl reload nginx
# Setup port forwarding if in container
if [ "$(hostname)" = "aitbc" ]; then
print_status "Setting up port forwarding..."
iptables -t nat -A PREROUTING -p tcp --dport 3000 -j DNAT --to-destination 192.168.100.10:3000
iptables -t nat -A POSTROUTING -p tcp -d 192.168.100.10 --dport 3000 -j MASQUERADE
iptables-save > /etc/iptables/rules.v4
fi
print_status "Checking nginx status..."
systemctl status nginx --no-pager | head -10
print_success "✅ Blockchain explorer deployed!"
echo ""
echo "Explorer URL: http://localhost:3000"
if [ "$(hostname)" = "aitbc" ]; then
echo "External URL: http://aitbc.keisanki.net:3000"
else
echo "External URL: http://aitbc.keisanki.net:3000"
fi
echo ""
echo "The explorer is a static HTML site served by nginx."

View File

@@ -0,0 +1,66 @@
#!/bin/bash
# Deploy AITBC Explorer to the server
set -e
SERVER="root@10.1.223.93"
EXPLORER_DIR="/root/aitbc/apps/explorer-web"
NGINX_CONFIG="/etc/nginx/sites-available/aitbc"
echo "🚀 Deploying AITBC Explorer to Server"
echo "====================================="
echo "Server: $SERVER"
echo ""
# Colors
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
print_status() {
echo -e "${GREEN}[INFO]${NC} $1"
}
print_warning() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
# Build the explorer locally first
print_status "Building explorer locally..."
cd /home/oib/windsurf/aitbc/apps/explorer-web
npm run build
# Copy built files to server
print_status "Copying explorer build to server..."
scp -r dist $SERVER:$EXPLORER_DIR/
# Update nginx config to include explorer
print_status "Updating nginx configuration..."
# Backup current config
ssh $SERVER "cp $NGINX_CONFIG ${NGINX_CONFIG}.backup"
# Add explorer location to nginx config
ssh $SERVER "sed -i '/# Health endpoint/i\\
# Explorer\\
location /explorer/ {\\
alias /root/aitbc/apps/explorer-web/dist/;\\
try_files \$uri \$uri/ /explorer/index.html;\\
}\\
\\
# Explorer mock data\\
location /explorer/mock/ {\\
alias /root/aitbc/apps/explorer-web/public/mock/;\\
}\\
' $NGINX_CONFIG"
# Test and reload nginx
print_status "Testing and reloading nginx..."
ssh $SERVER "nginx -t && systemctl reload nginx"
print_status "✅ Explorer deployment complete!"
echo ""
echo "📋 Explorer URL:"
echo " 🌐 Explorer: https://aitbc.bubuit.net/explorer/"
echo ""

View File

@@ -0,0 +1,121 @@
#!/bin/bash
# Deploy the first blockchain node
set -e
echo "🚀 Deploying First Blockchain Node"
echo "================================="
# Colors
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
print_status() {
echo -e "${GREEN}[INFO]${NC} $1"
}
print_warning() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
NODE1_DIR="/opt/blockchain-node"
# Create configuration for first node
print_status "Creating configuration for first node..."
cat > $NODE1_DIR/.env << EOF
CHAIN_ID=ait-devnet
DB_PATH=./data/chain.db
RPC_BIND_HOST=127.0.0.1
RPC_BIND_PORT=8080
P2P_BIND_HOST=0.0.0.0
P2P_BIND_PORT=7070
PROPOSER_KEY=node1_proposer_key_$(date +%s)
MINT_PER_UNIT=1000
COORDINATOR_RATIO=0.05
GOSSIP_BACKEND=http
GOSSIP_BROADCAST_URL=http://127.0.0.1:7071/gossip
EOF
# Create data directory
mkdir -p $NODE1_DIR/data/devnet
# Generate genesis file
print_status "Generating genesis file..."
cd $NODE1_DIR
export PYTHONPATH="${NODE1_DIR}/src:${NODE1_DIR}/scripts:${PYTHONPATH:-}"
python3 scripts/make_genesis.py --output data/devnet/genesis.json --force
# Create systemd service
print_status "Creating systemd service..."
sudo cat > /etc/systemd/system/blockchain-node.service << EOF
[Unit]
Description=AITBC Blockchain Node 1
After=network.target
[Service]
Type=exec
User=root
WorkingDirectory=$NODE1_DIR
Environment=PATH=$NODE1_DIR/.venv/bin:/usr/local/bin:/usr/bin:/bin
Environment=PYTHONPATH=$NODE1_DIR/src:$NODE1_DIR/scripts
ExecStart=$NODE1_DIR/.venv/bin/python3 -m aitbc_chain.main
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
# Create RPC API service
print_status "Creating RPC API service..."
sudo cat > /etc/systemd/system/blockchain-rpc.service << EOF
[Unit]
Description=AITBC Blockchain RPC API 1
After=blockchain-node.service
[Service]
Type=exec
User=root
WorkingDirectory=$NODE1_DIR
Environment=PATH=$NODE1_DIR/.venv/bin:/usr/local/bin:/usr/bin:/bin
Environment=PYTHONPATH=$NODE1_DIR/src:$NODE1_DIR/scripts
ExecStart=$NODE1_DIR/.venv/bin/python3 -m uvicorn aitbc_chain.app:app --host 0.0.0.0 --port 8080
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
# Setup Python environment if not exists
if [ ! -d "$NODE1_DIR/.venv" ]; then
print_status "Setting up Python environment..."
cd $NODE1_DIR
python3 -m venv .venv
source .venv/bin/activate
pip install --upgrade pip
pip install -e .
fi
# Enable and start services
print_status "Enabling and starting services..."
sudo systemctl daemon-reload
sudo systemctl enable blockchain-node blockchain-rpc
sudo systemctl start blockchain-node blockchain-rpc
# Check status
print_status "Checking service status..."
sudo systemctl status blockchain-node --no-pager -l
sudo systemctl status blockchain-rpc --no-pager -l
echo ""
print_status "✅ First blockchain node deployed!"
echo ""
echo "Node 1 RPC: http://127.0.0.1:8080"
echo "Node 2 RPC: http://127.0.0.1:8081"
echo ""
echo "To check logs:"
echo " Node 1: sudo journalctl -u blockchain-node -f"
echo " Node 2: sudo journalctl -u blockchain-node-2 -f"

View File

@@ -0,0 +1,306 @@
#!/bin/bash
# Deploy blockchain node and explorer inside the container
set -e
echo "🚀 Deploying Inside Container"
echo "============================"
# Colors
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
print_status() {
echo -e "${GREEN}[INFO]${NC} $1"
}
print_warning() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
# Check if we're in the container
if [ ! -f /proc/1/environ ] || ! grep -q container=lxc /proc/1/environ 2>/dev/null; then
if [ "$(hostname)" != "aitbc" ]; then
print_warning "This script must be run inside the aitbc container"
exit 1
fi
fi
# Stop existing services
print_status "Stopping existing services..."
systemctl stop blockchain-node blockchain-rpc nginx 2>/dev/null || true
# Install dependencies
print_status "Installing dependencies..."
apt-get update
apt-get install -y python3 python3-venv python3-pip git curl nginx
# Deploy blockchain node
print_status "Deploying blockchain node..."
cd /opt
rm -rf blockchain-node
# The source is already in blockchain-node-src, copy it properly
cp -r blockchain-node-src blockchain-node
cd blockchain-node
# Check if pyproject.toml exists
if [ ! -f pyproject.toml ]; then
print_warning "pyproject.toml not found, looking for it..."
find . -name "pyproject.toml" -type f
# If it's in a subdirectory, move everything up
if [ -f blockchain-node-src/pyproject.toml ]; then
print_status "Moving files from nested directory..."
mv blockchain-node-src/* .
rmdir blockchain-node-src
fi
fi
# Create configuration
print_status "Creating configuration..."
cat > .env << EOL
CHAIN_ID=ait-devnet
DB_PATH=./data/chain.db
RPC_BIND_HOST=0.0.0.0
RPC_BIND_PORT=8082
P2P_BIND_HOST=0.0.0.0
P2P_BIND_PORT=7070
PROPOSER_KEY=proposer_key_$(date +%s)
MINT_PER_UNIT=1000
COORDINATOR_RATIO=0.05
GOSSIP_BACKEND=memory
EOL
# Create fresh data directory
rm -rf data
mkdir -p data/devnet
# Setup Python environment
python3 -m venv .venv
source .venv/bin/activate
pip install --upgrade pip
pip install -e .
# Generate genesis
export PYTHONPATH="${PWD}/src:${PWD}/scripts:${PYTHONPATH:-}"
python scripts/make_genesis.py --output data/devnet/genesis.json --force
# Create systemd services
print_status "Creating systemd services..."
cat > /etc/systemd/system/blockchain-node.service << EOL
[Unit]
Description=AITBC Blockchain Node
After=network.target
[Service]
Type=exec
User=root
WorkingDirectory=/opt/blockchain-node
Environment=PATH=/opt/blockchain-node/.venv/bin:/usr/local/bin:/usr/bin:/bin
Environment=PYTHONPATH=/opt/blockchain-node/src:/opt/blockchain-node/scripts
ExecStart=/opt/blockchain-node/.venv/bin/python3 -m aitbc_chain.main
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
EOL
cat > /etc/systemd/system/blockchain-rpc.service << EOL
[Unit]
Description=AITBC Blockchain RPC API
After=blockchain-node.service
[Service]
Type=exec
User=root
WorkingDirectory=/opt/blockchain-node
Environment=PATH=/opt/blockchain-node/.venv/bin:/usr/local/bin:/usr/bin:/bin
Environment=PYTHONPATH=/opt/blockchain-node/src:/opt/blockchain-node/scripts
ExecStart=/opt/blockchain-node/.venv/bin/python3 -m uvicorn aitbc_chain.app:app --host 0.0.0.0 --port 8082
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
EOL
# Start blockchain services
print_status "Starting blockchain services..."
systemctl daemon-reload
systemctl enable blockchain-node blockchain-rpc
systemctl start blockchain-node blockchain-rpc
# Deploy explorer
print_status "Deploying blockchain explorer..."
cd /opt
rm -rf blockchain-explorer
mkdir -p blockchain-explorer
cd blockchain-explorer
# Create HTML explorer
cat > index.html << 'EOF'
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AITBC Blockchain Explorer</title>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://unpkg.com/lucide@latest"></script>
</head>
<body class="bg-gray-50">
<header class="bg-blue-600 text-white shadow-lg">
<div class="container mx-auto px-4 py-4">
<div class="flex items-center justify-between">
<div class="flex items-center space-x-3">
<i data-lucide="cube" class="w-8 h-8"></i>
<h1 class="text-2xl font-bold">AITBC Blockchain Explorer</h1>
</div>
<button onclick="refreshData()" class="bg-blue-500 hover:bg-blue-400 px-3 py-1 rounded flex items-center space-x-1">
<i data-lucide="refresh-cw" class="w-4 h-4"></i>
<span>Refresh</span>
</button>
</div>
</div>
</header>
<main class="container mx-auto px-4 py-8">
<div class="grid grid-cols-1 md:grid-cols-3 gap-6 mb-8">
<div class="bg-white rounded-lg shadow p-6">
<div class="flex items-center justify-between">
<div>
<p class="text-gray-500 text-sm">Current Height</p>
<p class="text-2xl font-bold" id="chain-height">-</p>
</div>
<i data-lucide="trending-up" class="w-10 h-10 text-green-500"></i>
</div>
</div>
<div class="bg-white rounded-lg shadow p-6">
<div class="flex items-center justify-between">
<div>
<p class="text-gray-500 text-sm">Latest Block</p>
<p class="text-lg font-mono" id="latest-hash">-</p>
</div>
<i data-lucide="hash" class="w-10 h-10 text-blue-500"></i>
</div>
</div>
<div class="bg-white rounded-lg shadow p-6">
<div class="flex items-center justify-between">
<div>
<p class="text-gray-500 text-sm">Node Status</p>
<p class="text-lg font-semibold" id="node-status">-</p>
</div>
<i data-lucide="activity" class="w-10 h-10 text-purple-500"></i>
</div>
</div>
</div>
<div class="bg-white rounded-lg shadow">
<div class="px-6 py-4 border-b">
<h2 class="text-xl font-semibold flex items-center">
<i data-lucide="blocks" class="w-5 h-5 mr-2"></i>
Latest Blocks
</h2>
</div>
<div class="p-6">
<table class="w-full">
<thead>
<tr class="text-left text-gray-500 text-sm">
<th class="pb-3">Height</th>
<th class="pb-3">Hash</th>
<th class="pb-3">Timestamp</th>
<th class="pb-3">Transactions</th>
</tr>
</thead>
<tbody id="blocks-table">
<tr>
<td colspan="4" class="text-center py-8 text-gray-500">
Loading blocks...
</td>
</tr>
</tbody>
</table>
</div>
</div>
</main>
<script>
lucide.createIcons();
const RPC_URL = 'http://localhost:8082';
async function refreshData() {
try {
const response = await fetch(`${RPC_URL}/rpc/head`);
const head = await response.json();
document.getElementById('chain-height').textContent = head.height || '-';
document.getElementById('latest-hash').textContent = head.hash ? head.hash.substring(0, 16) + '...' : '-';
document.getElementById('node-status').innerHTML = '<span class="text-green-500">Online</span>';
// Load last 10 blocks
const tbody = document.getElementById('blocks-table');
tbody.innerHTML = '';
for (let i = 0; i < 10 && head.height - i >= 0; i++) {
const blockResponse = await fetch(`${RPC_URL}/rpc/blocks/${head.height - i}`);
const block = await blockResponse.json();
const row = tbody.insertRow();
row.innerHTML = `
<td class="py-3 font-mono">${block.height}</td>
<td class="py-3 font-mono text-sm">${block.hash ? block.hash.substring(0, 16) + '...' : '-'}</td>
<td class="py-3 text-sm">${new Date(block.timestamp * 1000).toLocaleString()}</td>
<td class="py-3">${block.transactions ? block.transactions.length : 0}</td>
`;
}
} catch (error) {
console.error('Error:', error);
document.getElementById('node-status').innerHTML = '<span class="text-red-500">Error</span>';
}
}
refreshData();
setInterval(refreshData, 30000);
</script>
</body>
</html>
EOF
# Configure nginx
print_status "Configuring nginx..."
cat > /etc/nginx/sites-available/blockchain-explorer << EOL
server {
listen 3000;
server_name _;
root /opt/blockchain-explorer;
index index.html;
location / {
try_files \$uri \$uri/ =404;
}
}
EOL
ln -sf /etc/nginx/sites-available/blockchain-explorer /etc/nginx/sites-enabled/
rm -f /etc/nginx/sites-enabled/default
nginx -t
systemctl reload nginx
# Wait for services to start
print_status "Waiting for services to start..."
sleep 5
# Check services
print_status "Checking service status..."
systemctl status blockchain-node blockchain-rpc nginx --no-pager | grep -E 'Active:|Main PID:'
print_success "✅ Deployment complete in container!"
echo ""
echo "Services:"
echo " - Blockchain Node RPC: http://localhost:8082"
echo " - Blockchain Explorer: http://localhost:3000"
echo ""
echo "These are accessible from the host via port forwarding."

View File

@@ -0,0 +1,56 @@
#!/bin/bash
# Deploy Modern Blockchain Explorer
set -e
echo "🚀 Deploying Modern Blockchain Explorer"
echo "======================================"
# Colors
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
print_status() {
echo -e "${GREEN}[INFO]${NC} $1"
}
print_warning() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
# Stop existing services
print_status "Stopping existing services..."
systemctl stop nginx 2>/dev/null || true
# Create directory
print_status "Creating explorer directory..."
rm -rf /opt/blockchain-explorer
mkdir -p /opt/blockchain-explorer/assets
# Copy files
print_status "Copying explorer files..."
cp -r /opt/blockchain-node-src/apps/blockchain-explorer/* /opt/blockchain-explorer/
# Update nginx configuration
print_status "Updating nginx configuration..."
cp /opt/blockchain-explorer/nginx.conf /etc/nginx/sites-available/blockchain-explorer
ln -sf /etc/nginx/sites-available/blockchain-explorer /etc/nginx/sites-enabled/
rm -f /etc/nginx/sites-enabled/default
# Test and start nginx
print_status "Starting nginx..."
nginx -t
systemctl start nginx
print_success "✅ Modern explorer deployed!"
echo ""
echo "Access URLs:"
echo " - Explorer: http://localhost:3000/"
echo " - API: http://localhost:3000/api/v1/"
echo ""
echo "Standardized API Endpoints:"
echo " - GET /api/v1/chain/head"
echo " - GET /api/v1/chain/blocks?limit=N"
echo " - GET /api/v1/chain/blocks/{height}"

View File

@@ -0,0 +1,160 @@
#!/bin/bash
# Deploy nginx reverse proxy for AITBC services
# This replaces firehol/iptables port forwarding with nginx reverse proxy
set -e
echo "🚀 Deploying Nginx Reverse Proxy for AITBC"
echo "=========================================="
# Colors
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
NC='\033[0m'
print_status() {
echo -e "${GREEN}[INFO]${NC} $1"
}
print_warning() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
print_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
# Check if we're on the host server
if ! grep -q "ns3-root" ~/.ssh/config 2>/dev/null; then
print_error "ns3-root SSH configuration not found. Please add it to ~/.ssh/config"
exit 1
fi
# Install nginx on host if not already installed
print_status "Checking nginx installation on host..."
ssh ns3-root "which nginx > /dev/null || (apt-get update && apt-get install -y nginx)"
# Install certbot for SSL certificates
print_status "Checking certbot installation..."
ssh ns3-root "which certbot > /dev/null || (apt-get update && apt-get install -y certbot python3-certbot-nginx)"
# Copy nginx configuration
print_status "Copying nginx configuration..."
scp infra/nginx/nginx-aitbc-reverse-proxy.conf ns3-root:/tmp/aitbc-reverse-proxy.conf
# Backup existing nginx configuration
print_status "Backing up existing nginx configuration..."
ssh ns3-root "mkdir -p /etc/nginx/backup && cp -r /etc/nginx/sites-available/* /etc/nginx/backup/ 2>/dev/null || true"
# Install the new configuration
print_status "Installing nginx reverse proxy configuration..."
ssh ns3-root << 'EOF'
# Remove existing configurations
rm -f /etc/nginx/sites-enabled/default
rm -f /etc/nginx/sites-available/aitbc*
# Copy new configuration
cp /tmp/aitbc-reverse-proxy.conf /etc/nginx/sites-available/aitbc-reverse-proxy.conf
# Create symbolic link
ln -sf /etc/nginx/sites-available/aitbc-reverse-proxy.conf /etc/nginx/sites-enabled/
# Test nginx configuration
nginx -t
EOF
# Check if SSL certificate exists
print_status "Checking SSL certificate..."
if ! ssh ns3-root "test -f /etc/letsencrypt/live/aitbc.keisanki.net/fullchain.pem"; then
print_warning "SSL certificate not found. Obtaining Let's Encrypt certificate..."
# Obtain SSL certificate
ssh ns3-root << 'EOF'
# Stop nginx temporarily
systemctl stop nginx 2>/dev/null || true
# Obtain certificate
certbot certonly --standalone -d aitbc.keisanki.net -d api.aitbc.keisanki.net -d rpc.aitbc.keisanki.net --email admin@keisanki.net --agree-tos --non-interactive
# Start nginx
systemctl start nginx
EOF
if [ $? -ne 0 ]; then
print_error "Failed to obtain SSL certificate. Please run certbot manually:"
echo "certbot certonly --standalone -d aitbc.keisanki.net -d api.aitbc.keisanki.net -d rpc.aitbc.keisanki.net"
exit 1
fi
fi
# Restart nginx
print_status "Restarting nginx..."
ssh ns3-root "systemctl restart nginx && systemctl enable nginx"
# Remove old iptables rules (optional)
print_warning "Removing old iptables port forwarding rules (if they exist)..."
ssh ns3-root << 'EOF'
# Flush existing NAT rules for AITBC ports
iptables -t nat -D PREROUTING -p tcp --dport 8000 -j DNAT --to-destination 192.168.100.10:8000 2>/dev/null || true
iptables -t nat -D POSTROUTING -p tcp -d 192.168.100.10 --dport 8000 -j MASQUERADE 2>/dev/null || true
iptables -t nat -D PREROUTING -p tcp --dport 8081 -j DNAT --to-destination 192.168.100.10:8081 2>/dev/null || true
iptables -t nat -D POSTROUTING -p tcp -d 192.168.100.10 --dport 8081 -j MASQUERADE 2>/dev/null || true
iptables -t nat -D PREROUTING -p tcp --dport 8082 -j DNAT --to-destination 192.168.100.10:8082 2>/dev/null || true
iptables -t nat -D POSTROUTING -p tcp -d 192.168.100.10 --dport 8082 -j MASQUERADE 2>/dev/null || true
iptables -t nat -D PREROUTING -p tcp --dport 9080 -j DNAT --to-destination 192.168.100.10:9080 2>/dev/null || true
iptables -t nat -D POSTROUTING -p tcp -d 192.168.100.10 --dport 9080 -j MASQUERADE 2>/dev/null || true
iptables -t nat -D PREROUTING -p tcp --dport 3000 -j DNAT --to-destination 192.168.100.10:3000 2>/dev/null || true
iptables -t nat -D POSTROUTING -p tcp -d 192.168.100.10 --dport 3000 -j MASQUERADE 2>/dev/null || true
# Save iptables rules
iptables-save > /etc/iptables/rules.v4 2>/dev/null || true
EOF
# Wait for nginx to start
sleep 2
# Test the configuration
print_status "Testing reverse proxy configuration..."
echo ""
# Test main domain
if curl -s -o /dev/null -w "%{http_code}" https://aitbc.keisanki.net/health | grep -q "200"; then
print_status "✅ Main domain (aitbc.keisanki.net) - OK"
else
print_error "❌ Main domain (aitbc.keisanki.net) - FAILED"
fi
# Test API endpoint
if curl -s -o /dev/null -w "%{http_code}" https://aitbc.keisanki.net/api/health | grep -q "200"; then
print_status "✅ API endpoint - OK"
else
print_warning "⚠️ API endpoint - Not responding (service may not be running)"
fi
# Test RPC endpoint
if curl -s -o /dev/null -w "%{http_code}" https://aitbc.keisanki.net/rpc/head | grep -q "200"; then
print_status "✅ RPC endpoint - OK"
else
print_warning "⚠️ RPC endpoint - Not responding (blockchain node may not be running)"
fi
echo ""
print_status "🎉 Nginx reverse proxy deployment complete!"
echo ""
echo "Service URLs:"
echo " • Blockchain Explorer: https://aitbc.keisanki.net"
echo " • API: https://aitbc.keisanki.net/api/"
echo " • RPC: https://aitbc.keisanki.net/rpc/"
echo " • Exchange: https://aitbc.keisanki.net/exchange/"
echo ""
echo "Alternative URLs:"
echo " • API-only: https://api.aitbc.keisanki.net"
echo " • RPC-only: https://rpc.aitbc.keisanki.net"
echo ""
echo "Note: Make sure all services are running in the container:"
echo " • blockchain-explorer.service (port 3000)"
echo " • coordinator-api.service (port 8000)"
echo " • blockchain-rpc.service (port 8082)"
echo " • aitbc-exchange.service (port 9080)"

View File

@@ -0,0 +1,55 @@
#!/bin/bash
echo "🚀 Deploying AITBC for Production..."
# 1. Setup production assets
echo "📦 Setting up production assets..."
bash setup-production-assets.sh
# 2. Copy assets to server
echo "📋 Copying assets to server..."
scp -r assets/ aitbc:/var/www/html/
# 3. Update Nginx configuration
echo "⚙️ Updating Nginx configuration..."
ssh aitbc "cat >> /etc/nginx/sites-available/aitbc.conf << 'EOF'
# Serve production assets
location /assets/ {
alias /var/www/html/assets/;
expires 1y;
add_header Cache-Control \"public, immutable\";
add_header X-Content-Type-Options nosniff;
# Gzip compression
gzip on;
gzip_types text/css application/javascript image/svg+xml;
}
# Security headers
add_header Referrer-Policy \"strict-origin-when-cross-origin\" always;
add_header X-Frame-Options \"SAMEORIGIN\" always;
add_header X-Content-Type-Options \"nosniff\" always;
EOF"
# 4. Reload Nginx
echo "🔄 Reloading Nginx..."
ssh aitbc "nginx -t && systemctl reload nginx"
# 5. Update Exchange page to use production assets
echo "🔄 Updating Exchange page..."
scp apps/trade-exchange/index.prod.html aitbc:/root/aitbc/apps/trade-exchange/index.html
# 6. Update Marketplace page
echo "🔄 Updating Marketplace page..."
sed -i 's|https://cdn.tailwindcss.com|/assets/js/tailwind.js|g' apps/marketplace-ui/index.html
sed -i 's|https://unpkg.com/axios/dist/axios.min.js|/assets/js/axios.min.js|g' apps/marketplace-ui/index.html
sed -i 's|https://unpkg.com/lucide@latest|/assets/js/lucide.js|g' apps/marketplace-ui/index.html
scp apps/marketplace-ui/index.html aitbc:/root/aitbc/apps/marketplace-ui/
echo "✅ Production deployment complete!"
echo ""
echo "📝 Next steps:"
echo "1. Restart services: ssh aitbc 'systemctl restart aitbc-exchange aitbc-marketplace-ui'"
echo "2. Clear browser cache"
echo "3. Test all pages"

View File

@@ -0,0 +1,18 @@
#!/bin/bash
# Deploy blockchain node by building directly on ns3 server
echo "🚀 Remote Blockchain Deployment (Build on Server)"
echo "=============================================="
# Copy deployment script to server
echo "Copying deployment script to ns3..."
scp scripts/deploy/deploy-blockchain-remote.sh ns3-root:/opt/
# Execute deployment on server
echo "Executing deployment on ns3 (utilizing gigabit connection)..."
ssh ns3-root "cd /opt && chmod +x deploy-blockchain-remote.sh && ./deploy-blockchain-remote.sh"
echo ""
echo "Deployment complete!"
echo "The blockchain node was built directly on ns3 using its fast connection."

View File

@@ -0,0 +1,127 @@
#!/bin/bash
# Deploy a second blockchain node on the same server
set -e
echo "🚀 Deploying Second Blockchain Node"
echo "=================================="
# Colors
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
print_status() {
echo -e "${GREEN}[INFO]${NC} $1"
}
print_warning() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
# Create directory for second node
print_status "Creating directory for second node..."
NODE2_DIR="/opt/blockchain-node-2"
sudo mkdir -p $NODE2_DIR
sudo chown $USER:$USER $NODE2_DIR
# Copy blockchain node code
print_status "Copying blockchain node code..."
cp -r /opt/blockchain-node/* $NODE2_DIR/
# Create configuration for second node
print_status "Creating configuration for second node..."
cat > $NODE2_DIR/.env << EOF
CHAIN_ID=ait-devnet
DB_PATH=./data/chain2.db
RPC_BIND_HOST=127.0.0.1
RPC_BIND_PORT=8081
P2P_BIND_HOST=0.0.0.0
P2P_BIND_PORT=7071
PROPOSER_KEY=node2_proposer_key_$(date +%s)
MINT_PER_UNIT=1000
COORDINATOR_RATIO=0.05
GOSSIP_BACKEND=http
GOSSIP_BROADCAST_URL=http://127.0.0.1:7070/gossip
EOF
# Create data directory
mkdir -p $NODE2_DIR/data/devnet
# Generate genesis file (same as first node)
print_status "Generating genesis file..."
cd $NODE2_DIR
export PYTHONPATH="${NODE2_DIR}/src:${NODE2_DIR}/scripts:${PYTHONPATH:-}"
python3 scripts/make_genesis.py --output data/devnet/genesis.json --force
# Create systemd service
print_status "Creating systemd service..."
sudo cat > /etc/systemd/system/blockchain-node-2.service << EOF
[Unit]
Description=AITBC Blockchain Node 2
After=network.target
[Service]
Type=exec
User=root
WorkingDirectory=$NODE2_DIR
Environment=PATH=$NODE2_DIR/.venv/bin:/usr/local/bin:/usr/bin:/bin
Environment=PYTHONPATH=$NODE2_DIR/src:$NODE2_DIR/scripts
ExecStart=$NODE2_DIR/.venv/bin/python3 -m aitbc_chain.main
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
# Create RPC API service
print_status "Creating RPC API service..."
sudo cat > /etc/systemd/system/blockchain-rpc-2.service << EOF
[Unit]
Description=AITBC Blockchain RPC API 2
After=blockchain-node-2.service
[Service]
Type=exec
User=root
WorkingDirectory=$NODE2_DIR
Environment=PATH=$NODE2_DIR/.venv/bin:/usr/local/bin:/usr/bin:/bin
Environment=PYTHONPATH=$NODE2_DIR/src:$NODE2_DIR/scripts
ExecStart=$NODE2_DIR/.venv/bin/python3 -m uvicorn aitbc_chain.app:app --host 0.0.0.0 --port 8081
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
# Setup Python environment
print_status "Setting up Python environment..."
cd $NODE2_DIR
python3 -m venv .venv
source .venv/bin/activate
pip install --upgrade pip
pip install -e .
# Enable and start services
print_status "Enabling and starting services..."
sudo systemctl daemon-reload
sudo systemctl enable blockchain-node-2 blockchain-rpc-2
sudo systemctl start blockchain-node-2 blockchain-rpc-2
# Check status
print_status "Checking service status..."
sudo systemctl status blockchain-node-2 --no-pager -l
sudo systemctl status blockchain-rpc-2 --no-pager -l
echo ""
print_status "✅ Second blockchain node deployed!"
echo ""
echo "Node 1 RPC: http://127.0.0.1:8080"
echo "Node 2 RPC: http://127.0.0.1:8081"
echo ""
echo "To check logs:"
echo " Node 1: sudo journalctl -u blockchain-node -f"
echo " Node 2: sudo journalctl -u blockchain-node-2 -f"

View File

@@ -0,0 +1,84 @@
#!/bin/bash
# Deploy blockchain node inside incus container aitbc
set -e
echo "🚀 AITBC Deployment in Incus Container"
echo "======================================"
echo "This will deploy inside the aitbc container"
echo ""
# Colors
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
print_status() {
echo -e "${GREEN}[INFO]${NC} $1"
}
print_warning() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
# Check if we're on ns3 host
if [ "$(hostname)" != "ns3" ]; then
print_warning "This script must be run on ns3 host"
echo "Run: ssh ns3-root"
exit 1
fi
# Check if container exists
if ! incus list | grep -q "aitbc.*RUNNING"; then
print_warning "Container aitbc is not running"
exit 1
fi
# Copy source to container
print_status "Copying source code to container..."
incus exec aitbc -- rm -rf /opt/blockchain-node-src 2>/dev/null || true
incus exec aitbc -- mkdir -p /opt/blockchain-node-src
# Use the source already on the server
incus file push -r /opt/blockchain-node-src/. aitbc/opt/blockchain-node-src/
# Fix the nested directory issue - move everything up one level
incus exec aitbc -- sh -c 'if [ -d /opt/blockchain-node-src/blockchain-node-src ]; then mv /opt/blockchain-node-src/blockchain-node-src/* /opt/blockchain-node-src/ && rmdir /opt/blockchain-node-src/blockchain-node-src; fi'
# Copy deployment script to container
print_status "Copying deployment script to container..."
incus file push /opt/deploy-in-container.sh aitbc/opt/
# Execute deployment inside container
print_status "Deploying inside container..."
incus exec aitbc -- bash /opt/deploy-in-container.sh
# Setup port forwarding on host
print_status "Setting up port forwarding on host..."
iptables -t nat -F PREROUTING 2>/dev/null || true
iptables -t nat -F POSTROUTING 2>/dev/null || true
# Forward blockchain RPC
iptables -t nat -A PREROUTING -p tcp --dport 8082 -j DNAT --to-destination 192.168.100.10:8082
iptables -t nat -A POSTROUTING -p tcp -d 192.168.100.10 --dport 8082 -j MASQUERADE
# Forward explorer
iptables -t nat -A PREROUTING -p tcp --dport 3000 -j DNAT --to-destination 192.168.100.10:3000
iptables -t nat -A POSTROUTING -p tcp -d 192.168.100.10 --dport 3000 -j MASQUERADE
# Save rules
mkdir -p /etc/iptables
iptables-save > /etc/iptables/rules.v4
# Check services
print_status "Checking services in container..."
incus exec aitbc -- systemctl status blockchain-node blockchain-rpc nginx --no-pager | grep -E 'Active:|Main PID:'
print_success "✅ Deployment complete!"
echo ""
echo "Services in container aitbc:"
echo " - Blockchain Node RPC: http://192.168.100.10:8082"
echo " - Blockchain Explorer: http://192.168.100.10:3000"
echo ""
echo "External access via ns3:"
echo " - Blockchain Node RPC: http://aitbc.keisanki.net:8082"
echo " - Blockchain Explorer: http://aitbc.keisanki.net:3000"

View File

@@ -0,0 +1,253 @@
#!/bin/bash
# AITBC Services Deployment to Incus Container
# This script deploys all AITBC services to the 'aitbc' container
set -e
CONTAINER_NAME="aitbc"
CONTAINER_IP="10.1.223.93"
PROJECT_DIR="/home/oib/windsurf/aitbc"
echo "🚀 Deploying AITBC services to container: $CONTAINER_NAME"
echo "Container IP: $CONTAINER_IP"
echo ""
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# Function to print colored output
print_status() {
echo -e "${GREEN}[INFO]${NC} $1"
}
print_warning() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
print_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
# Stop local services
print_status "Stopping local AITBC services..."
sudo fuser -k 8000/tcp 2>/dev/null || true
sudo fuser -k 9080/tcp 2>/dev/null || true
sudo fuser -k 3001/tcp 2>/dev/null || true
sudo fuser -k 3002/tcp 2>/dev/null || true
pkill -f "aitbc_chain.app" 2>/dev/null || true
pkill -f "marketplace-ui" 2>/dev/null || true
pkill -f "trade-exchange" 2>/dev/null || true
# Copy project to container
print_status "Copying AITBC project to container..."
incus file push -r $PROJECT_DIR $CONTAINER_NAME/home/oib/
# Setup container environment
print_status "Setting up container environment..."
incus exec $CONTAINER_NAME -- bash -c "
cd /home/oib/aitbc
python -m venv .venv
source .venv/bin/activate
pip install --upgrade pip
"
# Install dependencies for each service
print_status "Installing dependencies..."
# Coordinator API
print_status "Installing Coordinator API dependencies..."
incus exec $CONTAINER_NAME -- bash -c "
cd /home/oib/aitbc/apps/coordinator-api
source ../.venv/bin/activate
pip install -e .
pip install fastapi uvicorn
"
# Blockchain Node
print_status "Installing Blockchain Node dependencies..."
incus exec $CONTAINER_NAME -- bash -c "
cd /home/oib/aitbc/apps/blockchain-node
source ../.venv/bin/activate
pip install -e .
pip install fastapi uvicorn
"
# Create systemd service files
print_status "Creating systemd services..."
# Coordinator API service
incus exec $CONTAINER_NAME -- tee /etc/systemd/system/aitbc-coordinator.service > /dev/null <<EOF
[Unit]
Description=AITBC Coordinator API
After=network.target
[Service]
Type=exec
User=oib
Group=oib
WorkingDirectory=/home/oib/aitbc/apps/coordinator-api
Environment=PATH=/home/oib/aitbc/.venv/bin
ExecStart=/home/oib/aitbc/.venv/bin/python -m uvicorn src.app.main:app --host 0.0.0.0 --port 8000
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
EOF
# Blockchain Node service
incus exec $CONTAINER_NAME -- tee /etc/systemd/system/aitbc-blockchain.service > /dev/null <<EOF
[Unit]
Description=AITBC Blockchain Node
After=network.target
[Service]
Type=exec
User=oib
Group=oib
WorkingDirectory=/home/oib/aitbc/apps/blockchain-node
Environment=PATH=/home/oib/aitbc/.venv/bin
ExecStart=/home/oib/aitbc/.venv/bin/python -m uvicorn aitbc_chain.app:app --host 0.0.0.0 --port 9080
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
EOF
# Marketplace UI service
incus exec $CONTAINER_NAME -- tee /etc/systemd/system/aitbc-marketplace.service > /dev/null <<EOF
[Unit]
Description=AITBC Marketplace UI
After=network.target
[Service]
Type=exec
User=oib
Group=oib
WorkingDirectory=/home/oib/aitbc/apps/marketplace-ui
Environment=PATH=/home/oib/aitbc/.venv/bin
ExecStart=/home/oib/aitbc/.venv/bin/python server.py --port 3001
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
EOF
# Trade Exchange service
incus exec $CONTAINER_NAME -- tee /etc/systemd/system/aitbc-exchange.service > /dev/null <<EOF
[Unit]
Description=AITBC Trade Exchange
After=network.target
[Service]
Type=exec
User=oib
Group=oib
WorkingDirectory=/home/oib/aitbc/apps/trade-exchange
Environment=PATH=/home/oib/aitbc/.venv/bin
ExecStart=/home/oib/aitbc/.venv/bin/python server.py --port 3002
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
EOF
# Reload systemd and start services
print_status "Starting AITBC services..."
incus exec $CONTAINER_NAME -- systemctl daemon-reload
incus exec $CONTAINER_NAME -- systemctl enable aitbc-coordinator
incus exec $CONTAINER_NAME -- systemctl enable aitbc-blockchain
incus exec $CONTAINER_NAME -- systemctl enable aitbc-marketplace
incus exec $CONTAINER_NAME -- systemctl enable aitbc-exchange
incus exec $CONTAINER_NAME -- systemctl start aitbc-coordinator
incus exec $CONTAINER_NAME -- systemctl start aitbc-blockchain
incus exec $CONTAINER_NAME -- systemctl start aitbc-marketplace
incus exec $CONTAINER_NAME -- systemctl start aitbc-exchange
# Wait for services to start
print_status "Waiting for services to start..."
sleep 10
# Check service status
print_status "Checking service status..."
incus exec $CONTAINER_NAME -- systemctl status aitbc-coordinator --no-pager -l
incus exec $CONTAINER_NAME -- systemctl status aitbc-blockchain --no-pager -l
incus exec $CONTAINER_NAME -- systemctl status aitbc-marketplace --no-pager -l
incus exec $CONTAINER_NAME -- systemctl status aitbc-exchange --no-pager -l
# Create nginx configuration for reverse proxy
print_status "Setting up Nginx reverse proxy..."
incus exec $CONTAINER_NAME -- tee /etc/nginx/sites-available/aitbc > /dev/null <<EOF
server {
listen 80;
server_name _;
# Coordinator API
location /api/ {
proxy_pass http://127.0.0.1:8000/v1/;
proxy_set_header Host \$host;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto \$scheme;
}
# Blockchain RPC
location /rpc/ {
proxy_pass http://127.0.0.1:9080/rpc/;
proxy_set_header Host \$host;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto \$scheme;
}
# Marketplace UI
location /marketplace/ {
proxy_pass http://127.0.0.1:3001/;
proxy_set_header Host \$host;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto \$scheme;
}
# Trade Exchange
location /exchange/ {
proxy_pass http://127.0.0.1:3002/;
proxy_set_header Host \$host;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto \$scheme;
}
# Default redirect to marketplace
location / {
return 301 /marketplace/;
}
}
EOF
# Enable nginx site
incus exec $CONTAINER_NAME -- ln -sf /etc/nginx/sites-available/aitbc /etc/nginx/sites-enabled/
incus exec $CONTAINER_NAME -- rm -f /etc/nginx/sites-enabled/default
incus exec $CONTAINER_NAME -- nginx -t && incus exec $CONTAINER_NAME -- systemctl reload nginx
# Print access information
echo ""
print_status "✅ AITBC services deployed successfully!"
echo ""
echo "📋 Service URLs:"
echo " 🌐 Public IP: $CONTAINER_IP"
echo " 📊 Marketplace: http://$CONTAINER_IP/marketplace/"
echo " 💱 Trade Exchange: http://$CONTAINER_IP/exchange/"
echo " 🔗 API: http://$CONTAINER_IP/api/"
echo " ⛓️ Blockchain RPC: http://$CONTAINER_IP/rpc/"
echo ""
print_status "To check logs: incus exec $CONTAINER_NAME -- journalctl -u aitbc-coordinator -f"
print_status "To restart services: incus exec $CONTAINER_NAME -- systemctl restart aitbc-*"

View File

@@ -0,0 +1,50 @@
#!/bin/bash
# AITBC Services Deployment to Container
# Copy to deploy-to-container.sh and adjust variables for your environment
set -e
# === CONFIGURE THESE ===
CONTAINER_NAME="aitbc"
CONTAINER_IP="YOUR_CONTAINER_IP"
PROJECT_DIR="/path/to/your/aitbc"
SSH_ALIAS="your-ssh-alias" # or user@host
echo "🚀 Deploying AITBC services to container: $CONTAINER_NAME"
echo "Container IP: $CONTAINER_IP"
echo ""
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
# 1. Push website
echo -e "${YELLOW}Deploying website...${NC}"
scp -r "$PROJECT_DIR/website/index.html" "$PROJECT_DIR/website/404.html" \
"$SSH_ALIAS:/var/www/html/"
scp -r "$PROJECT_DIR/website/docs/"*.html "$SSH_ALIAS:/var/www/html/docs/"
scp "$PROJECT_DIR/website/docs/css/docs.css" "$SSH_ALIAS:/var/www/html/docs/css/"
scp "$PROJECT_DIR/website/docs/js/theme.js" "$SSH_ALIAS:/var/www/html/docs/js/"
echo -e "${GREEN}✓ Website deployed${NC}"
# 2. Deploy coordinator API
echo -e "${YELLOW}Deploying coordinator API...${NC}"
ssh "$SSH_ALIAS" "cd /opt/aitbc && pip install -e apps/coordinator-api/"
ssh "$SSH_ALIAS" "systemctl restart aitbc-coordinator"
echo -e "${GREEN}✓ Coordinator deployed${NC}"
# 3. Deploy blockchain node
echo -e "${YELLOW}Deploying blockchain node...${NC}"
ssh "$SSH_ALIAS" "cd /opt/aitbc && pip install -e apps/blockchain-node/"
ssh "$SSH_ALIAS" "systemctl restart aitbc-blockchain"
echo -e "${GREEN}✓ Blockchain node deployed${NC}"
# 4. Verify
echo ""
echo -e "${YELLOW}Verifying services...${NC}"
ssh "$SSH_ALIAS" "curl -s http://127.0.0.1:8000/v1/health | head -1"
ssh "$SSH_ALIAS" "curl -s http://127.0.0.1:9080/rpc/health | head -1"
echo -e "${GREEN}✓ All services running${NC}"

View File

@@ -0,0 +1,241 @@
#!/bin/bash
# Deploy AITBC services to the aitbc server (10.1.223.93)
set -e
SERVER="root@10.1.223.93"
PROJECT_DIR="/root/aitbc"
echo "🚀 Deploying AITBC to Server"
echo "=========================="
echo "Server: $SERVER"
echo ""
# Colors
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
print_status() {
echo -e "${GREEN}[INFO]${NC} $1"
}
print_warning() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
# Test SSH connection
print_status "Testing SSH connection..."
ssh $SERVER "hostname && ip a show eth0 | grep inet"
# Copy project to server
print_status "Copying project to server..."
ssh $SERVER "rm -rf $PROJECT_DIR 2>/dev/null || true"
scp -r /home/oib/windsurf/aitbc $SERVER:/root/
# Setup Python environment
print_status "Setting up Python environment..."
ssh $SERVER "cd $PROJECT_DIR && python3 -m venv .venv && source .venv/bin/activate && pip install --upgrade pip"
# Install dependencies
print_status "Installing dependencies..."
ssh $SERVER "cd $PROJECT_DIR/apps/coordinator-api && source ../../.venv/bin/activate && pip install -e ."
ssh $SERVER "cd $PROJECT_DIR/apps/blockchain-node && source ../../.venv/bin/activate && pip install -e ."
# Create systemd service files
print_status "Creating systemd services..."
# Coordinator API service
ssh $SERVER 'cat > /etc/systemd/system/aitbc-coordinator.service << EOF
[Unit]
Description=AITBC Coordinator API
After=network.target
[Service]
Type=exec
User=root
WorkingDirectory=/root/aitbc/apps/coordinator-api
Environment=PATH=/root/aitbc/.venv/bin
ExecStart=/root/aitbc/.venv/bin/python -m uvicorn src.app.main:app --host 0.0.0.0 --port 8000
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
EOF'
# Blockchain Node service
ssh $SERVER 'cat > /etc/systemd/system/aitbc-blockchain.service << EOF
[Unit]
Description=AITBC Blockchain Node
After=network.target
[Service]
Type=exec
User=root
WorkingDirectory=/root/aitbc/apps/blockchain-node
Environment=PATH=/root/aitbc/.venv/bin
ExecStart=/root/aitbc/.venv/bin/python -m uvicorn aitbc_chain.app:app --host 0.0.0.0 --port 9080
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
EOF'
# Marketplace UI service
ssh $SERVER 'cat > /etc/systemd/system/aitbc-marketplace.service << EOF
[Unit]
Description=AITBC Marketplace UI
After=network.target
[Service]
Type=exec
User=root
WorkingDirectory=/root/aitbc/apps/marketplace-ui
Environment=PATH=/root/aitbc/.venv/bin
ExecStart=/root/aitbc/.venv/bin/python server.py --port 3001
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
EOF'
# Trade Exchange service
ssh $SERVER 'cat > /etc/systemd/system/aitbc-exchange.service << EOF
[Unit]
Description=AITBC Trade Exchange
After=network.target
[Service]
Type=exec
User=root
WorkingDirectory=/root/aitbc/apps/trade-exchange
Environment=PATH=/root/aitbc/.venv/bin
ExecStart=/root/aitbc/.venv/bin/python server.py --port 3002
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
EOF'
# Install nginx if not installed
print_status "Installing nginx..."
ssh $SERVER "apt update && apt install -y nginx"
# Create nginx configuration
print_status "Configuring nginx..."
ssh $SERVER 'cat > /etc/nginx/sites-available/aitbc << EOF
server {
listen 80;
server_name aitbc.bubuit.net;
# API routes
location /api/ {
proxy_pass http://127.0.0.1:8000/v1/;
proxy_set_header Host \$host;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto \$scheme;
}
# Admin routes
location /admin/ {
proxy_pass http://127.0.0.1:8000/admin/;
proxy_set_header Host \$host;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto \$scheme;
}
# Blockchain RPC
location /rpc/ {
proxy_pass http://127.0.0.1:9080/rpc/;
proxy_set_header Host \$host;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto \$scheme;
}
# Marketplace UI
location /Marketplace {
proxy_pass http://127.0.0.1:3001/;
proxy_set_header Host \$host;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto \$scheme;
}
# Trade Exchange
location /Exchange {
proxy_pass http://127.0.0.1:3002/;
proxy_set_header Host \$host;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto \$scheme;
}
# Health endpoint
location /health {
proxy_pass http://127.0.0.1:8000/v1/health;
proxy_set_header Host \$host;
}
# Default redirect
location / {
return 301 /Marketplace;
}
}
EOF'
# Enable nginx site
ssh $SERVER "ln -sf /etc/nginx/sites-available/aitbc /etc/nginx/sites-enabled/"
ssh $SERVER "rm -f /etc/nginx/sites-enabled/default"
# Test and reload nginx
ssh $SERVER "nginx -t && systemctl reload nginx"
# Start services
print_status "Starting AITBC services..."
ssh $SERVER "systemctl daemon-reload"
ssh $SERVER "systemctl enable aitbc-coordinator aitbc-blockchain aitbc-marketplace aitbc-exchange"
ssh $SERVER "systemctl start aitbc-coordinator aitbc-blockchain aitbc-marketplace aitbc-exchange"
# Wait for services to start
print_status "Waiting for services to start..."
sleep 10
# Check service status
print_status "Checking service status..."
ssh $SERVER "systemctl status aitbc-coordinator --no-pager -l | head -10"
ssh $SERVER "systemctl status aitbc-blockchain --no-pager -l | head -10"
# Test endpoints
print_status "Testing endpoints..."
ssh $SERVER "curl -s http://127.0.0.1:8000/v1/health | head -c 100"
echo ""
ssh $SERVER "curl -s http://127.0.0.1:8000/v1/admin/stats -H 'X-Api-Key: ${ADMIN_API_KEY}' | head -c 100"
echo ""
echo ""
print_status "✅ Deployment complete!"
echo ""
echo "📋 Service URLs:"
echo " 🌐 Server IP: 10.1.223.93"
echo " 📊 Marketplace: http://10.1.223.93/Marketplace"
echo " 💱 Trade Exchange: http://10.1.223.93/Exchange"
echo " 🔗 API: http://10.1.223.93/api"
echo " ⛓️ Blockchain RPC: http://10.1.223.93/rpc"
echo ""
echo "🔒 Domain URLs (with SSL):"
echo " 📊 Marketplace: https://aitbc.bubuit.net/Marketplace"
echo " 💱 Trade Exchange: https://aitbc.bubuit.net/Exchange"
echo " 🔗 API: https://aitbc.bubuit.net/api"
echo " ⛓️ Blockchain RPC: https://aitbc.bubuit.net/rpc"
echo ""
print_status "To manage services:"
echo " ssh aitbc 'systemctl status aitbc-coordinator'"
echo " ssh aitbc 'journalctl -u aitbc-coordinator -f'"

View File

@@ -0,0 +1,158 @@
#!/usr/bin/env python3
"""
Deploy AITBC services to incus container with GPU miner integration
"""
import subprocess
import time
import sys
def run_command(cmd, container=None):
"""Run command locally or in container"""
if container:
cmd = f"incus exec {container} -- {cmd}"
print(f"Running: {cmd}")
result = subprocess.run(cmd, shell=True, capture_output=True, text=True)
if result.returncode != 0:
print(f"Error: {result.stderr}")
return False
return True
def deploy_to_container():
container = "aitbc"
container_ip = "10.1.223.93"
print("🚀 Deploying AITBC services to container with GPU miner...")
# Check if container exists
result = subprocess.run("incus list -c n", shell=True, capture_output=True, text=True)
if container not in result.stdout:
print(f"\n📦 Creating container {container}...")
subprocess.run(f"incus launch images:ubuntu/22.04 {container}", shell=True)
time.sleep(10)
# Ensure container is running
subprocess.run(f"incus start {container}", shell=True)
time.sleep(5)
# Update and install packages in container
print("\n📦 Installing packages in container...")
run_command("apt-get update", container)
run_command("apt-get install -y python3 python3-pip python3-venv curl", container)
# Stop local services
print("\n📋 Stopping local services...")
subprocess.run("sudo fuser -k 8000/tcp 2>/dev/null || true", shell=True)
subprocess.run("sudo fuser -k 9080/tcp 2>/dev/null || true", shell=True)
subprocess.run("pkill -f 'marketplace-ui' 2>/dev/null || true", shell=True)
subprocess.run("pkill -f 'trade-exchange' 2>/dev/null || true", shell=True)
# Copy project to container
print("\n📁 Copying project to container...")
subprocess.run(f"incus file push -r /home/oib/windsurf/aitbc {container}/home/oib/", shell=True)
# Setup Python environment in container
print("\n🐍 Setting up Python environment...")
run_command("cd /home/oib/aitbc && python3 -m venv .venv", container)
run_command("cd /home/oib/aitbc && source .venv/bin/activate && pip install fastapi uvicorn httpx sqlmodel psutil", container)
# Install dependencies
print("\n📦 Installing dependencies...")
run_command("cd /home/oib/aitbc/apps/coordinator-api && source ../../.venv/bin/activate && pip install -e .", container)
run_command("cd /home/oib/aitbc/apps/blockchain-node && source ../../.venv/bin/activate && pip install -e .", container)
# Create startup script with GPU miner
print("\n🔧 Creating startup script with GPU miner...")
startup_script = """#!/bin/bash
cd /home/oib/aitbc
source .venv/bin/activate
# Start coordinator API
echo "Starting Coordinator API..."
cd apps/coordinator-api
source ../../.venv/bin/activate
python -m uvicorn app.main:app --host 0.0.0.0 --port 8000 &
COORD_PID=$!
# Start blockchain node
echo "Starting Blockchain Node..."
cd ../../apps/blockchain-node
source ../../.venv/bin/activate
python -m uvicorn aitbc_chain.app:app --host 0.0.0.0 --port 9080 &
BLOCK_PID=$!
# Start trade exchange
echo "Starting Trade Exchange..."
cd ../../apps/trade-exchange
source ../../.venv/bin/activate
python simple_exchange_api.py &
EXCHANGE_PID=$!
# Start GPU registry
echo "Starting GPU Registry..."
cd ../..
python gpu_registry_demo.py &
REGISTRY_PID=$!
# Start GPU miner
echo "Starting GPU Miner..."
python gpu_miner_with_wait.py &
MINER_PID=$!
echo "All services started!"
echo "Coordinator API: http://10.1.223.93:8000"
echo "Blockchain RPC: http://10.1.223.93:9080"
echo "Trade Exchange: http://10.1.223.93:3002"
echo "GPU Registry: http://10.1.223.93:8091"
# Wait for services
wait $COORD_PID $BLOCK_PID $EXCHANGE_PID $REGISTRY_PID $MINER_PID
"""
# Write startup script to container
with open('/tmp/startup.sh', 'w') as f:
f.write(startup_script)
subprocess.run(f"incus file push /tmp/startup.sh {container}/home/oib/aitbc/", shell=True)
run_command("chmod +x /home/oib/aitbc/startup.sh", container)
# Create systemd service
print("\n⚙️ Creating systemd service...")
service_content = """[Unit]
Description=AITBC Services with GPU Miner
After=network.target
[Service]
Type=simple
User=oib
WorkingDirectory=/home/oib/aitbc
ExecStart=/home/oib/aitbc/startup.sh
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
"""
with open('/tmp/aitbc.service', 'w') as f:
f.write(service_content)
subprocess.run(f"incus file push /tmp/aitbc.service {container}/tmp/", shell=True)
run_command("mv /tmp/aitbc.service /etc/systemd/system/", container)
run_command("systemctl daemon-reload", container)
run_command("systemctl enable aitbc.service", container)
run_command("systemctl start aitbc.service", container)
print("\n✅ Deployment complete!")
print(f"\n📊 Service URLs:")
print(f" - Coordinator API: http://{container_ip}:8000")
print(f" - Blockchain RPC: http://{container_ip}:9080")
print(f" - Trade Exchange: http://{container_ip}:3002")
print(f" - GPU Registry: http://{container_ip}:8091")
print(f"\n🔍 Check GPU status:")
print(f" curl http://{container_ip}:8091/miners/list")
print(f"\n📋 To manage services in container:")
print(f" incus exec {container} -- systemctl status aitbc")
print(f" incus exec {container} -- journalctl -u aitbc -f")
if __name__ == "__main__":
deploy_to_container()

View File

@@ -0,0 +1,130 @@
#!/usr/bin/env python3
"""
Deploy GPU Miner Integration to AITBC Container
"""
import subprocess
import sys
def run_in_container(cmd):
"""Run command in aitbc container"""
full_cmd = f"incus exec aitbc -- {cmd}"
print(f"Running: {full_cmd}")
result = subprocess.run(full_cmd, shell=True, capture_output=True, text=True)
if result.returncode != 0:
print(f"Error: {result.stderr}")
return False, result.stderr
return True, result.stdout
def deploy_gpu_miner_to_container():
print("🚀 Deploying GPU Miner Integration to AITBC Container...")
# Check container access
print("\n1. 🔍 Checking container access...")
success, output = run_in_container("whoami")
if success:
print(f" Container user: {output.strip()}")
else:
print(" ❌ Cannot access container")
return
# Copy GPU miner files to container
print("\n2. 📁 Copying GPU miner files...")
files_to_copy = [
"gpu_miner_with_wait.py",
"gpu_registry_demo.py"
]
for file in files_to_copy:
cmd = f"incus file push /home/oib/windsurf/aitbc/{file} aitbc/home/oib/"
print(f" Copying {file}...")
result = subprocess.run(cmd, shell=True)
if result.returncode == 0:
print(f"{file} copied")
else:
print(f" ❌ Failed to copy {file}")
# Install dependencies in container
print("\n3. 📦 Installing dependencies...")
run_in_container("pip install httpx fastapi uvicorn psutil")
# Create GPU miner service in container
print("\n4. ⚙️ Creating GPU miner service...")
service_content = """[Unit]
Description=AITBC GPU Miner Client
After=network.target
[Service]
Type=simple
User=oib
WorkingDirectory=/home/oib
ExecStart=/usr/bin/python3 gpu_miner_with_wait.py
Restart=always
RestartSec=30
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
"""
# Write service file to container
with open('/tmp/gpu-miner.service', 'w') as f:
f.write(service_content)
subprocess.run("incus file push /tmp/gpu-miner.service aitbc/tmp/", shell=True)
run_in_container("sudo mv /tmp/gpu-miner.service /etc/systemd/system/")
run_in_container("sudo systemctl daemon-reload")
run_in_container("sudo systemctl enable gpu-miner.service")
run_in_container("sudo systemctl start gpu-miner.service")
# Create GPU registry service in container
print("\n5. 🎮 Creating GPU registry service...")
registry_service = """[Unit]
Description=AITBC GPU Registry
After=network.target
[Service]
Type=simple
User=oib
WorkingDirectory=/home/oib
ExecStart=/usr/bin/python3 gpu_registry_demo.py
Restart=always
RestartSec=10
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
"""
with open('/tmp/gpu-registry.service', 'w') as f:
f.write(registry_service)
subprocess.run("incus file push /tmp/gpu-registry.service aitbc/tmp/", shell=True)
run_in_container("sudo mv /tmp/gpu-registry.service /etc/systemd/system/")
run_in_container("sudo systemctl daemon-reload")
run_in_container("sudo systemctl enable gpu-registry.service")
run_in_container("sudo systemctl start gpu-registry.service")
# Check services
print("\n6. 📊 Checking services...")
success, output = run_in_container("sudo systemctl status gpu-miner.service --no-pager")
print(output)
success, output = run_in_container("sudo systemctl status gpu-registry.service --no-pager")
print(output)
# Update coordinator to include miner endpoints
print("\n7. 🔗 Updating coordinator API...")
print("\n✅ GPU Miner deployed to container!")
print("\n📊 Access URLs:")
print(" - Container IP: 10.1.223.93")
print(" - GPU Registry: http://10.1.223.93:8091/miners/list")
print(" - Coordinator API: http://10.1.223.93:8000")
print("\n🔧 To manage services in container:")
print(" incus exec aitbc -- sudo systemctl status gpu-miner")
print(" incus exec aitbc -- sudo journalctl -u gpu-miner -f")
if __name__ == "__main__":
deploy_gpu_miner_to_container()

View File

@@ -0,0 +1,113 @@
#!/bin/bash
# Setup gossip relay to connect blockchain nodes
set -e
echo "🌐 Setting up Gossip Relay for Blockchain Nodes"
echo "=============================================="
# Colors
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
print_status() {
echo -e "${GREEN}[INFO]${NC} $1"
}
print_warning() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
# Stop existing nodes
print_status "Stopping blockchain nodes..."
sudo systemctl stop blockchain-node blockchain-node-2 blockchain-rpc blockchain-rpc-2 2>/dev/null || true
# Update node configurations to use broadcast backend
print_status "Updating Node 1 configuration..."
sudo cat > /opt/blockchain-node/.env << EOF
CHAIN_ID=ait-devnet
DB_PATH=./data/chain.db
RPC_BIND_HOST=127.0.0.1
RPC_BIND_PORT=8082
P2P_BIND_HOST=0.0.0.0
P2P_BIND_PORT=7070
PROPOSER_KEY=node1_proposer_key_$(date +%s)
MINT_PER_UNIT=1000
COORDINATOR_RATIO=0.05
GOSSIP_BACKEND=broadcast
GOSSIP_BROADCAST_URL=http://127.0.0.1:7070/gossip
EOF
print_status "Updating Node 2 configuration..."
sudo cat > /opt/blockchain-node-2/.env << EOF
CHAIN_ID=ait-devnet
DB_PATH=./data/chain2.db
RPC_BIND_HOST=127.0.0.1
RPC_BIND_PORT=8081
P2P_BIND_HOST=0.0.0.0
P2P_BIND_PORT=7071
PROPOSER_KEY=node2_proposer_key_$(date +%s)
MINT_PER_UNIT=1000
COORDINATOR_RATIO=0.05
GOSSIP_BACKEND=broadcast
GOSSIP_BROADCAST_URL=http://127.0.0.1:7070/gossip
EOF
# Create gossip relay service
print_status "Creating gossip relay service..."
sudo cat > /etc/systemd/system/blockchain-gossip-relay.service << EOF
[Unit]
Description=AITBC Blockchain Gossip Relay
After=network.target
[Service]
Type=exec
User=root
WorkingDirectory=/opt/blockchain-node
Environment=PATH=/opt/blockchain-node/.venv/bin:/usr/local/bin:/usr/bin:/bin
Environment=PYTHONPATH=/opt/blockchain-node/src:/opt/blockchain-node/scripts
ExecStart=/opt/blockchain-node/.venv/bin/python3 -m aitbc_chain.gossip.relay --port 7070 --host 0.0.0.0
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
# Enable and start gossip relay
print_status "Starting gossip relay..."
sudo systemctl daemon-reload
sudo systemctl enable blockchain-gossip-relay
sudo systemctl start blockchain-gossip-relay
# Wait for relay to start
sleep 2
# Check if relay is running
print_status "Checking gossip relay status..."
sudo systemctl status blockchain-gossip-relay --no-pager | head -10
# Restart blockchain nodes
print_status "Restarting blockchain nodes with shared gossip..."
sudo systemctl start blockchain-node blockchain-node-2 blockchain-rpc blockchain-rpc-2
# Wait for nodes to start
sleep 3
# Check status
print_status "Checking node status..."
sudo systemctl status blockchain-node blockchain-node-2 --no-pager | grep -E 'Active:|Main PID:'
echo ""
print_status "✅ Gossip relay setup complete!"
echo ""
echo "Nodes are now connected via shared gossip backend."
echo "They should sync blocks and transactions."
echo ""
echo "To verify connectivity:"
echo " 1. Run: python /opt/test_blockchain_simple.py"
echo " 2. Check if heights are converging"
echo ""
echo "Gossip relay logs: sudo journalctl -u blockchain-gossip-relay -f"

View File

@@ -0,0 +1,40 @@
#!/bin/bash
# Test if blockchain node and explorer are running
echo "🔍 Testing Blockchain Deployment"
echo "==============================="
# Test blockchain RPC
echo "Testing blockchain RPC..."
if curl -s http://aitbc.keisanki.net:8082/rpc/head > /dev/null; then
echo "✅ Blockchain RPC is accessible"
curl -s http://aitbc.keisanki.net:8082/rpc/head | jq '.height'
else
echo "❌ Blockchain RPC is not accessible"
fi
# Test explorer
echo ""
echo "Testing blockchain explorer..."
if curl -s http://aitbc.keisanki.net:3000 > /dev/null; then
echo "✅ Explorer is accessible"
else
echo "❌ Explorer is not accessible"
fi
# Check services on server
echo ""
echo "Checking service status on ns3..."
ssh ns3-root "systemctl is-active blockchain-node blockchain-rpc nginx" | while read service status; do
if [ "$status" = "active" ]; then
echo "$service is running"
else
echo "$service is not running"
fi
done
# Check logs if needed
echo ""
echo "Recent blockchain logs:"
ssh ns3-root "journalctl -u blockchain-node -n 5 --no-pager"