Initial commit
Build & Deploy / build (push) Failing after 1m23s

This commit is contained in:
2026-07-14 19:09:58 +02:00
commit 96fde6a099
43 changed files with 6913 additions and 0 deletions
+291
View File
@@ -0,0 +1,291 @@
#!/usr/bin/env bash
set -euo pipefail
# ── Defaults ──────────────────────────────────────────────────────────────────
DEFAULT_INSTALL_DIR="/opt/reversellama-client"
DEFAULT_SERVICE_NAME="reversellama-client"
DEFAULT_UPSTREAM="http://localhost:11434"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
INSTALL_DIR="$DEFAULT_INSTALL_DIR"
SERVICE_NAME="$DEFAULT_SERVICE_NAME"
SERVER_URL=""
TOKEN=""
CLIENT_ID="$(hostname -s 2>/dev/null || echo "linux-client")"
UPSTREAM="$DEFAULT_UPSTREAM"
SKIP_OLLAMA=false
# ── Colors ────────────────────────────────────────────────────────────────────
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
NC='\033[0m'
info() { echo -e "${GREEN}[INFO]${NC} $*"; }
warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
err() { echo -e "${RED}[ERROR]${NC} $*" >&2; }
die() { err "$@"; exit 1; }
# ── Usage ─────────────────────────────────────────────────────────────────────
usage() {
cat <<EOF
Usage: $0 [OPTIONS]
Installs the ReverseLlama client as a systemd service on Linux.
Required:
--server <url> ReverseLlama server URL (e.g. http://my-server:5050)
--token <value> Shared secret token for the server
Optional:
--client-id <name> Client identifier; defaults to hostname
--upstream <url> Local Ollama URL; defaults to $DEFAULT_UPSTREAM
--install-dir <dir> Install directory; defaults to $DEFAULT_INSTALL_DIR
--service-name <n> systemd service name; defaults to $DEFAULT_SERVICE_NAME
--no-ollama Skip Ollama installation and status check
-h, --help Show this help message
Examples:
$0 --server http://gpu-server:5050 --token "my-secret"
$0 --server http://gpu-server:5050 --token "my-secret" --no-ollama
EOF
exit 0
}
# ── Argument parsing ──────────────────────────────────────────────────────────
while [[ $# -gt 0 ]]; do
case "$1" in
--server) SERVER_URL="$2"; shift 2 ;;
--token) TOKEN="$2"; shift 2 ;;
--client-id) CLIENT_ID="$2"; shift 2 ;;
--upstream) UPSTREAM="$2"; shift 2 ;;
--install-dir) INSTALL_DIR="$2"; shift 2 ;;
--service-name) SERVICE_NAME="$2"; shift 2 ;;
--no-ollama) SKIP_OLLAMA=true; shift ;;
-h|--help) usage ;;
*) die "Unknown option: $1" ;;
esac
done
# ── Prompt for missing required values ───────────────────────────────────────
if [[ -z "$SERVER_URL" ]]; then
read -rp "ReverseLlama server URL (e.g. http://my-server:5050): " SERVER_URL
fi
if [[ -z "$SERVER_URL" ]]; then
die "Server URL is required."
fi
if [[ -z "$TOKEN" ]]; then
read -rsp "Server token: " TOKEN
echo
fi
if [[ -z "$TOKEN" ]]; then
die "Token is required."
fi
# ── Root check ────────────────────────────────────────────────────────────────
if [[ $EUID -ne 0 ]]; then
die "This script must be run as root (or with sudo)."
fi
# ── Check / install .NET 10 SDK ──────────────────────────────────────────────
install_dotnet() {
info "Installing .NET 10 SDK..."
if command -v apt-get &>/dev/null; then
apt-get update -qq
apt-get install -y -qq wget apt-transport-https
# Detect distro codename for the Microsoft package repo
if grep -qi "ubuntu" /etc/os-release 2>/dev/null; then
DISTRO="ubuntu"
CODENAME="$(. /etc/os-release && echo "$VERSION_CODENAME")"
case "$CODENAME" in
noble|jammy|focal) ;; # supported
*)
warn "Ubuntu $CODENAME may not have .NET 10 packages yet; using latest available."
CODENAME="noble"
;;
esac
elif grep -qi "debian" /etc/os-release 2>/dev/null; then
DISTRO="debian"
CODENAME="$(. /etc/os-release && echo "$VERSION_CODENAME")"
case "$CODENAME" in
trixie|bookworm|bullseye) ;;
*)
warn "Debian $CODENAME may not have .NET 10 packages; using latest available."
CODENAME="trixie"
;;
esac
else
die "Unsupported distro. Install .NET 10 SDK manually: https://dotnet.microsoft.com/download"
fi
# Add Microsoft package repository GPG key and repo
curl -fsSL "https://packages.microsoft.com/config/$DISTRO/$CODENAME/packages-microsoft-prod.deb" \
-o /tmp/packages-microsoft-prod.deb
dpkg -i /tmp/packages-microsoft-prod.deb
rm -f /tmp/packages-microsoft-prod.deb
apt-get update -qq
apt-get install -y -qq dotnet-sdk-10.0
elif command -v dnf &>/dev/null || command -v yum &>/dev/null; then
PKG_MGR="dnf"
command -v dnf &>/dev/null || PKG_MGR="yum"
# Add Microsoft package repository for RHEL/CentOS/Fedora
cat > /etc/yum.repos.d/microsoft-prod.repo <<'REPO'
[microsoft-prod]
name=Microsoft Production Repository
baseurl=https://packages.microsoft.com/rhel/9/prod/
enabled=1
gpgcheck=1
gpgkey=https://packages.microsoft.com/keys/microsoft.asc
REPO
$PKG_MGR install -y dotnet-sdk-10.0
elif command -v pacman &>/dev/null; then
warn "Arch Linux detected. .NET 10 may need to be installed from the AUR or manually."
warn "See: https://dotnet.microsoft.com/download"
die "Cannot auto-install .NET SDK on Arch. Please install dotnet-sdk-10 manually."
else
die "Unsupported package manager. Install .NET 10 SDK manually: https://dotnet.microsoft.com/download"
fi
DOTNET_CMD="$(command -v dotnet 2>/dev/null || echo /usr/share/dotnet/dotnet)"
if [[ ! -x "$DOTNET_CMD" ]]; then
DOTNET_CMD="/usr/bin/dotnet"
fi
if [[ ! -x "$DOTNET_CMD" ]]; then
die ".NET SDK installation succeeded but dotnet binary not found. Please add it to PATH."
fi
DOTNET_VER="$("$DOTNET_CMD" --version 2>/dev/null || true)"
info ".NET SDK installed: $DOTNET_CMD ($DOTNET_VER)"
}
DOTNET_CMD=""
if command -v dotnet &>/dev/null; then
DOTNET_CMD="$(command -v dotnet)"
DOTNET_VER="$("$DOTNET_CMD" --version 2>/dev/null || true)"
if [[ "$DOTNET_VER" == 10.* ]]; then
info "dotnet 10 is already installed: $DOTNET_CMD ($DOTNET_VER)"
else
warn "dotnet is installed ($DOTNET_VER) but version 10.x is required."
install_dotnet
fi
else
install_dotnet
fi
# ── Check / install Ollama ───────────────────────────────────────────────────
if [[ "$SKIP_OLLAMA" == "false" ]]; then
if command -v ollama &>/dev/null; then
info "Ollama is installed: $(command -v ollama)"
if systemctl is-active --quiet ollama 2>/dev/null; then
info "Ollama service is running."
else
warn "Ollama is installed but not running. Starting..."
systemctl start ollama
systemctl enable ollama 2>/dev/null || true
info "Ollama started."
fi
else
info "Ollama is not installed. Installing..."
curl -fsSL https://ollama.com/install.sh | sh
info "Ollama installed."
systemctl start ollama
systemctl enable ollama 2>/dev/null || true
info "Ollama started."
fi
else
info "Skipping Ollama check (--no-ollama)."
fi
# ── Build client from source ─────────────────────────────────────────────────
CLIENT_SRC="$REPO_ROOT/src/ReverseLlama.Client"
if [[ ! -d "$CLIENT_SRC" ]]; then
die "Client source not found at $CLIENT_SRC. Run this script from the repository or pass --install-dir."
fi
info "Building ReverseLlama client (self-contained, linux-x64)..."
BUILD_DIR="$(mktemp -d /tmp/reversellama-build.XXXXXX)"
trap 'rm -rf "$BUILD_DIR"' EXIT
"$DOTNET_CMD" publish "$CLIENT_SRC/ReverseLlama.Client.csproj" \
-c Release \
-r linux-x64 \
--self-contained true \
-o "$BUILD_DIR"
if [[ ! -f "$BUILD_DIR/ReverseLlama.Client" ]]; then
die "Build failed. ReverseLlama.Client binary not found in output."
fi
info "Build successful."
# ── Install ───────────────────────────────────────────────────────────────────
info "Installing to $INSTALL_DIR..."
mkdir -p "$INSTALL_DIR"
cp -a "$BUILD_DIR"/. "$INSTALL_DIR/"
chmod +x "$INSTALL_DIR/ReverseLlama.Client"
info "Client installed to $INSTALL_DIR."
# ── Create systemd service ───────────────────────────────────────────────────
SERVICE_FILE="/etc/systemd/system/${SERVICE_NAME}.service"
if systemctl list-unit-files "$SERVICE_NAME.service" &>/dev/null 2>&1; then
info "Stopping existing service $SERVICE_NAME..."
systemctl stop "$SERVICE_NAME" 2>/dev/null || true
fi
cat > "$SERVICE_FILE" <<EOF
[Unit]
Description=ReverseLlama Tunnel Client
After=network-online.target
Wants=network-online.target
$([ "$SKIP_OLLAMA" = "false" ] && echo "After=ollama.service")
$([ "$SKIP_OLLAMA" = "false" ] && echo "Wants=ollama.service")
[Service]
Type=simple
ExecStart=$INSTALL_DIR/ReverseLlama.Client --server "$SERVER_URL" --upstream "$UPSTREAM" --token "$TOKEN" --client-id "$CLIENT_ID"
Restart=always
RestartSec=5
Environment=DOTNET_CLI_TELEMETRY_OPTOUT=1
Environment=DOTNET_NOLOGO=1
WorkingDirectory=$INSTALL_DIR
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable "$SERVICE_NAME"
systemctl start "$SERVICE_NAME"
sleep 1
if systemctl is-active --quiet "$SERVICE_NAME"; then
info "Service $SERVICE_NAME is running."
else
warn "Service $SERVICE_NAME was started but may not be healthy. Check: systemctl status $SERVICE_NAME"
fi
# ── Done ──────────────────────────────────────────────────────────────────────
echo
info "Installation complete."
echo " Server: $SERVER_URL"
echo " Client ID: $CLIENT_ID"
echo " Upstream: $UPSTREAM"
echo " Service: $SERVICE_NAME"
echo " Install dir: $INSTALL_DIR"
echo
echo " Manage: systemctl {start|stop|restart|status} $SERVICE_NAME"
echo " Logs: journalctl -u $SERVICE_NAME -f"
echo " Uninstall: systemctl stop $SERVICE_NAME && systemctl disable $SERVICE_NAME && rm $SERVICE_FILE $INSTALL_DIR -rf && systemctl daemon-reload"