845 lines
26 KiB
Bash
Executable File
845 lines
26 KiB
Bash
Executable File
#!/bin/bash
|
|
#
|
|
# 🐍 OPHION - Instalador Interativo
|
|
# Plataforma de Observabilidade Open Source
|
|
#
|
|
# Uso: curl -fsSL https://get.ophion.com.br | bash
|
|
#
|
|
|
|
set -e
|
|
|
|
# Cores
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
PURPLE='\033[0;35m'
|
|
CYAN='\033[0;36m'
|
|
NC='\033[0m' # No Color
|
|
|
|
# ASCII Art
|
|
show_banner() {
|
|
echo -e "${PURPLE}"
|
|
cat << "EOF"
|
|
____ _____ _ _ _____ ____ _ _
|
|
/ __ \| __ \| | | |_ _/ __ \| \ | |
|
|
| | | | |__) | |__| | | || | | | \| |
|
|
| | | | ___/| __ | | || | | | . ` |
|
|
| |__| | | | | | |_| || |__| | |\ |
|
|
\____/|_| |_| |_|_____\____/|_| \_|
|
|
|
|
Open Source Observability Platform
|
|
Made with 🖤 in Brazil
|
|
EOF
|
|
echo -e "${NC}"
|
|
}
|
|
|
|
# Logging
|
|
log_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
|
|
log_success() { echo -e "${GREEN}[✓]${NC} $1"; }
|
|
log_warn() { echo -e "${YELLOW}[!]${NC} $1"; }
|
|
log_error() { echo -e "${RED}[✗]${NC} $1"; }
|
|
|
|
# Verificar requisitos
|
|
check_requirements() {
|
|
log_info "Verificando requisitos..."
|
|
|
|
# Docker
|
|
if ! command -v docker &> /dev/null; then
|
|
log_error "Docker não encontrado!"
|
|
echo ""
|
|
echo "Instale o Docker primeiro:"
|
|
echo " curl -fsSL https://get.docker.com | sh"
|
|
exit 1
|
|
fi
|
|
log_success "Docker instalado"
|
|
|
|
# Docker Compose
|
|
if ! docker compose version &> /dev/null && ! command -v docker-compose &> /dev/null; then
|
|
log_error "Docker Compose não encontrado!"
|
|
exit 1
|
|
fi
|
|
log_success "Docker Compose instalado"
|
|
|
|
# Verificar se Docker está rodando
|
|
if ! docker info &> /dev/null; then
|
|
log_error "Docker não está rodando!"
|
|
echo " sudo systemctl start docker"
|
|
exit 1
|
|
fi
|
|
log_success "Docker está rodando"
|
|
}
|
|
|
|
# Gerar string aleatória
|
|
generate_secret() {
|
|
openssl rand -hex 32 2>/dev/null || head -c 64 /dev/urandom | base64 | tr -dc 'a-zA-Z0-9' | head -c 64
|
|
}
|
|
|
|
# Gerar API Key
|
|
generate_api_key() {
|
|
echo "ophion_$(openssl rand -hex 32 2>/dev/null || head -c 64 /dev/urandom | base64 | tr -dc 'a-zA-Z0-9' | head -c 64)"
|
|
}
|
|
|
|
# Coletar informações do cliente
|
|
collect_info() {
|
|
echo ""
|
|
echo -e "${CYAN}═══════════════════════════════════════════════════════════${NC}"
|
|
echo -e "${CYAN} CONFIGURAÇÃO INICIAL ${NC}"
|
|
echo -e "${CYAN}═══════════════════════════════════════════════════════════${NC}"
|
|
echo ""
|
|
|
|
# Nome da organização
|
|
read -p "📋 Nome da sua empresa/organização: " ORG_NAME
|
|
ORG_NAME=${ORG_NAME:-"Minha Empresa"}
|
|
|
|
# Email do admin
|
|
read -p "📧 Email do administrador: " ADMIN_EMAIL
|
|
while [[ ! "$ADMIN_EMAIL" =~ ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ ]]; do
|
|
log_warn "Email inválido!"
|
|
read -p "📧 Email do administrador: " ADMIN_EMAIL
|
|
done
|
|
|
|
# Senha do admin
|
|
echo -n "🔐 Senha do administrador (mín. 8 caracteres): "
|
|
read -s ADMIN_PASSWORD
|
|
echo ""
|
|
while [[ ${#ADMIN_PASSWORD} -lt 8 ]]; do
|
|
log_warn "Senha muito curta!"
|
|
echo -n "🔐 Senha do administrador (mín. 8 caracteres): "
|
|
read -s ADMIN_PASSWORD
|
|
echo ""
|
|
done
|
|
|
|
# Domínio (opcional)
|
|
read -p "🌐 Domínio (deixe vazio para localhost): " DOMAIN
|
|
DOMAIN=${DOMAIN:-"localhost"}
|
|
|
|
# Porta
|
|
read -p "🔌 Porta do servidor [8080]: " SERVER_PORT
|
|
SERVER_PORT=${SERVER_PORT:-8080}
|
|
|
|
# Porta do dashboard
|
|
read -p "🖥️ Porta do dashboard [3000]: " DASHBOARD_PORT
|
|
DASHBOARD_PORT=${DASHBOARD_PORT:-3000}
|
|
|
|
# Habilitar HTTPS?
|
|
if [[ "$DOMAIN" != "localhost" ]]; then
|
|
read -p "🔒 Habilitar HTTPS com Let's Encrypt? (s/n) [s]: " ENABLE_HTTPS
|
|
ENABLE_HTTPS=${ENABLE_HTTPS:-s}
|
|
else
|
|
ENABLE_HTTPS="n"
|
|
fi
|
|
|
|
# Telegram para alertas (opcional)
|
|
echo ""
|
|
read -p "📱 Configurar alertas no Telegram? (s/n) [n]: " ENABLE_TELEGRAM
|
|
if [[ "$ENABLE_TELEGRAM" =~ ^[sS]$ ]]; then
|
|
read -p " Bot Token: " TELEGRAM_BOT_TOKEN
|
|
read -p " Chat ID: " TELEGRAM_CHAT_ID
|
|
fi
|
|
|
|
echo ""
|
|
log_success "Informações coletadas!"
|
|
}
|
|
|
|
# Criar diretório de instalação
|
|
setup_directory() {
|
|
INSTALL_DIR="/opt/ophion"
|
|
|
|
log_info "Criando diretório de instalação em $INSTALL_DIR..."
|
|
|
|
sudo mkdir -p "$INSTALL_DIR"
|
|
sudo mkdir -p "$INSTALL_DIR/data/postgres"
|
|
sudo mkdir -p "$INSTALL_DIR/data/clickhouse"
|
|
sudo mkdir -p "$INSTALL_DIR/data/redis"
|
|
sudo mkdir -p "$INSTALL_DIR/configs"
|
|
sudo mkdir -p "$INSTALL_DIR/logs"
|
|
|
|
sudo chown -R $USER:$USER "$INSTALL_DIR"
|
|
|
|
cd "$INSTALL_DIR"
|
|
log_success "Diretório criado"
|
|
}
|
|
|
|
# Gerar arquivo .env
|
|
generate_env() {
|
|
log_info "Gerando configuração..."
|
|
|
|
JWT_SECRET=$(generate_secret)
|
|
POSTGRES_PASSWORD=$(generate_secret | head -c 32)
|
|
API_KEY=$(generate_api_key)
|
|
|
|
cat > "$INSTALL_DIR/.env" << EOF
|
|
# ═══════════════════════════════════════════════════════════
|
|
# 🐍 OPHION - Configuração
|
|
# Gerado em: $(date)
|
|
# Organização: $ORG_NAME
|
|
# ═══════════════════════════════════════════════════════════
|
|
|
|
# Organização
|
|
ORG_NAME="$ORG_NAME"
|
|
ADMIN_EMAIL="$ADMIN_EMAIL"
|
|
ADMIN_PASSWORD="$ADMIN_PASSWORD"
|
|
|
|
# Rede
|
|
DOMAIN=$DOMAIN
|
|
SERVER_PORT=$SERVER_PORT
|
|
DASHBOARD_PORT=$DASHBOARD_PORT
|
|
API_URL=http://ophion-server:8080
|
|
|
|
# Segurança (NÃO COMPARTILHE!)
|
|
JWT_SECRET=$JWT_SECRET
|
|
API_KEY=$API_KEY
|
|
|
|
# PostgreSQL
|
|
POSTGRES_USER=ophion
|
|
POSTGRES_PASSWORD=$POSTGRES_PASSWORD
|
|
POSTGRES_DB=ophion
|
|
DATABASE_URL=postgres://ophion:$POSTGRES_PASSWORD@postgres:5432/ophion
|
|
|
|
# ClickHouse
|
|
CLICKHOUSE_URL=clickhouse://clickhouse:9000/ophion
|
|
|
|
# Redis
|
|
REDIS_URL=redis://redis:6379
|
|
|
|
# Telegram Alertas
|
|
TELEGRAM_ENABLED=${ENABLE_TELEGRAM:-n}
|
|
TELEGRAM_BOT_TOKEN=${TELEGRAM_BOT_TOKEN:-}
|
|
TELEGRAM_CHAT_ID=${TELEGRAM_CHAT_ID:-}
|
|
|
|
# OpenAI (para recursos de IA)
|
|
OPENAI_API_KEY=
|
|
|
|
# Timezone
|
|
TZ=America/Sao_Paulo
|
|
EOF
|
|
|
|
chmod 600 "$INSTALL_DIR/.env"
|
|
log_success "Arquivo .env gerado"
|
|
}
|
|
|
|
# Gerar docker-compose.yml
|
|
generate_compose() {
|
|
log_info "Gerando docker-compose.yml..."
|
|
|
|
cat > "$INSTALL_DIR/docker-compose.yml" << 'EOF'
|
|
version: '3.8'
|
|
|
|
services:
|
|
# ═══════════════════════════════════════════════════════════
|
|
# 🐍 OPHION Server (API)
|
|
# ═══════════════════════════════════════════════════════════
|
|
ophion-server:
|
|
image: ghcr.io/bigtux/ophion-server:latest
|
|
container_name: ophion-server
|
|
ports:
|
|
- "${SERVER_PORT}:8080"
|
|
environment:
|
|
- DATABASE_URL=${DATABASE_URL}
|
|
- CLICKHOUSE_URL=${CLICKHOUSE_URL}
|
|
- REDIS_URL=${REDIS_URL}
|
|
- JWT_SECRET=${JWT_SECRET}
|
|
- ADMIN_EMAIL=${ADMIN_EMAIL}
|
|
- ADMIN_PASSWORD=${ADMIN_PASSWORD}
|
|
- ORG_NAME=${ORG_NAME}
|
|
- TELEGRAM_ENABLED=${TELEGRAM_ENABLED}
|
|
- TELEGRAM_BOT_TOKEN=${TELEGRAM_BOT_TOKEN}
|
|
- TELEGRAM_CHAT_ID=${TELEGRAM_CHAT_ID}
|
|
- OPENAI_API_KEY=${OPENAI_API_KEY}
|
|
- TZ=${TZ}
|
|
volumes:
|
|
- ./configs:/app/configs:ro
|
|
- ./logs:/app/logs
|
|
depends_on:
|
|
postgres:
|
|
condition: service_healthy
|
|
clickhouse:
|
|
condition: service_started
|
|
redis:
|
|
condition: service_started
|
|
healthcheck:
|
|
test: ["CMD", "wget", "-q", "--spider", "http://localhost:8080/health"]
|
|
interval: 30s
|
|
timeout: 10s
|
|
retries: 3
|
|
restart: unless-stopped
|
|
networks:
|
|
- ophion-net
|
|
|
|
# ═══════════════════════════════════════════════════════════
|
|
# 🖥️ OPHION Dashboard (Web UI)
|
|
# ═══════════════════════════════════════════════════════════
|
|
ophion-web:
|
|
image: ghcr.io/bigtux/ophion-web:latest
|
|
container_name: ophion-web
|
|
ports:
|
|
- "${DASHBOARD_PORT}:3000"
|
|
environment:
|
|
- API_URL=http://ophion-server:8080
|
|
- NEXT_PUBLIC_API_URL=http://${DOMAIN}:${SERVER_PORT}
|
|
- ORG_NAME=${ORG_NAME}
|
|
depends_on:
|
|
- ophion-server
|
|
restart: unless-stopped
|
|
networks:
|
|
- ophion-net
|
|
|
|
# ═══════════════════════════════════════════════════════════
|
|
# 🐘 PostgreSQL (Metadados, Usuários, Config)
|
|
# ═══════════════════════════════════════════════════════════
|
|
postgres:
|
|
image: postgres:16-alpine
|
|
container_name: ophion-postgres
|
|
environment:
|
|
- POSTGRES_USER=${POSTGRES_USER}
|
|
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
|
|
- POSTGRES_DB=${POSTGRES_DB}
|
|
volumes:
|
|
- ./data/postgres:/var/lib/postgresql/data
|
|
- ./init/postgres:/docker-entrypoint-initdb.d:ro
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
|
|
interval: 10s
|
|
timeout: 5s
|
|
retries: 5
|
|
restart: unless-stopped
|
|
networks:
|
|
- ophion-net
|
|
|
|
# ═══════════════════════════════════════════════════════════
|
|
# 🏠 ClickHouse (Métricas, Logs, Traces)
|
|
# ═══════════════════════════════════════════════════════════
|
|
clickhouse:
|
|
image: clickhouse/clickhouse-server:24.1
|
|
container_name: ophion-clickhouse
|
|
volumes:
|
|
- ./data/clickhouse:/var/lib/clickhouse
|
|
- ./init/clickhouse:/docker-entrypoint-initdb.d:ro
|
|
ulimits:
|
|
nofile:
|
|
soft: 262144
|
|
hard: 262144
|
|
restart: unless-stopped
|
|
networks:
|
|
- ophion-net
|
|
|
|
# ═══════════════════════════════════════════════════════════
|
|
# 🔴 Redis (Cache, Sessions, Filas)
|
|
# ═══════════════════════════════════════════════════════════
|
|
redis:
|
|
image: redis:7-alpine
|
|
container_name: ophion-redis
|
|
command: redis-server --appendonly yes
|
|
volumes:
|
|
- ./data/redis:/data
|
|
healthcheck:
|
|
test: ["CMD", "redis-cli", "ping"]
|
|
interval: 10s
|
|
timeout: 5s
|
|
retries: 3
|
|
restart: unless-stopped
|
|
networks:
|
|
- ophion-net
|
|
|
|
networks:
|
|
ophion-net:
|
|
driver: bridge
|
|
|
|
EOF
|
|
|
|
log_success "docker-compose.yml gerado"
|
|
}
|
|
|
|
# Gerar scripts SQL de inicialização
|
|
generate_init_scripts() {
|
|
log_info "Gerando scripts de inicialização..."
|
|
|
|
mkdir -p "$INSTALL_DIR/init/postgres"
|
|
mkdir -p "$INSTALL_DIR/init/clickhouse"
|
|
|
|
# PostgreSQL init
|
|
cat > "$INSTALL_DIR/init/postgres/01-schema.sql" << 'EOF'
|
|
-- ═══════════════════════════════════════════════════════════
|
|
-- 🐍 OPHION - Schema PostgreSQL
|
|
-- ═══════════════════════════════════════════════════════════
|
|
|
|
-- Extensões
|
|
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
|
|
CREATE EXTENSION IF NOT EXISTS "pgcrypto";
|
|
|
|
-- Organizações
|
|
CREATE TABLE organizations (
|
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
name VARCHAR(255) NOT NULL,
|
|
slug VARCHAR(100) UNIQUE NOT NULL,
|
|
settings JSONB DEFAULT '{}',
|
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ DEFAULT NOW()
|
|
);
|
|
|
|
-- Usuários
|
|
CREATE TABLE users (
|
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
org_id UUID REFERENCES organizations(id) ON DELETE CASCADE,
|
|
email VARCHAR(255) UNIQUE NOT NULL,
|
|
password_hash VARCHAR(255) NOT NULL,
|
|
name VARCHAR(255),
|
|
role VARCHAR(50) DEFAULT 'viewer',
|
|
avatar_url TEXT,
|
|
settings JSONB DEFAULT '{}',
|
|
last_login_at TIMESTAMPTZ,
|
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ DEFAULT NOW()
|
|
);
|
|
|
|
-- API Keys
|
|
CREATE TABLE api_keys (
|
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
org_id UUID REFERENCES organizations(id) ON DELETE CASCADE,
|
|
key_hash VARCHAR(64) NOT NULL,
|
|
key_prefix VARCHAR(20) NOT NULL,
|
|
name VARCHAR(255),
|
|
description TEXT,
|
|
scopes TEXT[] DEFAULT ARRAY['metrics:write', 'logs:write'],
|
|
created_by UUID REFERENCES users(id),
|
|
last_used_at TIMESTAMPTZ,
|
|
expires_at TIMESTAMPTZ,
|
|
revoked BOOLEAN DEFAULT FALSE,
|
|
created_at TIMESTAMPTZ DEFAULT NOW()
|
|
);
|
|
|
|
-- Hosts/Agents
|
|
CREATE TABLE hosts (
|
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
org_id UUID REFERENCES organizations(id) ON DELETE CASCADE,
|
|
hostname VARCHAR(255) NOT NULL,
|
|
ip_address INET,
|
|
os VARCHAR(100),
|
|
arch VARCHAR(50),
|
|
agent_version VARCHAR(50),
|
|
tags JSONB DEFAULT '{}',
|
|
status VARCHAR(50) DEFAULT 'unknown',
|
|
last_seen_at TIMESTAMPTZ,
|
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
UNIQUE(org_id, hostname)
|
|
);
|
|
|
|
-- Alert Rules
|
|
CREATE TABLE alert_rules (
|
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
org_id UUID REFERENCES organizations(id) ON DELETE CASCADE,
|
|
name VARCHAR(255) NOT NULL,
|
|
description TEXT,
|
|
query TEXT NOT NULL,
|
|
condition VARCHAR(50) NOT NULL,
|
|
threshold DECIMAL,
|
|
severity VARCHAR(50) DEFAULT 'warning',
|
|
enabled BOOLEAN DEFAULT TRUE,
|
|
notify_channels JSONB DEFAULT '[]',
|
|
created_by UUID REFERENCES users(id),
|
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ DEFAULT NOW()
|
|
);
|
|
|
|
-- Alert History
|
|
CREATE TABLE alert_history (
|
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
rule_id UUID REFERENCES alert_rules(id) ON DELETE CASCADE,
|
|
org_id UUID REFERENCES organizations(id) ON DELETE CASCADE,
|
|
host_id UUID REFERENCES hosts(id),
|
|
severity VARCHAR(50),
|
|
status VARCHAR(50) DEFAULT 'firing',
|
|
message TEXT,
|
|
value DECIMAL,
|
|
fired_at TIMESTAMPTZ DEFAULT NOW(),
|
|
resolved_at TIMESTAMPTZ,
|
|
acknowledged_by UUID REFERENCES users(id),
|
|
acknowledged_at TIMESTAMPTZ
|
|
);
|
|
|
|
-- Dashboards
|
|
CREATE TABLE dashboards (
|
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
org_id UUID REFERENCES organizations(id) ON DELETE CASCADE,
|
|
name VARCHAR(255) NOT NULL,
|
|
description TEXT,
|
|
layout JSONB DEFAULT '[]',
|
|
is_default BOOLEAN DEFAULT FALSE,
|
|
created_by UUID REFERENCES users(id),
|
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ DEFAULT NOW()
|
|
);
|
|
|
|
-- Índices
|
|
CREATE INDEX idx_users_org ON users(org_id);
|
|
CREATE INDEX idx_users_email ON users(email);
|
|
CREATE INDEX idx_api_keys_org ON api_keys(org_id);
|
|
CREATE INDEX idx_api_keys_prefix ON api_keys(key_prefix);
|
|
CREATE INDEX idx_hosts_org ON hosts(org_id);
|
|
CREATE INDEX idx_hosts_status ON hosts(status);
|
|
CREATE INDEX idx_alert_history_org ON alert_history(org_id);
|
|
CREATE INDEX idx_alert_history_status ON alert_history(status);
|
|
CREATE INDEX idx_alert_history_fired ON alert_history(fired_at DESC);
|
|
|
|
EOF
|
|
|
|
# ClickHouse init
|
|
cat > "$INSTALL_DIR/init/clickhouse/01-schema.sql" << 'EOF'
|
|
-- ═══════════════════════════════════════════════════════════
|
|
-- 🐍 OPHION - Schema ClickHouse
|
|
-- ═══════════════════════════════════════════════════════════
|
|
|
|
CREATE DATABASE IF NOT EXISTS ophion;
|
|
|
|
-- Métricas de Sistema
|
|
CREATE TABLE IF NOT EXISTS ophion.metrics (
|
|
org_id UUID,
|
|
host_id UUID,
|
|
hostname LowCardinality(String),
|
|
metric_name LowCardinality(String),
|
|
metric_type LowCardinality(String),
|
|
value Float64,
|
|
tags Map(String, String),
|
|
timestamp DateTime64(3),
|
|
INDEX idx_metric_name metric_name TYPE bloom_filter GRANULARITY 4,
|
|
INDEX idx_hostname hostname TYPE bloom_filter GRANULARITY 4
|
|
) ENGINE = MergeTree()
|
|
PARTITION BY toYYYYMM(timestamp)
|
|
ORDER BY (org_id, host_id, metric_name, timestamp)
|
|
TTL timestamp + INTERVAL 90 DAY;
|
|
|
|
-- Logs
|
|
CREATE TABLE IF NOT EXISTS ophion.logs (
|
|
org_id UUID,
|
|
host_id UUID,
|
|
hostname LowCardinality(String),
|
|
service LowCardinality(String),
|
|
level LowCardinality(String),
|
|
message String,
|
|
attributes Map(String, String),
|
|
trace_id String,
|
|
span_id String,
|
|
timestamp DateTime64(3),
|
|
INDEX idx_level level TYPE set(0) GRANULARITY 4,
|
|
INDEX idx_service service TYPE bloom_filter GRANULARITY 4,
|
|
INDEX idx_message message TYPE tokenbf_v1(10240, 3, 0) GRANULARITY 4
|
|
) ENGINE = MergeTree()
|
|
PARTITION BY toYYYYMM(timestamp)
|
|
ORDER BY (org_id, timestamp, host_id)
|
|
TTL timestamp + INTERVAL 30 DAY;
|
|
|
|
-- Traces (Spans)
|
|
CREATE TABLE IF NOT EXISTS ophion.traces (
|
|
org_id UUID,
|
|
trace_id String,
|
|
span_id String,
|
|
parent_span_id String,
|
|
operation_name LowCardinality(String),
|
|
service_name LowCardinality(String),
|
|
kind LowCardinality(String),
|
|
status_code UInt8,
|
|
status_message String,
|
|
attributes Map(String, String),
|
|
events Nested(
|
|
name String,
|
|
timestamp DateTime64(3),
|
|
attributes Map(String, String)
|
|
),
|
|
duration_ms Float64,
|
|
start_time DateTime64(3),
|
|
end_time DateTime64(3),
|
|
INDEX idx_trace_id trace_id TYPE bloom_filter GRANULARITY 4,
|
|
INDEX idx_service service_name TYPE bloom_filter GRANULARITY 4
|
|
) ENGINE = MergeTree()
|
|
PARTITION BY toYYYYMM(start_time)
|
|
ORDER BY (org_id, service_name, start_time, trace_id)
|
|
TTL start_time + INTERVAL 14 DAY;
|
|
|
|
-- Aggregated metrics (rollups)
|
|
CREATE TABLE IF NOT EXISTS ophion.metrics_hourly (
|
|
org_id UUID,
|
|
host_id UUID,
|
|
metric_name LowCardinality(String),
|
|
hour DateTime,
|
|
min_value Float64,
|
|
max_value Float64,
|
|
avg_value Float64,
|
|
count UInt64
|
|
) ENGINE = SummingMergeTree()
|
|
PARTITION BY toYYYYMM(hour)
|
|
ORDER BY (org_id, host_id, metric_name, hour)
|
|
TTL hour + INTERVAL 1 YEAR;
|
|
|
|
-- Materialized view para rollup
|
|
CREATE MATERIALIZED VIEW IF NOT EXISTS ophion.metrics_hourly_mv
|
|
TO ophion.metrics_hourly AS
|
|
SELECT
|
|
org_id,
|
|
host_id,
|
|
metric_name,
|
|
toStartOfHour(timestamp) AS hour,
|
|
min(value) AS min_value,
|
|
max(value) AS max_value,
|
|
avg(value) AS avg_value,
|
|
count() AS count
|
|
FROM ophion.metrics
|
|
GROUP BY org_id, host_id, metric_name, hour;
|
|
|
|
EOF
|
|
|
|
log_success "Scripts de inicialização gerados"
|
|
}
|
|
|
|
# Gerar script do Agent
|
|
generate_agent_installer() {
|
|
log_info "Gerando instalador do agent..."
|
|
|
|
mkdir -p "$INSTALL_DIR/scripts"
|
|
|
|
cat > "$INSTALL_DIR/scripts/install-agent.sh" << EOF
|
|
#!/bin/bash
|
|
#
|
|
# 🐍 OPHION Agent Installer
|
|
# Servidor: http://${DOMAIN}:${SERVER_PORT}
|
|
#
|
|
|
|
set -e
|
|
|
|
API_KEY="${API_KEY}"
|
|
SERVER_URL="http://${DOMAIN}:${SERVER_PORT}"
|
|
|
|
echo "🐍 Instalando OPHION Agent..."
|
|
|
|
# Detectar OS
|
|
if [[ -f /etc/debian_version ]]; then
|
|
OS="debian"
|
|
elif [[ -f /etc/redhat-release ]]; then
|
|
OS="redhat"
|
|
else
|
|
echo "OS não suportado!"
|
|
exit 1
|
|
fi
|
|
|
|
# Baixar agent
|
|
curl -fsSL -o /tmp/ophion-agent "\${SERVER_URL}/downloads/agent/linux/amd64/ophion-agent"
|
|
chmod +x /tmp/ophion-agent
|
|
sudo mv /tmp/ophion-agent /usr/local/bin/
|
|
|
|
# Criar config
|
|
sudo mkdir -p /etc/ophion
|
|
sudo tee /etc/ophion/agent.yaml > /dev/null << AGENTEOF
|
|
server:
|
|
url: \${SERVER_URL}
|
|
api_key: \${API_KEY}
|
|
|
|
collection:
|
|
interval: 30s
|
|
|
|
metrics:
|
|
enabled: true
|
|
include:
|
|
- cpu
|
|
- memory
|
|
- disk
|
|
- network
|
|
- processes
|
|
|
|
logs:
|
|
enabled: true
|
|
paths:
|
|
- /var/log/syslog
|
|
- /var/log/auth.log
|
|
AGENTEOF
|
|
|
|
# Criar systemd service
|
|
sudo tee /etc/systemd/system/ophion-agent.service > /dev/null << SERVICEEOF
|
|
[Unit]
|
|
Description=OPHION Monitoring Agent
|
|
After=network.target
|
|
|
|
[Service]
|
|
Type=simple
|
|
ExecStart=/usr/local/bin/ophion-agent -config /etc/ophion/agent.yaml
|
|
Restart=always
|
|
RestartSec=10
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
SERVICEEOF
|
|
|
|
# Iniciar
|
|
sudo systemctl daemon-reload
|
|
sudo systemctl enable ophion-agent
|
|
sudo systemctl start ophion-agent
|
|
|
|
echo ""
|
|
echo "✅ OPHION Agent instalado!"
|
|
echo " Status: sudo systemctl status ophion-agent"
|
|
echo " Logs: sudo journalctl -u ophion-agent -f"
|
|
EOF
|
|
|
|
chmod +x "$INSTALL_DIR/scripts/install-agent.sh"
|
|
log_success "Instalador do agent gerado"
|
|
}
|
|
|
|
# Gerar comandos de gerenciamento
|
|
generate_cli() {
|
|
log_info "Gerando CLI de gerenciamento..."
|
|
|
|
cat > "$INSTALL_DIR/ophion" << 'EOF'
|
|
#!/bin/bash
|
|
#
|
|
# 🐍 OPHION CLI
|
|
#
|
|
|
|
INSTALL_DIR="/opt/ophion"
|
|
cd "$INSTALL_DIR"
|
|
|
|
case "$1" in
|
|
start)
|
|
echo "🚀 Iniciando OPHION..."
|
|
docker compose up -d
|
|
echo "✅ OPHION iniciado!"
|
|
echo " Dashboard: http://localhost:${DASHBOARD_PORT:-3000}"
|
|
echo " API: http://localhost:${SERVER_PORT:-8080}"
|
|
;;
|
|
stop)
|
|
echo "🛑 Parando OPHION..."
|
|
docker compose down
|
|
echo "✅ OPHION parado"
|
|
;;
|
|
restart)
|
|
echo "🔄 Reiniciando OPHION..."
|
|
docker compose restart
|
|
echo "✅ OPHION reiniciado"
|
|
;;
|
|
status)
|
|
docker compose ps
|
|
;;
|
|
logs)
|
|
docker compose logs -f ${2:-ophion-server}
|
|
;;
|
|
update)
|
|
echo "📦 Atualizando OPHION..."
|
|
docker compose pull
|
|
docker compose up -d
|
|
echo "✅ OPHION atualizado!"
|
|
;;
|
|
backup)
|
|
BACKUP_DIR="$INSTALL_DIR/backups/$(date +%Y%m%d_%H%M%S)"
|
|
mkdir -p "$BACKUP_DIR"
|
|
echo "💾 Criando backup em $BACKUP_DIR..."
|
|
docker compose exec -T postgres pg_dump -U ophion ophion > "$BACKUP_DIR/postgres.sql"
|
|
cp "$INSTALL_DIR/.env" "$BACKUP_DIR/"
|
|
echo "✅ Backup criado!"
|
|
;;
|
|
api-key)
|
|
NEW_KEY="ophion_$(openssl rand -hex 32)"
|
|
echo "🔑 Nova API Key gerada:"
|
|
echo ""
|
|
echo " $NEW_KEY"
|
|
echo ""
|
|
echo "⚠️ Salve esta key! Ela não será mostrada novamente."
|
|
;;
|
|
agent-install)
|
|
echo ""
|
|
echo "Para instalar o agent em outro servidor, execute:"
|
|
echo ""
|
|
echo " curl -fsSL http://$(hostname -I | awk '{print $1}'):${SERVER_PORT:-8080}/install-agent.sh | sudo bash"
|
|
echo ""
|
|
;;
|
|
*)
|
|
echo "🐍 OPHION CLI"
|
|
echo ""
|
|
echo "Uso: ophion <comando>"
|
|
echo ""
|
|
echo "Comandos:"
|
|
echo " start Iniciar todos os serviços"
|
|
echo " stop Parar todos os serviços"
|
|
echo " restart Reiniciar todos os serviços"
|
|
echo " status Ver status dos serviços"
|
|
echo " logs [svc] Ver logs (padrão: ophion-server)"
|
|
echo " update Atualizar para última versão"
|
|
echo " backup Criar backup dos dados"
|
|
echo " api-key Gerar nova API key"
|
|
echo " agent-install Mostrar comando de instalação do agent"
|
|
;;
|
|
esac
|
|
EOF
|
|
|
|
chmod +x "$INSTALL_DIR/ophion"
|
|
sudo ln -sf "$INSTALL_DIR/ophion" /usr/local/bin/ophion
|
|
|
|
log_success "CLI instalado em /usr/local/bin/ophion"
|
|
}
|
|
|
|
# Resumo final
|
|
show_summary() {
|
|
echo ""
|
|
echo -e "${GREEN}═══════════════════════════════════════════════════════════${NC}"
|
|
echo -e "${GREEN} 🎉 OPHION INSTALADO COM SUCESSO! ${NC}"
|
|
echo -e "${GREEN}═══════════════════════════════════════════════════════════${NC}"
|
|
echo ""
|
|
echo -e " ${CYAN}Organização:${NC} $ORG_NAME"
|
|
echo -e " ${CYAN}Admin:${NC} $ADMIN_EMAIL"
|
|
echo ""
|
|
echo -e " ${CYAN}Dashboard:${NC} http://${DOMAIN}:${DASHBOARD_PORT}"
|
|
echo -e " ${CYAN}API:${NC} http://${DOMAIN}:${SERVER_PORT}"
|
|
echo ""
|
|
echo -e " ${YELLOW}🔑 API Key (SALVE AGORA!):${NC}"
|
|
echo -e " ${PURPLE}$API_KEY${NC}"
|
|
echo ""
|
|
echo -e " ${CYAN}Diretório:${NC} $INSTALL_DIR"
|
|
echo ""
|
|
echo -e "${GREEN}───────────────────────────────────────────────────────────${NC}"
|
|
echo ""
|
|
echo " Comandos úteis:"
|
|
echo ""
|
|
echo " ophion start # Iniciar"
|
|
echo " ophion stop # Parar"
|
|
echo " ophion status # Ver status"
|
|
echo " ophion logs # Ver logs"
|
|
echo " ophion agent-install # Instalar agent em outros servidores"
|
|
echo ""
|
|
echo -e "${GREEN}───────────────────────────────────────────────────────────${NC}"
|
|
echo ""
|
|
|
|
read -p "🚀 Iniciar OPHION agora? (s/n) [s]: " START_NOW
|
|
START_NOW=${START_NOW:-s}
|
|
|
|
if [[ "$START_NOW" =~ ^[sS]$ ]]; then
|
|
echo ""
|
|
log_info "Iniciando serviços..."
|
|
cd "$INSTALL_DIR"
|
|
docker compose up -d
|
|
|
|
echo ""
|
|
log_success "OPHION está rodando!"
|
|
echo ""
|
|
echo -e " Acesse: ${CYAN}http://${DOMAIN}:${DASHBOARD_PORT}${NC}"
|
|
echo -e " Login: ${CYAN}${ADMIN_EMAIL}${NC}"
|
|
echo ""
|
|
fi
|
|
}
|
|
|
|
# ═══════════════════════════════════════════════════════════
|
|
# MAIN
|
|
# ═══════════════════════════════════════════════════════════
|
|
|
|
main() {
|
|
clear
|
|
show_banner
|
|
check_requirements
|
|
collect_info
|
|
setup_directory
|
|
generate_env
|
|
generate_compose
|
|
generate_init_scripts
|
|
generate_agent_installer
|
|
generate_cli
|
|
show_summary
|
|
}
|
|
|
|
main "$@"
|