bb17615f41
SLICE-03 (devops-engineer): ported from coreci/scripts/proxmox/: api.sh (verbatim), ct-exists.sh, lxc-clone.sh (4GB/16GB, hostname=praxis), lxc-config.sh (praxis env vars, praxis-firstboot.sh snippet), lxc-start.sh, stage-snippet.sh (G-101 FIX: bakes GITEA_TOKEN into snippet via sed), timing.sh (verbatim), rollback.sh (proxy code removed) SLICE-04 (devops-engineer): health-check.sh adapted for /health:8789 (G-104 FIX: timeout bumped 300s→600s for Docker build margin) REQ-DEPLOY-03, 04, 05, 07, 08 covered. ---ci--- project: praxis phase: 1 milestone: v0.2 status: execute slice: 03-04 wave: 2 ---/ci---
127 lines
5.7 KiB
Bash
Executable File
127 lines
5.7 KiB
Bash
Executable File
#!/bin/sh
|
|
# Praxis — Configure a created LXC container.
|
|
#
|
|
# Sets memory + onboot via the REST PUT /config (API-token-accepted),
|
|
# then sets hookscript + lxc.environment via SSH to the PVE host (these
|
|
# are root-only via REST: `hookscript` rejects API tokens, and
|
|
# `lxc.environment` is not in the REST schema). The hookscript points
|
|
# at the snippet staged by stage-snippet.sh (local:snippets/praxis-
|
|
# firstboot.sh).
|
|
#
|
|
# G-101: The GITEA_TOKEN must be available to the hookscript which runs
|
|
# on the PVE HOST (lxc.environment is NOT visible to the host-side
|
|
# hookscript). The token is baked into the snippet by stage-snippet.sh.
|
|
# The lxc.environment lines here put GITEA_TOKEN into the CT for the
|
|
# CT's own use (docker-compose env_file reads it), but the hookscript
|
|
# relies on the baked-in value.
|
|
#
|
|
# Env: PROXMOX_API_URL, PROXMOX_API_TOKEN, PROXMOX_NODE,
|
|
# PRAXIS_VERSION (git clone tag/branch, default latest),
|
|
# GITEA_TOKEN (for the private repo fetch inside the CT),
|
|
# DEEPGRAM_API_KEY, CARTESIA_API_KEY, OLLAMA_API_KEY (secrets,
|
|
# may be empty in v0.2 infrastructure-only),
|
|
# PRAXIS_DB_PATH (default /app/data/praxis.db),
|
|
# PRAXIS_TTS, PRAXIS_SCENARIO (optional, with defaults),
|
|
# OLLAMA_BASE_URL, OLLAMA_CHAT_URL, OLLAMA_ROLEPLAY_MODEL,
|
|
# OLLAMA_DEBRIEF_MODEL,
|
|
# DEEPGRAM_MODEL, DEEPGRAM_LANGUAGE, DEEPGRAM_REGION,
|
|
# CARTESIA_VOICE_ID,
|
|
# PRAXIS_PORT (default 8789),
|
|
# PROXMOX_MEMORY_MB (optional, default 4096),
|
|
# PROXMOX_STORAGE (for the hookscript volid prefix),
|
|
# PROXMOX_SSH_HOST (optional; defaults to PROXMOX_NODE)
|
|
# Args: $1 = VMID
|
|
# Exit: 0 on success, 1 on failure
|
|
|
|
set -eu
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
# shellcheck source=api.sh disable=SC1091
|
|
. "${SCRIPT_DIR}/api.sh"
|
|
|
|
pve_env PROXMOX_API_URL PROXMOX_API_TOKEN PROXMOX_NODE
|
|
|
|
vmid="${1:?usage: lxc-config.sh <vmid>}"
|
|
node="${PROXMOX_NODE}"
|
|
memory="${PROXMOX_MEMORY_MB:-4096}"
|
|
version="${PRAXIS_VERSION:-latest}"
|
|
port="${PRAXIS_PORT:-8789}"
|
|
db_path="${PRAXIS_DB_PATH:-/app/data/praxis.db}"
|
|
storage="${PROXMOX_STORAGE:-local}"
|
|
hookscript_volid="${storage}:snippets/praxis-firstboot.sh"
|
|
ssh_host="${PROXMOX_SSH_HOST:-${node}}"
|
|
|
|
# Optional praxis config (with defaults; empty is valid for v0.2).
|
|
praxis_tts="${PRAXIS_TTS:-deepgram}"
|
|
praxis_scenario="${PRAXIS_SCENARIO:-default}"
|
|
|
|
# Secret keys (may be empty in v0.2 infrastructure-only slice).
|
|
deepgram_key="${DEEPGRAM_API_KEY:-}"
|
|
cartesia_key="${CARTESIA_API_KEY:-}"
|
|
ollama_key="${OLLAMA_API_KEY:-}"
|
|
|
|
# Ollama config (with defaults).
|
|
ollama_base="${OLLAMA_BASE_URL:-http://ollama.cloudinit.dev:11434}"
|
|
ollama_chat="${OLLAMA_CHAT_URL:-${ollama_base}/v1/chat/completions}"
|
|
ollama_roleplay="${OLLAMA_ROLEPLAY_MODEL:-gemma4:cloud}"
|
|
ollama_debrief="${OLLAMA_DEBRIEF_MODEL:-deepseek-v4-flash:cloud}"
|
|
|
|
# Deepgram config (with defaults).
|
|
deepgram_model="${DEEPGRAM_MODEL:-nova-3}"
|
|
deepgram_lang="${DEEPGRAM_LANGUAGE:-en-US}"
|
|
deepgram_region="${DEEPGRAM_REGION:-us-east-1}"
|
|
|
|
# Cartesia config (with defaults; empty in v0.2).
|
|
cartesia_voice="${CARTESIA_VOICE_ID:-}"
|
|
|
|
config_path="/nodes/${node}/lxc/${vmid}/config"
|
|
|
|
echo "lxc-config: configuring VMID ${vmid} (memory=${memory}MB, onboot=1, hookscript=${hookscript_volid})" >&2
|
|
|
|
# Step 1: REST-accepted fields (memory, onboot). PUT /config is
|
|
# synchronous (no UPID), returns null on success.
|
|
pve_curl PUT "$config_path" "onboot=1" "memory=${memory}"
|
|
|
|
# Step 2: root-only fields (hookscript, lxc.environment) via SSH to the
|
|
# PVE host config file. These are rejected by the REST API for API
|
|
# tokens and lxc.environment is not in the REST schema at all.
|
|
conf_file="/etc/pve/lxc/${vmid}.conf"
|
|
ssh_opts="-o StrictHostKeyChecking=no"
|
|
# Build the lines to append (remove any prior hookscript/onboot/lxc.environment
|
|
# lines first to keep the config idempotent).
|
|
append_lines() {
|
|
printf 'onboot: 1\n'
|
|
printf 'hookscript: %s\n' "$hookscript_volid"
|
|
printf 'lxc.environment: PRAXIS_VERSION=%s\n' "$version"
|
|
printf 'lxc.environment: PRAXIS_PORT=%s\n' "$port"
|
|
printf 'lxc.environment: PRAXIS_DB_PATH=%s\n' "$db_path"
|
|
printf 'lxc.environment: PRAXIS_TTS=%s\n' "$praxis_tts"
|
|
printf 'lxc.environment: PRAXIS_SCENARIO=%s\n' "$praxis_scenario"
|
|
if [ -n "${GITEA_TOKEN:-}" ]; then
|
|
printf 'lxc.environment: GITEA_TOKEN=%s\n' "$GITEA_TOKEN"
|
|
fi
|
|
printf 'lxc.environment: DEEPGRAM_API_KEY=%s\n' "$deepgram_key"
|
|
printf 'lxc.environment: CARTESIA_API_KEY=%s\n' "$cartesia_key"
|
|
printf 'lxc.environment: OLLAMA_API_KEY=%s\n' "$ollama_key"
|
|
printf 'lxc.environment: OLLAMA_BASE_URL=%s\n' "$ollama_base"
|
|
printf 'lxc.environment: OLLAMA_CHAT_URL=%s\n' "$ollama_chat"
|
|
printf 'lxc.environment: OLLAMA_ROLEPLAY_MODEL=%s\n' "$ollama_roleplay"
|
|
printf 'lxc.environment: OLLAMA_DEBRIEF_MODEL=%s\n' "$ollama_debrief"
|
|
printf 'lxc.environment: DEEPGRAM_MODEL=%s\n' "$deepgram_model"
|
|
printf 'lxc.environment: DEEPGRAM_LANGUAGE=%s\n' "$deepgram_lang"
|
|
printf 'lxc.environment: DEEPGRAM_REGION=%s\n' "$deepgram_region"
|
|
printf 'lxc.environment: CARTESIA_VOICE_ID=%s\n' "$cartesia_voice"
|
|
}
|
|
# shellcheck disable=SC2029
|
|
# SC2029: conf='${conf_file}' intentionally expands on the client side —
|
|
# the script builds the remote /etc/pve/lxc/<vmid>.conf path from the
|
|
# local variable and ships the literal path to the remote host.
|
|
append_lines | ssh "$ssh_opts" "root@${ssh_host}" "
|
|
conf='${conf_file}'
|
|
# Remove prior hookscript/onboot/lxc.environment lines.
|
|
sed -i '/^hookscript:/d;/^onboot:/d;/^lxc\.environment: PRAXIS/d;/^lxc\.environment: GITEA_TOKEN/d;/^lxc\.environment: DEEPGRAM/d;/^lxc\.environment: CARTESIA/d;/^lxc\.environment: OLLAMA/d' \"\$conf\" 2>/dev/null || true
|
|
cat >> \"\$conf\"
|
|
echo 'lxc-config: SSH config updated' >&2
|
|
"
|
|
|
|
echo "lxc-config: VMID ${vmid} configured" >&2 |