#!/usr/bin/env bash # ============================================================================== # AgenticSeek Deployment Script (Docker Compose + Traefik) # ============================================================================== # Clones and deploys AgenticSeek (multi-container) behind Traefik. # Source: https://github.com/Fosowl/agenticSeek # # Usage: deploy-docker-agenticseek.sh # deploy-docker-agenticseek.sh --domain agent.an2.io # deploy-docker-agenticseek.sh --remove [--purge] [--yes] # ============================================================================== set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" source "${SCRIPT_DIR}/common.sh" # --- Parse arguments --- parse_args "$@" # --- Service config --- SERVICE_NAME="agenticseek" BASE_DIR="/opt/${SERVICE_NAME}" CONFIG_NAME="${SERVICE_NAME}" UNIT_NAME="${SERVICE_NAME}-docker" AGENTICSEEK_REPO="${AGENTICSEEK_REPO:-https://github.com/Fosowl/agenticSeek.git}" # --- Handle --remove --- if [[ "$ARG_REMOVE" == "1" ]]; then require_root do_remove "$SERVICE_NAME" "$CONFIG_NAME" "$UNIT_NAME" "$BASE_DIR" exit 0 fi # --- Domain resolution --- if [[ -n "$ARG_DOMAIN" ]]; then DOMAIN="$ARG_DOMAIN" elif [[ -f "${BASE_DIR}/.env" ]] && grep -q '^DOMAIN=' "${BASE_DIR}/.env"; then DOMAIN="$(grep '^DOMAIN=' "${BASE_DIR}/.env" | cut -d= -f2)" else DOMAIN="seek.an2.io" fi # --- Detect current state for banner --- traefik_status="Not found — will deploy" if docker ps --format '{{.Names}}' 2>/dev/null | grep -q '^traefik$'; then traefik_status="Running" elif [[ -f "${TRAEFIK_DIR}/docker-compose.yml" ]]; then traefik_status="Stopped — will start" fi install_mode="Fresh install" if [[ -f "${BASE_DIR}/.env" ]]; then install_mode="Re-run (preserving data)" fi # --- Print deployment plan --- echo "" echo -e "${CYAN}══════════════════════════════════════════════${NC}" echo -e "${CYAN} Deploying AgenticSeek (Docker)${NC}" echo -e "${CYAN}══════════════════════════════════════════════${NC}" echo -e " Domain: ${DOMAIN}" echo -e " Data: ${BASE_DIR}" echo -e " Traefik: ${traefik_status}" echo -e " Mode: ${install_mode}" echo -e "${CYAN}══════════════════════════════════════════════${NC}" echo "" # --- Check if already deployed and running --- # AgenticSeek uses repo compose — check for frontend container if [[ -f "${BASE_DIR}/docker-compose.yml" ]] && \ docker compose -f "${BASE_DIR}/docker-compose.yml" ps --format '{{.State}}' 2>/dev/null | grep -q 'running'; then echo -e "${GREEN} AgenticSeek is already running — nothing to do.${NC}" echo "" echo -e " Logs: cd ${BASE_DIR} && docker compose logs -f" echo -e " Backup: ${SCRIPT_DIR}/backup-agenticseek.sh" echo -e " Remove: $0 --remove [--purge]" echo "" exit 0 fi # --- Shared infrastructure --- require_root detect_os install_prerequisites ensure_docker_network ensure_traefik configure_firewall # --- Backup restore check --- if check_and_restore_backup "$SERVICE_NAME"; then saved_domain="$DOMAIN" # shellcheck source=/dev/null source "${BASE_DIR}/.env" DOMAIN="$saved_domain" else # --- Fresh install / update --- # Clone or update repo if [[ -d "${BASE_DIR}/.git" ]]; then info "Updating AgenticSeek source..." (cd "$BASE_DIR" && git pull) else info "Cloning AgenticSeek from ${AGENTICSEEK_REPO}..." git clone "$AGENTICSEEK_REPO" "$BASE_DIR" fi # Set up .env from example if fresh if [[ ! -f "${BASE_DIR}/.env" ]] && [[ -f "${BASE_DIR}/.env.example" ]]; then cp "${BASE_DIR}/.env.example" "${BASE_DIR}/.env" fi # Ensure our DOMAIN is in .env if grep -q '^DOMAIN=' "${BASE_DIR}/.env" 2>/dev/null; then sed -i "s|^DOMAIN=.*|DOMAIN=${DOMAIN}|" "${BASE_DIR}/.env" else echo "DOMAIN=${DOMAIN}" >> "${BASE_DIR}/.env" fi chmod 600 "${BASE_DIR}/.env" mkdir -p "${BASE_DIR}/data" # Create override to add traefik-public network to frontend cat > "${BASE_DIR}/docker-compose.override.yml" <<'OVERRIDE' services: frontend: networks: - default - traefik-public networks: traefik-public: external: true OVERRIDE ok "docker-compose.override.yml written (traefik-public network)." fi # --- Always do these (fresh or restored) --- write_traefik_dynamic_config "$CONFIG_NAME" "$DOMAIN" "http://frontend:3000" # AgenticSeek uses repo compose + our override — no custom systemd unit for compose # since the compose file is the repo's own, install unit pointing to BASE_DIR install_systemd_unit "$UNIT_NAME" "$BASE_DIR" (cd "$BASE_DIR" && docker compose up -d --build) info "Waiting for AgenticSeek frontend (up to 120s)..." elapsed=0 while (( elapsed < 120 )); do if curl -sf "http://localhost:3000" > /dev/null 2>&1; then ok "AgenticSeek frontend is responding." break fi sleep 5 (( elapsed += 5 )) done if (( elapsed >= 120 )); then warn "Frontend did not respond within 120s. Check: cd ${BASE_DIR} && docker compose logs" fi # --- Summary --- echo "" echo -e "${GREEN}══════════════════════════════════════════════${NC}" echo -e "${GREEN} AgenticSeek deployed successfully${NC}" echo -e "${GREEN}══════════════════════════════════════════════${NC}" echo -e " URL: https://${DOMAIN}" echo -e " Data: ${BASE_DIR}/data/" echo -e " Traefik: ${TRAEFIK_DYNAMIC_DIR}/${CONFIG_NAME}.yml" echo -e " Systemd: systemctl status ${UNIT_NAME}" echo -e " Logs: cd ${BASE_DIR} && docker compose logs -f" echo "" echo -e " ${YELLOW}Configure API keys in ${BASE_DIR}/.env${NC}" echo -e "${GREEN}══════════════════════════════════════════════${NC}" echo ""