-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathsetup.sh
More file actions
executable file
·262 lines (236 loc) · 9.66 KB
/
Copy pathsetup.sh
File metadata and controls
executable file
·262 lines (236 loc) · 9.66 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
#!/bin/bash
# Interactive first-time setup for Teranode Quickstart.
# Picks network + mode, gathers credentials, and writes .env.
set -eo pipefail
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$REPO_ROOT"
source "${REPO_ROOT}/lib/colors.sh"
ENV_FILE="${REPO_ROOT}/.env"
ENV_EXAMPLE="${REPO_ROOT}/.env.example"
prompt() {
local msg="$1"
local default="$2"
local var
if [ -n "$default" ]; then
read -r -p "$(echo -e "${CYAN}${msg}${NC} [${default}]: ")" var
echo "${var:-$default}"
else
read -r -p "$(echo -e "${CYAN}${msg}${NC}: ")" var
echo "$var"
fi
}
pick_one() {
local prompt_msg="$1"; shift
local options=("$@")
local i=1
echo_cyan "$prompt_msg" >&2
for opt in "${options[@]}"; do
if [ "$i" -eq 1 ]; then
echo " $i) $opt (default — press Enter)" >&2
else
echo " $i) $opt" >&2
fi
i=$((i + 1))
done
local choice
while true; do
read -r -p "Selection [1-${#options[@]}]: " choice
choice="${choice:-1}"
if [[ "$choice" =~ ^[0-9]+$ ]] && [ "$choice" -ge 1 ] && [ "$choice" -le "${#options[@]}" ]; then
echo "${options[$((choice - 1))]}"
return
fi
echo_warning "Pick a number between 1 and ${#options[@]}." >&2
done
}
# yes_no <prompt> [Y|N]
# Default Y → enter accepts yes. Default N → enter accepts no.
# Returns 0 on yes, 1 on no.
yes_no() {
local msg="$1"
local default="${2:-Y}"
local hint
if [ "$default" = "Y" ]; then hint="Y/n"; else hint="y/N"; fi
local var
while true; do
read -r -p "$(echo -e "${CYAN}${msg}${NC} [${hint}]: ")" var
var="${var:-$default}"
case "$var" in
[Yy]|[Yy][Ee][Ss]) return 0 ;;
[Nn]|[Nn][Oo]) return 1 ;;
*) echo_warning "Answer y or n." >&2 ;;
esac
done
}
gen_secret() {
openssl rand -hex 16 2>/dev/null || head -c 32 /dev/urandom | xxd -p | head -c 32
}
echo_green "=================================================="
echo_green " Teranode Quickstart — first-time setup"
echo_green "=================================================="
echo ""
NETWORK=$(pick_one "Which network?" "teratestnet" "testnet" "mainnet" "regtest")
echo_info "Selected: $NETWORK"
echo ""
if [ "$NETWORK" = "mainnet" ]; then
echo_yellow "Mainnet has substantial resource requirements; review docs/NETWORKS.md before continuing."
echo ""
fi
echo_cyan "Run mode:"
echo " listen_only — safe default, no public exposure"
echo " full — requires public endpoints (asset URL + P2P advertise addr)"
if yes_no "Run in full mode?" N; then
MODE=full
else
MODE=listen_only
fi
echo_info "Mode: $MODE"
echo ""
echo_cyan "Archival mode runs the optional blockpersister service, which keeps full"
echo_cyan "raw block history on disk. Most operators don't need it (Teranode prunes"
echo_cyan "spent UTXOs after 288 blocks by default). Useful for indexers / explorers /"
echo_cyan "research. Costs significant disk (multiple TB on mainnet)."
if yes_no "Enable archival mode?" N; then ARCHIVAL=true; else ARCHIVAL=false; fi
echo ""
echo_cyan "Monitoring stack: Grafana dashboards, Prometheus, Aerospike exporter, and"
echo_cyan "the Kafka (Redpanda) console. Optional — handy for visibility while syncing"
echo_cyan "and tuning, but not required to run a node. Adds ~4 containers and ~1GB RAM."
if yes_no "Enable monitoring stack?" Y; then MONITORING=true; else MONITORING=false; fi
echo ""
PROFILES="legacy,p2p"
[ "$ARCHIVAL" = "true" ] && PROFILES="${PROFILES},blockpersister"
[ "$MONITORING" = "true" ] && PROFILES="${PROFILES},monitoring"
echo_info "Running system checks for $NETWORK..."
if ! "${REPO_ROOT}/lib/check_requirements.sh" "$NETWORK" "$PROFILES"; then
echo_warning "Some checks warned."
yes_no "Proceed anyway?" N || exit 1
fi
echo ""
ASSET_PUBLIC_URL=""
P2P_ADVERTISE_ADDR=""
if [ "$MODE" = "full" ]; then
echo_cyan "Full mode requires you to expose this node to the public internet."
echo_cyan "Quickstart does NOT configure a reverse proxy, TLS, or tunnel for you."
echo_cyan "Set these up yourself (Caddy, Cloudflare Tunnel, nginx, VPS, etc.)"
echo_cyan "then tell us the resulting public addresses:"
echo ""
ASSET_BASE_URL=""
while [ -z "$ASSET_BASE_URL" ]; do
ASSET_BASE_URL=$(prompt "Asset API public base URL (https://node.example.com)" "")
done
ASSET_PUBLIC_URL="${ASSET_BASE_URL%/}/api/v1"
echo_cyan "P2P advertise address — libp2p multiaddr format:"
echo " /dns4/<hostname>/tcp/9905 (DNS, recommended)"
echo " /ip4/<ip>/tcp/9905 (IPv4 literal)"
echo " /ip6/<ip>/tcp/9905 (IPv6 literal)"
while [ -z "$P2P_ADVERTISE_ADDR" ]; do
P2P_ADVERTISE_ADDR=$(prompt "P2P advertise addr" "")
done
echo_info "Reachability will be probed automatically after start.sh."
echo ""
fi
default_client_name="teranode-$(gen_secret | head -c 4)"
CLIENT_NAME=$(prompt "Client name (shown in explorer)" "$default_client_name")
echo ""
if yes_no "Auto-generate RPC credentials?" Y; then
RPC_USER="teranode"
RPC_PASS=$(gen_secret)
else
RPC_USER=""
while [ -z "$RPC_USER" ]; do
RPC_USER=$(prompt "RPC user" "teranode")
done
RPC_PASS=""
while [ -z "$RPC_PASS" ]; do
RPC_PASS=$(prompt "RPC password" "$(gen_secret)")
done
fi
echo ""
echo_cyan "Host IP binding — controls ONLY these 3 ports:"
echo " 8090 asset viewer UI (always on)"
echo " 8000 asset-cache public API (p2p profile only)"
echo " 9905 P2P inbound peer connections (p2p profile only)"
echo_cyan "Everything else (RPC, Grafana, Prometheus, Kafka, Postgres, Aerospike) stays"
echo_cyan "hardcoded to 127.0.0.1 regardless. Options:"
echo " 127.0.0.1 localhost only (safe default, works behind NAT)"
echo " 0.0.0.0 all interfaces (needed when another host / reverse proxy needs to reach these)"
HOST_IP=$(prompt "Host IP" "127.0.0.1")
echo ""
echo_green "Summary"
echo " Network: $NETWORK"
echo " Mode: $MODE"
echo " Archival: $ARCHIVAL"
echo " Monitoring: $MONITORING"
echo " Client name: $CLIENT_NAME"
[ -n "$ASSET_PUBLIC_URL" ] && echo " Asset URL: $ASSET_PUBLIC_URL"
[ -n "$P2P_ADVERTISE_ADDR" ] && echo " P2P addr: $P2P_ADVERTISE_ADDR"
[ -n "$RPC_USER" ] && echo " RPC user: $RPC_USER (password hidden)"
echo " Host IP: $HOST_IP"
echo ""
if ! yes_no "Write .env?" Y; then
echo_warning "Aborted — nothing written."
exit 0
fi
if [ -f "$ENV_FILE" ]; then
cp "$ENV_FILE" "${ENV_FILE}.bak"
echo_info "Backed up existing .env to .env.bak"
fi
cp "$ENV_EXAMPLE" "$ENV_FILE"
echo_info "Wrote fresh .env from .env.example"
case "$NETWORK" in
mainnet) MIN_FEE="0.00000100"; BLOCK_MAX="4294967296"; EXCESSIVE="10737418240" ;;
testnet) MIN_FEE="0.00000001"; BLOCK_MAX="4294967296"; EXCESSIVE="10737418240" ;;
regtest) MIN_FEE="0"; BLOCK_MAX="4294967296"; EXCESSIVE="10737418240" ;;
teratestnet) MIN_FEE="0.00000001"; BLOCK_MAX="1073741824"; EXCESSIVE="1073741824" ;;
esac
"${REPO_ROOT}/lib/env_writer.sh" "$ENV_FILE" network "$NETWORK"
"${REPO_ROOT}/lib/env_writer.sh" "$ENV_FILE" SETTINGS_CONTEXT "docker.m"
"${REPO_ROOT}/lib/env_writer.sh" "$ENV_FILE" HOST_IP "$HOST_IP"
"${REPO_ROOT}/lib/env_writer.sh" "$ENV_FILE" COMPOSE_PROFILES "$PROFILES"
"${REPO_ROOT}/lib/env_writer.sh" "$ENV_FILE" listen_mode "$MODE"
"${REPO_ROOT}/lib/env_writer.sh" "$ENV_FILE" asset_httpPublicAddress "$ASSET_PUBLIC_URL"
"${REPO_ROOT}/lib/env_writer.sh" "$ENV_FILE" p2p_advertise_addresses "$P2P_ADVERTISE_ADDR"
"${REPO_ROOT}/lib/env_writer.sh" "$ENV_FILE" rpc_user "$RPC_USER"
"${REPO_ROOT}/lib/env_writer.sh" "$ENV_FILE" rpc_pass "$RPC_PASS"
"${REPO_ROOT}/lib/env_writer.sh" "$ENV_FILE" clientName "$CLIENT_NAME"
"${REPO_ROOT}/lib/env_writer.sh" "$ENV_FILE" minminingtxfee "$MIN_FEE"
"${REPO_ROOT}/lib/env_writer.sh" "$ENV_FILE" blockmaxsize "$BLOCK_MAX"
"${REPO_ROOT}/lib/env_writer.sh" "$ENV_FILE" excessiveblocksize "$EXCESSIVE"
if [ "$ARCHIVAL" = "true" ]; then
PRUNER_TRIGGER="OnBlockPersisted"
else
PRUNER_TRIGGER="OnBlockMined"
fi
"${REPO_ROOT}/lib/env_writer.sh" "$ENV_FILE" pruner_block_trigger "$PRUNER_TRIGGER"
"${REPO_ROOT}/lib/env_writer.sh" "$ENV_FILE" POSTGRES_PASSWORD "$(gen_secret)"
# Per-service container memory caps scaled to this host's RAM. Teranode
# derives GOMEMLIMIT from each cap, keeping any single service from starving
# Aerospike/Postgres on the host. See lib/mem_limits.sh.
source "${REPO_ROOT}/lib/mem_limits.sh"
TOTAL_RAM_GB=$(detect_total_ram_gb)
MEM_LIMITS=$(compute_mem_limits "$NETWORK" "$TOTAL_RAM_GB")
echo ""
echo_info "Writing per-service memory limits for a ${TOTAL_RAM_GB}GB host:"
echo "$MEM_LIMITS" | sed 's/^/ /'
write_mem_limits "$ENV_FILE" "$NETWORK" "$TOTAL_RAM_GB"
echo ""
echo_green "Setup complete."
case "$NETWORK" in
teratestnet)
echo_info "Next — pick one:"
echo_info " ./start.sh"
echo_info " (sync from scratch)"
echo_info " ./seed.sh 000000002ea94a515ad9fd40d710fd249fe8610acef7b74f459446812d565187 && ./start.sh"
echo_info " (seed from the canonical teratestnet snapshot first — much faster)"
;;
mainnet|testnet)
echo_info "Next — pick one:"
echo_info " ./start.sh"
echo_info " (sync from scratch)"
echo_info " ./seed.sh && ./start.sh"
echo_info " (prompts to fetch latest BSVA-hosted ${NETWORK} snapshot, then seeds — much faster)"
;;
*)
echo_info "Next: ./start.sh"
;;
esac