Commit d3361308 authored by Lisa's avatar Lisa

Fix: Linux installer self-contained with complete embedded tarball

parent 7a2ff30d
......@@ -21,7 +21,7 @@ PIP_CMD=""
if command -v pip3 &> /dev/null; then PIP_CMD="pip3"; elif command -v pip &> /dev/null; then PIP_CMD="pip"; fi
if [ -z "$PIP_CMD" ]; then echo "ERROR: pip not found."; exit 1; fi
echo "[1/5] Installing websockets...?"
echo "[1/5] Installing websockets..."
python3 -c "import websockets" 2>/dev/null || $PIP_CMD install --quiet websockets
echo "✓ websockets installed"
......@@ -40,110 +40,103 @@ echo "[2/5] Extracting embedded files..."
TMP=$(mktemp -d)
cd "$TMP"
cat <<'TAR' | base64 -d | tar xzf -
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
TAR
# Find and install the agent
if [ -f "./hermes-node-agent" ]; then SRC="./hermes-node-agent";
elif [ -f "./hermes_node_agent/hermes-node-agent" ]; then SRC="./hermes_node_agent/hermes-node-agent";
else echo "ERROR: Agent not found in tarball"; ls -la; exit 1; fi
cp "$SRC" "$AGENT_DIR/hermes-node-agent"
echo "✓ Extracted $(ls -1 | wc -l) embedded files"
cp hermes_node_agent.py "$AGENT_DIR/hermes-node-agent"
chmod +x "$AGENT_DIR/hermes-node-agent"
echo "✓ Agent: $AGENT_DIR/hermes-node-agent"
cp browser_controller.py "$AGENT_DIR/"
mkdir -p "$AGENT_DIR/hermes_lib"
cp requirements.txt "$AGENT_DIR/hermes_lib/"
# Install init.d if root
if [ "$RUN_AS_ROOT" = true ]; then
if [ -f "./init.d" ]; then CP="./init.d";
elif [ -f "./hermes_node_agent/init.d" ]; then CP="./hermes_node_agent/init.d";
else CP=""; fi
if [ -n "$CP" ]; then cp "$CP" /etc/init.d/hermes-node-agent && chmod +x /etc/init.d/hermes-node-agent; echo "✓ Init: /etc/init.d/hermes-node-agent"; fi
cp hermes-node-agent.init.d /etc/init.d/hermes-node-agent
chmod +x /etc/init.d/hermes-node-agent
update-rc.d hermes-node-agent defaults 2>/dev/null || chkconfig --add hermes-node-agent 2>/dev/null || true
echo "✓ Installed system service"
else
mkdir -p "$(dirname "$CONFIG_DIR")"
cp hermes-node-agent.init.d "$CONFIG_DIR/"
echo "✓ Skipped system service (not root)"
fi
cd /
rm -rf "$TMP"
echo "[3/5] Config..."
if [ ! -f "$CONFIG_DIR/config.json" ]; then
echo "[4/5] Configuring node..."
echo ""
# Gather settings interactively
read -p "Gateway host (default: localhost): " GATEWAY_HOST
GATEWAY_HOST="${GATEWAY_HOST:-localhost}"
read -p "Gateway port (default: 8765): " GATEWAY_PORT
GATEWAY_PORT="${GATEWAY_PORT:-8765}"
read -p "Token (leave empty to generate): " NODE_TOKEN
if [ -z "$NODE_TOKEN" ]; then
NODE_TOKEN=$(python3 -c "import secrets; print(secrets.token_hex(16))")
echo " Generated token: $NODE_TOKEN"
fi
# Select capabilities individually
echo ""
read -p "Enable exec? (Y/n): " ENABLE_EXEC
[[ "$ENABLE_EXEC" =~ ^[Nn]$ ]] && EXEC_CAP="" || EXEC_CAP="exec"
read -p "Enable browser_control? (y/N): " ENABLE_BROWSER
[[ "$ENABLE_BROWSER" =~ ^[Yy]$ ]] && BROWSER_CAP="browser_control" || BROWSER_CAP=""
read -p "Enable computer_control? (y/N): " ENABLE_COMPUTER
[[ "$ENABLE_COMPUTER" =~ ^[Yy]$ ]] && COMPUTER_CAP="computer_control" || COMPUTER_CAP=""
# Build JSON array manually
CAPABILITIES="["
first=1
for cap in $EXEC_CAP $BROWSER_CAP $COMPUTER_CAP; do
if [ -n "$cap" ]; then
if [ $first -eq 0 ]; then CAPABILITIES="$CAPABILITIES, "; fi
CAPABILITIES="$CAPABILITIES\"$cap\""
first=0
fi
done
CAPABILITIES="$CAPABILITIES]"
# Ask about sexec
read -p "Enable sexec? (y/N): " ENABLE_SEXEC
SEXEC_LINE=""
if [[ "$ENABLE_SEXEC" =~ ^[Yy]$ ]]; then
SEXEC_LINE=' "sexec_path": "${HOME}/.config/hermes-node-agent/sexec/sexec.sh",'
echo " sexec will be installed at: $HOME/.config/hermes-node-agent/sexec/sexec.sh"
fi
NODE_NAME=$(hostname)
# Build config
cat > "$CONFIG_DIR/config.json" << END
echo "[3/5] Configuring node..."
echo
# Prompt for gateway
read -p "Gateway host (default: localhost): " GATEWAY_HOST
GATEWAY_HOST=${GATEWAY_HOST:-localhost}
read -p "Gateway port (default: 8765): " GATEWAY_PORT
GATEWP=":${GATEWAY_PORT:-8765}"
# Prompt for token
read -p "Token (leave empty to auto-generate): " NODE_TOKEN
if [ -z "$NODE_TOKEN" ]; then
NODE_TOKEN=$(python3 -c "import secrets; print(secrets.token_hex(32))")
echo " Generated token: $NODE_TOKEN"
fi
# Prompt for each capability individually
echo
echo "Select capabilities [Y/n]:"
read -p " Enable exec? (Y/n): " E_EXEC
[[ "$E_EXEC" =~ ^[Nn]$ ]] && EXEC_CAP="" || EXEC_CAP="exec"
read -p " Enable browser_control? (y/N): " E_BROWSER
[[ "$E_BROWSER" =~ ^[Yy]$ ]] && BROWSER_CAP="browser_control" || BROWSER_CAP=""
read -p " Enable computer_control? (y/N): " E_COMPUTER
[[ "$E_COMPUTER" =~ ^[Yy]$ ]] && COMPUTER_CAP="computer_control" || COMPUTER_CAP=""
# Build capabilities array
CAPABILITIES="["
FIRST=1
for cap in $EXEC_CAP $BROWSER_CAP $COMPUTER_CAP; do
[ -n "$cap" ] || continue
[ $FIRST -eq 0 ] && CAPABILITIES="$CAPABILITIES, "
CAPABILITIES="$CAPABILITIES"$cap""
FIRST=0
done
CAPABILITIES="$CAPABILITIES]"
# Prompt for sexec
read -p "Enable sexec? (y/N): " E_SEXEC
SEXEC_LINE=""
if [[ "$E_SEXEC" =~ ^[Yy]$ ]]; then
SEXEC_LINE=" \"sexec_path\": \"$HOME/.config/hermes-node-agent/sexec/sexec.sh\","
echo " sexec will be installed at: $HOME/.config/hermes-node-agent/sexec/sexec.sh"
fi
NODE_NAME=$(hostname)
cat > "$CONFIG_DIR/config.json" << END
{
"gateway_url": "wss://${GATEWAY_HOST}:${GATEWAY_PORT}",
"gateway_url": "wss://${GATEWAY_HOST}${GATEWP}",
"node_name": "${NODE_NAME}",
"token": "${NODE_TOKEN}",
${SEXEC_LINE}
"sexec_path": "${HOME}/.config/hermes-node-agent/sexec/sexec.sh",
$SEXEC_LINE
"reconnect_interval": 5,
"heartbeat_interval": 30,
"capabilities": ${CAPABILITIES}
"capabilities": $CAPABILITIES,
"protocol_version": "1.0"
}
END
echo ""
echo "✓ Config: $CONFIG_DIR/config.json"
else
echo "[4/5] Config exists — skipping"
echo " Config: $CONFIG_DIR/config.json"
fi
if [ "$RUN_AS_ROOT" = true ]; then
update-rc.d hermes-node-agent defaults 2>/dev/null || true
echo "✓ Service enabled: /etc/init.d/hermes-node-agent"
echo ""
echo "Commands: /etc/init.d/hermes-node-agent start|stop|restart|status"
else
echo ""
echo "Run manually: $AGENT_DIR/hermes-node-agent --config $CONFIG_DIR/config.json &"
fi
echo "✓ Config: $CONFIG_DIR/config.json"
echo
echo "[4/5] Verifying installation..."
python3 -c "import hermes_node_agent" 2>/dev/null && echo "✓ Agent module OK" || true
echo ""
echo "=== Done ==="
echo
echo "[5/5] Done ==="
echo "Agent: $AGENT_DIR/hermes-node-agent"
echo "Config: $CONFIG_DIR/config.json"
echo
if [ "$RUN_AS_ROOT" = true ]; then
echo "Run system service: /etc/init.d/hermes-node-agent start"
else
echo "Run manually: $AGENT_DIR/hermes-node-agent --config $CONFIG_DIR/config.json &"
fi
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment