Files
gpu-rent/src/gpu_rent/remote/bootstrap.sh
T
Leonid Pershin 7ed6a99df2 Enhance LLM and SwarmUI integration with improved configuration options
- Updated `env.example` and `gpu-rent.vars.example` to include new variables for LLM runtime and SwarmUI options.
- Refactored CLI commands to support interactive selection of LLM runtime and workload type (SwarmUI, LLM, or both).
- Improved access link generation to handle cases where SwarmUI is disabled, providing clearer user feedback.
- Enhanced provisioning logic to conditionally bootstrap SwarmUI based on user configuration, allowing for LLM-only setups.
- Updated documentation across multiple files to reflect changes in LLM integration, CLI usage, and configuration management.
2026-08-21 06:44:50 +03:00

202 lines
6.8 KiB
Bash

#!/usr/bin/env bash
# Idempotent gpu-rent first-boot on the VM. No Docker. Do not apt-upgrade the kernel.
set -euo pipefail
SWARM_USER="${SWARM_USER:-ubuntu}"
SWARM_ROOT="/opt/swarmui"
DATA_ROOT="/mnt/swarm_data"
MARKER_DATA="${DATA_ROOT}/.gpu-rent-ready"
MARKER_BOOT="${SWARM_ROOT}/.gpu-rent-bootstrapped"
SWARM_REPO="https://github.com/mcmonkeyprojects/SwarmUI.git"
log() { echo "[gpu-rent] $*"; }
if [[ "$(id -u)" -ne 0 ]]; then
echo "нужен root (sudo -n bash $0)" >&2
exit 1
fi
export DEBIAN_FRONTEND=noninteractive
pick_data_disk() {
local root_src root_pk name type
root_src="$(findmnt -n -o SOURCE / || true)"
root_pk="$(lsblk -no PKNAME "$root_src" 2>/dev/null | head -n1 || true)"
if [[ -z "$root_pk" && -n "$root_src" ]]; then
root_pk="$(lsblk -no NAME "$root_src" 2>/dev/null | head -n1 | sed 's/[0-9]*$//' || true)"
fi
while read -r name type; do
[[ "$type" == "disk" ]] || continue
[[ -n "$root_pk" && "$name" == "$root_pk" ]] && continue
if findmnt "/dev/${name}" >/dev/null 2>&1; then
continue
fi
echo "/dev/${name}"
return 0
done < <(lsblk -dn -o NAME,TYPE)
return 1
}
ensure_data_mount() {
mkdir -p "$DATA_ROOT"
if findmnt "$DATA_ROOT" >/dev/null 2>&1; then
log "data volume уже на ${DATA_ROOT}"
return 0
fi
local disk fstype uuid
disk="$(pick_data_disk)" || {
log "нет второго диска — проверь BDM data volume"
exit 1
}
fstype="$(blkid -s TYPE -o value "$disk" 2>/dev/null || true)"
if [[ -z "$fstype" ]]; then
if [[ -e "$MARKER_DATA" ]]; then
log "маркер есть, а FS на ${disk} нет — не mkfs, разбери вручную"
exit 1
fi
log "mkfs.ext4 ${disk} (пустой data volume)"
mkfs.ext4 -F -L swarm-data "$disk"
fi
mount "$disk" "$DATA_ROOT"
uuid="$(blkid -s UUID -o value "$disk")"
if [[ -n "$uuid" ]] && ! grep -q "UUID=${uuid}" /etc/fstab; then
echo "UUID=${uuid} ${DATA_ROOT} ext4 defaults,nofail 0 2" >> /etc/fstab
fi
log "смонтирован ${disk} -> ${DATA_ROOT}"
}
ensure_bind() {
local src="$1" dst="$2"
mkdir -p "$src" "$dst"
if ! findmnt "$dst" >/dev/null 2>&1; then
mount --bind "$src" "$dst"
fi
if ! grep -Fq " ${dst} " /etc/fstab; then
echo "${src} ${dst} none bind,nofail 0 0" >> /etc/fstab
fi
}
log "пакеты (без upgrade ядра)"
if [[ "${GPU_RENT_BOOTSTRAP_LIGHT:-0}" == "1" && -f "$MARKER_BOOT" ]]; then
log "light bootstrap — пропускаем apt-get"
else
apt-get update -qq
apt-get install -y -qq git python3 python3-venv python3-pip python3-full curl ca-certificates
fi
ensure_data_mount
mkdir -p \
"${DATA_ROOT}/Models" \
"${DATA_ROOT}/Output" \
"${DATA_ROOT}/Data" \
"${DATA_ROOT}/Data/Autocompletions" \
"${DATA_ROOT}/Data/Wildcards" \
"${DATA_ROOT}/dlbackend" \
"${DATA_ROOT}/Extensions" \
"${DATA_ROOT}/DLNodes" \
"${DATA_ROOT}/CustomWorkflows" \
"${DATA_ROOT}/ollama" \
"${DATA_ROOT}/llamacpp/models"
# LLM-only: data disk + tools, no SwarmUI clone / unit.
if [[ "${GPU_RENT_SKIP_SWARMUI:-0}" == "1" ]]; then
chown -R "${SWARM_USER}:${SWARM_USER}" "$DATA_ROOT"
date -u +"%Y-%m-%dT%H:%M:%SZ" >"$MARKER_DATA"
date -u +"%Y-%m-%dT%H:%M:%SZ" >"${DATA_ROOT}/.gpu-rent-llm-only"
chown "${SWARM_USER}:${SWARM_USER}" "$MARKER_DATA" "${DATA_ROOT}/.gpu-rent-llm-only"
systemctl stop swarmui 2>/dev/null || true
systemctl disable swarmui 2>/dev/null || true
if command -v nvidia-smi >/dev/null 2>&1; then
nvidia-smi -L || true
fi
log "bootstrap ok (llm-only; без SwarmUI)"
exit 0
fi
rm -f "${DATA_ROOT}/.gpu-rent-llm-only" 2>/dev/null || true
if [[ ! -d "${SWARM_ROOT}/.git" ]]; then
log "clone SwarmUI -> ${SWARM_ROOT}"
mkdir -p "$(dirname "$SWARM_ROOT")"
git clone --depth 1 "$SWARM_REPO" "$SWARM_ROOT"
elif [[ "${GPU_RENT_UPDATE_GIT:-1}" == "1" ]]; then
log "обновляю SwarmUI в ${SWARM_ROOT}"
branch="$(git -C "$SWARM_ROOT" remote show origin 2>/dev/null | sed -n '/HEAD branch/s/.*: //p' || true)"
branch="${branch:-master}"
# shallow clone: deepen tip of default branch
git -C "$SWARM_ROOT" fetch --depth 1 origin "$branch" || git -C "$SWARM_ROOT" fetch --depth 1 origin
if git -C "$SWARM_ROOT" rev-parse --verify -q "origin/${branch}" >/dev/null; then
git -C "$SWARM_ROOT" checkout -B "$branch" "origin/${branch}"
git -C "$SWARM_ROOT" reset --hard "origin/${branch}"
else
git -C "$SWARM_ROOT" pull --ff-only || true
fi
log "SwarmUI @ $(git -C "$SWARM_ROOT" rev-parse --short HEAD)"
else
log "SwarmUI уже в ${SWARM_ROOT} (update off)"
fi
if [[ ! -x /usr/share/dotnet/dotnet && ! -x "/home/${SWARM_USER}/.dotnet/dotnet" ]]; then
if [[ -x "${SWARM_ROOT}/launchtools/linux-dotnet-install.sh" ]]; then
log "ставим .NET SDK (скрипт SwarmUI)"
sudo -u "$SWARM_USER" bash "${SWARM_ROOT}/launchtools/linux-dotnet-install.sh" || true
fi
fi
mkdir -p \
"${SWARM_ROOT}/Models" \
"${SWARM_ROOT}/Output" \
"${SWARM_ROOT}/Data" \
"${SWARM_ROOT}/dlbackend" \
"${SWARM_ROOT}/src/Extensions" \
"${SWARM_ROOT}/src/BuiltinExtensions/ComfyUIBackend/DLNodes" \
"${SWARM_ROOT}/src/BuiltinExtensions/ComfyUIBackend/CustomWorkflows"
ensure_bind "${DATA_ROOT}/Models" "${SWARM_ROOT}/Models"
ensure_bind "${DATA_ROOT}/Output" "${SWARM_ROOT}/Output"
ensure_bind "${DATA_ROOT}/Data" "${SWARM_ROOT}/Data"
ensure_bind "${DATA_ROOT}/dlbackend" "${SWARM_ROOT}/dlbackend"
ensure_bind "${DATA_ROOT}/Extensions" "${SWARM_ROOT}/src/Extensions"
ensure_bind "${DATA_ROOT}/DLNodes" "${SWARM_ROOT}/src/BuiltinExtensions/ComfyUIBackend/DLNodes"
ensure_bind "${DATA_ROOT}/CustomWorkflows" "${SWARM_ROOT}/src/BuiltinExtensions/ComfyUIBackend/CustomWorkflows"
chown -R "${SWARM_USER}:${SWARM_USER}" "$DATA_ROOT" "$SWARM_ROOT"
cat >/etc/systemd/system/swarmui.service <<EOF
[Unit]
Description=SwarmUI (gpu-rent)
After=network-online.target local-fs.target
Wants=network-online.target
[Service]
Type=simple
User=${SWARM_USER}
Group=${SWARM_USER}
WorkingDirectory=${SWARM_ROOT}
Environment=HOME=/home/${SWARM_USER}
Environment=DOTNET_ROOT=/home/${SWARM_USER}/.dotnet
Environment=DOTNET_CLI_HOME=/home/${SWARM_USER}
Environment=PATH=/home/${SWARM_USER}/.dotnet:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
ExecStart=${SWARM_ROOT}/launch-linux.sh --launch_mode none --host 127.0.0.1 --port 7801
Restart=on-failure
RestartSec=8
TimeoutStartSec=0
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable swarmui
# Не стартуем UI здесь: сначала extensions / autocomplete / Civitai / push.
date -u +"%Y-%m-%dT%H:%M:%SZ" >"$MARKER_DATA"
date -u +"%Y-%m-%dT%H:%M:%SZ" >"$MARKER_BOOT"
chown "${SWARM_USER}:${SWARM_USER}" "$MARKER_DATA" "$MARKER_BOOT"
if command -v nvidia-smi >/dev/null 2>&1; then
nvidia-smi -L || true
fi
log "bootstrap ok (unit готов; swarmui старт после seed)"