-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathinstall.sh
More file actions
executable file
·189 lines (158 loc) · 5.18 KB
/
Copy pathinstall.sh
File metadata and controls
executable file
·189 lines (158 loc) · 5.18 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
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
#!/usr/bin/env bash
set -euo pipefail
COMPOSE_URL="https://raw.githubusercontent.com/MiniMax-AI-Dev/parsar/main/docker-compose.yml"
usage() {
cat <<'USAGE'
Install or upgrade Parsar with Docker Compose.
Usage:
./install.sh [options]
curl -fsSL https://raw.githubusercontent.com/MiniMax-AI-Dev/parsar/main/install.sh | bash
Options:
--home PATH Install directory. Default: ~/.parsar
--port PORT Web UI port. Default: 18080
--bind ADDRESS Web UI bind address. Default: 127.0.0.1
--image IMAGE Override the server image.
--sandbox-image IMAGE
Override the sandbox image.
--compose-file PATH Use an existing Compose file.
--dry-run Prepare and validate without starting containers.
--help Show this help.
Advanced Compose settings can be added directly to ~/.parsar/.env.
USAGE
}
log() {
printf '[parsar-install] %s\n' "$*"
}
die() {
printf '[parsar-install] ERROR: %s\n' "$*" >&2
exit 1
}
expand_path() {
case "$1" in
"~") printf '%s\n' "$HOME" ;;
"~/"*) printf '%s/%s\n' "$HOME" "${1#~/}" ;;
/*) printf '%s\n' "$1" ;;
*) die "path must be absolute or start with ~/: $1" ;;
esac
}
random_hex() {
if command -v openssl >/dev/null 2>&1; then
openssl rand -hex "$1"
else
od -An -N"$1" -tx1 /dev/urandom | tr -d ' \n'
fi
}
ensure_env() {
local key="$1" value="$2"
grep -q "^${key}=" "$env_file" 2>/dev/null || printf '%s=%s\n' "$key" "$value" >>"$env_file"
}
set_env() {
local key="$1" value="$2" temp_file="${env_file}.tmp.$$"
grep -v "^${key}=" "$env_file" 2>/dev/null >"$temp_file" || true
printf '%s=%s\n' "$key" "$value" >>"$temp_file"
mv "$temp_file" "$env_file"
}
detect_docker() {
if docker compose version >/dev/null 2>&1 </dev/null && docker info >/dev/null 2>&1 </dev/null; then
DOCKER=(docker)
elif command -v sudo >/dev/null 2>&1 &&
sudo -n docker compose version >/dev/null 2>&1 </dev/null &&
sudo -n docker info >/dev/null 2>&1 </dev/null; then
DOCKER=(sudo -n docker)
else
die "Docker Compose v2 is required and the current user cannot reach Docker"
fi
}
docker_run() {
"${DOCKER[@]}" "$@" </dev/null
}
compose() {
docker_run compose -f "$compose_file" --env-file "$env_file" "$@"
}
download_compose() {
if command -v curl >/dev/null 2>&1; then
curl -fsSL "$COMPOSE_URL" -o "$compose_file"
elif command -v wget >/dev/null 2>&1; then
wget -qO "$compose_file" "$COMPOSE_URL"
else
die "curl or wget is required"
fi
}
wait_for_health() {
for _ in $(seq 1 60); do
if compose exec -T parsar-server wget -qO- http://127.0.0.1:8080/healthz >/dev/null 2>&1; then
return 0
fi
sleep 1
done
return 1
}
home="${PARSAR_HOME:-$HOME/.parsar}"
port="${PARSAR_LOCAL_PORT:-18080}"
bind="${PARSAR_BIND_ADDR:-127.0.0.1}"
server_image="${PARSAR_SERVER_IMAGE:-}"
sandbox_image="${PARSAR_SANDBOX_IMAGE:-}"
compose_source="${PARSAR_COMPOSE_FILE:-}"
dry_run=false
while [ "$#" -gt 0 ]; do
case "$1" in
--home) home="${2:?missing value for --home}"; shift 2 ;;
--port) port="${2:?missing value for --port}"; shift 2 ;;
--bind) bind="${2:?missing value for --bind}"; shift 2 ;;
--image) server_image="${2:?missing value for --image}"; shift 2 ;;
--sandbox-image) sandbox_image="${2:?missing value for --sandbox-image}"; shift 2 ;;
--compose-file) compose_source="${2:?missing value for --compose-file}"; shift 2 ;;
--dry-run) dry_run=true; shift ;;
--help|-h) usage; exit 0 ;;
*) die "unknown option: $1" ;;
esac
done
case "$port" in (*[!0-9]*|"") die "--port must be numeric" ;; esac
home="$(expand_path "$home")"
mkdir -p "$home/postgres" "$home/data"
umask 077
env_file="$home/.env"
touch "$env_file"
if [ -n "$compose_source" ]; then
compose_file="$(expand_path "$compose_source")"
[ -f "$compose_file" ] || die "compose file does not exist: $compose_file"
elif [ -f "$PWD/docker-compose.yml" ]; then
compose_file="$PWD/docker-compose.yml"
else
compose_file="$home/docker-compose.yml"
download_compose
fi
set_env PARSAR_LOCAL_PORT "$port"
set_env PARSAR_BIND_ADDR "$bind"
set_env PARSAR_PG_DATA_DIR "$home/postgres"
set_env PARSAR_DATA_DIR "$home/data"
[ -z "$server_image" ] || set_env PARSAR_SERVER_IMAGE "$server_image"
[ -z "$sandbox_image" ] || set_env PARSAR_SANDBOX_IMAGE "$sandbox_image"
ensure_env PARSAR_PG_PASSWORD "$(random_hex 24)"
ensure_env PARSAR_MASTER_KEY "$(random_hex 32)"
ensure_env PARSAR_SHARED_RUNTIME_TOKEN "$(random_hex 32)"
detect_docker
log "Using $compose_file"
log "Using $env_file"
compose config --quiet
if [ "$dry_run" = true ]; then
log "Dry run complete"
exit 0
fi
log "Pulling images"
compose pull parsar-server parsar-runtime
log "Starting Parsar"
compose up -d --remove-orphans
if ! wait_for_health; then
compose ps >&2 || true
compose logs --tail 120 parsar-server >&2 || true
die "parsar-server did not become healthy"
fi
cat <<EOF
Parsar is running at http://${bind}:${port}
Create the first owner account in the web setup flow.
Manage the stack:
${DOCKER[*]} compose -f "$compose_file" --env-file "$env_file" ps
${DOCKER[*]} compose -f "$compose_file" --env-file "$env_file" logs -f
${DOCKER[*]} compose -f "$compose_file" --env-file "$env_file" down
EOF