agenthub/scripts/bootstrap.sh
Paperclip FoundingEngineer bdd5d92ba7 Initial AgentHub codebase for Coolify deployment
Complete implementation ready for Coolify:
- Node.js 22 + Fastify + socket.io backend
- PostgreSQL 16 + Redis 7 services
- Docker Compose configuration
- Deployment scripts and documentation

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-05-01 21:25:57 +00:00

232 lines
11 KiB
Bash
Executable file

#!/usr/bin/env bash
set -euo pipefail
# AgentHub Bootstrap Script — J10 Phase 1 LAN Deployment
# Idempotent setup for Ubuntu 22.04/24.04 LTS
# Target: < 15 min from bare metal to running stack
AGENTHUB_USER="agenthub"
AGENTHUB_UID=1001
AGENTHUB_HOME="/opt/agenthub"
AGENTHUB_REPO="https://forgejo.barodine.net/barodine/agenthub.git"
AGENTHUB_BRANCH="${AGENTHUB_BRANCH:-main}"
echo "╔════════════════════════════════════════════════════╗"
echo "║ AgentHub Bootstrap — Phase 1 LAN Deployment ║"
echo "╚════════════════════════════════════════════════════╝"
echo ""
# Require root or sudo
if [[ $EUID -ne 0 ]]; then
echo "❌ This script must be run as root (use sudo)"
exit 1
fi
# ─────────────────────────────────────────────────────────
# Step 1 — System Update
# ─────────────────────────────────────────────────────────
echo "[1/10] Updating system packages..."
export DEBIAN_FRONTEND=noninteractive
apt-get update -qq
apt-get upgrade -y -qq
echo "✅ System updated"
echo ""
# ─────────────────────────────────────────────────────────
# Step 2 — Unattended Upgrades
# ─────────────────────────────────────────────────────────
echo "[2/10] Enabling unattended-upgrades..."
apt-get install -y -qq unattended-upgrades
# Configure automatic security updates
if [[ ! -f /etc/apt/apt.conf.d/20auto-upgrades ]]; then
cat > /etc/apt/apt.conf.d/20auto-upgrades <<'EOF'
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Download-Upgradeable-Packages "1";
APT::Periodic::AutocleanInterval "7";
APT::Periodic::Unattended-Upgrade "1";
EOF
fi
systemctl enable --now unattended-upgrades
echo "✅ Unattended upgrades enabled"
echo ""
# ─────────────────────────────────────────────────────────
# Step 3 — Create agenthub user (UID 1001)
# ─────────────────────────────────────────────────────────
echo "[3/10] Creating agenthub user (UID ${AGENTHUB_UID})..."
if id "${AGENTHUB_USER}" &>/dev/null; then
echo " User ${AGENTHUB_USER} already exists, skipping"
else
useradd --system --uid "${AGENTHUB_UID}" --shell /bin/bash --create-home "${AGENTHUB_USER}"
echo "✅ User ${AGENTHUB_USER} created"
fi
echo ""
# ─────────────────────────────────────────────────────────
# Step 4 — Install Docker Engine + Compose v2
# ─────────────────────────────────────────────────────────
echo "[4/10] Installing Docker Engine + Compose v2..."
if command -v docker &>/dev/null; then
echo " Docker already installed: $(docker --version)"
else
# Install prerequisites
apt-get install -y -qq \
ca-certificates \
curl \
gnupg \
lsb-release
# Add Docker's official GPG key
install -m 0755 -d /etc/apt/keyrings
if [[ ! -f /etc/apt/keyrings/docker.gpg ]]; then
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
chmod a+r /etc/apt/keyrings/docker.gpg
fi
# Add Docker repository
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
# Install Docker
apt-get update -qq
apt-get install -y -qq docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
echo "✅ Docker installed: $(docker --version)"
fi
echo ""
# ─────────────────────────────────────────────────────────
# Step 5 — Enable and start Docker
# ─────────────────────────────────────────────────────────
echo "[5/10] Enabling Docker service..."
systemctl enable --now docker
usermod -aG docker "${AGENTHUB_USER}"
echo "✅ Docker enabled and running"
echo ""
# ─────────────────────────────────────────────────────────
# Step 6 — Create /opt/agenthub directory
# ─────────────────────────────────────────────────────────
echo "[6/10] Creating ${AGENTHUB_HOME} directory..."
mkdir -p "${AGENTHUB_HOME}"
chown "${AGENTHUB_USER}:${AGENTHUB_USER}" "${AGENTHUB_HOME}"
chmod 750 "${AGENTHUB_HOME}"
echo "✅ Directory created: $(ls -ld ${AGENTHUB_HOME})"
echo ""
# ─────────────────────────────────────────────────────────
# Step 7 — Clone agenthub repository
# ─────────────────────────────────────────────────────────
echo "[7/10] Cloning agenthub repository..."
if [[ -d "${AGENTHUB_HOME}/.git" ]]; then
echo " Repository already cloned, pulling latest..."
su - "${AGENTHUB_USER}" -c "cd ${AGENTHUB_HOME} && git pull origin ${AGENTHUB_BRANCH}"
else
# Install git if not present
if ! command -v git &>/dev/null; then
apt-get install -y -qq git
fi
su - "${AGENTHUB_USER}" -c "git clone --branch ${AGENTHUB_BRANCH} ${AGENTHUB_REPO} ${AGENTHUB_HOME}"
fi
echo "✅ Repository cloned/updated"
echo ""
# ─────────────────────────────────────────────────────────
# Step 8 — Load .env file (mode 600)
# ─────────────────────────────────────────────────────────
echo "[8/10] Configuring .env file..."
ENV_FILE="${AGENTHUB_HOME}/.env"
if [[ -f "${ENV_FILE}" ]]; then
echo " .env already exists, preserving existing configuration"
else
# Create .env from template if it doesn't exist
if [[ -f "${AGENTHUB_HOME}/.env.example" ]]; then
cp "${AGENTHUB_HOME}/.env.example" "${ENV_FILE}"
# Generate secure JWT secret
JWT_SECRET=$(openssl rand -base64 32)
POSTGRES_PASSWORD=$(openssl rand -base64 24)
# Replace placeholders in .env
sed -i "s|JWT_SECRET=.*|JWT_SECRET=${JWT_SECRET}|" "${ENV_FILE}"
sed -i "s|POSTGRES_PASSWORD=.*|POSTGRES_PASSWORD=${POSTGRES_PASSWORD}|" "${ENV_FILE}"
echo "✅ .env created with generated secrets"
else
echo "⚠️ Warning: .env.example not found, you must create .env manually"
fi
fi
chown "${AGENTHUB_USER}:${AGENTHUB_USER}" "${ENV_FILE}"
chmod 600 "${ENV_FILE}"
echo "✅ .env configured: $(ls -l ${ENV_FILE})"
echo ""
# ─────────────────────────────────────────────────────────
# Step 9 — Pull images and start stack
# ─────────────────────────────────────────────────────────
echo "[9/10] Starting AgentHub stack..."
cd "${AGENTHUB_HOME}"
# Pull latest images
su - "${AGENTHUB_USER}" -c "cd ${AGENTHUB_HOME} && docker compose -f compose.lan.yml pull"
# Start stack
su - "${AGENTHUB_USER}" -c "cd ${AGENTHUB_HOME} && docker compose -f compose.lan.yml up -d"
# Wait for services to be ready
echo " Waiting for services to start..."
sleep 10
echo "✅ Stack started"
echo ""
# ─────────────────────────────────────────────────────────
# Step 10 — Smoke test
# ─────────────────────────────────────────────────────────
echo "[10/10] Running smoke test..."
HEALTH_URL="http://127.0.0.1:3000/healthz"
# Retry health check up to 30 seconds
for i in {1..15}; do
if curl -sf "${HEALTH_URL}" > /dev/null; then
HEALTH_RESPONSE=$(curl -s "${HEALTH_URL}")
echo "✅ Smoke test passed: ${HEALTH_RESPONSE}"
echo ""
break
else
if [[ $i -eq 15 ]]; then
echo "❌ Smoke test failed: ${HEALTH_URL} not responding after 30s"
echo ""
echo "Logs:"
su - "${AGENTHUB_USER}" -c "cd ${AGENTHUB_HOME} && docker compose -f compose.lan.yml logs --tail=20"
exit 1
fi
echo " Attempt $i/15: waiting for health check..."
sleep 2
fi
done
# ─────────────────────────────────────────────────────────
# Complete
# ─────────────────────────────────────────────────────────
echo "╔════════════════════════════════════════════════════╗"
echo "║ ✅ AgentHub Bootstrap Complete! ║"
echo "╚════════════════════════════════════════════════════╝"
echo ""
echo "📋 Next steps:"
echo ""
echo " 1. Configure ufw firewall (see docs/RUNBOOK-lan.md)"
echo " 2. Test WebSocket connection from LAN client"
echo " 3. Set up monitoring (Uptime Kuma)"
echo ""
echo "🌐 Endpoints:"
echo " - Health: http://$(hostname -I | awk '{print $1}'):3000/healthz"
echo " - WebSocket: ws://$(hostname -I | awk '{print $1}'):3000/agents"
echo ""
echo "📖 Documentation: ${AGENTHUB_HOME}/docs/RUNBOOK-lan.md"
echo ""