Derive AGENT_NAME from ASSISTANT_NAME instead of hardcoding "clawdie". Database names, users, and identity vars now follow the agent name. Add configurable fields to build.cfg and shell-env.sh: - AGENT_GENDER, PI_TUI_PROVIDER, PI_TUI_MODEL - ZAI_API_KEY, OPENROUTER_API_KEY, EMBED_BASE_URL, EMBED_MODEL - TELEGRAM_BOT_TOKEN, FEATURE_TELEGRAM (pre-bakeable for cloud) Add gender selection to baremetal wizard (bsddialog radiolist). Update bhyve-test.sh with --name flag, tap0/bridge auto-setup, sparse disk reuse, and reduced default disk size (25G). Tested: dry-run env generation produces correct Mevy config (agent_name=mevy, db=mevy, provider=zai, model=glm-5). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
237 lines
6.7 KiB
Bash
Executable file
237 lines
6.7 KiB
Bash
Executable file
#!/bin/sh
|
|
# Clawdie Shell — Environment Configuration Module
|
|
# Purpose: Generate .env file with secrets and configuration
|
|
# POSIX-compliant (no bash-isms)
|
|
|
|
set -eu
|
|
|
|
# Configuration (can be overridden for testing)
|
|
CLAWDIE_HOME="${CLAWDIE_HOME:-/home/clawdie}"
|
|
ENV_FILE="${ENV_FILE:-$CLAWDIE_HOME/.env}"
|
|
LOG_FILE="${LOG_FILE:-/var/log/clawdie-firstboot.log}"
|
|
PROGRESS_FILE="${PROGRESS_FILE:-/var/log/clawdie-firstboot.progress}"
|
|
|
|
# Subnet base (default 10.0.0)
|
|
AGENT_SUBNET_BASE="${AGENT_SUBNET_BASE:-10.0.0}"
|
|
|
|
# ============================================================================
|
|
# MAIN ENTRY POINT
|
|
# ============================================================================
|
|
|
|
clawdie_shell_env_generate() {
|
|
# Main orchestrator: generate .env file with all required variables
|
|
|
|
log_msg "[env] Starting .env generation"
|
|
|
|
# Validate required inputs
|
|
if [ -z "${ASSISTANT_NAME:-}" ]; then
|
|
log_msg "[env] ERROR: ASSISTANT_NAME not set"
|
|
return 1
|
|
fi
|
|
|
|
if [ -z "${AGENT_DOMAIN:-}" ]; then
|
|
log_msg "[env] ERROR: AGENT_DOMAIN not set"
|
|
return 1
|
|
fi
|
|
|
|
if [ -z "${TZ:-}" ]; then
|
|
TZ="UTC"
|
|
log_msg "[env] WARNING: TZ not set, defaulting to UTC"
|
|
fi
|
|
|
|
# Step 1: Create directory
|
|
mkdir -p "$CLAWDIE_HOME"
|
|
chown clawdie:clawdie "$CLAWDIE_HOME" 2>/dev/null || true
|
|
|
|
# Step 2: Generate all .env variables
|
|
clawdie_shell_env_write_file || {
|
|
log_msg "[env] ERROR: Failed to write .env file"
|
|
return 1
|
|
}
|
|
|
|
log_msg "[env] .env file generated successfully"
|
|
|
|
# Step 3: Validate
|
|
clawdie_shell_env_validate || {
|
|
log_msg "[env] ERROR: .env validation failed"
|
|
return 1
|
|
}
|
|
|
|
echo "[ENV] SUCCESS" >> "$PROGRESS_FILE"
|
|
log_msg "[env] Environment configuration complete"
|
|
}
|
|
|
|
# ============================================================================
|
|
# .ENV FILE GENERATION
|
|
# ============================================================================
|
|
|
|
clawdie_shell_env_write_file() {
|
|
# Write complete .env file with all required variables
|
|
|
|
local db_ip mgmt_ip git_ip cms_ip worker_start
|
|
|
|
# Derive agent name from assistant name (lowercase, strip non-alnum)
|
|
local agent_name
|
|
agent_name=$(echo "$ASSISTANT_NAME" | tr 'A-Z' 'a-z' | sed 's/[^a-z0-9]//g')
|
|
|
|
# Derive jail IPs from subnet base
|
|
db_ip="${AGENT_SUBNET_BASE}.3"
|
|
mgmt_ip="${AGENT_SUBNET_BASE}.2"
|
|
git_ip="${AGENT_SUBNET_BASE}.4"
|
|
cms_ip="${AGENT_SUBNET_BASE}.5"
|
|
worker_start="${AGENT_SUBNET_BASE}.101"
|
|
|
|
# Remove existing .env if present
|
|
rm -f "$ENV_FILE" 2>/dev/null || true
|
|
|
|
# Create new .env with restricted permissions
|
|
touch "$ENV_FILE"
|
|
chmod 600 "$ENV_FILE"
|
|
chown clawdie:clawdie "$ENV_FILE" 2>/dev/null || true
|
|
|
|
# Generate secrets
|
|
local jwt_secret api_key db_password redis_password
|
|
jwt_secret=$(clawdie_shell_env_gen_secret)
|
|
api_key=$(clawdie_shell_env_gen_secret)
|
|
db_password=$(clawdie_shell_env_gen_secret)
|
|
redis_password=$(clawdie_shell_env_gen_secret)
|
|
|
|
# Write .env file
|
|
cat > "$ENV_FILE" <<EOF
|
|
# Clawdie-AI v0.9.0 Environment Configuration
|
|
# Auto-generated by firstboot installer
|
|
# Date: $(date '+%Y-%m-%d %H:%M:%S')
|
|
|
|
# === Identity ===
|
|
ASSISTANT_NAME="$ASSISTANT_NAME"
|
|
AGENT_NAME="$agent_name"
|
|
AGENT_GENDER="${AGENT_GENDER:-f}"
|
|
AGENT_DOMAIN="$AGENT_DOMAIN"
|
|
TZ="$TZ"
|
|
|
|
# === Secrets (auto-generated) ===
|
|
JWT_SECRET="$jwt_secret"
|
|
DB_PASSWORD="$db_password"
|
|
REDIS_PASSWORD="$redis_password"
|
|
|
|
# === LLM Provider ===
|
|
PI_TUI_PROVIDER="${PI_TUI_PROVIDER:-zai}"
|
|
PI_TUI_MODEL="${PI_TUI_MODEL:-glm-5}"
|
|
ZAI_API_KEY="${ZAI_API_KEY:-}"
|
|
OPENROUTER_API_KEY="${OPENROUTER_API_KEY:-}"
|
|
ANTHROPIC_API_KEY="${ANTHROPIC_API_KEY:-$api_key}"
|
|
|
|
# === Embeddings ===
|
|
EMBED_BASE_URL="${EMBED_BASE_URL:-https://openrouter.ai/api/v1}"
|
|
EMBED_MODEL="${EMBED_MODEL:-BAAI/bge-m3}"
|
|
|
|
# === Network Configuration ===
|
|
AGENT_SUBNET_BASE="$AGENT_SUBNET_BASE"
|
|
AGENT_GATEWAY_IP="${AGENT_SUBNET_BASE}.1"
|
|
MGMT_JAIL_IP="$mgmt_ip"
|
|
DB_JAIL_IP="$db_ip"
|
|
GIT_JAIL_IP="$git_ip"
|
|
CMS_JAIL_IP="$cms_ip"
|
|
WORKER_JAIL_IP_START="$worker_start"
|
|
|
|
# === Database ===
|
|
DB_HOST="$db_ip"
|
|
DB_PORT="5432"
|
|
DB_NAME="$agent_name"
|
|
DB_USER="$agent_name"
|
|
DB_PASSWORD="$db_password"
|
|
|
|
# === Features (optional) ===
|
|
FEATURE_MANAGEMENT_JAIL="true"
|
|
FEATURE_OLLAMA="false"
|
|
FEATURE_TELEGRAM="${FEATURE_TELEGRAM:-false}"
|
|
|
|
# === Telegram ===
|
|
TELEGRAM_BOT_TOKEN="${TELEGRAM_BOT_TOKEN:-}"
|
|
TELEGRAM_CHAT_ID="${TELEGRAM_CHAT_ID:-}"
|
|
|
|
# === Optional: SSH Public Key (if provided at install) ===
|
|
SSH_PUBLIC_KEY="${SSH_PUBLIC_KEY:-}"
|
|
|
|
# === System ===
|
|
FREEBSD_VERSION="15.0-RELEASE"
|
|
INSTALL_DATE="$(date '+%Y-%m-%d')"
|
|
EOF
|
|
|
|
log_msg "[env] Wrote .env with $(wc -l < "$ENV_FILE") configuration lines"
|
|
return 0
|
|
}
|
|
|
|
# ============================================================================
|
|
# SECRET GENERATION
|
|
# ============================================================================
|
|
|
|
clawdie_shell_env_gen_secret() {
|
|
# Generate a random 32-character secret suitable for JWT/API keys
|
|
# Uses /dev/urandom + base64 encoding
|
|
|
|
# Try openssl first (more portable)
|
|
if command -v openssl >/dev/null 2>&1; then
|
|
openssl rand -base64 32 | tr -d '\n' | head -c 32
|
|
return 0
|
|
fi
|
|
|
|
# Fallback: dd from /dev/urandom
|
|
if [ -r /dev/urandom ]; then
|
|
dd if=/dev/urandom bs=1 count=24 2>/dev/null | base64 | tr -d '\n' | head -c 32
|
|
return 0
|
|
fi
|
|
|
|
# Last resort: use /dev/random with longer read (slower)
|
|
dd if=/dev/random bs=1 count=24 2>/dev/null | base64 | tr -d '\n' | head -c 32
|
|
}
|
|
|
|
# ============================================================================
|
|
# VALIDATION
|
|
# ============================================================================
|
|
|
|
clawdie_shell_env_validate() {
|
|
# Verify .env file is properly formatted
|
|
|
|
if [ ! -f "$ENV_FILE" ]; then
|
|
log_msg "[env] ERROR: .env file not found: $ENV_FILE"
|
|
return 1
|
|
fi
|
|
|
|
# Check permissions (should be 600)
|
|
local perms
|
|
perms=$(stat -f "%OLp" "$ENV_FILE" 2>/dev/null || stat -c "%a" "$ENV_FILE" 2>/dev/null || echo "")
|
|
if [ "$perms" != "600" ] && [ -n "$perms" ]; then
|
|
log_msg "[env] WARNING: .env permissions are $perms (should be 600)"
|
|
fi
|
|
|
|
# Check for required variables
|
|
local required_vars="ASSISTANT_NAME AGENT_NAME AGENT_DOMAIN TZ JWT_SECRET DB_PASSWORD"
|
|
local missing=0
|
|
for var in $required_vars; do
|
|
if ! grep -q "^$var=" "$ENV_FILE" 2>/dev/null; then
|
|
log_msg "[env] ERROR: Missing required variable: $var"
|
|
missing=$((missing + 1))
|
|
fi
|
|
done
|
|
|
|
if [ $missing -gt 0 ]; then
|
|
return 1
|
|
fi
|
|
|
|
log_msg "[env] .env validation passed ($(wc -l < "$ENV_FILE") lines)"
|
|
return 0
|
|
}
|
|
|
|
# ============================================================================
|
|
# LOGGING HELPER
|
|
# ============================================================================
|
|
|
|
log_msg() {
|
|
echo "$(date '+%H:%M:%S') $1" | tee -a "$LOG_FILE" 2>/dev/null || true
|
|
}
|
|
|
|
# Only run if sourced directly (not during test)
|
|
if [ "${SHELL_ENV_TEST:-0}" -eq 0 ]; then
|
|
clawdie_shell_env_generate
|
|
fi
|