-
Notifications
You must be signed in to change notification settings - Fork 36
Expand file tree
/
Copy pathhelpers.sh
More file actions
executable file
·372 lines (339 loc) · 13 KB
/
helpers.sh
File metadata and controls
executable file
·372 lines (339 loc) · 13 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
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
# shellcheck shell=bash
read_from_env_file() {
if cat "$1" &>/dev/null; then
while IFS= read -r line; do
! [[ "$line" == "#"* ]] && [[ "$line" == *"="* ]] && export "${line?}" || true
done <"$1"
fi
}
read_from_env_file .deploy
bitcart_update_docker_env() {
touch "$BITCART_ENV_FILE"
cat >"$BITCART_ENV_FILE" <<EOF
BITCART_HOST=$BITCART_HOST
BITCART_LETSENCRYPT_EMAIL=$BITCART_LETSENCRYPT_EMAIL
REVERSEPROXY_HTTP_PORT=$REVERSEPROXY_HTTP_PORT
REVERSEPROXY_HTTPS_PORT=$REVERSEPROXY_HTTPS_PORT
REVERSEPROXY_PROXYPROTOCOL_HTTP_PORT=$REVERSEPROXY_PROXYPROTOCOL_HTTP_PORT
REVERSEPROXY_PROXYPROTOCOL_HTTPS_PORT=$REVERSEPROXY_PROXYPROTOCOL_HTTPS_PORT
REVERSEPROXY_PROXYPROTOCOL=$REVERSEPROXY_PROXYPROTOCOL
REVERSEPROXY_DEFAULT_HOST=$REVERSEPROXY_DEFAULT_HOST
REVERSEPROXY_TRUSTED_IPS=$REVERSEPROXY_TRUSTED_IPS
REVERSEPROXY_TRUSTED_IPS_PRESET=$REVERSEPROXY_TRUSTED_IPS_PRESET
REVERSEPROXY_TRUSTED_HEADERS=$REVERSEPROXY_TRUSTED_HEADERS
BITCART_SSH_KEY_FILE=$BITCART_SSH_KEY_FILE
BITCART_SSH_AUTHORIZED_KEYS=$BITCART_SSH_AUTHORIZED_KEYS
BITCART_HOST_SSH_AUTHORIZED_KEYS=$BITCART_HOST_SSH_AUTHORIZED_KEYS
BITCART_STORE_HOST=$BITCART_STORE_HOST
BITCART_STORE_API_URL=$BITCART_STORE_API_URL
BITCART_ADMIN_HOST=$BITCART_ADMIN_HOST
BITCART_ADMIN_API_URL=$BITCART_ADMIN_API_URL
BITCART_CRYPTOS=$BITCART_CRYPTOS
BTC_NETWORK=$BTC_NETWORK
BTC_LIGHTNING=$BTC_LIGHTNING
BCH_NETWORK=$BCH_NETWORK
ETH_NETWORK=$ETH_NETWORK
BNB_NETWORK=$BNB_NETWORK
MATIC_NETWORK=$MATIC_NETWORK
TRX_NETWORK=$TRX_NETWORK
XRG_NETWORK=$XRG_NETWORK
LTC_NETWORK=$LTC_NETWORK
LTC_LIGHTNING=$LTC_LIGHTNING
GRS_NETWORK=$GRS_NETWORK
GRS_LIGHTNING=$GRS_LIGHTNING
XMR_NETWORK=$XMR_NETWORK
TOR_RELAY_NICKNAME=$TOR_RELAY_NICKNAME
TOR_RELAY_EMAIL=$TOR_RELAY_EMAIL
CLOUDFLARE_TUNNEL_TOKEN=$CLOUDFLARE_TUNNEL_TOKEN
BITCART_HTTPS_ENABLED=$BITCART_HTTPS_ENABLED
BITCART_BEHIND_REVERSEPROXY=$BITCART_BEHIND_REVERSEPROXY
BITCART_VERSION=$BITCART_VERSION
BITCART_UPDATE_URL=$BITCART_UPDATE_URL
BITCART_SENTRY_DSN=$BITCART_SENTRY_DSN
BITCART_API_WORKERS=$BITCART_API_WORKERS
BITCART_PROMETHEUS_METRICS_ENABLED=$BITCART_PROMETHEUS_METRICS_ENABLED
$(env | awk -F "=" '{print "\n"$0}' | grep "BITCART_.*.*_PORT")
$(env | awk -F "=" '{print "\n"$0}' | grep "BITCART_.*.*_EXPOSE")
$(env | awk -F "=" '{print "\n"$0}' | grep "BITCART_.*.*_SCALE")
$(env | awk -F "=" '{print "\n"$0}' | grep "BITCART_.*.*_ROOTPATH")
$(env | awk -F "=" '{print "\n"$0}' | grep ".*_SERVER")
$(env | awk -F "=" '{print "\n"$0}' | grep ".*_DEBUG")
$(env | awk -F "=" '{print "\n"$0}' | grep ".*_LIGHTNING_GOSSIP")
EOF
}
bitcart_start() {
create_backup_volume
install_plugins
docker compose -p "$NAME" -f compose/generated.yml up --build --remove-orphans -d "$@"
}
bitcart_stop() {
docker compose -p "$NAME" -f compose/generated.yml down
}
bitcart_reset_plugins() {
export ADMIN_PLUGINS_HASH=
export STORE_PLUGINS_HASH=
export BACKEND_PLUGINS_HASH=
export DOCKER_PLUGINS_HASH=
}
bitcart_pull() {
docker compose -f compose/generated.yml pull
bitcart_reset_plugins
}
bitcart_restart() {
bitcart_stop
bitcart_start
}
get_profile_file() {
CHECK_ROOT=${2:-true}
if [[ "$OSTYPE" == "darwin"* ]]; then
# Mac OS
if $CHECK_ROOT && [[ $EUID -eq 0 ]]; then
# Running as root is discouraged on Mac OS. Run under the current user instead.
echo "This script should not be run as root."
exit 1
fi
BASH_PROFILE_SCRIPT="$HOME/bitcart-env$1.sh"
# Mac OS doesn't use /etc/profile.d/xxx.sh. Instead we create a new file and load that from ~/.bash_profile or ~/.zprofile
if [[ "$SHELL" == */zsh ]]; then
if [[ ! -f "$HOME/.zprofile" ]]; then
touch "$HOME/.zprofile"
fi
if ! grep -q ". \"$BASH_PROFILE_SCRIPT\"" "$HOME/.zprofile"; then
# Line does not exist, add it
echo ". \"$BASH_PROFILE_SCRIPT\"" >>"$HOME/.zprofile"
fi
else
if [[ ! -f "$HOME/.bash_profile" ]]; then
touch "$HOME/.bash_profile"
fi
if ! grep -q ". \"$BASH_PROFILE_SCRIPT\"" "$HOME/.bash_profile"; then
# Line does not exist, add it
echo ". \"$BASH_PROFILE_SCRIPT\"" >>"$HOME/.bash_profile"
fi
fi
else
BASH_PROFILE_SCRIPT="/etc/profile.d/bitcart-env$1.sh"
if $CHECK_ROOT && [[ $EUID -ne 0 ]]; then
echo "This script must be run as root after running \"sudo su -\""
exit 1
fi
fi
export BASH_PROFILE_SCRIPT
}
load_env() {
get_profile_file "$SCRIPTS_POSTFIX" "${1:-false}"
# shellcheck source=/dev/null
. "${BASH_PROFILE_SCRIPT}"
}
try() {
"$@" || true
}
remove_host() {
if grep -wq "$1$" /etc/hosts; then
try sudo sed -ie "/[[:space:]]$1/d" /etc/hosts
fi
}
add_host() {
if ! grep -Eq "[[:space:]]$2" /etc/hosts; then
try sudo printf "%s\t%s\n" "$1" "$2" | sudo tee -a /etc/hosts >/dev/null
fi
}
modify_host() {
if [ -z "$2" ]; then
return
fi
remove_host "$2"
add_host "$1" "$2"
}
apply_local_modifications() {
if [[ "$BITCART_HOST" == *.local ]]; then
echo "Local setup detected."
if [[ "$BITCART_NOHOSTSEDIT" = true ]]; then
echo "Not modifying hosts."
else
echo "WARNING! Modifying /etc/hosts to make local setup work. It may require superuser privileges."
modify_host 172.17.0.1 "$BITCART_STORE_HOST"
modify_host 172.17.0.1 "$BITCART_HOST"
modify_host 172.17.0.1 "$BITCART_ADMIN_HOST"
fi
fi
}
container_name() {
deployment_name=${NAME:-compose}
echo "${deployment_name}-$1"
}
volume_name() {
deployment_name=${NAME:-compose}
echo "${deployment_name}_$1"
}
create_backup_volume() {
backup_dir="/var/lib/docker/volumes/backup_datadir/_data"
if [ ! -d "$backup_dir" ]; then
docker volume create backup_datadir >/dev/null 2>&1
fi
}
bitcart_dump_db() {
create_backup_volume
docker exec "$(container_name "database-1")" pg_dumpall -c -U postgres >"$backup_dir/$1"
}
bitcart_restore_db() {
bitcart_start database
# wait for db to be up
until docker exec -i "$(container_name "database-1")" psql -U postgres -c '\l'; do
echo >&2 "Postgres is unavailable - sleeping"
sleep 1
done
docker exec -i "$(container_name "database-1")" psql -U postgres <"$1"
}
version() {
echo "$@" | awk -F. '{ printf("%d%03d%03d%03d\n", $1,$2,$3,$4); }'
}
check_docker_compose() {
if docker-compose --version 2>/dev/null | grep -q docker-compose || ! [[ $(docker compose version 2>/dev/null) ]] || [ "$(version "$(docker compose version --short)")" -lt "$(version "2.9.0")" ]; then
install_docker_compose
fi
}
install_docker_compose() {
OS=$(uname -s)
ARCH=$(uname -m)
INSTALL_PATH=/usr/local/lib/docker/cli-plugins
if [[ "$OS" == "Darwin" ]]; then
INSTALL_PATH=~/.docker/cli-plugins
if [[ "$ARCH" == "arm64" ]]; then
ARCH="aarch64"
fi
fi
DOCKER_COMPOSE_DOWNLOAD="https://github.com/docker/compose/releases/latest/download/docker-compose-$OS-$ARCH"
echo "Trying to install docker-compose by downloading on $DOCKER_COMPOSE_DOWNLOAD ($(uname -m))"
sudo mkdir -p "$INSTALL_PATH"
sudo curl -L "$DOCKER_COMPOSE_DOWNLOAD" -o "$INSTALL_PATH/docker-compose"
sudo chmod +x "$INSTALL_PATH/docker-compose"
# remove old docker-compose
try sudo rm "$(command -v docker-compose)" &>/dev/null
}
install_tooling() {
if [[ "$OSTYPE" == "darwin"* ]]; then
if [[ "$SHELL" == */zsh ]]; then
AUTOCOMPLETE_FILE="cli-zsh-autocomplete.sh"
if [ -d "/opt/homebrew/share/zsh/site-functions" ]; then
COMPLETION_DIR="/opt/homebrew/share/zsh/site-functions"
elif [ -d "/usr/local/share/zsh/site-functions" ]; then
COMPLETION_DIR="/usr/local/share/zsh/site-functions"
else
COMPLETION_DIR="$HOME/.zsh/completions"
mkdir -p "$COMPLETION_DIR"
if ! grep -q "fpath.*\.zsh/completions" "$HOME/.zshrc" 2>/dev/null; then
echo "fpath=($COMPLETION_DIR \$fpath)" >>"$HOME/.zshrc"
fi
fi
else
AUTOCOMPLETE_FILE="cli-autocomplete.sh"
if [ -d "/opt/homebrew/etc/bash_completion.d" ]; then
COMPLETION_DIR="/opt/homebrew/etc/bash_completion.d"
elif [ -d "/usr/local/etc/bash_completion.d" ]; then
COMPLETION_DIR="/usr/local/etc/bash_completion.d"
else
COMPLETION_DIR="$HOME/.bash_completion.d"
mkdir -p "$COMPLETION_DIR"
if ! grep -q "bash_completion.d/bitcart-cli.sh" "$HOME/.bash_profile" 2>/dev/null; then
echo ". \"$COMPLETION_DIR/bitcart-cli.sh\" 2>/dev/null" >>"$HOME/.bash_profile"
fi
fi
fi
if [[ "$SHELL" == */zsh ]]; then
{
echo "#compdef bitcart-cli.sh"
cat "compose/scripts/$AUTOCOMPLETE_FILE"
} >"$COMPLETION_DIR/_bitcart-cli.sh"
try chmod +x "$COMPLETION_DIR/_bitcart-cli.sh"
else
try cp "compose/scripts/$AUTOCOMPLETE_FILE" "$COMPLETION_DIR/bitcart-cli.sh"
try chmod +x "$COMPLETION_DIR/bitcart-cli.sh"
fi
else
try sudo cp compose/scripts/cli-autocomplete.sh /etc/bash_completion.d/bitcart-cli.sh
try sudo chmod +x /etc/bash_completion.d/bitcart-cli.sh
fi
}
save_deploy_config() {
BITCART_DEPLOYMENT_CONFIG="$BITCART_BASE_DIRECTORY/.deploy"
if [ -f "$BITCART_DEPLOYMENT_CONFIG" ]; then
existing_key=$(grep "^BACKUP_ENCRYPTION_KEY=" "$BITCART_DEPLOYMENT_CONFIG" 2>/dev/null | cut -d'=' -f2)
fi
if [ -z "$existing_key" ]; then
BACKUP_ENCRYPTION_KEY=$(openssl rand -base64 48 | tr -d '\n')
else
BACKUP_ENCRYPTION_KEY="$existing_key"
fi
cat >"${BITCART_DEPLOYMENT_CONFIG}" <<EOF
#!/bin/bash
NAME=$NAME
SCRIPTS_POSTFIX=$SCRIPTS_POSTFIX
ADMIN_PLUGINS_HASH=$(get_plugins_hash admin)
STORE_PLUGINS_HASH=$(get_plugins_hash store)
BACKEND_PLUGINS_HASH=$(get_plugins_hash backend)
DOCKER_PLUGINS_HASH=$(get_plugins_hash docker)
BACKUP_ENCRYPTION_KEY=$BACKUP_ENCRYPTION_KEY
EOF
chmod +x "${BITCART_DEPLOYMENT_CONFIG}"
read_from_env_file "$BITCART_DEPLOYMENT_CONFIG"
}
get_plugins_hash() {
LC_ALL=C find "compose/plugins/$1" -type f -print0 2>/dev/null | sort -z | xargs -0 sha1sum | sha1sum | awk '{print $1}'
}
make_backup_image() {
if [ "$(docker inspect --format '{{ index .Config.Labels "org.bitcart.plugins"}}' "$1:stable")" = true ]; then
:
else
docker tag "$1:stable" "$1:original"
fi
}
install_plugins() {
COMPONENTS=$(./build.sh --components-only | tail -1)
COIN_COMPONENTS=$(./build.sh --cryptos-only | tail -1)
failed_file="/var/lib/docker/volumes/$(volume_name "bitcart_datadir")/_data/.plugins-failed"
error=false
rm -f "$failed_file"
if [[ " ${COMPONENTS[*]} " == *" backend "* ]]; then
make_backup_image bitcart/bitcart
fi
if [[ " ${COMPONENTS[*]} " == *" admin "* ]]; then
make_backup_image bitcart/bitcart-admin
fi
if [[ " ${COMPONENTS[*]} " == *" store "* ]]; then
make_backup_image bitcart/bitcart-store
fi
for coin in $COIN_COMPONENTS; do
make_backup_image "bitcart/bitcart-$coin"
done
if [[ "$DOCKER_PLUGINS_HASH" != "$(get_plugins_hash docker)" ]]; then
./build.sh || touch "$failed_file"
docker compose -f compose/generated.yml config || touch "$failed_file"
fi
if [[ " ${COMPONENTS[*]} " == *" backend "* ]] && [[ "$BACKEND_PLUGINS_HASH" != "$(get_plugins_hash backend)" ]]; then
docker build -t bitcart/bitcart:stable -f compose/backend-plugins.Dockerfile compose || error=true
fi
if [[ "$error" = false ]] && [[ " ${COMPONENTS[*]} " == *" admin "* ]] && [[ "$ADMIN_PLUGINS_HASH" != "$(get_plugins_hash admin)" ]]; then
docker build -t bitcart/bitcart-admin:stable -f compose/admin-plugins.Dockerfile compose || error=true
fi
if [[ "$error" = false ]] && [[ " ${COMPONENTS[*]} " == *" store "* ]] && [[ "$STORE_PLUGINS_HASH" != "$(get_plugins_hash store)" ]]; then
docker build -t bitcart/bitcart-store:stable -f compose/store-plugins.Dockerfile compose || error=true
fi
if [[ "$error" = true ]]; then
echo "Plugins installation failed, restoring original images"
if [[ " ${COMPONENTS[*]} " == *" backend "* ]]; then
docker tag bitcart/bitcart:original bitcart/bitcart:stable
fi
if [[ " ${COMPONENTS[*]} " == *" admin "* ]]; then
docker tag bitcart/bitcart-admin:original bitcart/bitcart-admin:stable
fi
if [[ " ${COMPONENTS[*]} " == *" store "* ]]; then
docker tag bitcart/bitcart-store:original bitcart/bitcart-store:stable
fi
for coin in $COIN_COMPONENTS; do
docker tag "bitcart/bitcart-$coin:original" "bitcart/bitcart-$coin:stable"
done
touch "$failed_file"
fi
save_deploy_config
}