|
|
@@ -0,0 +1,555 @@
|
|
|
+#!/bin/bash
|
|
|
+# Smartbotic Service Installer
|
|
|
+# Installs Smartbotic service packages with config preservation and proper security
|
|
|
+#
|
|
|
+# Usage:
|
|
|
+# sudo ./install.sh smartbotic-*.tar.gz
|
|
|
+# sudo ./install.sh --dry-run smartbotic-database-*.tar.gz smartbotic-microbit-*.tar.gz
|
|
|
+
|
|
|
+set -e
|
|
|
+
|
|
|
+# Default paths
|
|
|
+PREFIX="/opt/smartbotic"
|
|
|
+BINDIR="$PREFIX/bin"
|
|
|
+CONFDIR="/etc/smartbotic"
|
|
|
+DATADIR="/var/lib/smartbotic"
|
|
|
+LOGDIR="/var/log/smartbotic"
|
|
|
+SYSTEMD_DIR="/etc/systemd/system"
|
|
|
+
|
|
|
+# Smartbotic system user
|
|
|
+SMARTBOTIC_USER="smartbotic"
|
|
|
+SMARTBOTIC_GROUP="smartbotic"
|
|
|
+
|
|
|
+# Log file (set after PREFIX is finalized)
|
|
|
+INSTALL_LOG=""
|
|
|
+
|
|
|
+# Output control
|
|
|
+VERBOSE=false
|
|
|
+QUIET=false
|
|
|
+
|
|
|
+# Colors for output
|
|
|
+RED='\033[0;31m'
|
|
|
+GREEN='\033[0;32m'
|
|
|
+YELLOW='\033[1;33m'
|
|
|
+BLUE='\033[0;34m'
|
|
|
+NC='\033[0m'
|
|
|
+
|
|
|
+# Initialize logging
|
|
|
+init_logging() {
|
|
|
+ mkdir -p "$PREFIX"
|
|
|
+ INSTALL_LOG="$PREFIX/install-$(date +%Y%m%d-%H%M%S).log"
|
|
|
+ echo "Smartbotic Install Log - $(date)" > "$INSTALL_LOG"
|
|
|
+ echo "Command: $0 $ORIGINAL_ARGS" >> "$INSTALL_LOG"
|
|
|
+ echo "========================================" >> "$INSTALL_LOG"
|
|
|
+}
|
|
|
+
|
|
|
+# Log to file only
|
|
|
+log() {
|
|
|
+ echo "[$(date +%H:%M:%S)] $1" >> "$INSTALL_LOG"
|
|
|
+}
|
|
|
+
|
|
|
+# Print to console (respects quiet mode)
|
|
|
+print_info() {
|
|
|
+ log "INFO: $1"
|
|
|
+ if [ "$QUIET" = false ]; then
|
|
|
+ if [ "$VERBOSE" = true ]; then
|
|
|
+ echo -e "${GREEN}[INFO]${NC} $1"
|
|
|
+ fi
|
|
|
+ fi
|
|
|
+}
|
|
|
+
|
|
|
+print_warn() {
|
|
|
+ log "WARN: $1"
|
|
|
+ if [ "$QUIET" = false ]; then
|
|
|
+ echo -e "${YELLOW}[WARN]${NC} $1"
|
|
|
+ fi
|
|
|
+}
|
|
|
+
|
|
|
+print_error() {
|
|
|
+ log "ERROR: $1"
|
|
|
+ echo -e "${RED}[ERROR]${NC} $1" >&2
|
|
|
+}
|
|
|
+
|
|
|
+# Always show steps (progress indicator)
|
|
|
+print_step() {
|
|
|
+ log "STEP: $1"
|
|
|
+ if [ "$QUIET" = false ]; then
|
|
|
+ echo -e "${BLUE}▶${NC} $1"
|
|
|
+ fi
|
|
|
+}
|
|
|
+
|
|
|
+# Summary line (always shown unless quiet)
|
|
|
+print_summary() {
|
|
|
+ log "SUMMARY: $1"
|
|
|
+ if [ "$QUIET" = false ]; then
|
|
|
+ echo -e " ${GREEN}✓${NC} $1"
|
|
|
+ fi
|
|
|
+}
|
|
|
+
|
|
|
+usage() {
|
|
|
+ cat <<EOF
|
|
|
+Smartbotic Service Installer
|
|
|
+
|
|
|
+Usage: $0 [OPTIONS] PACKAGE.tar.gz [PACKAGE2.tar.gz ...]
|
|
|
+
|
|
|
+Options:
|
|
|
+ --prefix DIR Install prefix (default: /opt/smartbotic)
|
|
|
+ --confdir DIR Config directory (default: /etc/smartbotic)
|
|
|
+ --user USER Service user (default: smartbotic)
|
|
|
+ --group GROUP Service group (default: smartbotic)
|
|
|
+ --no-systemd Skip systemd service installation
|
|
|
+ --no-user Skip user/group creation (use existing)
|
|
|
+ --no-deps Skip apt dependency installation
|
|
|
+ --preserve-all Preserve all existing files (no overwrites)
|
|
|
+ --force Overwrite existing binaries
|
|
|
+ --dry-run Show what would be done without making changes
|
|
|
+ -v, --verbose Show detailed output
|
|
|
+ -q, --quiet Minimal output (errors only)
|
|
|
+ -h, --help Show this help
|
|
|
+
|
|
|
+Log file: Install details are logged to \$PREFIX/install-YYYYMMDD-HHMMSS.log
|
|
|
+
|
|
|
+Examples:
|
|
|
+ # Install all packages (minimal output)
|
|
|
+ sudo $0 smartbotic-*.tar.gz
|
|
|
+
|
|
|
+ # Install with verbose output
|
|
|
+ sudo $0 -v smartbotic-*.tar.gz
|
|
|
+
|
|
|
+ # Test installation
|
|
|
+ $0 --dry-run smartbotic-*.tar.gz
|
|
|
+EOF
|
|
|
+}
|
|
|
+
|
|
|
+# Parse arguments
|
|
|
+NO_SYSTEMD=false
|
|
|
+NO_USER=false
|
|
|
+NO_DEPS=false
|
|
|
+PRESERVE_ALL=false
|
|
|
+FORCE=false
|
|
|
+DRY_RUN=false
|
|
|
+PACKAGES=()
|
|
|
+ALL_DEPS=""
|
|
|
+ORIGINAL_ARGS="$*"
|
|
|
+
|
|
|
+while [[ $# -gt 0 ]]; do
|
|
|
+ case $1 in
|
|
|
+ --prefix)
|
|
|
+ PREFIX="$2"
|
|
|
+ BINDIR="$PREFIX/bin"
|
|
|
+ shift 2
|
|
|
+ ;;
|
|
|
+ --confdir)
|
|
|
+ CONFDIR="$2"
|
|
|
+ shift 2
|
|
|
+ ;;
|
|
|
+ --user)
|
|
|
+ SMARTBOTIC_USER="$2"
|
|
|
+ shift 2
|
|
|
+ ;;
|
|
|
+ --group)
|
|
|
+ SMARTBOTIC_GROUP="$2"
|
|
|
+ shift 2
|
|
|
+ ;;
|
|
|
+ --no-systemd)
|
|
|
+ NO_SYSTEMD=true
|
|
|
+ shift
|
|
|
+ ;;
|
|
|
+ --no-user)
|
|
|
+ NO_USER=true
|
|
|
+ shift
|
|
|
+ ;;
|
|
|
+ --no-deps)
|
|
|
+ NO_DEPS=true
|
|
|
+ shift
|
|
|
+ ;;
|
|
|
+ --preserve-all)
|
|
|
+ PRESERVE_ALL=true
|
|
|
+ shift
|
|
|
+ ;;
|
|
|
+ --force)
|
|
|
+ FORCE=true
|
|
|
+ shift
|
|
|
+ ;;
|
|
|
+ --dry-run)
|
|
|
+ DRY_RUN=true
|
|
|
+ shift
|
|
|
+ ;;
|
|
|
+ -v|--verbose)
|
|
|
+ VERBOSE=true
|
|
|
+ shift
|
|
|
+ ;;
|
|
|
+ -q|--quiet)
|
|
|
+ QUIET=true
|
|
|
+ shift
|
|
|
+ ;;
|
|
|
+ -h|--help)
|
|
|
+ usage
|
|
|
+ exit 0
|
|
|
+ ;;
|
|
|
+ -*)
|
|
|
+ print_error "Unknown option: $1"
|
|
|
+ usage
|
|
|
+ exit 1
|
|
|
+ ;;
|
|
|
+ *)
|
|
|
+ PACKAGES+=("$1")
|
|
|
+ shift
|
|
|
+ ;;
|
|
|
+ esac
|
|
|
+done
|
|
|
+
|
|
|
+if [ ${#PACKAGES[@]} -eq 0 ]; then
|
|
|
+ print_error "No packages specified"
|
|
|
+ usage
|
|
|
+ exit 1
|
|
|
+fi
|
|
|
+
|
|
|
+# Check root privileges
|
|
|
+if [ "$EUID" -ne 0 ] && [ "$DRY_RUN" = false ]; then
|
|
|
+ print_error "This script must be run as root (or use --dry-run)"
|
|
|
+ exit 1
|
|
|
+fi
|
|
|
+
|
|
|
+# Run command, log output
|
|
|
+run_cmd() {
|
|
|
+ log "CMD: $*"
|
|
|
+ if [ "$DRY_RUN" = true ]; then
|
|
|
+ log " [DRY-RUN] Skipped"
|
|
|
+ if [ "$VERBOSE" = true ]; then
|
|
|
+ echo " [DRY-RUN] $*"
|
|
|
+ fi
|
|
|
+ else
|
|
|
+ local output
|
|
|
+ if output=$("$@" 2>&1); then
|
|
|
+ if [ -n "$output" ]; then
|
|
|
+ echo "$output" >> "$INSTALL_LOG"
|
|
|
+ fi
|
|
|
+ else
|
|
|
+ local exit_code=$?
|
|
|
+ if [ -n "$output" ]; then
|
|
|
+ echo "$output" >> "$INSTALL_LOG"
|
|
|
+ fi
|
|
|
+ return $exit_code
|
|
|
+ fi
|
|
|
+ fi
|
|
|
+}
|
|
|
+
|
|
|
+# Collect dependencies from package
|
|
|
+collect_deps() {
|
|
|
+ local deps="$1"
|
|
|
+ if [ -n "$deps" ]; then
|
|
|
+ for dep in $deps; do
|
|
|
+ if [[ ! " $ALL_DEPS " =~ " $dep " ]]; then
|
|
|
+ ALL_DEPS="$ALL_DEPS $dep"
|
|
|
+ fi
|
|
|
+ done
|
|
|
+ fi
|
|
|
+}
|
|
|
+
|
|
|
+# Install all collected dependencies
|
|
|
+install_deps() {
|
|
|
+ if [ "$NO_DEPS" = true ]; then
|
|
|
+ print_info "Skipping dependency installation (--no-deps)"
|
|
|
+ return
|
|
|
+ fi
|
|
|
+
|
|
|
+ ALL_DEPS=$(echo "$ALL_DEPS" | xargs)
|
|
|
+
|
|
|
+ if [ -z "$ALL_DEPS" ]; then
|
|
|
+ print_info "No dependencies to install"
|
|
|
+ return
|
|
|
+ fi
|
|
|
+
|
|
|
+ print_step "Installing dependencies..."
|
|
|
+ log "Dependencies: $ALL_DEPS"
|
|
|
+
|
|
|
+ if [ "$DRY_RUN" = true ]; then
|
|
|
+ log "[DRY-RUN] apt-get update && apt-get install -y $ALL_DEPS"
|
|
|
+ else
|
|
|
+ apt-get update -qq >> "$INSTALL_LOG" 2>&1
|
|
|
+ apt-get install -y --no-install-recommends $ALL_DEPS >> "$INSTALL_LOG" 2>&1
|
|
|
+ fi
|
|
|
+ print_summary "Dependencies installed"
|
|
|
+}
|
|
|
+
|
|
|
+# Create system user and group
|
|
|
+create_user() {
|
|
|
+ if [ "$NO_USER" = true ]; then
|
|
|
+ print_info "Skipping user creation (--no-user)"
|
|
|
+ return
|
|
|
+ fi
|
|
|
+
|
|
|
+ print_step "Setting up system user..."
|
|
|
+
|
|
|
+ if ! getent group "$SMARTBOTIC_GROUP" > /dev/null 2>&1; then
|
|
|
+ log "Creating group: $SMARTBOTIC_GROUP"
|
|
|
+ run_cmd groupadd --system "$SMARTBOTIC_GROUP"
|
|
|
+ fi
|
|
|
+
|
|
|
+ if ! getent passwd "$SMARTBOTIC_USER" > /dev/null 2>&1; then
|
|
|
+ log "Creating user: $SMARTBOTIC_USER"
|
|
|
+ run_cmd useradd --system \
|
|
|
+ --gid "$SMARTBOTIC_GROUP" \
|
|
|
+ --home-dir "$DATADIR" \
|
|
|
+ --shell /usr/sbin/nologin \
|
|
|
+ --comment "Smartbotic Service User" \
|
|
|
+ "$SMARTBOTIC_USER"
|
|
|
+ fi
|
|
|
+ print_summary "User $SMARTBOTIC_USER ready"
|
|
|
+}
|
|
|
+
|
|
|
+# Create directory structure
|
|
|
+create_directories() {
|
|
|
+ print_step "Creating directories..."
|
|
|
+
|
|
|
+ local dirs=(
|
|
|
+ "$PREFIX"
|
|
|
+ "$BINDIR"
|
|
|
+ "$PREFIX/share/smartbotic/nginx"
|
|
|
+ "$CONFDIR"
|
|
|
+ "$DATADIR"
|
|
|
+ "$DATADIR/database"
|
|
|
+ "$DATADIR/database/storage"
|
|
|
+ "$DATADIR/database/migrations"
|
|
|
+ "$DATADIR/microbit"
|
|
|
+ "$DATADIR/microbit/webui"
|
|
|
+ "$LOGDIR"
|
|
|
+ )
|
|
|
+
|
|
|
+ for dir in "${dirs[@]}"; do
|
|
|
+ if [ ! -d "$dir" ]; then
|
|
|
+ log "Creating: $dir"
|
|
|
+ run_cmd mkdir -p "$dir"
|
|
|
+ fi
|
|
|
+ done
|
|
|
+
|
|
|
+ if [ "$DRY_RUN" = false ]; then
|
|
|
+ chown -R "$SMARTBOTIC_USER:$SMARTBOTIC_GROUP" "$DATADIR" "$LOGDIR"
|
|
|
+ chown root:"$SMARTBOTIC_GROUP" "$CONFDIR"
|
|
|
+ chmod 750 "$CONFDIR"
|
|
|
+ fi
|
|
|
+ print_summary "Directories created"
|
|
|
+}
|
|
|
+
|
|
|
+# Install a single package
|
|
|
+install_package() {
|
|
|
+ local pkg="$1"
|
|
|
+ local pkg_basename=$(basename "$pkg")
|
|
|
+ local pkg_name="${pkg_basename%.tar.gz}"
|
|
|
+ # Extract short name (e.g., "database" from "smartbotic-database-0.1.0-debian13")
|
|
|
+ local short_name=$(echo "$pkg_name" | sed -E 's/smartbotic-([^-]+).*/\1/')
|
|
|
+
|
|
|
+ print_step "Installing $short_name..."
|
|
|
+
|
|
|
+ local tmpdir
|
|
|
+ tmpdir=$(mktemp -d)
|
|
|
+ trap "rm -rf '$tmpdir'" RETURN
|
|
|
+
|
|
|
+ tar -xzf "$pkg" -C "$tmpdir"
|
|
|
+
|
|
|
+ local pkg_root="$tmpdir/$pkg_name"
|
|
|
+ if [ ! -d "$pkg_root" ]; then
|
|
|
+ pkg_root=$(find "$tmpdir" -maxdepth 1 -type d ! -path "$tmpdir" | head -1)
|
|
|
+ fi
|
|
|
+
|
|
|
+ if [ ! -d "$pkg_root" ]; then
|
|
|
+ print_error "Could not find package root in archive"
|
|
|
+ return 1
|
|
|
+ fi
|
|
|
+
|
|
|
+ # Collect dependencies
|
|
|
+ if [ -f "$pkg_root/DEPS" ]; then
|
|
|
+ collect_deps "$(cat "$pkg_root/DEPS")"
|
|
|
+ fi
|
|
|
+
|
|
|
+ local installed_items=()
|
|
|
+
|
|
|
+ # Install binaries
|
|
|
+ if [ -d "$pkg_root/bin" ]; then
|
|
|
+ for binary in "$pkg_root/bin"/*; do
|
|
|
+ if [ -f "$binary" ]; then
|
|
|
+ local bin_name=$(basename "$binary")
|
|
|
+ local dest="$BINDIR/$bin_name"
|
|
|
+
|
|
|
+ if [ -f "$dest" ] && [ "$FORCE" = false ] && [ "$PRESERVE_ALL" = true ]; then
|
|
|
+ log "Skipping existing: $dest"
|
|
|
+ else
|
|
|
+ log "Installing binary: $dest"
|
|
|
+ run_cmd install -m 755 "$binary" "$dest"
|
|
|
+ installed_items+=("binary")
|
|
|
+ fi
|
|
|
+ fi
|
|
|
+ done
|
|
|
+ fi
|
|
|
+
|
|
|
+ # Install configs (never overwrite existing)
|
|
|
+ if [ -d "$pkg_root/etc/smartbotic" ]; then
|
|
|
+ for cfg in "$pkg_root/etc/smartbotic"/*; do
|
|
|
+ if [ -f "$cfg" ]; then
|
|
|
+ local cfg_name=$(basename "$cfg")
|
|
|
+ local dest_name="${cfg_name%.default}"
|
|
|
+ local dest="$CONFDIR/$dest_name"
|
|
|
+
|
|
|
+ if [ -f "$dest" ]; then
|
|
|
+ log "Config exists, preserving: $dest"
|
|
|
+ if [ "$DRY_RUN" = false ]; then
|
|
|
+ cp "$cfg" "$dest.new"
|
|
|
+ chown root:"$SMARTBOTIC_GROUP" "$dest.new"
|
|
|
+ chmod 640 "$dest.new"
|
|
|
+ fi
|
|
|
+ else
|
|
|
+ log "Installing config: $dest"
|
|
|
+ run_cmd install -m 640 -o root -g "$SMARTBOTIC_GROUP" "$cfg" "$dest"
|
|
|
+ installed_items+=("config")
|
|
|
+ fi
|
|
|
+ fi
|
|
|
+ done
|
|
|
+ fi
|
|
|
+
|
|
|
+ # Install systemd services
|
|
|
+ if [ -d "$pkg_root/etc/systemd/system" ] && [ "$NO_SYSTEMD" = false ]; then
|
|
|
+ for service in "$pkg_root/etc/systemd/system"/*.service; do
|
|
|
+ if [ -f "$service" ]; then
|
|
|
+ local svc_name=$(basename "$service")
|
|
|
+ log "Installing systemd service: $svc_name"
|
|
|
+ run_cmd install -m 644 "$service" "$SYSTEMD_DIR/$svc_name"
|
|
|
+ installed_items+=("service")
|
|
|
+ fi
|
|
|
+ done
|
|
|
+ fi
|
|
|
+
|
|
|
+ # Install data files
|
|
|
+ if [ -d "$pkg_root/share/smartbotic" ]; then
|
|
|
+ log "Installing data files..."
|
|
|
+ if [ "$DRY_RUN" = false ]; then
|
|
|
+ # WebUI files
|
|
|
+ if [ -d "$pkg_root/share/smartbotic/webui" ]; then
|
|
|
+ rm -rf "$DATADIR/microbit/webui"/*
|
|
|
+ cp -a "$pkg_root/share/smartbotic/webui"/* "$DATADIR/microbit/webui/" 2>/dev/null || true
|
|
|
+ installed_items+=("webui")
|
|
|
+ fi
|
|
|
+
|
|
|
+ # Database migrations
|
|
|
+ if [ -d "$pkg_root/share/smartbotic/database/migrations" ]; then
|
|
|
+ cp -a "$pkg_root/share/smartbotic/database/migrations"/* "$DATADIR/database/migrations/" 2>/dev/null || true
|
|
|
+ installed_items+=("migrations")
|
|
|
+ fi
|
|
|
+
|
|
|
+ # Nginx template
|
|
|
+ if [ -d "$pkg_root/share/smartbotic/nginx" ]; then
|
|
|
+ cp -a "$pkg_root/share/smartbotic/nginx"/* "$PREFIX/share/smartbotic/nginx/" 2>/dev/null || true
|
|
|
+ installed_items+=("nginx")
|
|
|
+ fi
|
|
|
+
|
|
|
+ chown -R "$SMARTBOTIC_USER:$SMARTBOTIC_GROUP" "$DATADIR"
|
|
|
+ fi
|
|
|
+ fi
|
|
|
+
|
|
|
+ print_summary "$short_name installed"
|
|
|
+}
|
|
|
+
|
|
|
+# Main installation
|
|
|
+main() {
|
|
|
+ # Initialize logging first
|
|
|
+ init_logging
|
|
|
+
|
|
|
+ if [ "$QUIET" = false ]; then
|
|
|
+ echo ""
|
|
|
+ echo -e "${GREEN}Smartbotic Installer${NC}"
|
|
|
+ echo "===================="
|
|
|
+ fi
|
|
|
+
|
|
|
+ log "PREFIX=$PREFIX"
|
|
|
+ log "CONFDIR=$CONFDIR"
|
|
|
+ log "DATADIR=$DATADIR"
|
|
|
+ log "USER=$SMARTBOTIC_USER"
|
|
|
+ log "PACKAGES=${#PACKAGES[@]}"
|
|
|
+
|
|
|
+ if [ "$DRY_RUN" = true ]; then
|
|
|
+ print_warn "DRY-RUN MODE - no changes will be made"
|
|
|
+ fi
|
|
|
+
|
|
|
+ # Create user and directories
|
|
|
+ create_user
|
|
|
+ create_directories
|
|
|
+
|
|
|
+ # Sort packages: database first, then microbit, then webui, then others
|
|
|
+ local sorted_packages=()
|
|
|
+ local database_pkg=""
|
|
|
+ local microbit_pkg=""
|
|
|
+ local webui_pkg=""
|
|
|
+ local other_packages=()
|
|
|
+
|
|
|
+ for pkg in "${PACKAGES[@]}"; do
|
|
|
+ case "$pkg" in
|
|
|
+ *smartbotic-database*) database_pkg="$pkg" ;;
|
|
|
+ *smartbotic-microbit*) microbit_pkg="$pkg" ;;
|
|
|
+ *smartbotic-webui*) webui_pkg="$pkg" ;;
|
|
|
+ *) other_packages+=("$pkg") ;;
|
|
|
+ esac
|
|
|
+ done
|
|
|
+
|
|
|
+ [ -n "$database_pkg" ] && sorted_packages+=("$database_pkg")
|
|
|
+ [ -n "$microbit_pkg" ] && sorted_packages+=("$microbit_pkg")
|
|
|
+ [ -n "$webui_pkg" ] && sorted_packages+=("$webui_pkg")
|
|
|
+ sorted_packages+=("${other_packages[@]}")
|
|
|
+
|
|
|
+ # First pass: collect dependencies
|
|
|
+ for pkg in "${sorted_packages[@]}"; do
|
|
|
+ if [ -f "$pkg" ]; then
|
|
|
+ local tmpdir=$(mktemp -d)
|
|
|
+ tar -xzf "$pkg" -C "$tmpdir" 2>/dev/null
|
|
|
+ local pkg_root=$(find "$tmpdir" -maxdepth 1 -type d ! -path "$tmpdir" | head -1)
|
|
|
+ if [ -f "$pkg_root/DEPS" ]; then
|
|
|
+ collect_deps "$(cat "$pkg_root/DEPS")"
|
|
|
+ fi
|
|
|
+ rm -rf "$tmpdir"
|
|
|
+ fi
|
|
|
+ done
|
|
|
+
|
|
|
+ # Install dependencies
|
|
|
+ install_deps
|
|
|
+
|
|
|
+ # Install packages
|
|
|
+ for pkg in "${sorted_packages[@]}"; do
|
|
|
+ if [ ! -f "$pkg" ]; then
|
|
|
+ print_error "Package not found: $pkg"
|
|
|
+ continue
|
|
|
+ fi
|
|
|
+ install_package "$pkg"
|
|
|
+ done
|
|
|
+
|
|
|
+ # Post-installation
|
|
|
+ print_step "Finalizing..."
|
|
|
+
|
|
|
+ if [ "$NO_SYSTEMD" = false ] && [ "$DRY_RUN" = false ]; then
|
|
|
+ log "Reloading systemd daemon..."
|
|
|
+ systemctl daemon-reload >> "$INSTALL_LOG" 2>&1
|
|
|
+ fi
|
|
|
+
|
|
|
+ print_summary "Installation complete"
|
|
|
+
|
|
|
+ if [ "$QUIET" = false ]; then
|
|
|
+ echo ""
|
|
|
+ echo -e "${GREEN}Done!${NC} Log: $INSTALL_LOG"
|
|
|
+ echo ""
|
|
|
+ echo "Next steps:"
|
|
|
+ echo " 1. Configure: $CONFDIR/smartbotic.env"
|
|
|
+ echo " (copy from $CONFDIR/smartbotic.env.default if not exists)"
|
|
|
+ echo " Set JWT_SECRET, SMTP, and CallerAI API settings"
|
|
|
+ echo " 2. Review configs: $CONFDIR/database.json, $CONFDIR/microbit.json"
|
|
|
+ echo " 3. Enable services:"
|
|
|
+ echo " systemctl enable smartbotic-database smartbotic-microbit"
|
|
|
+ echo " 4. Start services:"
|
|
|
+ echo " systemctl start smartbotic-database"
|
|
|
+ echo " systemctl start smartbotic-microbit"
|
|
|
+ echo " 5. Setup nginx (optional):"
|
|
|
+ echo " $BINDIR/smartbotic-setup-nginx --domain example.com --email admin@example.com"
|
|
|
+ echo ""
|
|
|
+ fi
|
|
|
+
|
|
|
+ log "Installation completed successfully"
|
|
|
+}
|
|
|
+
|
|
|
+main
|