deploy.sh raw

   1  #!/bin/bash
   2  
   3  # ORLY Relay Deployment Script
   4  # This script installs Go, builds the relay, and sets up systemd service
   5  
   6  set -e
   7  
   8  # Configuration
   9  GO_VERSION="1.25.3"
  10  GOROOT="$HOME/go"
  11  GOPATH="$HOME"
  12  GOBIN="$HOME/.local/bin"
  13  GOENV_FILE="$HOME/.goenv"
  14  BASHRC_FILE="$HOME/.bashrc"
  15  SERVICE_NAME="orly"
  16  BINARY_NAME="orly"
  17  
  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  
  25  # Logging functions
  26  log_info() {
  27      echo -e "${BLUE}[INFO]${NC} $1"
  28  }
  29  
  30  log_success() {
  31      echo -e "${GREEN}[SUCCESS]${NC} $1"
  32  }
  33  
  34  log_warning() {
  35      echo -e "${YELLOW}[WARNING]${NC} $1"
  36  }
  37  
  38  log_error() {
  39      echo -e "${RED}[ERROR]${NC} $1"
  40  }
  41  
  42  # Check if running as root for certain operations
  43  check_root() {
  44      if [[ $EUID -eq 0 ]]; then
  45          return 0
  46      else
  47          return 1
  48      fi
  49  }
  50  
  51  # Check if bun is installed
  52  check_bun_installation() {
  53      if command -v bun >/dev/null 2>&1; then
  54          local installed_version=$(bun --version)
  55          log_success "Bun $installed_version is already installed"
  56          return 0
  57      else
  58          log_info "Bun is not installed"
  59          return 1
  60      fi
  61  }
  62  
  63  # Install bun
  64  install_bun() {
  65      log_info "Installing Bun..."
  66      
  67      # Install bun using official installer
  68      curl -fsSL https://bun.com/install | bash
  69      
  70      # Source bashrc to pick up bun in current session
  71      if [[ -f "$HOME/.bashrc" ]]; then
  72          source "$HOME/.bashrc"
  73      fi
  74      
  75      # Verify installation
  76      if command -v bun >/dev/null 2>&1; then
  77          log_success "Bun installed successfully"
  78      else
  79          log_error "Failed to install Bun"
  80          exit 1
  81      fi
  82  }
  83  
  84  # Check if Go is installed and get version
  85  check_go_installation() {
  86      if command -v go >/dev/null 2>&1; then
  87          local installed_version=$(go version | grep -o 'go[0-9]\+\.[0-9]\+\.[0-9]\+' | sed 's/go//')
  88          local required_version=$(echo $GO_VERSION | sed 's/go//')
  89          
  90          if [[ "$installed_version" == "$required_version" ]]; then
  91              log_success "Go $installed_version is already installed"
  92              return 0
  93          else
  94              log_warning "Go $installed_version is installed, but version $required_version is required"
  95              return 1
  96          fi
  97      else
  98          log_info "Go is not installed"
  99          return 1
 100      fi
 101  }
 102  
 103  # Install Go
 104  install_go() {
 105      log_info "Installing Go $GO_VERSION..."
 106      
 107      # Save original directory
 108      local original_dir=$(pwd)
 109      
 110      # Determine architecture
 111      local arch=$(uname -m)
 112      case $arch in
 113          x86_64) arch="amd64" ;;
 114          aarch64|arm64) arch="arm64" ;;
 115          armv7l) arch="armv6l" ;;
 116          *) log_error "Unsupported architecture: $arch"; exit 1 ;;
 117      esac
 118      
 119      local go_archive="go${GO_VERSION}.linux-${arch}.tar.gz"
 120      local download_url="https://golang.org/dl/${go_archive}"
 121      
 122      # Remove existing installation if present (before download to save space/time)
 123      if [[ -d "$GOROOT" ]]; then
 124          log_info "Removing existing Go installation..."
 125          # Make it writable in case it's read-only
 126          chmod -R u+w "$GOROOT" 2>/dev/null || true
 127          rm -rf "$GOROOT"
 128      fi
 129      
 130      # Create directories
 131      mkdir -p "$GOBIN"
 132      
 133      # Change to home directory and download Go
 134      log_info "Downloading Go from $download_url..."
 135      cd ~
 136      wget -q "$download_url" || {
 137          log_error "Failed to download Go"
 138          exit 1
 139      }
 140      
 141      # Extract Go to a temporary location first, then move to final destination
 142      log_info "Extracting Go..."
 143      tar -xf "$go_archive" -C /tmp
 144      mv /tmp/go "$GOROOT"
 145  
 146      # Clean up
 147      rm -f "$go_archive"
 148      
 149      # Return to original directory
 150      cd "$original_dir"
 151      
 152      log_success "Go $GO_VERSION installed successfully"
 153  }
 154  
 155  # Setup Go environment
 156  setup_go_environment() {
 157      log_info "Setting up Go environment..."
 158      
 159      # Create .goenv file
 160      cat > "$GOENV_FILE" << EOF
 161  # Go environment configuration
 162  export GOROOT="$GOROOT"
 163  export GOPATH="$GOPATH"
 164  export GOBIN="$GOBIN"
 165  export PATH="\$GOBIN:\$GOROOT/bin:\$PATH"
 166  EOF
 167      
 168      # Source the environment for current session
 169      source "$GOENV_FILE"
 170      
 171      # Add to .bashrc if not already present
 172      if ! grep -q "source $GOENV_FILE" "$BASHRC_FILE" 2>/dev/null; then
 173          log_info "Adding Go environment to $BASHRC_FILE..."
 174          echo "" >> "$BASHRC_FILE"
 175          echo "# Go environment" >> "$BASHRC_FILE"
 176          echo "if [[ -f \"$GOENV_FILE\" ]]; then" >> "$BASHRC_FILE"
 177          echo "    source \"$GOENV_FILE\"" >> "$BASHRC_FILE"
 178          echo "fi" >> "$BASHRC_FILE"
 179          log_success "Go environment added to $BASHRC_FILE"
 180      else
 181          log_info "Go environment already configured in $BASHRC_FILE"
 182      fi
 183  }
 184  
 185  # Build the application
 186  build_application() {
 187      log_info "Building ORLY relay..."
 188      
 189      # Source Go environment
 190      source "$GOENV_FILE"
 191      
 192      # Update embedded web assets
 193      log_info "Updating embedded web assets..."
 194      ./scripts/update-embedded-web.sh
 195      
 196      # Build the binary in the current directory
 197      log_info "Building binary in current directory (pure Go + purego)..."
 198      CGO_ENABLED=0 go build -o "$BINARY_NAME"
 199      
 200      # Verify libsecp256k1.so exists in repo (used by purego for runtime crypto)
 201      if [[ -f "./libsecp256k1.so" ]]; then
 202          chmod +x libsecp256k1.so
 203          log_success "Found libsecp256k1.so in repository"
 204      else
 205          log_warning "libsecp256k1.so not found in repo - relay will still work but may have slower crypto"
 206      fi
 207      
 208      if [[ -f "./$BINARY_NAME" ]]; then
 209          log_success "ORLY relay built successfully"
 210      else
 211          log_error "Failed to build ORLY relay"
 212          exit 1
 213      fi
 214  }
 215  
 216  # Set capabilities for port 443 binding
 217  set_capabilities() {
 218      log_info "Setting capabilities for port 443 binding..."
 219      
 220      if check_root; then
 221          setcap 'cap_net_bind_service=+ep' "./$BINARY_NAME"
 222      else
 223          sudo setcap 'cap_net_bind_service=+ep' "./$BINARY_NAME"
 224      fi
 225      
 226      log_success "Capabilities set for port 443 binding"
 227  }
 228  
 229  # Install binary
 230  install_binary() {
 231      log_info "Installing binary to $GOBIN..."
 232      
 233      # Ensure GOBIN directory exists
 234      mkdir -p "$GOBIN"
 235      
 236      # Copy binary and library
 237      cp "./$BINARY_NAME" "$GOBIN/"
 238      chmod +x "$GOBIN/$BINARY_NAME"
 239      
 240      # Copy library if it exists
 241      if [[ -f "./libsecp256k1.so" ]]; then
 242          cp "./libsecp256k1.so" "$GOBIN/"
 243          log_info "Copied libsecp256k1.so to $GOBIN/"
 244      fi
 245      
 246      log_success "Binary installed to $GOBIN/$BINARY_NAME"
 247  }
 248  
 249  # Create systemd service
 250  create_systemd_service() {
 251      local port="$1"
 252      log_info "Creating systemd service (port: $port)..."
 253  
 254      local service_file="/etc/systemd/system/${SERVICE_NAME}.service"
 255      local working_dir=$(pwd)
 256  
 257      # Create service file content
 258      local service_content="[Unit]
 259  Description=ORLY Nostr Relay
 260  After=network.target
 261  Wants=network.target
 262  
 263  [Service]
 264  Type=simple
 265  User=$USER
 266  Group=$USER
 267  WorkingDirectory=$working_dir
 268  Environment=ORLY_PORT=$port
 269  ExecStart=$GOBIN/$BINARY_NAME
 270  Restart=always
 271  RestartSec=5
 272  StandardOutput=journal
 273  StandardError=journal
 274  SyslogIdentifier=$SERVICE_NAME
 275  
 276  # Network settings
 277  AmbientCapabilities=CAP_NET_BIND_SERVICE
 278  
 279  [Install]
 280  WantedBy=multi-user.target"
 281  
 282      # Write service file
 283      if check_root; then
 284          echo "$service_content" > "$service_file"
 285      else
 286          echo "$service_content" | sudo tee "$service_file" > /dev/null
 287      fi
 288      
 289      # Reload systemd and enable service
 290      if check_root; then
 291          systemctl daemon-reload
 292          systemctl enable "$SERVICE_NAME"
 293      else
 294          sudo systemctl daemon-reload
 295          sudo systemctl enable "$SERVICE_NAME"
 296      fi
 297      
 298      log_success "Systemd service created and enabled"
 299  }
 300  
 301  # Main deployment function
 302  main() {
 303      local port="${1:-3334}"
 304      log_info "Starting ORLY relay deployment (port: $port)..."
 305  
 306      # Check if we're in the right directory
 307      if [[ ! -f "go.mod" ]] || ! grep -q "next.orly.dev" go.mod; then
 308          log_error "This script must be run from the next.orly.dev project root directory"
 309          exit 1
 310      fi
 311  
 312      # Check and install Bun if needed
 313      if ! check_bun_installation; then
 314          install_bun
 315      fi
 316  
 317      # Check and install Go if needed
 318      if ! check_go_installation; then
 319          install_go
 320          setup_go_environment
 321      fi
 322  
 323      # Build application
 324      build_application
 325  
 326      # Set capabilities
 327      set_capabilities
 328  
 329      # Install binary
 330      install_binary
 331  
 332      # Create systemd service
 333      create_systemd_service "$port"
 334      
 335      log_success "ORLY relay deployment completed successfully!"
 336      echo ""
 337      log_info "Next steps:"
 338      echo "  1. Reload your terminal environment: source ~/.bashrc"
 339      echo "  2. Configure your relay by setting environment variables"
 340      echo "  3. Start the service: sudo systemctl start $SERVICE_NAME"
 341      echo "  4. Check service status: sudo systemctl status $SERVICE_NAME"
 342      echo "  5. View logs: sudo journalctl -u $SERVICE_NAME -f"
 343      echo ""
 344      log_info "Service management commands:"
 345      echo "  Start:   sudo systemctl start $SERVICE_NAME"
 346      echo "  Stop:    sudo systemctl stop $SERVICE_NAME"
 347      echo "  Restart: sudo systemctl restart $SERVICE_NAME"
 348      echo "  Enable:  sudo systemctl enable $SERVICE_NAME --now"
 349      echo "  Disable: sudo systemctl disable $SERVICE_NAME --now"
 350      echo "  Status:  sudo systemctl status $SERVICE_NAME"
 351      echo "  Logs:    sudo journalctl -u $SERVICE_NAME -f"
 352  }
 353  
 354  # Handle command line arguments
 355  PORT=""
 356  case "${1:-}" in
 357      --help|-h)
 358          echo "ORLY Relay Deployment Script"
 359          echo ""
 360          echo "Usage: $0 [options] [port]"
 361          echo ""
 362          echo "Arguments:"
 363          echo "  port         Port number for the relay to listen on (default: 3334)"
 364          echo ""
 365          echo "Options:"
 366          echo "  --help, -h   Show this help message"
 367          echo ""
 368          echo "This script will:"
 369          echo "  1. Install Bun if not present"
 370          echo "  2. Install Go $GO_VERSION if not present"
 371          echo "  3. Set up Go environment in ~/.goenv"
 372          echo "  4. Install build dependencies (requires sudo)"
 373          echo "  5. Build the ORLY relay"
 374          echo "  6. Set capabilities for port 443 binding"
 375          echo "  7. Install the binary to ~/.local/bin"
 376          echo "  8. Create and enable systemd service"
 377          echo ""
 378          echo "Examples:"
 379          echo "  $0              # Deploy with default port 3334"
 380          echo "  $0 8080         # Deploy with port 8080"
 381          exit 0
 382          ;;
 383      [0-9]*)
 384          # First argument is a number, treat it as port
 385          PORT="$1"
 386          shift
 387          main "$PORT" "$@"
 388          ;;
 389      *)
 390          main "$@"
 391          ;;
 392  esac
 393