168 lines
5.1 KiB
YAML
168 lines
5.1 KiB
YAML
|
|
#cloud-config
|
||
|
|
# ------------------------------------------------------------------
|
||
|
|
# Deploy-time cloud-init for Vultr Marketplace
|
||
|
|
#
|
||
|
|
# The snapshot already has Hermes Agent, Docker, Caddy, ttyd, code-server
|
||
|
|
# installed. This script:
|
||
|
|
# 1. Fetches per-instance metadata from the Vultr metadata service
|
||
|
|
# 2. Configures Hermes Agent with Vultr Inference provider
|
||
|
|
# 3. Configures code-server with password
|
||
|
|
# 4. Starts ttyd and code-server services
|
||
|
|
# 5. Configures Caddy as a TLS reverse proxy
|
||
|
|
# - / → ttyd (Hermes terminal)
|
||
|
|
# - /code/* → code-server
|
||
|
|
# ------------------------------------------------------------------
|
||
|
|
|
||
|
|
runcmd:
|
||
|
|
# ── Fetch Vultr metadata and persist ──
|
||
|
|
- |
|
||
|
|
APP_PASSWORD=$(curl -sf -H "METADATA-TOKEN: vultr" http://169.254.169.254/v1/internal/app-password)
|
||
|
|
APP_INF_API_KEY=$(curl -sf -H "METADATA-TOKEN: vultr" http://169.254.169.254/v1/internal/app-inf_api_key)
|
||
|
|
APP_DOMAIN=$(curl -sf -H "METADATA-TOKEN: vultr" http://169.254.169.254/v1/internal/app-domain)
|
||
|
|
printf 'APP_PASSWORD="%s"\nAPP_INF_API_KEY="%s"\nAPP_DOMAIN="%s"\n' \
|
||
|
|
"$APP_PASSWORD" "$APP_INF_API_KEY" "$APP_DOMAIN" \
|
||
|
|
> /etc/hermes-deploy.env
|
||
|
|
chmod 600 /etc/hermes-deploy.env
|
||
|
|
|
||
|
|
# ── Configure Hermes Agent with Vultr Inference provider ──
|
||
|
|
- |
|
||
|
|
. /etc/hermes-deploy.env
|
||
|
|
|
||
|
|
# Create .env with API keys
|
||
|
|
cat > /home/hermes/.hermes/.env << ENV_EOF
|
||
|
|
# =============================================================================
|
||
|
|
# VULTR INFERENCE PROVIDER (Pre-configured)
|
||
|
|
# =============================================================================
|
||
|
|
VULTR_API_KEY=${APP_INF_API_KEY}
|
||
|
|
VULTR_BASE_URL=https://api.vultrinference.com/v1
|
||
|
|
|
||
|
|
# For OpenAI-compatible custom endpoint mode:
|
||
|
|
OPENAI_API_KEY=${APP_INF_API_KEY}
|
||
|
|
OPENAI_BASE_URL=https://api.vultrinference.com/v1
|
||
|
|
ENV_EOF
|
||
|
|
chown hermes:hermes /home/hermes/.hermes/.env
|
||
|
|
chmod 600 /home/hermes/.hermes/.env
|
||
|
|
|
||
|
|
# Create config.yaml
|
||
|
|
cat > /home/hermes/.hermes/config.yaml << 'CONFIG_EOF'
|
||
|
|
# Hermes Agent Configuration - Vultr Inference
|
||
|
|
# =============================================================================
|
||
|
|
# Pre-configured for Vultr Inference API (OpenAI-compatible)
|
||
|
|
|
||
|
|
model:
|
||
|
|
# Default model (GLM-5-FP8 - 200K context, reasoning-capable)
|
||
|
|
default: "zai-org/GLM-5-FP8"
|
||
|
|
# Use custom provider for Vultr Inference (OpenAI-compatible)
|
||
|
|
provider: "custom"
|
||
|
|
base_url: "https://api.vultrinference.com/v1"
|
||
|
|
# api_key will be substituted from .env
|
||
|
|
|
||
|
|
# Terminal backend (local execution)
|
||
|
|
terminal:
|
||
|
|
backend: "local"
|
||
|
|
cwd: "."
|
||
|
|
timeout: 180
|
||
|
|
lifetime_seconds: 300
|
||
|
|
|
||
|
|
# Enable persistent memory
|
||
|
|
memory:
|
||
|
|
memory_enabled: true
|
||
|
|
user_profile_enabled: true
|
||
|
|
memory_char_limit: 2200
|
||
|
|
user_char_limit: 1375
|
||
|
|
nudge_interval: 10
|
||
|
|
|
||
|
|
# Context compression for long conversations
|
||
|
|
compression:
|
||
|
|
enabled: true
|
||
|
|
threshold: 0.50
|
||
|
|
target_ratio: 0.20
|
||
|
|
protect_last_n: 20
|
||
|
|
summary_model: "zai-org/GLM-5-FP8"
|
||
|
|
|
||
|
|
# Agent settings
|
||
|
|
agent:
|
||
|
|
max_turns: 60
|
||
|
|
verbose: false
|
||
|
|
reasoning_effort: "medium"
|
||
|
|
|
||
|
|
# Toolsets for CLI
|
||
|
|
platform_toolsets:
|
||
|
|
cli: [hermes-cli]
|
||
|
|
|
||
|
|
# Display settings
|
||
|
|
display:
|
||
|
|
compact: false
|
||
|
|
tool_progress: all
|
||
|
|
streaming: true
|
||
|
|
CONFIG_EOF
|
||
|
|
chown hermes:hermes /home/hermes/.hermes/config.yaml
|
||
|
|
chmod 600 /home/hermes/.hermes/config.yaml
|
||
|
|
|
||
|
|
# ── Configure and start code-server ──
|
||
|
|
- |
|
||
|
|
. /etc/hermes-deploy.env
|
||
|
|
cat > /home/hermes/.config/code-server/config.yaml << CSCFG
|
||
|
|
bind-addr: 127.0.0.1:8080
|
||
|
|
auth: password
|
||
|
|
password: ${APP_PASSWORD}
|
||
|
|
cert: false
|
||
|
|
CSCFG
|
||
|
|
chown hermes:hermes /home/hermes/.config/code-server/config.yaml
|
||
|
|
chmod 600 /home/hermes/.config/code-server/config.yaml
|
||
|
|
|
||
|
|
# ── Start ttyd and code-server services ──
|
||
|
|
- systemctl enable ttyd-hermes code-server-hermes
|
||
|
|
- systemctl start ttyd-hermes code-server-hermes
|
||
|
|
|
||
|
|
# ── Write Caddyfile ──
|
||
|
|
# ttyd at root, code-server at /code/
|
||
|
|
# ZeroSSL primary (avoids LE rate limits), Let's Encrypt fallback
|
||
|
|
- |
|
||
|
|
. /etc/hermes-deploy.env
|
||
|
|
HASHED=$(caddy hash-password --plaintext "$APP_PASSWORD")
|
||
|
|
cat > /etc/caddy/Caddyfile << CADDY
|
||
|
|
${APP_DOMAIN} {
|
||
|
|
tls {
|
||
|
|
issuer acme {
|
||
|
|
dir https://acme.zerossl.com/v2/DV90
|
||
|
|
eab ur6CkPWFhPtp8af1SASQEA dRKaIDk9u4tn7MYrHNczzl_tnKSJ8Hipb2IFVui3oxEHCj_3wkGBA-zG93X7NXaROh-pzDJOugrtn1nxxGasxw
|
||
|
|
}
|
||
|
|
issuer acme {
|
||
|
|
dir https://acme-v02.api.letsencrypt.org/directory
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
basic_auth {
|
||
|
|
hermes ${HASHED}
|
||
|
|
}
|
||
|
|
|
||
|
|
# code-server at /code/
|
||
|
|
handle_path /code/* {
|
||
|
|
reverse_proxy 127.0.0.1:8080
|
||
|
|
}
|
||
|
|
|
||
|
|
# Default: Hermes terminal (ttyd) at root
|
||
|
|
handle {
|
||
|
|
reverse_proxy 127.0.0.1:7681
|
||
|
|
}
|
||
|
|
}
|
||
|
|
CADDY
|
||
|
|
|
||
|
|
# ── Start Caddy and wait for cert issuance ──
|
||
|
|
# ZeroSSL can take 30-60s; wait up to 90s for cert before proceeding
|
||
|
|
- systemctl enable caddy
|
||
|
|
- systemctl restart caddy
|
||
|
|
- |
|
||
|
|
echo "Waiting for TLS certificate issuance (up to 90s)..."
|
||
|
|
for i in $(seq 1 90); do
|
||
|
|
if find /var/lib/caddy -name '*.crt' 2>/dev/null | grep -q .; then
|
||
|
|
echo "Certificate obtained!"
|
||
|
|
break
|
||
|
|
fi
|
||
|
|
sleep 1
|
||
|
|
done
|
||
|
|
|
||
|
|
# ── Clean up secrets from disk ──
|
||
|
|
- rm -f /etc/hermes-deploy.env
|