#!/bin/bash # Robotunnel Agent Installer # Usage: curl -fsSL https://api.robotunnel.io/api/get-agent | RT_KEY=xxx sudo bash set -e # Configuration VERSION="0.1.3" GITHUB_REPO="RussellTNY/robotunnel" INSTALL_DIR="/opt/robotunnel" BIN_DIR="/usr/local/bin" SERVICE_NAME="robotunnel" API_URL="${ROBOTUNNEL_API_URL:-https://api.robotunnel.io}" DATA_DIR="/var/lib/robotunnel" # Colors RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' log_info() { echo -e "${GREEN}[INFO]${NC} $1"; } log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; } log_error() { echo -e "${RED}[ERROR]${NC} $1"; } log_step() { echo -e "${BLUE}[STEP]${NC} $1"; } # Check if running as root if [ "$EUID" -ne 0 ]; then log_error "Please run as root (use sudo)" exit 1 fi # Platform Detection OS=$(uname -s) ARCH=$(uname -m) if [ "$OS" != "Linux" ]; then log_error "This installer only supports Linux. Detected OS: $OS" exit 1 fi case "$ARCH" in x86_64) ARCH_TAG="x86_64" ;; aarch64|arm64) ARCH_TAG="aarch64" ;; *) log_error "Unsupported architecture: $ARCH" exit 1 ;; esac log_info "Installing Robotunnel Agent v${VERSION} for ${OS}-${ARCH_TAG}" # Check ROS 2 installation if ! command -v ros2 &> /dev/null; then log_warn "ROS 2 command 'ros2' not found." log_warn "Please ensure ROS 2 Humble is installed before running the agent." log_warn "Installation will continue, but the agent won't start without ROS 2." fi # Preparation log_step "Creating directories..." mkdir -p "$INSTALL_DIR" mkdir -p "$DATA_DIR" # Download agent binary from GitHub Release ASSET_NAME="robotunnel-agent-${VERSION}-Linux-${ARCH_TAG}.tar.gz" DOWNLOAD_URL="https://github.com/${GITHUB_REPO}/releases/download/v${VERSION}/${ASSET_NAME}" log_step "Downloading agent binary..." log_info "URL: $DOWNLOAD_URL" if command -v curl &> /dev/null; then if ! curl -fsSL -o "/tmp/${ASSET_NAME}" "$DOWNLOAD_URL"; then log_error "Failed to download agent binary from GitHub Release" log_error "Please check if version ${VERSION} has been released" exit 1 fi elif command -v wget &> /dev/null; then if ! wget -q -O "/tmp/${ASSET_NAME}" "$DOWNLOAD_URL"; then log_error "Failed to download agent binary from GitHub Release" exit 1 fi else log_error "Neither curl nor wget found. Please install one of them." exit 1 fi log_step "Extracting agent binary..." tar -xzf "/tmp/${ASSET_NAME}" -C "$INSTALL_DIR" --strip-components=1 rm "/tmp/${ASSET_NAME}" # Make binaries executable chmod +x "$INSTALL_DIR/lib/robotunnel/robotunnel_agent" 2>/dev/null || true # Agent Registration with RT_KEY if [ -n "$RT_KEY" ]; then log_step "Registering robot with RT_KEY..." # Detect local IP LOCAL_IP="" if command -v ip &> /dev/null; then # Prefer private network IPs LOCAL_IP=$(ip -o -4 addr show scope global 2>/dev/null | awk '{print $4}' | cut -d/ -f1 | grep -E '^(192\.168\.|10\.)' | head -1 || true) if [ -z "$LOCAL_IP" ]; then LOCAL_IP=$(ip route get 1 2>/dev/null | awk '{for(i=1;i<=NF;i++) if ($i=="src") {print $(i+1); exit}}' || true) fi fi if [ -z "$LOCAL_IP" ] && command -v hostname &> /dev/null; then LOCAL_IP=$(hostname -I 2>/dev/null | tr ' ' '\n' | grep -E '^(192\.168\.|10\.)' | head -1 || true) fi if [ -n "$LOCAL_IP" ]; then log_info "Detected local IP: $LOCAL_IP" else log_warn "Could not detect local IP. Registration will proceed without it." fi # Call registration API RESPONSE=$(curl -s -X POST "${API_URL}/api/register-robot" \ -H "Content-Type: application/json" \ -d "{\"rt_key\": \"$RT_KEY\", \"local_ip\": \"${LOCAL_IP:-}\"}") # Check for errors ERROR=$(echo "$RESPONSE" | grep -o '"error":"[^"]*"' | sed 's/"error":"\([^"]*\)"/\1/' || true) if [ -n "$ERROR" ]; then log_error "Registration failed: $ERROR" log_warn "Agent will be installed but not registered. You can register later." else # Extract and save API key API_KEY=$(echo "$RESPONSE" | grep -o '"api_key":"[^"]*"' | sed 's/"api_key":"\([^"]*\)"/\1/' || true) if [ -n "$API_KEY" ]; then echo "$API_KEY" > "${DATA_DIR}/api_key" chmod 600 "${DATA_DIR}/api_key" log_info "✓ Robot registered successfully!" else log_warn "Registration response received but API key not found" fi fi else log_warn "No RT_KEY provided. Agent will be installed but not registered." log_info "To register later, set RT_KEY and restart the service." fi # Create systemd service log_step "Configuring systemd service..." cat > "/etc/systemd/system/${SERVICE_NAME}.service" <<'SERVICEEOF' [Unit] Description=Robotunnel Agent After=network.target network-online.target Wants=network-online.target [Service] Type=simple User=root WorkingDirectory=/opt/robotunnel # Environment Environment="ROS_DOMAIN_ID=0" Environment="ROBOTUNNEL_PORT=11411" Environment="ROBOTUNNEL_API_URL=https://api.robotunnel.io" # Source ROS 2 and run agent ExecStart=/bin/bash -c '\ if [ -f /opt/ros/humble/setup.bash ]; then \ source /opt/ros/humble/setup.bash; \ fi; \ if [ -f /opt/robotunnel/install/setup.bash ]; then \ source /opt/robotunnel/install/setup.bash; \ fi; \ exec /opt/robotunnel/lib/robotunnel/robotunnel_agent --ros-args -p listen_port:${ROBOTUNNEL_PORT}' Restart=on-failure RestartSec=5 [Install] WantedBy=multi-user.target SERVICEEOF systemctl daemon-reload log_info "✓ Installation complete!" echo "" log_info "To start the agent:" echo " sudo systemctl enable ${SERVICE_NAME}" echo " sudo systemctl start ${SERVICE_NAME}" echo "" log_info "To check agent status:" echo " sudo systemctl status ${SERVICE_NAME}" echo " sudo journalctl -u ${SERVICE_NAME} -f" echo "" # Auto-start if RT_KEY was provided if [ -n "$RT_KEY" ]; then log_step "Starting agent service..." systemctl enable "${SERVICE_NAME}" systemctl start "${SERVICE_NAME}" sleep 2 if systemctl is-active --quiet "${SERVICE_NAME}"; then log_info "✓ Agent is running!" else log_warn "Agent service started but may have encountered issues." log_info "Check logs with: sudo journalctl -u ${SERVICE_NAME} -n 50" fi fi