-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathinstall.sh
More file actions
executable file
·160 lines (140 loc) · 6.43 KB
/
Copy pathinstall.sh
File metadata and controls
executable file
·160 lines (140 loc) · 6.43 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
#!/bin/sh
# LocalGuard installer — downloads the prebuilt CLI binary from GitHub Releases
# and installs it as `localguard` (with `llm-security-proxy` kept as an alias).
#
# Usage:
# curl -fsSL https://raw.githubusercontent.com/Lexus2016/LocalGuard/main/install.sh | sh
#
# Optional environment overrides:
# LOCALGUARD_VERSION=v0.6.2 # pin a specific release tag (default: latest)
# LOCALGUARD_BIN_DIR=/path # install dir (default: /usr/local/bin if writable, else ~/.local/bin)
set -eu
REPO="Lexus2016/LocalGuard"
BIN="llm-security-proxy"
ALIAS="localguard"
# ── pretty output ────────────────────────────────────────────────
info() { printf '\033[0;34m==>\033[0m %s\n' "$*"; }
ok() { printf '\033[0;32m✓\033[0m %s\n' "$*"; }
warn() { printf '\033[0;33mwarning:\033[0m %s\n' "$*" >&2; }
die() { printf '\033[0;31merror:\033[0m %s\n' "$*" >&2; exit 1; }
# ── prerequisites ────────────────────────────────────────────────
need() { command -v "$1" >/dev/null 2>&1 || die "required tool not found: $1"; }
need uname
need tar
if command -v curl >/dev/null 2>&1; then
DL="curl -fsSL"
DL_OUT="curl -fsSL -o"
elif command -v wget >/dev/null 2>&1; then
DL="wget -qO-"
DL_OUT="wget -qO"
else
die "need either curl or wget"
fi
# ── detect OS + arch → release target triple ─────────────────────
os="$(uname -s)"
arch="$(uname -m)"
case "$arch" in
x86_64|amd64) arch="x86_64" ;;
aarch64|arm64) arch="aarch64" ;;
*) die "unsupported architecture: $arch" ;;
esac
case "$os" in
Linux)
target="${arch}-unknown-linux-gnu"
;;
Darwin)
# Apple Silicon under Rosetta reports x86_64 via uname; trust the hardware.
if [ "$arch" = "x86_64" ] && [ "$(sysctl -n hw.optional.arm64 2>/dev/null)" = "1" ]; then
arch="aarch64"
fi
if [ "$arch" != "aarch64" ]; then
die "no prebuilt CLI for macOS Intel. Install via Homebrew instead:
brew tap lexus2016/tap https://github.com/Lexus2016/homebrew-tap
brew install localguard
or build from source: https://github.com/$REPO"
fi
target="aarch64-apple-darwin"
;;
*) die "unsupported OS: $os (supported: Linux, macOS arm64)" ;;
esac
# ── resolve version (release tag) ────────────────────────────────
TAG="${LOCALGUARD_VERSION:-}"
if [ -z "$TAG" ]; then
info "Resolving latest release..."
TAG="$($DL "https://api.github.com/repos/$REPO/releases/latest" \
| grep '"tag_name"' \
| head -1 \
| cut -d'"' -f4)"
[ -n "$TAG" ] || die "could not determine latest release tag (check network, or set LOCALGUARD_VERSION=vX.Y.Z)"
fi
asset="${BIN}-${TAG}-${target}.tar.gz"
url="https://github.com/$REPO/releases/download/${TAG}/${asset}"
# ── pick install dir ─────────────────────────────────────────────
if [ -n "${LOCALGUARD_BIN_DIR:-}" ]; then
BIN_DIR="$LOCALGUARD_BIN_DIR"
elif [ -w /usr/local/bin ]; then
BIN_DIR="/usr/local/bin"
elif [ -n "${HOME:-}" ]; then
BIN_DIR="$HOME/.local/bin"
else
die "cannot determine an install dir (set LOCALGUARD_BIN_DIR)"
fi
mkdir -p "$BIN_DIR" || die "cannot create install dir: $BIN_DIR"
PREFIX="$(dirname "$BIN_DIR")"
info "Installing LocalGuard $TAG ($target) → $BIN_DIR"
# ── download + extract into a temp dir ───────────────────────────
tmp="$(mktemp -d 2>/dev/null || mktemp -d -t localguard)"
trap 'rm -rf "$tmp"' EXIT INT TERM
info "Downloading ${asset}"
$DL_OUT "$tmp/$asset" "$url" || die "download failed: $url"
info "Extracting..."
tar -xzf "$tmp/$asset" -C "$tmp" || die "extraction failed (corrupt archive?)"
# locate the binary inside the archive (root or a subdir)
src="$(find "$tmp" -type f -name "$BIN" 2>/dev/null | head -1)"
[ -n "$src" ] || die "binary '$BIN' not found inside archive"
# ── install binary + alias symlink ───────────────────────────────
chmod +x "$src"
mv -f "$src" "$BIN_DIR/$BIN" || die "cannot install to $BIN_DIR (is it writable?)"
ok "Installed $BIN_DIR/$BIN"
# The `localguard` alias is a convenience — don't fail the install if it can't be made.
if ln -sf "$BIN" "$BIN_DIR/$ALIAS" 2>/dev/null; then
ok "Created command '$ALIAS' → $BIN"
else
warn "Could not create the '$ALIAS' alias; use '$BIN' instead."
fi
# ── optional NER models (advanced detection) ─────────────────────
# Never fatal: the proxy works in regex-only mode without these.
models_src="$(find "$tmp" -type d -name models 2>/dev/null | head -1)"
models_dst="$PREFIX/share/localguard/models"
if [ -n "$models_src" ] && mkdir -p "$models_dst" 2>/dev/null && cp -R "$models_src/." "$models_dst/" 2>/dev/null; then
ok "Installed NER models → $models_dst"
# Mirror the Homebrew formula: expose models at ~/.llm-proxy/models so the
# daemon finds them when advanced (NER) detection is enabled in the config.
# Skip as root (e.g. via sudo) to avoid root-owned files in a user's home
# that the daemon later can't write.
if [ "$(id -u)" != 0 ] && [ -n "${HOME:-}" ]; then
user_models="$HOME/.llm-proxy/models"
if [ ! -e "$user_models" ] && [ ! -L "$user_models" ]; then
mkdir -p "$HOME/.llm-proxy" 2>/dev/null \
&& ln -s "$models_dst" "$user_models" 2>/dev/null \
&& ok "Linked $user_models → $models_dst" || true
fi
fi
else
info "NER models not installed — running in regex-only mode (enable 'advanced' in config for NER)."
fi
# ── PATH hint ────────────────────────────────────────────────────
case ":${PATH:-}:" in
*":$BIN_DIR:"*) : ;;
*) warn "$BIN_DIR is not in your PATH. Add it, e.g.:
echo 'export PATH=\"$BIN_DIR:\$PATH\"' >> ~/.profile && . ~/.profile" ;;
esac
printf '\n'
ok "Done. LocalGuard $TAG is installed."
cat <<EOF
Next steps:
localguard start # start the proxy daemon
localguard status # check it is running
localguard launch opencode # run opencode routed through the proxy
(the legacy name '$BIN' also still works)
EOF