Files
linux-scripts/setup-wickr-monitoring.sh
T
chiefgeek a1a17e81a1 Sync all scripts from website downloads — 352 scripts total
Includes updated JS challenge scripts with Claude-User whitelist,
same-site referer bypass, Blackbox-Exporter allowed bot, and all
new exporters, cheat sheets, and automation scripts.
2026-05-25 03:31:08 +02:00

1105 lines
36 KiB
Bash

#!/bin/bash
#############################################################
#### Wickr Enterprise Monitoring Setup ####
#### Install and configure all Prometheus exporters ####
#### and scrape targets for Wickr Enterprise ####
#### ####
#### Components: ####
#### - redis_exporter (Redis session cache) ####
#### - mysqld_exporter (MySQL data store) ####
#### - cAdvisor (container metrics) ####
#### - blackbox_exporter config (endpoint probing) ####
#### - wickr-metrics-exporter (Admin API) ####
#### - wickr-io-exporter (IO Gateway) ####
#### - Prometheus scrape config ####
#### - Prometheus alert rules ####
#### ####
#### Author: Phil Connor ####
#### Contact: contact@mylinux.work ####
#### Version: 1.0.0.20260308 ####
#############################################################
set -euo pipefail
SCRIPT_NAME=$(basename "$0")
readonly SCRIPT_NAME
#########################
### Defaults ###
#########################
readonly DEFAULT_REDIS_EXPORTER_VERSION="1.58.0"
readonly DEFAULT_MYSQL_EXPORTER_VERSION="0.15.1"
readonly DEFAULT_CADVISOR_VERSION="0.49.1"
readonly DEFAULT_NODE_DIR="/var/lib/node_exporter"
readonly DEFAULT_PROMETHEUS_DIR="/etc/prometheus"
readonly DEFAULT_INSTALL_DIR="/usr/local/bin"
# Configuration (overridable by environment or flags)
REDIS_EXPORTER_VERSION="${REDIS_EXPORTER_VERSION:-$DEFAULT_REDIS_EXPORTER_VERSION}"
MYSQL_EXPORTER_VERSION="${MYSQL_EXPORTER_VERSION:-$DEFAULT_MYSQL_EXPORTER_VERSION}"
CADVISOR_VERSION="${CADVISOR_VERSION:-$DEFAULT_CADVISOR_VERSION}"
NODE_DIR="${NODE_DIR:-$DEFAULT_NODE_DIR}"
PROMETHEUS_DIR="${PROMETHEUS_DIR:-$DEFAULT_PROMETHEUS_DIR}"
INSTALL_DIR="${INSTALL_DIR:-$DEFAULT_INSTALL_DIR}"
# Wickr-specific settings
WICKR_ADMIN_URL="${WICKR_ADMIN_URL:-}"
WICKR_ADMIN_TOKEN="${WICKR_ADMIN_TOKEN:-}"
WICKR_ENDPOINT="${WICKR_ENDPOINT:-}"
WICKR_IO_API_URL="${WICKR_IO_API_URL:-http://localhost:8080}"
WICKR_IO_API_KEY="${WICKR_IO_API_KEY:-}"
WICKR_DOCKER_NAME="${WICKR_DOCKER_NAME:-wickr-io}"
# Database settings
MYSQL_HOST="${MYSQL_HOST:-localhost}"
MYSQL_PORT="${MYSQL_PORT:-3306}"
MYSQL_EXPORTER_USER="${MYSQL_EXPORTER_USER:-exporter}"
MYSQL_EXPORTER_PASS="${MYSQL_EXPORTER_PASS:-}"
# Redis settings
REDIS_ADDR="${REDIS_ADDR:-redis://localhost:6379}"
# Component install flags
INSTALL_REDIS_EXPORTER=true
INSTALL_MYSQL_EXPORTER=true
INSTALL_CADVISOR=true
INSTALL_BLACKBOX_CONFIG=true
INSTALL_WICKR_METRICS=true
INSTALL_WICKR_IO=true
INSTALL_ALERT_RULES=true
INSTALL_PROMETHEUS_CONFIG=true
CADVISOR_MODE="docker"
UPDATE_MODE=false
DRY_RUN=false
SKIP_DEPS=false
# Runtime
LOGFILE="/var/log/wickr-monitoring-setup.log"
ERRORS=0
#########################
### Logging ###
#########################
log_info() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] INFO: $1" | tee -a "$LOGFILE"
}
log_error() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] ERROR: $1" | tee -a "$LOGFILE" >&2
ERRORS=$((ERRORS + 1))
}
log_warn() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] WARN: $1" | tee -a "$LOGFILE"
}
#########################
### Help ###
#########################
show_help() {
cat << EOF
Usage: $SCRIPT_NAME [OPTIONS]
Install and configure Prometheus monitoring for a Wickr Enterprise deployment.
Sets up infrastructure exporters, custom Wickr scripts, scrape configs, and alert rules.
COMPONENT FLAGS:
--all Install all components (default)
--redis-exporter Install redis_exporter
--mysql-exporter Install mysqld_exporter
--cadvisor Install cAdvisor (Docker container or binary)
--blackbox-config Install blackbox_exporter Wickr probe config
--wickr-metrics Install wickr-metrics-exporter.sh (Admin API)
--wickr-io Install wickr-io-exporter.sh (IO Gateway)
--alert-rules Install Wickr Prometheus alert rules
--prometheus-config Generate Wickr Prometheus scrape config
--no-<component> Skip a specific component
OPTIONS:
--cadvisor-mode <mode> cAdvisor install mode: docker or binary (default: docker)
--update Update existing installations
--dry-run Show what would be done without executing
--skip-deps Skip dependency checks
--help, -h Show this help message
WICKR SETTINGS:
--wickr-admin-url <url> Wickr Admin API URL (e.g. https://wickr-admin.example.com)
--wickr-admin-token <tok> Wickr Admin API token
--wickr-endpoint <host> Wickr endpoint hostname for blackbox probing
--wickr-io-url <url> Wickr IO REST API URL (default: http://localhost:8080)
--wickr-io-key <key> Wickr IO API key for statistics
--wickr-docker-name <name> Docker container name (default: wickr-io)
DATABASE SETTINGS:
--mysql-host <host> MySQL host (default: localhost)
--mysql-port <port> MySQL port (default: 3306)
--mysql-user <user> MySQL exporter user (default: exporter)
--mysql-pass <pass> MySQL exporter password
--redis-addr <addr> Redis address (default: redis://localhost:6379)
ENVIRONMENT VARIABLES:
WICKR_ADMIN_URL, WICKR_ADMIN_TOKEN, WICKR_ENDPOINT,
WICKR_IO_API_URL, WICKR_IO_API_KEY, WICKR_DOCKER_NAME,
MYSQL_HOST, MYSQL_PORT, MYSQL_EXPORTER_USER, MYSQL_EXPORTER_PASS,
REDIS_ADDR, REDIS_EXPORTER_VERSION, MYSQL_EXPORTER_VERSION,
CADVISOR_VERSION, NODE_DIR, PROMETHEUS_DIR
EXAMPLES:
# Install everything
$SCRIPT_NAME --all --wickr-admin-url https://wickr.example.com --wickr-admin-token xxx
# Just the infrastructure exporters
$SCRIPT_NAME --redis-exporter --mysql-exporter --cadvisor
# Just the custom Wickr scripts
$SCRIPT_NAME --wickr-metrics --wickr-io
# Dry run
$SCRIPT_NAME --all --dry-run
EOF
exit 0
}
#########################
### Parse Arguments ###
#########################
parse_arguments() {
# If no arguments, default to --all
[[ $# -eq 0 ]] && return
# If any component flag is given, disable all defaults first
local has_component_flag=false
for arg in "$@"; do
case "$arg" in
--redis-exporter|--mysql-exporter|--cadvisor|--blackbox-config|\
--wickr-metrics|--wickr-io|--alert-rules|--prometheus-config|--all)
has_component_flag=true
break
;;
esac
done
if [[ "$has_component_flag" == "true" ]]; then
INSTALL_REDIS_EXPORTER=false
INSTALL_MYSQL_EXPORTER=false
INSTALL_CADVISOR=false
INSTALL_BLACKBOX_CONFIG=false
INSTALL_WICKR_METRICS=false
INSTALL_WICKR_IO=false
INSTALL_ALERT_RULES=false
INSTALL_PROMETHEUS_CONFIG=false
fi
while [[ $# -gt 0 ]]; do
case $1 in
--all)
INSTALL_REDIS_EXPORTER=true
INSTALL_MYSQL_EXPORTER=true
INSTALL_CADVISOR=true
INSTALL_BLACKBOX_CONFIG=true
INSTALL_WICKR_METRICS=true
INSTALL_WICKR_IO=true
INSTALL_ALERT_RULES=true
INSTALL_PROMETHEUS_CONFIG=true
shift ;;
--redis-exporter) INSTALL_REDIS_EXPORTER=true; shift ;;
--no-redis-exporter) INSTALL_REDIS_EXPORTER=false; shift ;;
--mysql-exporter) INSTALL_MYSQL_EXPORTER=true; shift ;;
--no-mysql-exporter) INSTALL_MYSQL_EXPORTER=false; shift ;;
--cadvisor) INSTALL_CADVISOR=true; shift ;;
--no-cadvisor) INSTALL_CADVISOR=false; shift ;;
--blackbox-config) INSTALL_BLACKBOX_CONFIG=true; shift ;;
--no-blackbox-config) INSTALL_BLACKBOX_CONFIG=false; shift ;;
--wickr-metrics) INSTALL_WICKR_METRICS=true; shift ;;
--no-wickr-metrics) INSTALL_WICKR_METRICS=false; shift ;;
--wickr-io) INSTALL_WICKR_IO=true; shift ;;
--no-wickr-io) INSTALL_WICKR_IO=false; shift ;;
--alert-rules) INSTALL_ALERT_RULES=true; shift ;;
--no-alert-rules) INSTALL_ALERT_RULES=false; shift ;;
--prometheus-config) INSTALL_PROMETHEUS_CONFIG=true; shift ;;
--no-prometheus-config) INSTALL_PROMETHEUS_CONFIG=false; shift ;;
--cadvisor-mode) CADVISOR_MODE="$2"; shift 2 ;;
--wickr-admin-url) WICKR_ADMIN_URL="$2"; shift 2 ;;
--wickr-admin-token) WICKR_ADMIN_TOKEN="$2"; shift 2 ;;
--wickr-endpoint) WICKR_ENDPOINT="$2"; shift 2 ;;
--wickr-io-url) WICKR_IO_API_URL="$2"; shift 2 ;;
--wickr-io-key) WICKR_IO_API_KEY="$2"; shift 2 ;;
--wickr-docker-name) WICKR_DOCKER_NAME="$2"; shift 2 ;;
--mysql-host) MYSQL_HOST="$2"; shift 2 ;;
--mysql-port) MYSQL_PORT="$2"; shift 2 ;;
--mysql-user) MYSQL_EXPORTER_USER="$2"; shift 2 ;;
--mysql-pass) MYSQL_EXPORTER_PASS="$2"; shift 2 ;;
--redis-addr) REDIS_ADDR="$2"; shift 2 ;;
--update) UPDATE_MODE=true; shift ;;
--dry-run) DRY_RUN=true; shift ;;
--skip-deps) SKIP_DEPS=true; shift ;;
--help|-h) show_help ;;
*) log_error "Unknown option: $1"; show_help ;;
esac
done
}
#########################
### Pre-flight ###
#########################
check_permissions() {
if [[ $EUID -ne 0 ]]; then
log_error "This script must be run as root"
exit 1
fi
}
detect_arch() {
local arch
arch=$(uname -m)
case "$arch" in
x86_64) echo "amd64" ;;
aarch64) echo "arm64" ;;
armv7l) echo "armv7" ;;
*) log_error "Unsupported architecture: $arch"; exit 1 ;;
esac
}
check_dependencies() {
if [[ "$SKIP_DEPS" == "true" ]]; then
return
fi
local missing=()
for cmd in curl wget tar jq; do
command -v "$cmd" &>/dev/null || missing+=("$cmd")
done
if [[ ${#missing[@]} -gt 0 ]]; then
log_info "Installing missing dependencies: ${missing[*]}"
if command -v apt &>/dev/null; then
apt -y install "${missing[@]}" 2>/dev/null
elif command -v dnf &>/dev/null; then
dnf -y install "${missing[@]}" 2>/dev/null
elif command -v yum &>/dev/null; then
yum -y install "${missing[@]}" 2>/dev/null
else
log_error "Cannot install dependencies — install manually: ${missing[*]}"
exit 1
fi
fi
}
setup_directories() {
mkdir -p "$(dirname "$LOGFILE")"
touch "$LOGFILE"
# Textfile collector directory
local textfile_dir="${NODE_DIR}/textfile_collector"
if [[ ! -d "$textfile_dir" ]]; then
mkdir -p "$textfile_dir"
chown prometheus: "$textfile_dir" 2>/dev/null || true
log_info "Created textfile collector directory: $textfile_dir"
fi
# Prometheus rules directory
mkdir -p "${PROMETHEUS_DIR}/rules" 2>/dev/null || true
}
ensure_prometheus_user() {
if ! id prometheus &>/dev/null; then
log_info "Creating prometheus user"
groupadd --system prometheus 2>/dev/null || true
useradd -s /sbin/nologin --system -g prometheus prometheus 2>/dev/null || true
fi
}
cleanup() {
[[ -d "/tmp/wickr-monitoring-$$" ]] && rm -rf "/tmp/wickr-monitoring-$$"
}
trap cleanup EXIT
#########################
### redis_exporter ###
#########################
install_redis_exporter() {
log_info "Installing redis_exporter v${REDIS_EXPORTER_VERSION}"
if [[ "$DRY_RUN" == "true" ]]; then
log_info "[DRY RUN] Would install redis_exporter v${REDIS_EXPORTER_VERSION}"
return
fi
if systemctl is-active --quiet redis_exporter 2>/dev/null && [[ "$UPDATE_MODE" == "false" ]]; then
log_info "redis_exporter already running, skipping (use --update to reinstall)"
return
fi
local arch
arch=$(detect_arch)
local workdir="/tmp/wickr-monitoring-$$/redis_exporter"
mkdir -p "$workdir"
local tarball="redis_exporter-v${REDIS_EXPORTER_VERSION}.linux-${arch}.tar.gz"
local url="https://github.com/oliver006/redis_exporter/releases/download/v${REDIS_EXPORTER_VERSION}/${tarball}"
log_info "Downloading redis_exporter..."
if ! curl -fsSL -o "${workdir}/${tarball}" "$url"; then
log_error "Failed to download redis_exporter from $url"
return
fi
tar -xzf "${workdir}/${tarball}" -C "$workdir"
cp "${workdir}/redis_exporter-v${REDIS_EXPORTER_VERSION}.linux-${arch}/redis_exporter" "${INSTALL_DIR}/"
chmod +x "${INSTALL_DIR}/redis_exporter"
chown prometheus: "${INSTALL_DIR}/redis_exporter" 2>/dev/null || true
# Systemd unit
cat > /etc/systemd/system/redis_exporter.service << EOF
[Unit]
Description=Prometheus Redis Exporter
Documentation=https://github.com/oliver006/redis_exporter
After=network.target
[Service]
Type=simple
User=prometheus
Group=prometheus
ExecStart=${INSTALL_DIR}/redis_exporter \\
--redis.addr=${REDIS_ADDR} \\
--web.listen-address=:9121
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable redis_exporter
systemctl restart redis_exporter
log_info "redis_exporter installed (port 9121)"
}
#########################
### mysqld_exporter ###
#########################
install_mysqld_exporter() {
log_info "Installing mysqld_exporter v${MYSQL_EXPORTER_VERSION}"
if [[ "$DRY_RUN" == "true" ]]; then
log_info "[DRY RUN] Would install mysqld_exporter v${MYSQL_EXPORTER_VERSION}"
return
fi
if systemctl is-active --quiet mysqld_exporter 2>/dev/null && [[ "$UPDATE_MODE" == "false" ]]; then
log_info "mysqld_exporter already running, skipping (use --update to reinstall)"
return
fi
local arch
arch=$(detect_arch)
local workdir="/tmp/wickr-monitoring-$$/mysqld_exporter"
mkdir -p "$workdir"
local tarball="mysqld_exporter-${MYSQL_EXPORTER_VERSION}.linux-${arch}.tar.gz"
local url="https://github.com/prometheus/mysqld_exporter/releases/download/v${MYSQL_EXPORTER_VERSION}/${tarball}"
log_info "Downloading mysqld_exporter..."
if ! curl -fsSL -o "${workdir}/${tarball}" "$url"; then
log_error "Failed to download mysqld_exporter from $url"
return
fi
tar -xzf "${workdir}/${tarball}" -C "$workdir"
cp "${workdir}/mysqld_exporter-${MYSQL_EXPORTER_VERSION}.linux-${arch}/mysqld_exporter" "${INSTALL_DIR}/"
chmod +x "${INSTALL_DIR}/mysqld_exporter"
chown prometheus: "${INSTALL_DIR}/mysqld_exporter" 2>/dev/null || true
# MySQL credentials file
if [[ -n "$MYSQL_EXPORTER_PASS" ]]; then
cat > /etc/.mysqld_exporter.cnf << EOF
[client]
user=${MYSQL_EXPORTER_USER}
password=${MYSQL_EXPORTER_PASS}
host=${MYSQL_HOST}
port=${MYSQL_PORT}
EOF
chmod 600 /etc/.mysqld_exporter.cnf
chown prometheus: /etc/.mysqld_exporter.cnf 2>/dev/null || true
log_info "MySQL credentials written to /etc/.mysqld_exporter.cnf"
elif [[ ! -f /etc/.mysqld_exporter.cnf ]]; then
log_warn "No MySQL password provided — create /etc/.mysqld_exporter.cnf manually"
cat > /etc/.mysqld_exporter.cnf << EOF
[client]
user=${MYSQL_EXPORTER_USER}
password=CHANGEME
host=${MYSQL_HOST}
port=${MYSQL_PORT}
EOF
chmod 600 /etc/.mysqld_exporter.cnf
chown prometheus: /etc/.mysqld_exporter.cnf 2>/dev/null || true
fi
# Systemd unit
cat > /etc/systemd/system/mysqld_exporter.service << EOF
[Unit]
Description=Prometheus MySQL Exporter
Documentation=https://github.com/prometheus/mysqld_exporter
After=network.target
[Service]
Type=simple
User=prometheus
Group=prometheus
ExecStart=${INSTALL_DIR}/mysqld_exporter \\
--config.my-cnf=/etc/.mysqld_exporter.cnf \\
--web.listen-address=:9104
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable mysqld_exporter
systemctl restart mysqld_exporter
log_info "mysqld_exporter installed (port 9104)"
if [[ "$MYSQL_EXPORTER_PASS" == "" ]]; then
log_warn "Remember to create the MySQL exporter user:"
log_warn " CREATE USER '${MYSQL_EXPORTER_USER}'@'%' IDENTIFIED BY 'strong-password';"
log_warn " GRANT PROCESS, REPLICATION CLIENT, SELECT ON *.* TO '${MYSQL_EXPORTER_USER}'@'%';"
log_warn " FLUSH PRIVILEGES;"
fi
}
#########################
### cAdvisor ###
#########################
install_cadvisor() {
log_info "Installing cAdvisor v${CADVISOR_VERSION} (mode: ${CADVISOR_MODE})"
if [[ "$DRY_RUN" == "true" ]]; then
log_info "[DRY RUN] Would install cAdvisor v${CADVISOR_VERSION} (${CADVISOR_MODE})"
return
fi
case "$CADVISOR_MODE" in
docker) install_cadvisor_docker ;;
binary) install_cadvisor_binary ;;
*) log_error "Unknown cAdvisor mode: $CADVISOR_MODE"; return ;;
esac
}
install_cadvisor_docker() {
if ! command -v docker &>/dev/null; then
log_error "Docker not found — install Docker first or use --cadvisor-mode binary"
return
fi
local image="gcr.io/cadvisor/cadvisor:v${CADVISOR_VERSION}"
# Check if already running
if docker ps --format '{{.Names}}' 2>/dev/null | grep -q "^cadvisor$" && [[ "$UPDATE_MODE" == "false" ]]; then
log_info "cAdvisor container already running, skipping"
return
fi
# Remove existing container
docker rm -f cadvisor 2>/dev/null || true
log_info "Pulling cAdvisor image..."
docker pull "$image"
docker run -d \
--name cadvisor \
--restart unless-stopped \
-p 8080:8080 \
-v /:/rootfs:ro \
-v /var/run:/var/run:ro \
-v /sys:/sys:ro \
-v /var/lib/docker/:/var/lib/docker:ro \
-v /dev/disk/:/dev/disk:ro \
--privileged \
--device /dev/kmsg \
"$image"
log_info "cAdvisor container started (port 8080)"
}
install_cadvisor_binary() {
local arch
arch=$(detect_arch)
local url="https://github.com/google/cadvisor/releases/download/v${CADVISOR_VERSION}/cadvisor-v${CADVISOR_VERSION}-linux-${arch}"
log_info "Downloading cAdvisor binary..."
if ! curl -fsSL -o "${INSTALL_DIR}/cadvisor" "$url"; then
log_error "Failed to download cAdvisor"
return
fi
chmod +x "${INSTALL_DIR}/cadvisor"
cat > /etc/systemd/system/cadvisor.service << EOF
[Unit]
Description=cAdvisor - Container Advisor
Documentation=https://github.com/google/cadvisor
After=network.target docker.service
Wants=docker.service
[Service]
Type=simple
ExecStart=${INSTALL_DIR}/cadvisor \\
--port=8080 \\
--docker_only=true \\
--housekeeping_interval=30s \\
--storage_duration=2m0s
Restart=on-failure
RestartSec=5
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable cadvisor
systemctl restart cadvisor
log_info "cAdvisor systemd service started (port 8080)"
}
#########################
### Blackbox Config ###
#########################
install_blackbox_config() {
log_info "Installing blackbox_exporter Wickr probe configuration"
if [[ "$DRY_RUN" == "true" ]]; then
log_info "[DRY RUN] Would install Wickr blackbox probe config"
return
fi
if [[ ! -d "$PROMETHEUS_DIR" ]]; then
log_warn "Prometheus config directory not found: $PROMETHEUS_DIR — skipping blackbox config"
return
fi
# Check if blackbox_exporter is installed
if ! command -v blackbox_exporter &>/dev/null && [[ ! -f "${INSTALL_DIR}/blackbox_exporter" ]]; then
log_warn "blackbox_exporter not found — install it first (see install-prometheus-stack.sh)"
fi
local blackbox_config="${PROMETHEUS_DIR}/blackbox.yml"
# Add Wickr-specific modules if not already present
if [[ -f "$blackbox_config" ]] && grep -q "https_wickr" "$blackbox_config" 2>/dev/null; then
log_info "Wickr blackbox modules already configured"
return
fi
# If blackbox.yml doesn't exist, create it with Wickr modules
if [[ ! -f "$blackbox_config" ]]; then
cat > "$blackbox_config" << 'EOF'
modules:
http_2xx:
prober: http
timeout: 5s
tcp_connect:
prober: tcp
timeout: 5s
https_wickr:
prober: http
timeout: 10s
http:
valid_http_versions: ["HTTP/1.1", "HTTP/2.0"]
valid_status_codes: [200, 301, 302, 403]
tls_config:
insecure_skip_verify: false
EOF
chown prometheus: "$blackbox_config" 2>/dev/null || true
log_info "Created blackbox.yml with Wickr probe modules"
else
# Append Wickr module to existing config
cat >> "$blackbox_config" << 'EOF'
https_wickr:
prober: http
timeout: 10s
http:
valid_http_versions: ["HTTP/1.1", "HTTP/2.0"]
valid_status_codes: [200, 301, 302, 403]
tls_config:
insecure_skip_verify: false
EOF
log_info "Added https_wickr module to existing blackbox.yml"
fi
# Reload blackbox_exporter if running
if systemctl is-active --quiet blackbox_exporter 2>/dev/null; then
systemctl restart blackbox_exporter
log_info "blackbox_exporter restarted"
fi
}
####################################
### wickr-metrics-exporter.sh ###
####################################
install_wickr_metrics_exporter() {
log_info "Installing wickr-metrics-exporter.sh (Admin API collector)"
if [[ "$DRY_RUN" == "true" ]]; then
log_info "[DRY RUN] Would install wickr-metrics-exporter.sh"
return
fi
local script_path="${INSTALL_DIR}/wickr-metrics-exporter.sh"
local download_url="https://mylinux.work/downloads/wickr-metrics-exporter.sh"
if [[ -f "$script_path" ]] && [[ "$UPDATE_MODE" == "false" ]]; then
log_info "wickr-metrics-exporter.sh already exists, skipping (use --update to reinstall)"
return
fi
log_info "Downloading wickr-metrics-exporter.sh..."
if ! curl -fsSL -o "$script_path" "$download_url"; then
log_error "Failed to download wickr-metrics-exporter.sh"
return
fi
chmod +x "$script_path"
log_info "Installed $script_path"
# Create cron job if admin URL and token are set
if [[ -n "$WICKR_ADMIN_URL" && -n "$WICKR_ADMIN_TOKEN" ]]; then
local cron_file="/etc/cron.d/wickr-metrics-exporter"
cat > "$cron_file" << EOF
# Wickr Enterprise Admin API metrics collector
# Runs every minute, writes to node_exporter textfile directory
* * * * * root WICKR_ADMIN_URL=${WICKR_ADMIN_URL} WICKR_API_TOKEN=${WICKR_ADMIN_TOKEN} NODE_DIR=${NODE_DIR} ${script_path} --once >/dev/null 2>&1
EOF
chmod 644 "$cron_file"
log_info "Cron job installed: $cron_file"
else
log_warn "WICKR_ADMIN_URL and WICKR_ADMIN_TOKEN not set — skipping cron job"
log_warn "Set them and create /etc/cron.d/wickr-metrics-exporter manually"
fi
}
####################################
### wickr-io-exporter.sh ###
####################################
install_wickr_io_exporter() {
log_info "Installing wickr-io-exporter.sh (IO Gateway collector)"
if [[ "$DRY_RUN" == "true" ]]; then
log_info "[DRY RUN] Would install wickr-io-exporter.sh"
return
fi
local script_path="${INSTALL_DIR}/wickr-io-exporter.sh"
local download_url="https://mylinux.work/downloads/wickr-io-exporter.sh"
if [[ -f "$script_path" ]] && [[ "$UPDATE_MODE" == "false" ]]; then
log_info "wickr-io-exporter.sh already exists, skipping (use --update to reinstall)"
return
fi
log_info "Downloading wickr-io-exporter.sh..."
if ! curl -fsSL -o "$script_path" "$download_url"; then
log_error "Failed to download wickr-io-exporter.sh"
return
fi
chmod +x "$script_path"
log_info "Installed $script_path"
# Create cron job
local cron_file="/etc/cron.d/wickr-io-exporter"
local env_vars="NODE_EXPORTER_DIR=${NODE_DIR} WICKR_DOCKER_NAME=${WICKR_DOCKER_NAME} WICKR_API_URL=${WICKR_IO_API_URL}"
[[ -n "$WICKR_IO_API_KEY" ]] && env_vars="${env_vars} WICKR_API_KEY=${WICKR_IO_API_KEY}"
cat > "$cron_file" << EOF
# Wickr IO Gateway metrics collector
# Runs every 5 minutes, writes to node_exporter textfile directory
*/5 * * * * root ${env_vars} ${script_path} > ${NODE_DIR}/wickr_status.prom 2>&1
EOF
chmod 644 "$cron_file"
log_info "Cron job installed: $cron_file"
}
#########################
### Alert Rules ###
#########################
install_alert_rules() {
log_info "Installing Wickr Prometheus alert rules"
if [[ "$DRY_RUN" == "true" ]]; then
log_info "[DRY RUN] Would install Wickr alert rules"
return
fi
local rules_dir="${PROMETHEUS_DIR}/rules"
mkdir -p "$rules_dir"
# Wickr infrastructure alerts
cat > "${rules_dir}/wickr-infrastructure.yml" << 'RULES'
groups:
- name: wickr-mysql
rules:
- alert: WickrMySQLDown
expr: mysql_up == 0
for: 2m
labels:
severity: critical
annotations:
summary: "Wickr MySQL database is down"
- alert: WickrMySQLConnectionsHigh
expr: mysql_global_status_threads_connected / mysql_global_variables_max_connections * 100 > 80
for: 5m
labels:
severity: warning
annotations:
summary: "MySQL connections above 80% of max"
- alert: WickrMySQLSlowQueries
expr: rate(mysql_global_status_slow_queries[5m]) > 0.1
for: 10m
labels:
severity: warning
annotations:
summary: "MySQL slow queries increasing"
- name: wickr-redis
rules:
- alert: WickrRedisDown
expr: redis_up == 0
for: 2m
labels:
severity: critical
annotations:
summary: "Wickr Redis cache is down"
- alert: WickrRedisHighMemory
expr: redis_used_memory_bytes / redis_config_maxmemory * 100 > 90
for: 5m
labels:
severity: warning
annotations:
summary: "Redis memory usage above 90%"
- alert: WickrRedisCacheHitRateLow
expr: rate(redis_keyspace_hits_total[5m]) / (rate(redis_keyspace_hits_total[5m]) + rate(redis_keyspace_misses_total[5m])) < 0.8
for: 10m
labels:
severity: warning
annotations:
summary: "Redis cache hit rate below 80%"
- name: wickr-rabbitmq
rules:
- alert: WickrRabbitMQQueueBacklog
expr: rabbitmq_queue_messages_ready > 1000
for: 5m
labels:
severity: warning
annotations:
summary: "RabbitMQ queue backlog on {{ $labels.queue }}"
description: "Queue {{ $labels.queue }} has {{ $value }} messages waiting"
- alert: WickrRabbitMQNoConsumers
expr: rabbitmq_queue_consumers == 0 and rabbitmq_queue_messages > 0
for: 5m
labels:
severity: critical
annotations:
summary: "RabbitMQ queue {{ $labels.queue }} has no consumers"
RULES
# Wickr application alerts
cat > "${rules_dir}/wickr-application.yml" << 'RULES'
groups:
- name: wickr-admin-api
rules:
- alert: WickrAdminAPIDown
expr: wickr_instance_up == 0
for: 5m
labels:
severity: critical
annotations:
summary: "Wickr Admin API is unreachable"
- alert: WickrCollectorStale
expr: (time() - wickr_collector_last_run_timestamp) > 300
for: 5m
labels:
severity: warning
annotations:
summary: "Wickr metrics collector has not run in 5 minutes"
- alert: WickrNoActiveBots
expr: wickr_bots_active == 0 and wickr_bots_total > 0
for: 10m
labels:
severity: warning
annotations:
summary: "No active Wickr bots — all bots are inactive"
- name: wickr-io-gateway
rules:
- alert: WickrIOContainerDown
expr: wickr_docker_container_status == 0
for: 3m
labels:
severity: critical
annotations:
summary: "Wickr IO Gateway Docker container is not running"
- alert: WickrIOAPIDown
expr: wickr_api_status == 0
for: 3m
labels:
severity: critical
annotations:
summary: "Wickr IO Gateway REST API is not responding"
- alert: WickrIONetworkDown
expr: wickr_network_connectivity == 0
for: 5m
labels:
severity: critical
annotations:
summary: "Cannot reach Wickr cloud services"
- alert: WickrIOSendErrors
expr: wickr_send_errors_total > 0
for: 5m
labels:
severity: warning
annotations:
summary: "Wickr IO Gateway reporting message send errors"
- alert: WickrIOHighCPU
expr: wickr_docker_cpu_percent > 90
for: 10m
labels:
severity: warning
annotations:
summary: "Wickr IO container CPU usage above 90%"
- name: wickr-blackbox
rules:
- alert: WickrEndpointDown
expr: probe_success{job="blackbox-wickr"} == 0
for: 3m
labels:
severity: critical
annotations:
summary: "Wickr endpoint {{ $labels.instance }} is down"
- alert: WickrSSLExpiringSoon
expr: (probe_ssl_earliest_cert_expiry{job="blackbox-wickr"} - time()) / 86400 < 30
for: 1h
labels:
severity: warning
annotations:
summary: "Wickr SSL certificate expires in {{ $value | humanize }} days"
RULES
chown -R prometheus: "$rules_dir" 2>/dev/null || true
log_info "Alert rules installed to ${rules_dir}/"
# Reload Prometheus if running
if systemctl is-active --quiet prometheus 2>/dev/null; then
if promtool check rules "${rules_dir}/wickr-infrastructure.yml" &>/dev/null && \
promtool check rules "${rules_dir}/wickr-application.yml" &>/dev/null; then
systemctl reload prometheus 2>/dev/null || systemctl restart prometheus
log_info "Prometheus reloaded with new alert rules"
else
log_warn "Alert rule validation failed — check rules manually with promtool"
fi
fi
}
####################################
### Prometheus Scrape Config ###
####################################
install_prometheus_config() {
log_info "Generating Wickr Prometheus scrape configuration"
local config_file="${PROMETHEUS_DIR}/wickr-scrape.yml"
if [[ "$DRY_RUN" == "true" ]]; then
log_info "[DRY RUN] Would generate scrape config at $config_file"
return
fi
# Generate a standalone scrape config snippet
cat > "$config_file" << EOF
# Wickr Enterprise Prometheus Scrape Configuration
# Generated by $SCRIPT_NAME on $(date '+%Y-%m-%d %H:%M:%S')
#
# Include in prometheus.yml with:
# scrape_config_files:
# - ${config_file}
#
# Or copy the scrape_configs entries into your prometheus.yml
scrape_configs:
EOF
# Redis
if [[ "$INSTALL_REDIS_EXPORTER" == "true" ]]; then
cat >> "$config_file" << 'EOF'
- job_name: 'redis'
scrape_interval: 15s
static_configs:
- targets: ['localhost:9121']
EOF
fi
# MySQL
if [[ "$INSTALL_MYSQL_EXPORTER" == "true" ]]; then
cat >> "$config_file" << 'EOF'
- job_name: 'mysql'
scrape_interval: 15s
static_configs:
- targets: ['localhost:9104']
EOF
fi
# cAdvisor
if [[ "$INSTALL_CADVISOR" == "true" ]]; then
cat >> "$config_file" << 'EOF'
- job_name: 'cadvisor'
scrape_interval: 15s
static_configs:
- targets: ['localhost:8080']
EOF
fi
# Blackbox — HTTPS
if [[ "$INSTALL_BLACKBOX_CONFIG" == "true" && -n "$WICKR_ENDPOINT" ]]; then
cat >> "$config_file" << EOF
- job_name: 'blackbox-wickr'
metrics_path: /probe
params:
module: [https_wickr]
static_configs:
- targets:
- 'https://${WICKR_ENDPOINT}'
relabel_configs:
- source_labels: [__address__]
target_label: __param_target
- source_labels: [__param_target]
target_label: instance
- target_label: __address__
replacement: 'localhost:9115'
- job_name: 'blackbox-wickr-tcp'
metrics_path: /probe
params:
module: [tcp_connect]
static_configs:
- targets:
- '${WICKR_ENDPOINT}:443'
relabel_configs:
- source_labels: [__address__]
target_label: __param_target
- source_labels: [__param_target]
target_label: instance
- target_label: __address__
replacement: 'localhost:9115'
EOF
fi
chown prometheus: "$config_file" 2>/dev/null || true
log_info "Scrape config written to $config_file"
# Check if prometheus.yml already includes this file
local prom_config="${PROMETHEUS_DIR}/prometheus.yml"
if [[ -f "$prom_config" ]]; then
if grep -q "wickr-scrape.yml" "$prom_config" 2>/dev/null; then
log_info "prometheus.yml already includes wickr-scrape.yml"
elif grep -q "scrape_config_files" "$prom_config" 2>/dev/null; then
log_info "Add to your scrape_config_files in prometheus.yml:"
log_info " - ${config_file}"
else
log_info "Add to prometheus.yml:"
log_info " scrape_config_files:"
log_info " - ${config_file}"
fi
fi
}
#########################
### Main ###
#########################
main() {
parse_arguments "$@"
check_permissions
log_info "=== Wickr Enterprise Monitoring Setup ==="
log_info "Components selected:"
[[ "$INSTALL_REDIS_EXPORTER" == "true" ]] && log_info " - redis_exporter v${REDIS_EXPORTER_VERSION}"
[[ "$INSTALL_MYSQL_EXPORTER" == "true" ]] && log_info " - mysqld_exporter v${MYSQL_EXPORTER_VERSION}"
[[ "$INSTALL_CADVISOR" == "true" ]] && log_info " - cAdvisor v${CADVISOR_VERSION} (${CADVISOR_MODE})"
[[ "$INSTALL_BLACKBOX_CONFIG" == "true" ]] && log_info " - blackbox_exporter Wickr config"
[[ "$INSTALL_WICKR_METRICS" == "true" ]] && log_info " - wickr-metrics-exporter.sh"
[[ "$INSTALL_WICKR_IO" == "true" ]] && log_info " - wickr-io-exporter.sh"
[[ "$INSTALL_ALERT_RULES" == "true" ]] && log_info " - Prometheus alert rules"
[[ "$INSTALL_PROMETHEUS_CONFIG" == "true" ]] && log_info " - Prometheus scrape config"
check_dependencies
setup_directories
ensure_prometheus_user
# Install components
[[ "$INSTALL_REDIS_EXPORTER" == "true" ]] && install_redis_exporter
[[ "$INSTALL_MYSQL_EXPORTER" == "true" ]] && install_mysqld_exporter
[[ "$INSTALL_CADVISOR" == "true" ]] && install_cadvisor
[[ "$INSTALL_BLACKBOX_CONFIG" == "true" ]] && install_blackbox_config
[[ "$INSTALL_WICKR_METRICS" == "true" ]] && install_wickr_metrics_exporter
[[ "$INSTALL_WICKR_IO" == "true" ]] && install_wickr_io_exporter
[[ "$INSTALL_ALERT_RULES" == "true" ]] && install_alert_rules
[[ "$INSTALL_PROMETHEUS_CONFIG" == "true" ]] && install_prometheus_config
# Summary
echo
echo "=== Wickr Monitoring Setup Complete ==="
echo
if [[ "$DRY_RUN" == "false" ]]; then
echo "Installed components:"
[[ "$INSTALL_REDIS_EXPORTER" == "true" ]] && echo " ✓ redis_exporter http://localhost:9121/metrics"
[[ "$INSTALL_MYSQL_EXPORTER" == "true" ]] && echo " ✓ mysqld_exporter http://localhost:9104/metrics"
[[ "$INSTALL_CADVISOR" == "true" ]] && echo " ✓ cAdvisor http://localhost:8080/metrics"
[[ "$INSTALL_BLACKBOX_CONFIG" == "true" ]] && echo " ✓ blackbox config ${PROMETHEUS_DIR}/blackbox.yml"
[[ "$INSTALL_WICKR_METRICS" == "true" ]] && echo " ✓ wickr-metrics-exporter ${INSTALL_DIR}/wickr-metrics-exporter.sh"
[[ "$INSTALL_WICKR_IO" == "true" ]] && echo " ✓ wickr-io-exporter ${INSTALL_DIR}/wickr-io-exporter.sh"
[[ "$INSTALL_ALERT_RULES" == "true" ]] && echo " ✓ Alert rules ${PROMETHEUS_DIR}/rules/wickr-*.yml"
[[ "$INSTALL_PROMETHEUS_CONFIG" == "true" ]] && echo " ✓ Scrape config ${PROMETHEUS_DIR}/wickr-scrape.yml"
echo
fi
if [[ $ERRORS -gt 0 ]]; then
echo "Completed with $ERRORS error(s) — check $LOGFILE for details"
else
echo "All components installed successfully"
fi
echo "Log: $LOGFILE"
echo
}
main "$@"