1
0

setup-pi.sh 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376
  1. #!/bin/bash
  2. #
  3. # Dune Weaver Raspberry Pi Setup Script
  4. #
  5. # One-command setup for deploying Dune Weaver on Raspberry Pi
  6. # Run this script from the cloned dune-weaver directory:
  7. #
  8. # git clone https://github.com/tuanchris/dune-weaver --single-branch
  9. # cd dune-weaver
  10. # bash setup-pi.sh
  11. #
  12. # Options:
  13. # bash setup-pi.sh --no-docker # Use Python venv instead of Docker
  14. # bash setup-pi.sh --no-wifi-fix # Skip WiFi stability fix
  15. # bash setup-pi.sh --help # Show help
  16. #
  17. set -e
  18. # Colors for output
  19. RED='\033[0;31m'
  20. GREEN='\033[0;32m'
  21. YELLOW='\033[1;33m'
  22. BLUE='\033[0;34m'
  23. NC='\033[0m' # No Color
  24. # Default options
  25. USE_DOCKER=true
  26. FIX_WIFI=true # Applied by default for stability
  27. INSTALL_DIR="$(pwd)" # Assume running from cloned dune-weaver directory
  28. # Parse arguments
  29. while [[ $# -gt 0 ]]; do
  30. case $1 in
  31. --no-docker)
  32. USE_DOCKER=false
  33. shift
  34. ;;
  35. --no-wifi-fix)
  36. FIX_WIFI=false
  37. shift
  38. ;;
  39. --help|-h)
  40. echo "Dune Weaver Raspberry Pi Setup Script"
  41. echo ""
  42. echo "Usage:"
  43. echo " git clone https://github.com/tuanchris/dune-weaver --single-branch"
  44. echo " cd dune-weaver"
  45. echo " bash setup-pi.sh [OPTIONS]"
  46. echo ""
  47. echo "Options:"
  48. echo " --no-docker Use Python venv instead of Docker"
  49. echo " --no-wifi-fix Skip WiFi stability fix (applied by default)"
  50. echo " --help, -h Show this help message"
  51. echo ""
  52. echo "Examples:"
  53. echo " bash setup-pi.sh # Standard Docker installation + WiFi fix"
  54. echo " bash setup-pi.sh --no-docker # Python venv installation + WiFi fix"
  55. exit 0
  56. ;;
  57. *)
  58. echo -e "${RED}Unknown option: $1${NC}"
  59. echo "Use --help for usage information"
  60. exit 1
  61. ;;
  62. esac
  63. done
  64. # Helper functions
  65. print_step() {
  66. echo -e "\n${BLUE}==>${NC} ${GREEN}$1${NC}"
  67. }
  68. print_warning() {
  69. echo -e "${YELLOW}Warning:${NC} $1"
  70. }
  71. print_error() {
  72. echo -e "${RED}Error:${NC} $1"
  73. }
  74. print_success() {
  75. echo -e "${GREEN}$1${NC}"
  76. }
  77. # Check if running on Raspberry Pi
  78. check_raspberry_pi() {
  79. print_step "Checking system compatibility..."
  80. if [[ ! -f /proc/device-tree/model ]]; then
  81. print_warning "Could not detect Raspberry Pi model. Continuing anyway..."
  82. return
  83. fi
  84. MODEL=$(cat /proc/device-tree/model)
  85. echo "Detected: $MODEL"
  86. # Check for 64-bit OS
  87. ARCH=$(uname -m)
  88. if [[ "$ARCH" != "aarch64" && "$ARCH" != "arm64" ]]; then
  89. print_error "64-bit OS required. Detected: $ARCH"
  90. echo "Please reinstall Raspberry Pi OS (64-bit) using Raspberry Pi Imager"
  91. exit 1
  92. fi
  93. print_success "64-bit OS detected ($ARCH)"
  94. }
  95. # Disable WLAN power save
  96. disable_wlan_powersave() {
  97. print_step "Disabling WLAN power save for better stability..."
  98. # Check if already disabled
  99. if iwconfig wlan0 2>/dev/null | grep -q "Power Management:off"; then
  100. echo "WLAN power save already disabled"
  101. return
  102. fi
  103. # Create config to persist across reboots
  104. sudo tee /etc/NetworkManager/conf.d/wifi-powersave-off.conf > /dev/null << 'EOF'
  105. [connection]
  106. wifi.powersave = 2
  107. EOF
  108. # Also try immediate disable
  109. sudo iwconfig wlan0 power off 2>/dev/null || true
  110. print_success "WLAN power save disabled"
  111. }
  112. # Apply WiFi stability fix
  113. apply_wifi_fix() {
  114. print_step "Applying WiFi stability fix..."
  115. CMDLINE_FILE="/boot/firmware/cmdline.txt"
  116. if [[ ! -f "$CMDLINE_FILE" ]]; then
  117. CMDLINE_FILE="/boot/cmdline.txt"
  118. fi
  119. if [[ ! -f "$CMDLINE_FILE" ]]; then
  120. print_warning "Could not find cmdline.txt, skipping WiFi fix"
  121. return
  122. fi
  123. # Check if fix already applied
  124. if grep -q "brcmfmac.feature_disable=0x82000" "$CMDLINE_FILE"; then
  125. echo "WiFi fix already applied"
  126. return
  127. fi
  128. # Backup and apply fix
  129. sudo cp "$CMDLINE_FILE" "${CMDLINE_FILE}.backup"
  130. sudo sed -i 's/$/ brcmfmac.feature_disable=0x82000/' "$CMDLINE_FILE"
  131. print_success "WiFi fix applied. A reboot is recommended after setup."
  132. NEEDS_REBOOT=true
  133. }
  134. # Update system packages
  135. update_system() {
  136. print_step "Updating system packages..."
  137. sudo apt update
  138. sudo apt full-upgrade -y
  139. print_success "System updated"
  140. }
  141. # Install Docker
  142. install_docker() {
  143. print_step "Installing Docker..."
  144. if command -v docker &> /dev/null; then
  145. echo "Docker already installed: $(docker --version)"
  146. else
  147. curl -fsSL https://get.docker.com -o /tmp/get-docker.sh
  148. sudo sh /tmp/get-docker.sh
  149. rm /tmp/get-docker.sh
  150. print_success "Docker installed"
  151. fi
  152. # Add user to docker group
  153. if ! groups $USER | grep -q docker; then
  154. print_step "Adding $USER to docker group..."
  155. sudo usermod -aG docker $USER
  156. DOCKER_GROUP_ADDED=true
  157. print_warning "You'll need to log out and back in for docker group changes to take effect"
  158. fi
  159. }
  160. # Install Python dependencies (non-Docker)
  161. install_python_deps() {
  162. print_step "Installing Python dependencies..."
  163. # Install system packages
  164. sudo apt install -y python3-venv python3-pip git
  165. print_success "Python dependencies installed"
  166. }
  167. # Verify we're in the dune-weaver directory
  168. check_directory() {
  169. print_step "Verifying dune-weaver directory..."
  170. # Check for key files that indicate we're in the right directory
  171. if [[ ! -f "docker-compose.yml" ]] || [[ ! -f "main.py" ]]; then
  172. print_error "This script must be run from the dune-weaver directory"
  173. echo ""
  174. echo "Please run:"
  175. echo " git clone https://github.com/tuanchris/dune-weaver --single-branch"
  176. echo " cd dune-weaver"
  177. echo " bash setup-pi.sh"
  178. exit 1
  179. fi
  180. INSTALL_DIR="$(pwd)"
  181. print_success "Running from $INSTALL_DIR"
  182. }
  183. # Deploy with Docker
  184. deploy_docker() {
  185. print_step "Deploying Dune Weaver with Docker Compose..."
  186. cd "$INSTALL_DIR"
  187. # Use newgrp to apply docker group if just added, otherwise use sudo
  188. if [[ "$DOCKER_GROUP_ADDED" == "true" ]]; then
  189. echo "Starting Docker containers (using sudo since group not yet active)..."
  190. sudo docker compose up -d
  191. else
  192. docker compose up -d
  193. fi
  194. print_success "Docker deployment complete!"
  195. }
  196. # Deploy with Python venv
  197. deploy_python() {
  198. print_step "Setting up Python virtual environment..."
  199. cd "$INSTALL_DIR"
  200. # Create venv
  201. python3 -m venv .venv
  202. source .venv/bin/activate
  203. # Install dependencies
  204. print_step "Installing Python packages..."
  205. pip install --upgrade pip
  206. pip install -r requirements.txt
  207. # Create systemd service
  208. print_step "Creating systemd service..."
  209. sudo tee /etc/systemd/system/dune-weaver.service > /dev/null << EOF
  210. [Unit]
  211. Description=Dune Weaver Backend
  212. After=network.target
  213. [Service]
  214. ExecStart=$INSTALL_DIR/.venv/bin/python $INSTALL_DIR/main.py
  215. WorkingDirectory=$INSTALL_DIR
  216. Restart=always
  217. User=$USER
  218. Environment=PYTHONUNBUFFERED=1
  219. [Install]
  220. WantedBy=multi-user.target
  221. EOF
  222. # Enable and start service
  223. sudo systemctl daemon-reload
  224. sudo systemctl enable dune-weaver
  225. sudo systemctl start dune-weaver
  226. print_success "Python deployment complete!"
  227. }
  228. # Get IP address
  229. get_ip_address() {
  230. # Try multiple methods to get IP
  231. IP=$(hostname -I 2>/dev/null | awk '{print $1}')
  232. if [[ -z "$IP" ]]; then
  233. IP=$(ip route get 1 2>/dev/null | awk '{print $7}' | head -1)
  234. fi
  235. if [[ -z "$IP" ]]; then
  236. IP="<your-pi-ip>"
  237. fi
  238. echo "$IP"
  239. }
  240. # Print final instructions
  241. print_final_instructions() {
  242. IP=$(get_ip_address)
  243. HOSTNAME=$(hostname)
  244. echo ""
  245. echo -e "${GREEN}============================================${NC}"
  246. echo -e "${GREEN} Dune Weaver Setup Complete!${NC}"
  247. echo -e "${GREEN}============================================${NC}"
  248. echo ""
  249. echo -e "Access the web interface at:"
  250. echo -e " ${BLUE}http://$IP:8080${NC}"
  251. echo -e " ${BLUE}http://$HOSTNAME.local:8080${NC}"
  252. echo ""
  253. if [[ "$USE_DOCKER" == "true" ]]; then
  254. echo "Useful commands:"
  255. echo " View logs: cd $INSTALL_DIR && docker compose logs -f"
  256. echo " Restart: cd $INSTALL_DIR && docker compose restart"
  257. echo " Update: cd $INSTALL_DIR && git pull && docker compose pull && docker compose up -d"
  258. echo " Stop: cd $INSTALL_DIR && docker compose down"
  259. else
  260. echo "Useful commands:"
  261. echo " View logs: sudo journalctl -u dune-weaver -f"
  262. echo " Restart: sudo systemctl restart dune-weaver"
  263. echo " Status: sudo systemctl status dune-weaver"
  264. echo " Stop: sudo systemctl stop dune-weaver"
  265. fi
  266. echo ""
  267. if [[ "$DOCKER_GROUP_ADDED" == "true" ]]; then
  268. print_warning "Please log out and back in for docker group changes to take effect"
  269. fi
  270. if [[ "$NEEDS_REBOOT" == "true" ]]; then
  271. print_warning "A reboot is recommended to apply WiFi fixes"
  272. read -p "Reboot now? (y/N) " -n 1 -r
  273. echo
  274. if [[ $REPLY =~ ^[Yy]$ ]]; then
  275. sudo reboot
  276. fi
  277. fi
  278. }
  279. # Main installation flow
  280. main() {
  281. echo -e "${GREEN}"
  282. echo " ____ __ __ "
  283. echo " | _ \ _ _ _ __ ___\ \ / /__ __ ___ _____ _ __ "
  284. echo " | | | | | | | '_ \ / _ \\ \ /\ / / _ \/ _\` \ \ / / _ \ '__|"
  285. echo " | |_| | |_| | | | | __/ \ V V / __/ (_| |\ V / __/ | "
  286. echo " |____/ \__,_|_| |_|\___| \_/\_/ \___|\__,_| \_/ \___|_| "
  287. echo -e "${NC}"
  288. echo "Raspberry Pi Setup Script"
  289. echo ""
  290. # Detect deployment method
  291. if [[ "$USE_DOCKER" == "true" ]]; then
  292. echo "Deployment method: Docker (recommended)"
  293. else
  294. echo "Deployment method: Python virtual environment"
  295. fi
  296. echo "Install directory: $INSTALL_DIR"
  297. echo ""
  298. # Run setup steps
  299. check_directory
  300. check_raspberry_pi
  301. update_system
  302. disable_wlan_powersave
  303. if [[ "$FIX_WIFI" == "true" ]]; then
  304. apply_wifi_fix
  305. fi
  306. if [[ "$USE_DOCKER" == "true" ]]; then
  307. install_docker
  308. deploy_docker
  309. else
  310. install_python_deps
  311. deploy_python
  312. fi
  313. print_final_instructions
  314. }
  315. # Run main
  316. main