From fed35e116a1028b719263124b0112f663c23a763 Mon Sep 17 00:00:00 2001 From: "Rodrigo Rodriguez (Pragmatismo)" Date: Fri, 12 Dec 2025 13:43:40 -0300 Subject: [PATCH] Add embedded deployment script for Orange Pi, Raspberry Pi, ARM SBCs --- scripts/deploy-embedded.sh | 368 +++++++++++++++++++++++++++++++++++++ 1 file changed, 368 insertions(+) create mode 100644 scripts/deploy-embedded.sh diff --git a/scripts/deploy-embedded.sh b/scripts/deploy-embedded.sh new file mode 100644 index 00000000..e75a4897 --- /dev/null +++ b/scripts/deploy-embedded.sh @@ -0,0 +1,368 @@ +#!/bin/bash +# +# BotServer Embedded Deployment Script +# For Orange Pi, Raspberry Pi, and other ARM/x86 SBCs +# +# Usage: ./deploy-embedded.sh [target-host] [options] +# +# Examples: +# ./deploy-embedded.sh orangepi@192.168.1.100 +# ./deploy-embedded.sh pi@raspberrypi.local --with-ui +# ./deploy-embedded.sh --local --with-ui +# + +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_DIR="$(dirname "$SCRIPT_DIR")" +BOTUI_DIR="$(dirname "$PROJECT_DIR")/botui" + +# Colors +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' + +# Default values +TARGET_HOST="" +WITH_UI=false +LOCAL_INSTALL=false +ARCH="" +SERVICE_NAME="botserver" + +print_banner() { + echo -e "${BLUE}" + echo "╔════════════════════════════════════════════════════════════╗" + echo "║ BotServer Embedded Deployment ║" + echo "║ Orange Pi / Raspberry Pi / ARM SBCs ║" + echo "╚════════════════════════════════════════════════════════════╝" + echo -e "${NC}" +} + +detect_arch() { + local arch=$(uname -m) + case $arch in + aarch64|arm64) + ARCH="aarch64-unknown-linux-gnu" + echo -e "${GREEN}Detected: ARM64${NC}" + ;; + armv7l|armhf) + ARCH="armv7-unknown-linux-gnueabihf" + echo -e "${GREEN}Detected: ARMv7 (32-bit)${NC}" + ;; + x86_64) + ARCH="x86_64-unknown-linux-gnu" + echo -e "${GREEN}Detected: x86_64${NC}" + ;; + *) + echo -e "${RED}Unknown architecture: $arch${NC}" + exit 1 + ;; + esac +} + +install_rust_target() { + echo -e "${YELLOW}Installing Rust target: $ARCH${NC}" + rustup target add $ARCH 2>/dev/null || true +} + +install_cross_compiler() { + echo -e "${YELLOW}Installing cross-compilation tools...${NC}" + + case $ARCH in + aarch64-unknown-linux-gnu) + if ! command -v aarch64-linux-gnu-gcc &> /dev/null; then + echo "Installing aarch64 cross-compiler..." + sudo apt-get update + sudo apt-get install -y gcc-aarch64-linux-gnu + fi + export CC_aarch64_unknown_linux_gnu=aarch64-linux-gnu-gcc + export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc + ;; + armv7-unknown-linux-gnueabihf) + if ! command -v arm-linux-gnueabihf-gcc &> /dev/null; then + echo "Installing armv7 cross-compiler..." + sudo apt-get update + sudo apt-get install -y gcc-arm-linux-gnueabihf + fi + export CC_armv7_unknown_linux_gnueabihf=arm-linux-gnueabihf-gcc + export CARGO_TARGET_ARMV7_UNKNOWN_LINUX_GNUEABIHF_LINKER=arm-linux-gnueabihf-gcc + ;; + esac +} + +build_botserver() { + echo -e "${YELLOW}Building botserver for $ARCH...${NC}" + cd "$PROJECT_DIR" + + # Build release + cargo build --release --target $ARCH + + BINARY_PATH="$PROJECT_DIR/target/$ARCH/release/botserver" + + if [ -f "$BINARY_PATH" ]; then + echo -e "${GREEN}Build successful: $BINARY_PATH${NC}" + ls -lh "$BINARY_PATH" + else + echo -e "${RED}Build failed!${NC}" + exit 1 + fi +} + +build_local() { + echo -e "${YELLOW}Building botserver locally...${NC}" + cd "$PROJECT_DIR" + cargo build --release + BINARY_PATH="$PROJECT_DIR/target/release/botserver" +} + +create_systemd_service() { + cat > /tmp/botserver.service << 'EOF' +[Unit] +Description=BotServer - General Bots Server +After=network.target postgresql.service +Wants=network-online.target + +[Service] +Type=simple +User=botserver +Group=botserver +WorkingDirectory=/opt/botserver +ExecStart=/opt/botserver/botserver +Restart=always +RestartSec=5 +Environment=RUST_LOG=info +Environment=DATABASE_URL=postgres://localhost/botserver + +# Security +NoNewPrivileges=true +ProtectSystem=strict +ProtectHome=true +ReadWritePaths=/opt/botserver/data + +[Install] +WantedBy=multi-user.target +EOF +} + +create_kiosk_service() { + cat > /tmp/botui-kiosk.service << 'EOF' +[Unit] +Description=BotUI Kiosk Mode +After=graphical.target botserver.service +Wants=botserver.service + +[Service] +Type=simple +User=pi +Environment=DISPLAY=:0 +ExecStartPre=/bin/sleep 5 +ExecStart=/usr/bin/chromium-browser --kiosk --noerrdialogs --disable-infobars --disable-session-crashed-bubble --app=http://localhost:8088/embedded/ +Restart=always +RestartSec=10 + +[Install] +WantedBy=graphical.target +EOF +} + +deploy_remote() { + local host=$1 + + echo -e "${YELLOW}Deploying to $host...${NC}" + + # Create remote directory + ssh $host "sudo mkdir -p /opt/botserver/data && sudo chown -R \$(whoami):\$(whoami) /opt/botserver" + + # Copy binary + echo "Copying botserver binary..." + scp "$BINARY_PATH" "$host:/opt/botserver/botserver" + ssh $host "chmod +x /opt/botserver/botserver" + + # Copy config + if [ -f "$PROJECT_DIR/.env.example" ]; then + scp "$PROJECT_DIR/.env.example" "$host:/opt/botserver/.env" + fi + + # Copy systemd service + create_systemd_service + scp /tmp/botserver.service "$host:/tmp/" + ssh $host "sudo mv /tmp/botserver.service /etc/systemd/system/" + + # Create user and setup + ssh $host "sudo useradd -r -s /bin/false botserver 2>/dev/null || true" + ssh $host "sudo chown -R botserver:botserver /opt/botserver" + + # Enable and start service + ssh $host "sudo systemctl daemon-reload" + ssh $host "sudo systemctl enable botserver" + ssh $host "sudo systemctl start botserver" + + echo -e "${GREEN}BotServer deployed and running on $host${NC}" + + # Deploy UI if requested + if [ "$WITH_UI" = true ]; then + deploy_ui_remote $host + fi +} + +deploy_ui_remote() { + local host=$1 + + echo -e "${YELLOW}Deploying embedded UI to $host...${NC}" + + # Copy embedded UI files + if [ -d "$BOTUI_DIR/ui/embedded" ]; then + ssh $host "mkdir -p /opt/botserver/ui/embedded" + scp -r "$BOTUI_DIR/ui/embedded/"* "$host:/opt/botserver/ui/embedded/" + fi + + # Setup kiosk mode + create_kiosk_service + scp /tmp/botui-kiosk.service "$host:/tmp/" + ssh $host "sudo mv /tmp/botui-kiosk.service /etc/systemd/system/" + ssh $host "sudo systemctl daemon-reload" + ssh $host "sudo systemctl enable botui-kiosk" + + echo -e "${GREEN}Kiosk mode configured. Reboot to start.${NC}" +} + +deploy_local() { + echo -e "${YELLOW}Installing locally...${NC}" + + # Build + build_local + + # Install + sudo mkdir -p /opt/botserver/data + sudo cp "$BINARY_PATH" /opt/botserver/ + sudo chmod +x /opt/botserver/botserver + + if [ -f "$PROJECT_DIR/.env.example" ]; then + sudo cp "$PROJECT_DIR/.env.example" /opt/botserver/.env + fi + + # Create user + sudo useradd -r -s /bin/false botserver 2>/dev/null || true + sudo chown -R botserver:botserver /opt/botserver + + # Setup systemd + create_systemd_service + sudo mv /tmp/botserver.service /etc/systemd/system/ + sudo systemctl daemon-reload + sudo systemctl enable botserver + sudo systemctl start botserver + + echo -e "${GREEN}BotServer installed and running locally${NC}" + + if [ "$WITH_UI" = true ]; then + # Copy UI files + sudo mkdir -p /opt/botserver/ui/embedded + sudo cp -r "$BOTUI_DIR/ui/embedded/"* /opt/botserver/ui/embedded/ + + # Setup kiosk + create_kiosk_service + sudo mv /tmp/botui-kiosk.service /etc/systemd/system/ + sudo systemctl daemon-reload + sudo systemctl enable botui-kiosk + + echo -e "${GREEN}Kiosk mode configured. Reboot to start.${NC}" + fi +} + +show_help() { + echo "Usage: $0 [target-host] [options]" + echo "" + echo "Options:" + echo " --local Install on this machine" + echo " --with-ui Also deploy embedded UI with kiosk mode" + echo " --arch ARCH Force target architecture" + echo " -h, --help Show this help" + echo "" + echo "Examples:" + echo " $0 orangepi@192.168.1.100" + echo " $0 pi@raspberrypi.local --with-ui" + echo " $0 --local --with-ui" + echo "" + echo "Supported boards:" + echo " - Raspberry Pi (Zero, 3, 4, 5)" + echo " - Orange Pi (Zero, One, PC, etc)" + echo " - Banana Pi" + echo " - Rock Pi" + echo " - ODROID" + echo " - Any ARM64/ARMv7/x86_64 Linux SBC" +} + +# Parse arguments +while [[ $# -gt 0 ]]; do + case $1 in + --local) + LOCAL_INSTALL=true + shift + ;; + --with-ui) + WITH_UI=true + shift + ;; + --arch) + ARCH="$2" + shift 2 + ;; + -h|--help) + show_help + exit 0 + ;; + *) + if [ -z "$TARGET_HOST" ]; then + TARGET_HOST="$1" + fi + shift + ;; + esac +done + +# Main +print_banner + +if [ "$LOCAL_INSTALL" = true ]; then + detect_arch + deploy_local +elif [ -n "$TARGET_HOST" ]; then + # Get remote arch + echo "Detecting remote architecture..." + REMOTE_ARCH=$(ssh $TARGET_HOST "uname -m") + case $REMOTE_ARCH in + aarch64|arm64) + ARCH="aarch64-unknown-linux-gnu" + ;; + armv7l|armhf) + ARCH="armv7-unknown-linux-gnueabihf" + ;; + x86_64) + ARCH="x86_64-unknown-linux-gnu" + ;; + esac + echo -e "${GREEN}Remote arch: $ARCH${NC}" + + install_rust_target + install_cross_compiler + build_botserver + deploy_remote $TARGET_HOST +else + show_help + exit 1 +fi + +echo "" +echo -e "${GREEN}Deployment complete!${NC}" +echo "" +echo "Check status:" +echo " ssh $TARGET_HOST 'sudo systemctl status botserver'" +echo "" +echo "View logs:" +echo " ssh $TARGET_HOST 'sudo journalctl -u botserver -f'" +echo "" +if [ "$WITH_UI" = true ]; then + echo "Access UI at: http://$TARGET_HOST:8088/embedded/" +fi