#!/usr/bin/env bash # Copyright © 2018-2027 Tag-Insights LLC. All Rights Reserved. Proprietary and Confidential. - The reproduction, adaptation, distribution, display, or transmission of the content is strictly prohibited, unless authorized by Tag-Insights LLC. All other company & product names may be trademarks of the respective companies with which they are associated. #------------------------------------------------------------------------------------------------------- # * Version: 0.1.1 - Updated: 2026-07-07 # Updated by: AI (Claude Fable 5) # - [2026-07-07 v0.1.1] First-run setup: when config.txt is empty, run an interactive 'mag_monitor.py --setup' container first (generates encryption key, prompts for MagnetoAI credentials, saves encrypted config.txt) before starting the detached service; MAGNETO_EMAIL/MAGNETO_PASSWORD env passthrough for non-interactive provisioning - AI Claude Fable 5 # - [2026-07-07 v0.1.0] Initial: pulls magnetoai/mag_monitor:latest and (re)starts it as an always-on service ('--restart unless-stopped', detached); mounts config/settings/key/db+log volumes; optional f5_urlrep_cm updater mount for the Run Now / Cloud Scheduler run_update command; publishes dashboard ports 443/4433/80 - AI Claude Fable 5 # # Run: # curl -fsSL -k -o run_mag_monitor.sh https://feedlists.magnetoai.com/run_mag_monitor.txt && chmod +x run_mag_monitor.sh && ./run_mag_monitor.sh # ./run_mag_monitor.sh --dg lab1 # scope monitoring to one deployment group # ./run_mag_monitor.sh --once # single collection cycle, foreground, then exit # # Requirements: # Docker (user must be in docker group if running without sudo) # RockyOS 9 / Ubuntu 22.04+ / macOS # #------------------------------------------------------------------------------------------------------- set -eo pipefail clear 2>/dev/null || true # non-fatal when TERM is unset (non-TTY / automation) echo " MagnetoAI Monitor (mag_monitor) - Bootstrap Script Version: 0.1.0 - Updated: 2026-07-07 " ####################################### # Defaults ####################################### DG="all" DEBUGGING=0 RUN_ONCE=0 CONTAINER_NAME="mag_monitor" IMAGE="magnetoai/mag_monitor:latest" ####################################### # Usage ####################################### usage() { cat </dev/null || id -gn) PRIMARY_GID=$(id -g "$CURRENT_USER" 2>/dev/null || id -g) echo "Current User: $CURRENT_USER" echo "Running as root: $IS_ROOT" echo "Primary Group: $PRIMARY_GROUP (ID: $PRIMARY_GID)" echo "" if ! $IS_ROOT; then echo "Running as $CURRENT_USER — Docker must already be installed and $CURRENT_USER must be in the docker group." if ! groups "$CURRENT_USER" 2>/dev/null | grep -qw docker; then echo "WARNING: $CURRENT_USER is not in the docker group." echo " Run once with sudo, or add the user: sudo usermod -aG docker $CURRENT_USER (then log out/in)" fi echo "" fi #------------------------------------------------------------------------------------------------------- echo "----------------------------------------------------------------------------------------------------------" echo "Downloading latest run script..." echo "" curl -fsSL -k -o "run_mag_monitor.sh" "https://feedlists.magnetoai.com/run_mag_monitor.txt" chmod +x run_mag_monitor.sh #------------------------------------------------------------------------------------------------------- # Docker check if [[ "$OSTYPE" == "linux-gnu"* ]]; then if ! command -v docker &>/dev/null; then echo "ERROR: Docker is not installed." echo " Run the installer with sudo to install it automatically:" echo " curl -fsSL -o install_mag_monitor_docker.sh https://feedlists.magnetoai.com/install_mag_monitor_docker.txt && chmod +x install_mag_monitor_docker.sh && sudo ./install_mag_monitor_docker.sh" exit 1 fi if ! systemctl is-active --quiet docker 2>/dev/null; then echo "Docker is not running — starting Docker..." if $IS_ROOT; then systemctl start docker echo "Docker started." elif sudo -n systemctl start docker 2>/dev/null; then echo "Docker started via passwordless sudo." else echo "ERROR: Docker is not running. Start it with: sudo systemctl start docker" echo " Then re-run this script." exit 1 fi else echo "Docker is running." fi fi #------------------------------------------------------------------------------------------------------- # Runtime files (created by the installer; touched here so a bare run also works) SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" for f in config.txt cassandra_crypt.key config.yaml; do [ -f "$SCRIPT_DIR/$f" ] || touch "$SCRIPT_DIR/$f" done # Optional host settings overrides (web_allowed_cidrs etc.) — mounted only when present SETTINGS_VOLUME="" if [ -f "$SCRIPT_DIR/settings.json" ]; then SETTINGS_VOLUME="-v $SCRIPT_DIR/settings.json:/app/settings.json" fi # Optional f5_urlrep_cm updater — enables the web UI 'Run Now' / Cloud Scheduler # run_update command inside the container. Place the compiled LINUX binary next # to this script (glibc builds for ubuntu22/24 run on the image's debian base). UPDATER_VOLUME="" if [ -f "$SCRIPT_DIR/f5_urlrep_cm" ]; then chmod +x "$SCRIPT_DIR/f5_urlrep_cm" 2>/dev/null || true UPDATER_VOLUME="-v $SCRIPT_DIR/f5_urlrep_cm:/opt/f5-urlrep-cm/f5_urlrep_cm" echo "Found f5_urlrep_cm next to this script — run_update (Run Now / Cloud Scheduler) will be available." else echo "NOTE: f5_urlrep_cm binary not found next to this script." echo " The web UI 'Run Now' / Cloud Scheduler deployments will be unavailable until you place" echo " the compiled Linux f5_urlrep_cm here and re-run this script." fi echo "" ####################################### # Run Docker container ####################################### echo "Starting container:" echo " Image: $IMAGE" echo " Deployment Group: $DG" echo " Mode: $( [ "$RUN_ONCE" -eq 1 ] && echo 'single cycle (foreground)' || echo 'always-on service (detached, restart unless-stopped)' )" echo "" docker pull "$IMAGE" # Replace any previous instance (same name) so re-running upgrades in place if docker ps -a --format '{{.Names}}' | grep -qw "$CONTAINER_NAME"; then echo "Stopping and removing existing '$CONTAINER_NAME' container..." docker rm -f "$CONTAINER_NAME" >/dev/null fi # App arguments (ENTRYPOINT is python3; first arg is the script) APP_ARGS=(mag_monitor.py --dg "$DG") [ "$DEBUGGING" -eq 1 ] && APP_ARGS+=(--debug) [ "$RUN_ONCE" -eq 1 ] && APP_ARGS+=(--once) # Common volumes: # config.txt / cassandra_crypt.key / config.yaml — credentials + local key + runtime state # mag_monitor_data — TLS certs, MCP token, SQLite probe DB (persist across upgrades) # mag_monitor_logs — application logs COMMON_ARGS=( -v "$SCRIPT_DIR/config.txt:/app/config.txt" -v "$SCRIPT_DIR/cassandra_crypt.key:/app/cassandra_crypt.key" -v "$SCRIPT_DIR/config.yaml:/app/config.yaml" -v "mag_monitor_data:/var/lib/mag-monitor" -v "mag_monitor_etc:/etc/mag-monitor" -v "mag_monitor_logs:/var/log/mag_monitor" -p 443:443 -p 4433:4433 -p 80:80 ) # First-run setup: with an empty config.txt the monitor has no credentials. # Run an interactive one-shot setup container (prompts for MagnetoAI email + # password, generates the encryption key, saves encrypted config.txt) before # starting the always-on service. Skipped when MAGNETO_EMAIL/MAGNETO_PASSWORD # are exported — those are passed through for non-interactive provisioning. SETUP_ENV_ARGS=() if [ -n "${MAGNETO_EMAIL:-}" ] && [ -n "${MAGNETO_PASSWORD:-}" ]; then SETUP_ENV_ARGS=(-e "MAGNETO_EMAIL=$MAGNETO_EMAIL" -e "MAGNETO_PASSWORD=$MAGNETO_PASSWORD") fi CONFIG_SIZE=$(wc -c < "$SCRIPT_DIR/config.txt" 2>/dev/null || echo 0) if [ "${CONFIG_SIZE:-0}" -lt 10 ]; then echo "config.txt is empty — running first-time setup..." if [ ${#SETUP_ENV_ARGS[@]} -eq 0 ] && [ ! -t 0 ]; then echo "ERROR: First-run setup needs an interactive terminal (or MAGNETO_EMAIL/MAGNETO_PASSWORD env vars)." echo " Re-run this script from a terminal, or:" echo " MAGNETO_EMAIL=you@example.com MAGNETO_PASSWORD=... $0" exit 1 fi # shellcheck disable=SC2086 docker run --rm -ti \ -v "$SCRIPT_DIR/config.txt:/app/config.txt" \ -v "$SCRIPT_DIR/cassandra_crypt.key:/app/cassandra_crypt.key" \ -v "$SCRIPT_DIR/config.yaml:/app/config.yaml" \ "${SETUP_ENV_ARGS[@]}" \ $SETTINGS_VOLUME \ "$IMAGE" mag_monitor.py --setup echo "" echo "First-time setup complete." echo "" fi # shellcheck disable=SC2086 if [ "$RUN_ONCE" -eq 1 ]; then docker run --rm -ti \ --name "$CONTAINER_NAME" \ "${COMMON_ARGS[@]}" \ $SETTINGS_VOLUME \ $UPDATER_VOLUME \ "$IMAGE" "${APP_ARGS[@]}" else docker run -d \ --name "$CONTAINER_NAME" \ --restart unless-stopped \ "${COMMON_ARGS[@]}" \ $SETTINGS_VOLUME \ $UPDATER_VOLUME \ "$IMAGE" "${APP_ARGS[@]}" echo "" echo "----------------------------------------------------------------------------------------------------------" echo "" echo "MagnetoAI Monitor is running as an always-on service." echo "" echo " Follow logs: docker logs -f $CONTAINER_NAME" echo " Stop: docker stop $CONTAINER_NAME" echo " Start: docker start $CONTAINER_NAME" echo " Upgrade: re-run this script (pulls :latest and replaces the container)" echo " Web dashboard: https:/// (TLS 1.3; self-signed cert on first run)" echo "" echo " First run: put your MagnetoAI credentials in config.txt (or run the URL-Reputation" echo " tool once in this directory) — then: docker restart $CONTAINER_NAME" echo "" fi echo "" echo "Done." echo ""