#!/usr/bin/env bash # clawd one-click install script # Usage: curl -fsSL https://git.cutos.ai/claw-daemon/clawd/raw/branch/main/install.sh | sudo bash # Requires root and Node.js >= 18 set -e RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; NC='\033[0m' info() { echo -e "${GREEN}[clawd]${NC} $*"; } warn() { echo -e "${YELLOW}[clawd]${NC} $*"; } error() { echo -e "${RED}[clawd]${NC} $*"; exit 1; } # -- check root if [ "$EUID" -ne 0 ]; then error "Please run as root: sudo bash install.sh" fi # -- check Node.js if ! command -v node &>/dev/null; then error "Node.js not found. Please install Node.js >= 18 first." fi NODE_VER=$(node -e "process.stdout.write(process.versions.node)") MAJOR=$(echo "$NODE_VER" | cut -d. -f1) if [ "$MAJOR" -lt 18 ]; then error "Node.js version too low (current: $NODE_VER). Need >= 18." fi info "Node.js $NODE_VER OK" # -- install dnsmasq (needed for WiFi provisioning) if ! command -v dnsmasq &>/dev/null; then info "Installing dnsmasq..." if command -v apt-get &>/dev/null; then apt-get install -y -qq dnsmasq >/dev/null 2>&1 elif command -v yum &>/dev/null; then yum install -y -q dnsmasq >/dev/null 2>&1 elif command -v apk &>/dev/null; then apk add --quiet dnsmasq >/dev/null 2>&1 else warn "Cannot auto-install dnsmasq. WiFi provisioning may not work." fi systemctl disable dnsmasq 2>/dev/null || true systemctl stop dnsmasq 2>/dev/null || true fi if command -v dnsmasq &>/dev/null; then info "dnsmasq OK" fi # -- enable NetworkManager if command -v nmcli &>/dev/null; then if ! systemctl is-active --quiet NetworkManager 2>/dev/null; then info "Enabling NetworkManager..." systemctl enable --now NetworkManager 2>/dev/null || true fi info "NetworkManager OK" NM_DNSMASQ_DIR="/etc/NetworkManager/dnsmasq-shared.d" mkdir -p "$NM_DNSMASQ_DIR" cat > "$NM_DNSMASQ_DIR/clawd-captive.conf" << 'DNSCONF' # clawd captive portal DNS hijack # All DNS queries resolve to gateway to trigger captive portal address=/#/10.42.0.1 DNSCONF info "DNS hijack config written to $NM_DNSMASQ_DIR" fi # -- WiFi rfkill unblock for rf in /sys/class/rfkill/rfkill*; do if [ -f "$rf/type" ] && [ "$(cat "$rf/type")" = "wlan" ]; then if [ "$(cat "$rf/soft")" = "1" ]; then info "Unblocking WiFi ($(basename "$rf"))..." echo 0 > "$rf/soft" fi fi done RFKILL_SCRIPT="/usr/local/bin/clawd-unblock-wifi.sh" cat > "$RFKILL_SCRIPT" << 'SCRIPT' #!/bin/sh for rf in /sys/class/rfkill/rfkill*; do [ -f "$rf/type" ] || continue if [ "$(cat "$rf/type")" = "wlan" ] && [ "$(cat "$rf/soft")" = "1" ]; then echo 0 > "$rf/soft" echo "clawd-rfkill: unblocked $(basename "$rf")" fi done SCRIPT chmod +x "$RFKILL_SCRIPT" RFKILL_SERVICE="/etc/systemd/system/clawd-rfkill.service" cat > "$RFKILL_SERVICE" << 'UNIT' [Unit] Description=Unblock WiFi for clawd Before=NetworkManager.service clawd.service After=sys-subsystem-net-devices-wlan0.device [Service] Type=oneshot ExecStart=/usr/local/bin/clawd-unblock-wifi.sh RemainAfterExit=yes [Install] WantedBy=multi-user.target UNIT systemctl daemon-reload systemctl enable clawd-rfkill info "WiFi rfkill service created" # -- install ttyd info "Installing ttyd..." if apt-get install -y ttyd >/dev/null 2>&1; then info "ttyd installed" else warn "ttyd install failed. Web terminal may not be available." fi # -- install clawd INSTALL_DIR="/opt/clawd" CONFIG_DIR="/etc/clawd" ENV_FILE="$CONFIG_DIR/env" CUTOS_REPO="https://git.cutos.ai/claw-daemon/clawd.git" info "Installing to $INSTALL_DIR ..." mkdir -p "$INSTALL_DIR" cd "$INSTALL_DIR" # Download source (prioritise .git repo update over package.json skip) if command -v git &>/dev/null && [ -d ".git" ]; then # Migrate remote from GitHub to git.cutos.ai if needed CURRENT_REMOTE=$(git remote get-url origin 2>/dev/null || echo "") if echo "$CURRENT_REMOTE" | grep -q "github.com"; then info "Migrating git remote to git.cutos.ai ..." git remote set-url origin "$CUTOS_REPO" fi info "Pulling latest code..." git fetch origin git reset --hard origin/main git clean -fd elif [ -f "package.json" ]; then info "Source already present (no .git). Skipping download." elif command -v git &>/dev/null; then git clone --depth=1 "$CUTOS_REPO" . else TARBALL_URL="https://git.cutos.ai/claw-daemon/clawd/archive/main.tar.gz" curl -fsSL "$TARBALL_URL" | tar -xz --strip-components=1 fi # install npm deps info "Installing npm dependencies..." npm install --omit=dev --silent # create symlink ln -sf "$INSTALL_DIR/bin/clawd.js" /usr/local/bin/clawd chmod +x "$INSTALL_DIR/bin/clawd.js" info "clawd installed to /usr/local/bin/clawd" # -- create config dir + env file mkdir -p "$CONFIG_DIR" if [ ! -f "$CONFIG_DIR/config.json" ]; then cat > "$CONFIG_DIR/config.json" < "$ENV_FILE" < "$SERVICE_FILE" < "$JOURNAL_CONF" </dev/null || true info "journald limits configured" fi # -- enable and start systemctl daemon-reload systemctl enable clawd systemctl restart clawd sleep 2 if systemctl is-active --quiet clawd; then info "clawd service is running" echo "" echo " View logs: journalctl -u clawd -f" echo " View status: systemctl status clawd" echo " Stop: systemctl stop clawd" echo " Config: $CONFIG_DIR/config.json" echo " Env vars: $ENV_FILE" echo " Log file: $CONFIG_DIR/logs/clawd.log" echo "" else warn "Service failed to start. Check logs:" echo " journalctl -u clawd -n 50 --no-pager" fi