237 lines
7.3 KiB
Bash
Executable file
237 lines
7.3 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
#
|
|
# apricot.sh — apricot-specific provisioning (10.0.0.13, Fedora Atomic/Bluefin)
|
|
#
|
|
# Apricot is the GPU dev workstation. This module verifies/configures:
|
|
# - DNS client (→ 10.0.0.11 via resolved)
|
|
# - CA certificate
|
|
# - NPM registry (→ npm.black.local)
|
|
# - Feature databases (docker: analytics, i18n, seo, conv-assistant)
|
|
# - Dev nginx (podman: *.apricot.local)
|
|
# - CUDA/ML tools
|
|
# - Restic backups (systemd timer → black:8000)
|
|
# - WireGuard VPN (wg0)
|
|
# - host-status-monitor (systemd)
|
|
#
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
|
|
# Feature database containers
|
|
FEATURE_DBS=(
|
|
"analytics-postgres:5433"
|
|
"i18n-postgres:5434"
|
|
"seo-postgres:5435"
|
|
"conv-assistant-postgres:5436"
|
|
"analytics-redis:6381"
|
|
"i18n-redis:6382"
|
|
"seo-redis:6383"
|
|
"conv-assistant-redis:6384"
|
|
"conv-assistant-chromadb:6385"
|
|
"conv-assistant-qdrant:6386"
|
|
)
|
|
|
|
# ============================================================================
|
|
# Feature Databases
|
|
# ============================================================================
|
|
|
|
_apricot_feature_dbs() {
|
|
log_section "Feature Databases (Docker/Podman)"
|
|
|
|
local container_cmd="docker"
|
|
if command -v podman &>/dev/null && ! command -v docker &>/dev/null; then
|
|
container_cmd="podman"
|
|
fi
|
|
|
|
local running
|
|
running=$($container_cmd ps --format '{{.Names}}' 2>/dev/null)
|
|
|
|
for db_entry in "${FEATURE_DBS[@]}"; do
|
|
local name="${db_entry%%:*}"
|
|
local port="${db_entry##*:}"
|
|
|
|
if echo "$running" | grep -q "^${name}$"; then
|
|
log_info "Container: $name (:$port)"
|
|
else
|
|
log_warn "Container NOT running: $name (:$port)"
|
|
fi
|
|
done
|
|
}
|
|
|
|
# ============================================================================
|
|
# Dev nginx (podman)
|
|
# ============================================================================
|
|
|
|
_apricot_dev_nginx() {
|
|
log_section "Dev Nginx (*.apricot.local)"
|
|
|
|
local compose_file
|
|
compose_file="$(cd "$SCRIPT_DIR/../.." && pwd)/nginx/docker-compose.apricot.yml"
|
|
local container_name="apricot-dev-proxy"
|
|
|
|
local container_cmd="docker"
|
|
if command -v podman &>/dev/null && ! command -v docker &>/dev/null; then
|
|
container_cmd="podman"
|
|
fi
|
|
|
|
local running
|
|
running=$($container_cmd ps --filter "name=${container_name}" --filter "status=running" --format '{{.Names}}' 2>/dev/null || true)
|
|
|
|
if [[ -n "$running" ]]; then
|
|
log_info "Dev proxy container running ($container_name)"
|
|
|
|
# Validate nginx config
|
|
if $container_cmd exec "$container_name" nginx -t &>/dev/null; then
|
|
log_info "nginx config valid"
|
|
else
|
|
log_warn "nginx config INVALID"
|
|
$container_cmd exec "$container_name" nginx -t 2>&1 | sed 's/^/ /'
|
|
fi
|
|
|
|
# List configured vhosts
|
|
local vhosts
|
|
vhosts=$($container_cmd exec "$container_name" nginx -T 2>/dev/null \
|
|
| grep -oP 'server_name\s+\K[^;]+' \
|
|
| grep -v '^_$' \
|
|
| sort -u)
|
|
if [[ -n "$vhosts" ]]; then
|
|
log_info "Configured vhosts:"
|
|
echo "$vhosts" | sed 's/^/ /'
|
|
fi
|
|
else
|
|
log_warn "Dev proxy container not running"
|
|
if [[ -f "$compose_file" ]]; then
|
|
echo " Start with: docker compose -f $compose_file up -d"
|
|
else
|
|
echo " Compose file not found: $compose_file"
|
|
echo " Deploy from ~/Code/deployments/nginx/"
|
|
fi
|
|
fi
|
|
}
|
|
|
|
# ============================================================================
|
|
# CUDA / ML tools
|
|
# ============================================================================
|
|
|
|
_apricot_cuda() {
|
|
log_section "CUDA & ML Tools"
|
|
|
|
if command -v nvcc &>/dev/null; then
|
|
local cuda_version
|
|
cuda_version=$(nvcc --version 2>/dev/null | grep "release" | awk '{print $6}' | cut -d',' -f1 || echo "unknown")
|
|
log_info "CUDA toolkit: $cuda_version"
|
|
else
|
|
log_warn "CUDA toolkit not found (nvcc missing)"
|
|
fi
|
|
|
|
if command -v nvidia-smi &>/dev/null; then
|
|
local gpu_info
|
|
gpu_info=$(nvidia-smi --query-gpu=name,memory.total --format=csv,noheader 2>/dev/null | head -1)
|
|
log_info "GPU: $gpu_info"
|
|
else
|
|
log_warn "nvidia-smi not found"
|
|
fi
|
|
|
|
if python3 -c "import torch; print(f'PyTorch {torch.__version__}, CUDA {torch.version.cuda}')" 2>/dev/null; then
|
|
log_info "PyTorch with CUDA available"
|
|
else
|
|
log_warn "PyTorch not available or no CUDA support"
|
|
fi
|
|
}
|
|
|
|
# ============================================================================
|
|
# Restic backups
|
|
# ============================================================================
|
|
|
|
_apricot_restic() {
|
|
log_section "Restic Backups"
|
|
|
|
# Check systemd timers
|
|
local timers
|
|
timers=$(systemctl --user list-timers --no-pager 2>/dev/null || echo "")
|
|
|
|
if echo "$timers" | grep -q "restic-backup-code"; then
|
|
log_info "Code backup timer active"
|
|
else
|
|
log_warn "Code backup timer not found"
|
|
echo " Run setup-workstation.sh to configure restic backups"
|
|
fi
|
|
|
|
if echo "$timers" | grep -q "restic-backup-dotfiles"; then
|
|
log_info "Dotfiles backup timer active"
|
|
else
|
|
log_warn "Dotfiles backup timer not found"
|
|
fi
|
|
|
|
# Verify restic server reachable
|
|
if curl -sf "http://10.0.0.11:8000/" &>/dev/null; then
|
|
log_info "Restic REST server reachable"
|
|
else
|
|
log_warn "Restic REST server not reachable at http://10.0.0.11:8000/"
|
|
fi
|
|
}
|
|
|
|
# ============================================================================
|
|
# WireGuard VPN
|
|
# ============================================================================
|
|
|
|
_apricot_vpn() {
|
|
log_section "WireGuard VPN"
|
|
|
|
if ip addr show wg0 &>/dev/null 2>&1; then
|
|
log_info "WireGuard wg0 interface up"
|
|
|
|
if ping -c 1 -W 2 10.0.0.11 &>/dev/null; then
|
|
log_info "Can reach black (10.0.0.11) over VPN"
|
|
else
|
|
log_warn "wg0 up but cannot reach 10.0.0.11"
|
|
fi
|
|
elif nmcli con show --active 2>/dev/null | grep -qi wireguard; then
|
|
log_info "WireGuard active via NetworkManager"
|
|
else
|
|
log_warn "WireGuard not active"
|
|
fi
|
|
}
|
|
|
|
# ============================================================================
|
|
# Status monitor
|
|
# ============================================================================
|
|
|
|
_apricot_status_agent() {
|
|
log_section "Host Status Monitor"
|
|
|
|
if systemctl --user is-active host-status-monitor &>/dev/null 2>&1; then
|
|
log_info "host-status-monitor active (user service)"
|
|
elif systemctl is-active host-status-monitor &>/dev/null 2>&1; then
|
|
log_info "host-status-monitor active (system service)"
|
|
else
|
|
log_warn "host-status-monitor not active"
|
|
fi
|
|
}
|
|
|
|
# ============================================================================
|
|
# Public API
|
|
# ============================================================================
|
|
|
|
host_dns_setup() {
|
|
dns_client_setup
|
|
}
|
|
|
|
host_services_setup() {
|
|
_apricot_feature_dbs
|
|
_apricot_dev_nginx
|
|
_apricot_cuda
|
|
_apricot_restic
|
|
_apricot_vpn
|
|
_apricot_status_agent
|
|
}
|
|
|
|
host_verify() {
|
|
CHECK_ONLY=true
|
|
dns_client_verify || true
|
|
_apricot_feature_dbs
|
|
_apricot_dev_nginx
|
|
_apricot_cuda
|
|
_apricot_restic
|
|
_apricot_vpn
|
|
_apricot_status_agent
|
|
}
|