Files
tomasz-syn-grzegorza 359afb3a59 Initial import: bare-metal stacks, Server UI, GPU fan, tutorials.
Infrastructure configs for GMKtec K11 (Docker, vLLM, LocalAI, ComfyUI,
control-plane, gpu-fan agent, Server UI with CLI/file explorer/GPU fan curve).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-05 12:02:04 +00:00

108 lines
3.1 KiB
Bash
Executable File

#!/usr/bin/env bash
# Install Server UI as Docker container (profile server-ui).
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
STACK_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)"
CONTROL_PLANE_STACK="$(cd "${STACK_DIR}/../control-plane" && pwd)"
SERVICE_NAME="server-ui.service"
UI_PORT="${SERVER_UI_PORT:-8091}"
ENV_FILE="${CONTROL_PLANE_STACK}/.env"
if [[ "${EUID}" -ne 0 ]]; then
echo "Run as root: sudo ${SCRIPT_DIR}/install-docker.sh"
exit 1
fi
set_env_var() {
local file="$1" key="$2" val="$3"
if grep -q "^${key}=" "${file}"; then
sed -i "s|^${key}=.*|${key}=${val}|" "${file}"
else
echo "${key}=${val}" >> "${file}"
fi
}
detect_repo_root() {
if [[ -n "${REPO_ROOT:-}" ]]; then
echo "${REPO_ROOT}"
return
fi
local candidate
candidate="$(cd "${STACK_DIR}/../.." && pwd)"
if [[ -d "${candidate}/stacks/localai" ]]; then
echo "${candidate}"
return
fi
echo "${candidate}"
}
echo "=== Server UI — install (Docker) ==="
if ! command -v docker >/dev/null 2>&1; then
echo "ERROR: docker not found. Install Docker CE first."
exit 1
fi
bash "${SCRIPT_DIR}/setup-control-plane-env.sh"
REPO_ROOT_VAL="$(detect_repo_root)"
DOCKER_GID="$(getent group docker | cut -d: -f3 || echo 999)"
if [[ ! -f "${ENV_FILE}" ]]; then
cp "${CONTROL_PLANE_STACK}/.env.example" "${ENV_FILE}"
fi
set_env_var "${ENV_FILE}" "REPO_ROOT" "${REPO_ROOT_VAL}"
set_env_var "${ENV_FILE}" "SERVER_UI_HOST" "0.0.0.0"
set_env_var "${ENV_FILE}" "SERVER_UI_PORT" "${UI_PORT}"
set_env_var "${ENV_FILE}" "GPU_FAN_AGENT_URL" "http://host.docker.internal:18090"
set_env_var "${ENV_FILE}" "DOCKER_GID" "${DOCKER_GID}"
# Disable native systemd if present
if systemctl is-enabled "${SERVICE_NAME}" &>/dev/null; then
echo "Disabling native ${SERVICE_NAME}..."
systemctl disable --now "${SERVICE_NAME}" 2>/dev/null || true
fi
cd "${STACK_DIR}"
export REPO_ROOT="${REPO_ROOT_VAL}"
export DOCKER_GID
echo "Building server-ui image..."
docker compose --profile server-ui build
echo "Starting server-ui container..."
docker compose --profile server-ui up -d
sleep 2
LAN_IP="$(hostname -I 2>/dev/null | awk '{print $1}')"
API_KEY_VAL="$(grep '^API_KEY=' "${ENV_FILE}" | cut -d= -f2- || true)"
echo ""
echo "Runtime: Docker (profile server-ui)"
echo "Repo mount: ${REPO_ROOT_VAL} → /repo"
echo "Env: ${ENV_FILE}"
echo "Container: $(docker compose --profile server-ui ps --format '{{.Name}} {{.Status}}' 2>/dev/null || docker ps --filter name=server-ui --format '{{.Names}} {{.Status}}')"
echo ""
echo "Web UI (LAN):"
echo " http://${LAN_IP:-<server-ip>}:${UI_PORT}/"
echo ""
echo "API key:"
echo " grep ^API_KEY= ${ENV_FILE}"
echo ""
if [[ -n "${API_KEY_VAL}" ]]; then
HEALTH="$(curl -sf "http://127.0.0.1:${UI_PORT}/api/health" 2>/dev/null || echo '{"ok":false}')"
echo "Health: ${HEALTH}"
GF_HEALTH="$(curl -sf "http://127.0.0.1:${UI_PORT}/api/gpu-fan/health" -H "X-API-Key: ${API_KEY_VAL}" 2>/dev/null || echo '{"ok":false}')"
echo "GPU Fan proxy: ${GF_HEALTH}"
fi
echo ""
echo "Logs:"
echo " docker compose --profile server-ui logs -f"
echo "Stop:"
echo " docker compose --profile server-ui down"