ovtools 0.0.0-stage → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +121 -2
- package/assets/common/bond-inspect.sh +368 -0
- package/assets/common/config.sh +263 -0
- package/assets/common/extract-data.sh +197 -0
- package/assets/common/harden-host.sh +37 -0
- package/assets/common/install-deps.sh +93 -0
- package/assets/common/node-enroll.sh +65 -0
- package/assets/common/node-setup.sh +150 -0
- package/assets/common/node-start.sh +90 -0
- package/assets/common/node-stop.sh +18 -0
- package/assets/common/node-upgrade.sh +45 -0
- package/assets/common/pre-run.sh +497 -0
- package/assets/common/promote-validator.sh +104 -0
- package/assets/deploy/10-prepare-host.sh +98 -0
- package/assets/deploy/20-install-toolchain.sh +93 -0
- package/assets/deploy/30-setup-node.sh +82 -0
- package/assets/deploy/40-start-node.sh +75 -0
- package/assets/deploy/50-verify.sh +259 -0
- package/assets/deploy/60-enroll.sh +304 -0
- package/assets/deploy/70-promote.sh +152 -0
- package/assets/deploy/lib.sh +398 -0
- package/assets/manage/10-bond-increase.sh +149 -0
- package/assets/manage/10-diagnose-node.sh +169 -0
- package/assets/manage/20-exit-validator.sh +259 -0
- package/assets/manage/25-recover-node.sh +291 -0
- package/assets/manage/30-status.sh +64 -0
- package/assets/manage/40-exit-withdraw.sh +133 -0
- package/assets/manage/bond_inc.sh +318 -0
- package/assets/manage/dashboard_monitor/app.js +1544 -0
- package/assets/manage/dashboard_monitor/assets/v2.2/css/base.css +113 -0
- package/assets/manage/dashboard_monitor/assets/v2.2/css/components/content.css +133 -0
- package/assets/manage/dashboard_monitor/assets/v2.2/css/components/controls.css +229 -0
- package/assets/manage/dashboard_monitor/assets/v2.2/css/components/data.css +374 -0
- package/assets/manage/dashboard_monitor/assets/v2.2/css/components/icons.css +35 -0
- package/assets/manage/dashboard_monitor/assets/v2.2/css/components/motion.css +57 -0
- package/assets/manage/dashboard_monitor/assets/v2.2/css/components/shell.css +51 -0
- package/assets/manage/dashboard_monitor/assets/v2.2/css/components/sidebar.css +242 -0
- package/assets/manage/dashboard_monitor/assets/v2.2/css/components/topbar.css +138 -0
- package/assets/manage/dashboard_monitor/assets/v2.2/css/fonts.css +30 -0
- package/assets/manage/dashboard_monitor/assets/v2.2/css/synteq-ui-v2.css +25 -0
- package/assets/manage/dashboard_monitor/assets/v2.2/css/theme-dark.css +38 -0
- package/assets/manage/dashboard_monitor/assets/v2.2/css/theme-light.css +36 -0
- package/assets/manage/dashboard_monitor/assets/v2.2/css/tokens.css +61 -0
- package/assets/manage/dashboard_monitor/assets/v2.2/fonts/GoogleSansCode-Medium.ttf +0 -0
- package/assets/manage/dashboard_monitor/assets/v2.2/fonts/GoogleSansCode-Regular.ttf +0 -0
- package/assets/manage/dashboard_monitor/assets/v2.2/fonts/GoogleSansCode-SemiBold.ttf +0 -0
- package/assets/manage/dashboard_monitor/assets/v2.2/js/synteq-ui-v2.js +869 -0
- package/assets/manage/dashboard_monitor/deploy-dashboard.sh +230 -0
- package/assets/manage/dashboard_monitor/favicon.svg +13 -0
- package/assets/manage/dashboard_monitor/index.html +1197 -0
- package/assets/manage/dashboard_monitor/nginx-octra.conf +76 -0
- package/assets/manage/dashboard_monitor/octra-dashboard.service +29 -0
- package/assets/manage/dashboard_monitor/octra-node-prune.cron +12 -0
- package/assets/manage/dashboard_monitor/octra-node-prune.service +16 -0
- package/assets/manage/dashboard_monitor/octra-node-prune.timer +12 -0
- package/assets/manage/dashboard_monitor/prune-node-junk.sh +329 -0
- package/assets/manage/dashboard_monitor/server.py +1887 -0
- package/assets/manage/dashboard_monitor/ssl-certbot.sh +90 -0
- package/assets/manage/dashboard_monitor/styles.css +327 -0
- package/assets/manage/lib.sh +347 -0
- package/assets/manifest.json +143 -0
- package/assets/migrate/00-backup-identity.sh +67 -0
- package/assets/migrate/01-prepare-target.sh +145 -0
- package/assets/migrate/02-authorize-pull.sh +43 -0
- package/assets/migrate/03-pull-state.sh +102 -0
- package/assets/migrate/04-stop-source.sh +85 -0
- package/assets/migrate/05-finalize-target.sh +140 -0
- package/assets/migrate/06-start-target.sh +57 -0
- package/assets/migrate/07-verify.sh +237 -0
- package/assets/migrate/08-rollback.sh +54 -0
- package/assets/migrate/lib.sh +149 -0
- package/assets/upgrade/10-preflight.sh +120 -0
- package/assets/upgrade/20-upgrade.sh +142 -0
- package/assets/upgrade/30-manual-upgrade.sh +129 -0
- package/assets/upgrade/40-storage-prune.sh +65 -0
- package/assets/upgrade/50-status.sh +58 -0
- package/assets/upgrade/lib.sh +232 -0
- package/bin/ovtools.js +32 -0
- package/dist/api/checks.d.ts +6 -0
- package/dist/api/checks.d.ts.map +1 -0
- package/dist/api/checks.js +173 -0
- package/dist/api/checks.js.map +1 -0
- package/dist/api/hostkeys.d.ts +10 -0
- package/dist/api/hostkeys.d.ts.map +1 -0
- package/dist/api/hostkeys.js +58 -0
- package/dist/api/hostkeys.js.map +1 -0
- package/dist/api/jobs.d.ts +33 -0
- package/dist/api/jobs.d.ts.map +1 -0
- package/dist/api/jobs.js +486 -0
- package/dist/api/jobs.js.map +1 -0
- package/dist/api/nodes.d.ts +16 -0
- package/dist/api/nodes.d.ts.map +1 -0
- package/dist/api/nodes.js +126 -0
- package/dist/api/nodes.js.map +1 -0
- package/dist/api/server.d.ts +3 -0
- package/dist/api/server.d.ts.map +1 -0
- package/dist/api/server.js +443 -0
- package/dist/api/server.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +301 -0
- package/dist/cli.js.map +1 -0
- package/dist/constants.d.ts +76 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +150 -0
- package/dist/constants.js.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +60 -0
- package/dist/index.js.map +1 -0
- package/dist/orchestrator/base.d.ts +52 -0
- package/dist/orchestrator/base.d.ts.map +1 -0
- package/dist/orchestrator/base.js +219 -0
- package/dist/orchestrator/base.js.map +1 -0
- package/dist/orchestrator/deploy.d.ts +33 -0
- package/dist/orchestrator/deploy.d.ts.map +1 -0
- package/dist/orchestrator/deploy.js +313 -0
- package/dist/orchestrator/deploy.js.map +1 -0
- package/dist/orchestrator/manage.d.ts +28 -0
- package/dist/orchestrator/manage.d.ts.map +1 -0
- package/dist/orchestrator/manage.js +267 -0
- package/dist/orchestrator/manage.js.map +1 -0
- package/dist/orchestrator/migrate.d.ts +31 -0
- package/dist/orchestrator/migrate.d.ts.map +1 -0
- package/dist/orchestrator/migrate.js +442 -0
- package/dist/orchestrator/migrate.js.map +1 -0
- package/dist/ssh/client.d.ts +39 -0
- package/dist/ssh/client.d.ts.map +1 -0
- package/dist/ssh/client.js +418 -0
- package/dist/ssh/client.js.map +1 -0
- package/dist/test/core.test.d.ts +2 -0
- package/dist/test/core.test.d.ts.map +1 -0
- package/dist/test/core.test.js +188 -0
- package/dist/test/core.test.js.map +1 -0
- package/dist/types.d.ts +267 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/assets.d.ts +28 -0
- package/dist/utils/assets.d.ts.map +1 -0
- package/dist/utils/assets.js +583 -0
- package/dist/utils/assets.js.map +1 -0
- package/dist/utils/browser.d.ts +2 -0
- package/dist/utils/browser.d.ts.map +1 -0
- package/dist/utils/browser.js +23 -0
- package/dist/utils/browser.js.map +1 -0
- package/dist/utils/dashboard.d.ts +16 -0
- package/dist/utils/dashboard.d.ts.map +1 -0
- package/dist/utils/dashboard.js +177 -0
- package/dist/utils/dashboard.js.map +1 -0
- package/dist/utils/helpers.d.ts +29 -0
- package/dist/utils/helpers.d.ts.map +1 -0
- package/dist/utils/helpers.js +204 -0
- package/dist/utils/helpers.js.map +1 -0
- package/dist/utils/scripts.d.ts +60 -0
- package/dist/utils/scripts.d.ts.map +1 -0
- package/dist/utils/scripts.js +174 -0
- package/dist/utils/scripts.js.map +1 -0
- package/dist/utils/state.d.ts +12 -0
- package/dist/utils/state.d.ts.map +1 -0
- package/dist/utils/state.js +44 -0
- package/dist/utils/state.js.map +1 -0
- package/dist/utils/tar.d.ts +11 -0
- package/dist/utils/tar.d.ts.map +1 -0
- package/dist/utils/tar.js +93 -0
- package/dist/utils/tar.js.map +1 -0
- package/dist/utils/update.d.ts +9 -0
- package/dist/utils/update.d.ts.map +1 -0
- package/dist/utils/update.js +134 -0
- package/dist/utils/update.js.map +1 -0
- package/dist/utils/websocket.d.ts +10 -0
- package/dist/utils/websocket.d.ts.map +1 -0
- package/dist/utils/websocket.js +203 -0
- package/dist/utils/websocket.js.map +1 -0
- package/package.json +55 -4
- package/public/app.js +2736 -0
- package/public/assets/v2.2/css/base.css +113 -0
- package/public/assets/v2.2/css/components/content.css +133 -0
- package/public/assets/v2.2/css/components/controls.css +229 -0
- package/public/assets/v2.2/css/components/data.css +373 -0
- package/public/assets/v2.2/css/components/icons.css +35 -0
- package/public/assets/v2.2/css/components/motion.css +57 -0
- package/public/assets/v2.2/css/components/shell.css +51 -0
- package/public/assets/v2.2/css/components/sidebar.css +242 -0
- package/public/assets/v2.2/css/components/topbar.css +138 -0
- package/public/assets/v2.2/css/fonts.css +30 -0
- package/public/assets/v2.2/css/synteq-ui-v2.css +25 -0
- package/public/assets/v2.2/css/theme-dark.css +38 -0
- package/public/assets/v2.2/css/theme-light.css +36 -0
- package/public/assets/v2.2/css/tokens.css +61 -0
- package/public/assets/v2.2/fonts/GoogleSansCode-Medium.ttf +0 -0
- package/public/assets/v2.2/fonts/GoogleSansCode-Regular.ttf +0 -0
- package/public/assets/v2.2/fonts/GoogleSansCode-SemiBold.ttf +0 -0
- package/public/assets/v2.2/js/synteq-ui-v2.js +869 -0
- package/public/favicon.svg +13 -0
- package/public/index.html +1083 -0
- package/public/styles.css +580 -0
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# ===================================================================
|
|
3
|
+
# config.sh — shared configuration for Octra lite_node scripts
|
|
4
|
+
# Source this file from other scripts: source "$(dirname "$0")/config.sh"
|
|
5
|
+
# ===================================================================
|
|
6
|
+
|
|
7
|
+
set -euo pipefail
|
|
8
|
+
|
|
9
|
+
# --- Node identity -------------------------------------------------
|
|
10
|
+
NODE_REPO="https://github.com/octra-labs/lite_node.git"
|
|
11
|
+
NODE_BRANCH="main"
|
|
12
|
+
NODE_SRC_DIR="/opt/octra/libv_litecore"
|
|
13
|
+
NODE_DATA_ROOT="/var/lib/octra"
|
|
14
|
+
NODE_DATA_DIR="${NODE_DATA_ROOT}/devnet"
|
|
15
|
+
NODE_SYNC_STAGE="${NODE_DATA_ROOT}/devnet.state_sync"
|
|
16
|
+
NODE_USER="octra"
|
|
17
|
+
|
|
18
|
+
# --- Network / API ports (from official config_val.sh defaults) ---
|
|
19
|
+
API_PORT="8080" # REST API (dashboard reads from here)
|
|
20
|
+
CONSENSUS_PORT="19000" # consensus
|
|
21
|
+
P2P_PORT="9000" # peer-to-peer
|
|
22
|
+
|
|
23
|
+
# --- Disk / swap ---------------------------------------------------
|
|
24
|
+
SWAP_FILE="/swapfile"
|
|
25
|
+
# Swap size in GB. This kit is deployed for several projects, so the operator
|
|
26
|
+
# sets it in Project settings (console) or with SWAP_GB=<n> bash pre-run.sh.
|
|
27
|
+
SWAP_GB="${SWAP_GB:-8}"
|
|
28
|
+
SWAP_SIZE="${SWAP_SIZE:-${SWAP_GB}G}" # 8 GB swap by default
|
|
29
|
+
MOUNT_POINT="${NODE_DATA_ROOT}"
|
|
30
|
+
|
|
31
|
+
# Node data store: the chain lives here (~40 GB today, grows over time), so the
|
|
32
|
+
# target wants ~1 TB. pre-run.sh is fully automatic:
|
|
33
|
+
# * /dev/sdb (or BLOCK_DEVICE) when present and not the system disk
|
|
34
|
+
# * otherwise the largest non-system whole disk >= DATA_MIN_GB
|
|
35
|
+
# * otherwise the largest filesystem >= DATA_MIN_GB (main disk, no formatting)
|
|
36
|
+
BLOCK_DEVICE="${BLOCK_DEVICE:-/dev/sdb}"
|
|
37
|
+
DATA_MIN_GB="${DATA_MIN_GB:-1000}"
|
|
38
|
+
DATA_LABEL="${DATA_LABEL:-octra-data}"
|
|
39
|
+
DATA_MARKER="${DATA_MARKER:-.octra-data-volume}"
|
|
40
|
+
|
|
41
|
+
# --- Build profile ---
|
|
42
|
+
BUILD_PROFILE="release"
|
|
43
|
+
|
|
44
|
+
# --- Helpers -------------------------------------------------------
|
|
45
|
+
log() { echo -e "\033[1;32m[octra]\033[0m $*"; }
|
|
46
|
+
warn() { echo -e "\033[1;33m[warn]\033[0m $*"; }
|
|
47
|
+
err() { echo -e "\033[1;31m[err]\033[0m $*" >&2; }
|
|
48
|
+
|
|
49
|
+
# --- tools on the host: check -> install -> continue ------------------
|
|
50
|
+
# A VPS that was just re-installed is a bare image: `jq`, `rsync` or even
|
|
51
|
+
# `curl` may simply not be there yet, and a step that calls them dies half way
|
|
52
|
+
# through with "command not found". Every step therefore asks for the tool it
|
|
53
|
+
# needs instead of assuming it: the check is free, apt only runs when something
|
|
54
|
+
# is really missing, and a retry after a dropped SSH does not re-run a full
|
|
55
|
+
# `apt-get update`/install for tools that are already present.
|
|
56
|
+
OCTRA_APT_STAMP="${OCTRA_APT_STAMP:-/root/.octra-apt-update}"
|
|
57
|
+
OCTRA_APT_TTL="${OCTRA_APT_TTL:-900}" # seconds an apt-get update stays fresh
|
|
58
|
+
|
|
59
|
+
octra_have() { command -v "$1" >/dev/null 2>&1; }
|
|
60
|
+
|
|
61
|
+
octra_pkg_installed() {
|
|
62
|
+
dpkg-query -W -f='${Status}' "$1" 2>/dev/null | grep -q 'install ok installed'
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
# apt-get update at most once per OCTRA_APT_TTL seconds (checkpoint: a retry of a
|
|
66
|
+
# failed step must not re-sync the package lists).
|
|
67
|
+
apt_refresh() {
|
|
68
|
+
local now last
|
|
69
|
+
now=$(date +%s)
|
|
70
|
+
last=0
|
|
71
|
+
if [[ -f "${OCTRA_APT_STAMP}" ]]; then
|
|
72
|
+
last=$(tr -dc '0-9' < "${OCTRA_APT_STAMP}" 2>/dev/null || true)
|
|
73
|
+
fi
|
|
74
|
+
last="${last:-0}"
|
|
75
|
+
if (( now - last < OCTRA_APT_TTL )); then
|
|
76
|
+
log "apt lists are $(( now - last ))s old - skipping apt-get update"
|
|
77
|
+
return 0
|
|
78
|
+
fi
|
|
79
|
+
log "apt-get update"
|
|
80
|
+
if DEBIAN_FRONTEND=noninteractive apt-get update; then
|
|
81
|
+
echo "${now}" > "${OCTRA_APT_STAMP}" 2>/dev/null || true
|
|
82
|
+
return 0
|
|
83
|
+
fi
|
|
84
|
+
warn "apt-get update failed - trying once more in 10s"
|
|
85
|
+
sleep 10
|
|
86
|
+
DEBIAN_FRONTEND=noninteractive apt-get update || { err "apt-get update failed (network or mirror)"; return 1; }
|
|
87
|
+
echo "${now}" > "${OCTRA_APT_STAMP}" 2>/dev/null || true
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
# install_packages <pkg> ... - only the missing ones, with an apt-lock retry
|
|
91
|
+
# (unattended-upgrades holds the dpkg lock on a freshly booted VPS).
|
|
92
|
+
install_packages() {
|
|
93
|
+
local pkg missing=() attempt out
|
|
94
|
+
for pkg in "$@"; do
|
|
95
|
+
octra_pkg_installed "${pkg}" || missing+=("${pkg}")
|
|
96
|
+
done
|
|
97
|
+
if (( ${#missing[@]} == 0 )); then
|
|
98
|
+
return 0
|
|
99
|
+
fi
|
|
100
|
+
log "apt-get install: ${missing[*]}"
|
|
101
|
+
apt_refresh || return 1
|
|
102
|
+
for attempt in 1 2 3; do
|
|
103
|
+
if out=$(DEBIAN_FRONTEND=noninteractive apt-get install -y "${missing[@]}" 2>&1); then
|
|
104
|
+
printf '%s\n' "${out}"
|
|
105
|
+
return 0
|
|
106
|
+
fi
|
|
107
|
+
printf '%s\n' "${out}"
|
|
108
|
+
if [[ "${out}" == *"Could not get lock"* || "${out}" == *"dpkg frontend lock"* ]]; then
|
|
109
|
+
warn "dpkg is locked (another apt run) - retrying in $(( attempt * 10 ))s"
|
|
110
|
+
sleep $(( attempt * 10 ))
|
|
111
|
+
continue
|
|
112
|
+
fi
|
|
113
|
+
break
|
|
114
|
+
done
|
|
115
|
+
err "could not install: ${missing[*]}"
|
|
116
|
+
return 1
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
# ensure_package <pkg> - present, or installed now
|
|
120
|
+
ensure_package() {
|
|
121
|
+
local pkg="$1"
|
|
122
|
+
if octra_pkg_installed "${pkg}"; then
|
|
123
|
+
log "package ${pkg}: present"
|
|
124
|
+
return 0
|
|
125
|
+
fi
|
|
126
|
+
log "package ${pkg}: missing - installing"
|
|
127
|
+
install_packages "${pkg}" || return 1
|
|
128
|
+
octra_pkg_installed "${pkg}" && log "package ${pkg}: installed"
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
# ensure_tool <binary> [package] - check -> install -> continue
|
|
132
|
+
# returns 0 when the binary answers, 1 when it still does not exist
|
|
133
|
+
ensure_tool() {
|
|
134
|
+
local bin="$1" pkg="${2:-$1}"
|
|
135
|
+
if octra_have "${bin}"; then
|
|
136
|
+
log "tool ${bin}: present ($(command -v "${bin}"))"
|
|
137
|
+
return 0
|
|
138
|
+
fi
|
|
139
|
+
log "tool ${bin}: missing - installing package ${pkg}"
|
|
140
|
+
install_packages "${pkg}" || return 1
|
|
141
|
+
if octra_have "${bin}"; then
|
|
142
|
+
log "tool ${bin}: installed"
|
|
143
|
+
return 0
|
|
144
|
+
fi
|
|
145
|
+
err "tool ${bin} is still missing after installing ${pkg}"
|
|
146
|
+
return 1
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
# ensure_tools <bin[:package]> ... - the whole set or a non-zero return
|
|
150
|
+
ensure_tools() {
|
|
151
|
+
local spec bin pkg rc=0
|
|
152
|
+
for spec in "$@"; do
|
|
153
|
+
bin="${spec%%:*}"
|
|
154
|
+
pkg="${spec#*:}"
|
|
155
|
+
[[ "${pkg}" == "${bin}" ]] && pkg="${bin}"
|
|
156
|
+
ensure_tool "${bin}" "${pkg}" || rc=1
|
|
157
|
+
done
|
|
158
|
+
return "${rc}"
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
# --- Host hardening (MANDATORY, both programs) ----------------------
|
|
162
|
+
# MPTCP is dead weight on a node host and pure attack surface: the node, the
|
|
163
|
+
# dashboard and the SSH pull all speak plain TCP, nothing ever negotiates
|
|
164
|
+
# multipath. So every machine this toolkit prepares must come up with the knob
|
|
165
|
+
# off, persisted for the reboot:
|
|
166
|
+
#
|
|
167
|
+
# net.mptcp.enabled = 0 -> /etc/sysctl.d/99-disable-mptcp.conf
|
|
168
|
+
#
|
|
169
|
+
# Idempotent, and harmless on a kernel without MPTCP (the knob is absent and
|
|
170
|
+
# there is nothing to disable). Verify with: sysctl net.mptcp.enabled
|
|
171
|
+
# Both paths are overridable so the dev harness can drive every branch.
|
|
172
|
+
MPTCP_KNOB="${MPTCP_KNOB:-/proc/sys/net/mptcp/enabled}"
|
|
173
|
+
MPTCP_CONF="${MPTCP_CONF:-/etc/sysctl.d/99-disable-mptcp.conf}"
|
|
174
|
+
|
|
175
|
+
disable_mptcp() {
|
|
176
|
+
if [[ ! -e "${MPTCP_KNOB}" ]]; then
|
|
177
|
+
log "this kernel has no net.mptcp.enabled knob - MPTCP is not built in (nothing to disable)"
|
|
178
|
+
return 0
|
|
179
|
+
fi
|
|
180
|
+
printf 'net.mptcp.enabled = 0\n' > "${MPTCP_CONF}"
|
|
181
|
+
chmod 644 "${MPTCP_CONF}"
|
|
182
|
+
log "wrote ${MPTCP_CONF} (net.mptcp.enabled = 0)"
|
|
183
|
+
# immediate value first, then reload every drop-in so the running kernel and
|
|
184
|
+
# the files on disk agree (a stale 50-*.conf would otherwise win)
|
|
185
|
+
sysctl -w net.mptcp.enabled=0 >/dev/null 2>&1 || true
|
|
186
|
+
sysctl --system >/dev/null 2>&1 || warn "sysctl --system reported an error - the value below decides"
|
|
187
|
+
local value
|
|
188
|
+
value=$(sysctl -n net.mptcp.enabled 2>/dev/null || echo unknown)
|
|
189
|
+
if [[ "${value}" == "0" ]]; then
|
|
190
|
+
log "MPTCP disabled: $(sysctl net.mptcp.enabled 2>/dev/null || echo 'net.mptcp.enabled = 0')"
|
|
191
|
+
return 0
|
|
192
|
+
fi
|
|
193
|
+
err "net.mptcp.enabled is '${value}' - disabling MPTCP is mandatory on a node host"
|
|
194
|
+
return 1
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
# --- the node repo's local OCaml switch ------------------------------
|
|
198
|
+
# controls/install.sh --source-build builds the switch INSIDE the repo
|
|
199
|
+
# <repo>/runtime_data/toolchains/ocaml/_opam (holds .opam-switch)
|
|
200
|
+
# and links it as
|
|
201
|
+
# <repo>/_opam -> runtime_data/toolchains/ocaml/_opam
|
|
202
|
+
#
|
|
203
|
+
# opam 2.3 (Debian 13) CANNOT re-create that link: `opam switch link` calls
|
|
204
|
+
# rmdir(2) on the existing symlink, dies with
|
|
205
|
+
# «"rmdir" failed on <repo>/_opam: Not a directory»
|
|
206
|
+
# and the failed call leaves the switch prefix EMPTY - it throws away a 15-30
|
|
207
|
+
# minute build. Proven on 2026-11-02 with a throw-away switch: the first
|
|
208
|
+
# `switch link` creates the link, the second one destroys the switch.
|
|
209
|
+
#
|
|
210
|
+
# Both scripts of the node repo call `opam switch link` (controls/install.sh and
|
|
211
|
+
# controls/config_val.sh), so this kit unlinks <repo>/_opam first and lets them
|
|
212
|
+
# re-create it.
|
|
213
|
+
OCAML_SWITCH_REL="runtime_data/toolchains/ocaml"
|
|
214
|
+
|
|
215
|
+
ocaml_switch_root() { printf '%s/%s\n' "${NODE_SRC_DIR}" "${OCAML_SWITCH_REL}"; }
|
|
216
|
+
|
|
217
|
+
ocaml_switch_built() { [[ -d "$(ocaml_switch_root)/_opam/.opam-switch" ]]; }
|
|
218
|
+
|
|
219
|
+
unlink_ocaml_switch_link() { # unlink_ocaml_switch_link [<why>]
|
|
220
|
+
local link="${NODE_SRC_DIR}/_opam"
|
|
221
|
+
if [[ -L "${link}" ]]; then
|
|
222
|
+
log "unlinking ${link} (${1:-opam 2.3 cannot relink an existing _opam})"
|
|
223
|
+
rm -f "${link}"
|
|
224
|
+
elif [[ -d "${link}" ]]; then
|
|
225
|
+
if rmdir "${link}" 2>/dev/null; then
|
|
226
|
+
log "removed the empty ${link} directory (${1:-opam needs a free path})"
|
|
227
|
+
else
|
|
228
|
+
warn "${link} is a non-empty directory, not a link - leaving it as it is"
|
|
229
|
+
fi
|
|
230
|
+
fi
|
|
231
|
+
return 0
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
# A cached "<unit>.rc == 0" is NOT proof the toolchain is usable: the failed
|
|
235
|
+
# `opam switch link` above empties the switch prefix and leaves the exit code
|
|
236
|
+
# untouched. Drop what is left, so the next run rebuilds instead of reporting a
|
|
237
|
+
# cached success.
|
|
238
|
+
drop_broken_ocaml_switch() { # drop_broken_ocaml_switch [<rc file to forget>]
|
|
239
|
+
local root rc="${1:-}"
|
|
240
|
+
if ocaml_switch_built; then
|
|
241
|
+
return 0 # never touch a real switch
|
|
242
|
+
fi
|
|
243
|
+
unlink_ocaml_switch_link "the switch has to be rebuilt"
|
|
244
|
+
root=$(ocaml_switch_root)
|
|
245
|
+
if [[ -d "${root}" ]]; then
|
|
246
|
+
warn "dropping the incomplete switch prefix ${root} (no .opam-switch)"
|
|
247
|
+
rm -rf "${root}"
|
|
248
|
+
fi
|
|
249
|
+
if [[ -n "${rc}" ]]; then
|
|
250
|
+
rm -f "${rc}"
|
|
251
|
+
fi
|
|
252
|
+
return 0
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
# Run a command as the octra user
|
|
256
|
+
as_octra() {
|
|
257
|
+
sudo -iu "${NODE_USER}" "$@"
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
# Run a command inside the node source directory as octra
|
|
261
|
+
in_src() {
|
|
262
|
+
sudo -iu "${NODE_USER}" bash -c "cd '${NODE_SRC_DIR}' && $*"
|
|
263
|
+
}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# ===================================================================
|
|
3
|
+
# extract-data.sh — collect validator node data into a JSON file
|
|
4
|
+
#
|
|
5
|
+
# Gathers all critical files needed for migration to a new machine:
|
|
6
|
+
# - wallet.json (validator wallet + keys)
|
|
7
|
+
# - node.env (node configuration)
|
|
8
|
+
# - network.env (network parameters)
|
|
9
|
+
# - SOURCE_COMMIT (exact build commit)
|
|
10
|
+
# - node status (consensus head, sync state, peer count)
|
|
11
|
+
# - system info (hostname, IP, OS, kernel, uptime)
|
|
12
|
+
#
|
|
13
|
+
# Output: /tmp/octra-node-data.json (also printed to stdout)
|
|
14
|
+
#
|
|
15
|
+
# Usage: sudo bash extract-data.sh
|
|
16
|
+
# ===================================================================
|
|
17
|
+
|
|
18
|
+
set -euo pipefail
|
|
19
|
+
source "$(dirname "$0")/config.sh"
|
|
20
|
+
|
|
21
|
+
if [[ $EUID -ne 0 ]]; then
|
|
22
|
+
err "Run as root: sudo bash $0"
|
|
23
|
+
exit 1
|
|
24
|
+
fi
|
|
25
|
+
|
|
26
|
+
# --- Collect file contents -----------------------------------------
|
|
27
|
+
get_file() {
|
|
28
|
+
local f="$1"
|
|
29
|
+
if [[ -f "$f" ]]; then
|
|
30
|
+
cat "$f" 2>/dev/null || echo ""
|
|
31
|
+
else
|
|
32
|
+
echo ""
|
|
33
|
+
fi
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
# Helper: base64-encode a file (for binary or sensitive content)
|
|
37
|
+
get_file_b64() {
|
|
38
|
+
local f="$1"
|
|
39
|
+
if [[ -f "$f" ]]; then
|
|
40
|
+
base64 -w0 "$f" 2>/dev/null || echo ""
|
|
41
|
+
else
|
|
42
|
+
echo ""
|
|
43
|
+
fi
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
# --- Gather node status (best-effort, may fail if node not running) -
|
|
47
|
+
STAT_OUTPUT=""
|
|
48
|
+
STAT_LOGS=""
|
|
49
|
+
if su - "${NODE_USER}" -c "cd ${NODE_SRC_DIR} && sh controls/stat.sh" >/tmp/octra_stat.txt 2>&1; then
|
|
50
|
+
STAT_OUTPUT=$(cat /tmp/octra_stat.txt)
|
|
51
|
+
else
|
|
52
|
+
STAT_OUTPUT="$(cat /tmp/octra_stat.txt 2>/dev/null || echo 'node not running')"
|
|
53
|
+
fi
|
|
54
|
+
|
|
55
|
+
# --- Gather system info --------------------------------------------
|
|
56
|
+
HOSTNAME=$(hostname)
|
|
57
|
+
PUBLIC_IP=$(curl -s --max-time 5 https://api.ipify.org 2>/dev/null || echo "")
|
|
58
|
+
LOCAL_IP=$(hostname -I 2>/dev/null | awk '{print $1}' || echo "")
|
|
59
|
+
OS_INFO=$(. /etc/os-release 2>/dev/null && echo "${PRETTY_NAME:-unknown}" || echo "unknown")
|
|
60
|
+
KERNEL=$(uname -r)
|
|
61
|
+
UPTIME=$(uptime -p 2>/dev/null || echo "")
|
|
62
|
+
CPU_COUNT=$(nproc 2>/dev/null || echo 0)
|
|
63
|
+
MEM_TOTAL=$(free -h 2>/dev/null | awk '/^Mem:/ {print $2}' || echo "")
|
|
64
|
+
DISK_USAGE=$(df -h "${NODE_DATA_ROOT}" 2>/dev/null | tail -1 | awk '{print $3 "/" $2 " (" $5 " used)"}' || echo "")
|
|
65
|
+
|
|
66
|
+
# --- Gather storage info -------------------------------------------
|
|
67
|
+
STORAGE_INFO=""
|
|
68
|
+
if su - "${NODE_USER}" -c "cd ${NODE_SRC_DIR} && sh controls/storage.sh" >/tmp/octra_storage.txt 2>&1; then
|
|
69
|
+
STORAGE_INFO=$(cat /tmp/octra_storage.txt)
|
|
70
|
+
fi
|
|
71
|
+
|
|
72
|
+
# --- Gather enroll status -----------------------------------------
|
|
73
|
+
ENROLL_STATUS=""
|
|
74
|
+
if su - "${NODE_USER}" -c "cd ${NODE_SRC_DIR} && sh controls/enroll.sh status" >/tmp/octra_enroll.txt 2>&1; then
|
|
75
|
+
ENROLL_STATUS=$(cat /tmp/octra_enroll.txt)
|
|
76
|
+
fi
|
|
77
|
+
|
|
78
|
+
# --- Source commit -------------------------------------------------
|
|
79
|
+
SOURCE_COMMIT=$(get_file "${NODE_SRC_DIR}/SOURCE_COMMIT")
|
|
80
|
+
|
|
81
|
+
# --- Wallet (base64-encoded for safe transport) --------------------
|
|
82
|
+
WALLET_PATH="${NODE_SRC_DIR}/.keys/validator/wallet.json"
|
|
83
|
+
if [[ ! -f "${WALLET_PATH}" ]]; then
|
|
84
|
+
WALLET_PATH="${NODE_DATA_DIR}/wallet.json"
|
|
85
|
+
fi
|
|
86
|
+
WALLET_B64=$(get_file_b64 "${WALLET_PATH}")
|
|
87
|
+
|
|
88
|
+
# --- node.env (base64-encoded) ------------------------------------
|
|
89
|
+
NODE_ENV_PATH="${NODE_SRC_DIR}/.keys/validator/node.env"
|
|
90
|
+
if [[ ! -f "${NODE_ENV_PATH}" ]]; then
|
|
91
|
+
NODE_ENV_PATH="${NODE_SRC_DIR}/config/node.env"
|
|
92
|
+
fi
|
|
93
|
+
NODE_ENV_B64=$(get_file_b64 "${NODE_ENV_PATH}")
|
|
94
|
+
|
|
95
|
+
# --- network.env (base64-encoded) --------------------------------
|
|
96
|
+
NETWORK_ENV_PATH="${NODE_SRC_DIR}/config/network.env"
|
|
97
|
+
NETWORK_ENV_B64=$(get_file_b64 "${NETWORK_ENV_PATH}")
|
|
98
|
+
|
|
99
|
+
# --- network.env.sha256 -------------------------------------------
|
|
100
|
+
NETWORK_SHA256=$(get_file "${NETWORK_ENV_PATH}.sha256")
|
|
101
|
+
|
|
102
|
+
# --- Gather file list in data dir (for inventory) -----------------
|
|
103
|
+
DATA_DIR_FILES=""
|
|
104
|
+
if [[ -d "${NODE_DATA_DIR}" ]]; then
|
|
105
|
+
# NOTE: `| head -50` would SIGPIPE the find under `set -o pipefail` (rc 141)
|
|
106
|
+
# as soon as the data dir holds more than 50 files, so use sed instead.
|
|
107
|
+
DATA_DIR_FILES=$(find "${NODE_DATA_DIR}" -maxdepth 2 -type f 2>/dev/null | sed -n '1,50p' | while read -r f; do
|
|
108
|
+
SIZE=$(stat -c%s "$f" 2>/dev/null || echo 0)
|
|
109
|
+
echo "$(basename "$f"):${SIZE}"
|
|
110
|
+
done | tr '\n' ',' | sed 's/,$//')
|
|
111
|
+
fi
|
|
112
|
+
|
|
113
|
+
# --- Build the JSON ------------------------------------------------
|
|
114
|
+
# Using jq for proper JSON construction
|
|
115
|
+
TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
|
116
|
+
|
|
117
|
+
jq -n \
|
|
118
|
+
--arg timestamp "$TIMESTAMP" \
|
|
119
|
+
--arg hostname "$HOSTNAME" \
|
|
120
|
+
--arg public_ip "$PUBLIC_IP" \
|
|
121
|
+
--arg local_ip "$LOCAL_IP" \
|
|
122
|
+
--arg os "$OS_INFO" \
|
|
123
|
+
--arg kernel "$KERNEL" \
|
|
124
|
+
--arg uptime "$UPTIME" \
|
|
125
|
+
--arg cpu "$CPU_COUNT" \
|
|
126
|
+
--arg mem "$MEM_TOTAL" \
|
|
127
|
+
--arg disk "$DISK_USAGE" \
|
|
128
|
+
--arg source_commit "$SOURCE_COMMIT" \
|
|
129
|
+
--arg wallet_b64 "$WALLET_B64" \
|
|
130
|
+
--arg node_env_b64 "$NODE_ENV_B64" \
|
|
131
|
+
--arg network_env_b64 "$NETWORK_ENV_B64" \
|
|
132
|
+
--arg network_sha256 "$NETWORK_SHA256" \
|
|
133
|
+
--arg stat_output "$STAT_OUTPUT" \
|
|
134
|
+
--arg storage_info "$STORAGE_INFO" \
|
|
135
|
+
--arg enroll_status "$ENROLL_STATUS" \
|
|
136
|
+
--arg data_dir "$NODE_DATA_DIR" \
|
|
137
|
+
--arg src_dir "$NODE_SRC_DIR" \
|
|
138
|
+
--arg api_port "$API_PORT" \
|
|
139
|
+
--arg consensus_port "$CONSENSUS_PORT" \
|
|
140
|
+
--arg p2p_port "$P2P_PORT" \
|
|
141
|
+
--arg data_files "$DATA_DIR_FILES" \
|
|
142
|
+
'{
|
|
143
|
+
meta: {
|
|
144
|
+
extracted_at: $timestamp,
|
|
145
|
+
script_version: "1.0"
|
|
146
|
+
},
|
|
147
|
+
system: {
|
|
148
|
+
hostname: $hostname,
|
|
149
|
+
public_ip: $public_ip,
|
|
150
|
+
local_ip: $local_ip,
|
|
151
|
+
os: $os,
|
|
152
|
+
kernel: $kernel,
|
|
153
|
+
uptime: $uptime,
|
|
154
|
+
cpu_cores: ($cpu | tonumber),
|
|
155
|
+
memory_total: $mem,
|
|
156
|
+
disk_usage: $disk
|
|
157
|
+
},
|
|
158
|
+
node: {
|
|
159
|
+
source_dir: $src_dir,
|
|
160
|
+
source_commit: $source_commit,
|
|
161
|
+
data_dir: $data_dir,
|
|
162
|
+
ports: {
|
|
163
|
+
api: ($api_port | tonumber),
|
|
164
|
+
consensus: ($consensus_port | tonumber),
|
|
165
|
+
p2p: ($p2p_port | tonumber)
|
|
166
|
+
},
|
|
167
|
+
status_raw: $stat_output,
|
|
168
|
+
storage_raw: $storage_info,
|
|
169
|
+
enroll_status_raw: $enroll_status
|
|
170
|
+
},
|
|
171
|
+
migration_data: {
|
|
172
|
+
wallet_json_b64: $wallet_b64,
|
|
173
|
+
node_env_b64: $node_env_b64,
|
|
174
|
+
network_env_b64: $network_env_b64,
|
|
175
|
+
network_env_sha256: $network_sha256
|
|
176
|
+
},
|
|
177
|
+
data_files: ($data_files | split(",") | map(split(":") | {(.[0]): (.[1] | tonumber)}) | add // {})
|
|
178
|
+
}' > /tmp/octra-node-data.json
|
|
179
|
+
|
|
180
|
+
# Print summary
|
|
181
|
+
echo
|
|
182
|
+
log "Data extracted to /tmp/octra-node-data.json"
|
|
183
|
+
log "Summary:"
|
|
184
|
+
jq '{
|
|
185
|
+
hostname: .system.hostname,
|
|
186
|
+
public_ip: .system.public_ip,
|
|
187
|
+
source_commit: .node.source_commit,
|
|
188
|
+
has_wallet: (.migration_data.wallet_json_b64 | length > 0),
|
|
189
|
+
has_node_env: (.migration_data.node_env_b64 | length > 0),
|
|
190
|
+
has_network_env: (.migration_data.network_env_b64 | length > 0)
|
|
191
|
+
}' /tmp/octra-node-data.json
|
|
192
|
+
|
|
193
|
+
# Also copy to the source dir for easy access
|
|
194
|
+
cp /tmp/octra-node-data.json "${NODE_SRC_DIR}/config/node-data.json" 2>/dev/null || true
|
|
195
|
+
chown "${NODE_USER}:${NODE_USER}" "${NODE_SRC_DIR}/config/node-data.json" 2>/dev/null || true
|
|
196
|
+
|
|
197
|
+
log "Done. Copy it locally with scp if needed."
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# ===================================================================
|
|
3
|
+
# harden-host.sh - mandatory baseline hardening for an Octra node host
|
|
4
|
+
#
|
|
5
|
+
# net.mptcp.enabled = 0
|
|
6
|
+
#
|
|
7
|
+
# MPTCP is not used by the node, the dashboard or the SSH pull, and a host that
|
|
8
|
+
# answers on the MPTCP stack is an avoidable vector of attack on a public VPS.
|
|
9
|
+
# Disabling it is part of this project's baseline, so every program that
|
|
10
|
+
# prepares a machine applies it:
|
|
11
|
+
#
|
|
12
|
+
# * scripts/pre-run.sh (both programs, via disable_mptcp)
|
|
13
|
+
# * deploy/migrate/manage phases (every run, so a resumed run repairs the host)
|
|
14
|
+
# * migrate target, before anything is copied
|
|
15
|
+
#
|
|
16
|
+
# The three operator steps are the ones documented in the runbook:
|
|
17
|
+
#
|
|
18
|
+
# sudo sysctl -w net.mptcp.enabled=0
|
|
19
|
+
# echo "net.mptcp.enabled = 0" | sudo tee /etc/sysctl.d/99-disable-mptcp.conf
|
|
20
|
+
# sudo sysctl --system
|
|
21
|
+
# sysctl net.mptcp.enabled -> net.mptcp.enabled = 0
|
|
22
|
+
#
|
|
23
|
+
# Idempotent. Exits 1 when the kernel offers the knob but it stays enabled.
|
|
24
|
+
#
|
|
25
|
+
# Usage: sudo bash harden-host.sh
|
|
26
|
+
# ===================================================================
|
|
27
|
+
|
|
28
|
+
set -euo pipefail
|
|
29
|
+
source "$(dirname "$0")/config.sh"
|
|
30
|
+
|
|
31
|
+
if [[ $EUID -ne 0 ]]; then
|
|
32
|
+
err "run as root: sudo bash $0"
|
|
33
|
+
exit 1
|
|
34
|
+
fi
|
|
35
|
+
|
|
36
|
+
log "=== hardening $(hostname) (MPTCP off) ==="
|
|
37
|
+
disable_mptcp
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# ===================================================================
|
|
3
|
+
# install-deps.sh — install system build dependencies for Octra lite_node
|
|
4
|
+
#
|
|
5
|
+
# Installs: git, ca-certificates, build-essential, GMP, SQLite3, libev,
|
|
6
|
+
# Rust toolchain, OCaml/opam (via install.sh --source-build).
|
|
7
|
+
#
|
|
8
|
+
# Usage: sudo bash install-deps.sh
|
|
9
|
+
# Idempotent — apt skips packages already installed.
|
|
10
|
+
# ===================================================================
|
|
11
|
+
|
|
12
|
+
set -euo pipefail
|
|
13
|
+
source "$(dirname "$0")/config.sh"
|
|
14
|
+
|
|
15
|
+
if [[ $EUID -ne 0 ]]; then
|
|
16
|
+
err "Run as root: sudo bash $0"
|
|
17
|
+
exit 1
|
|
18
|
+
fi
|
|
19
|
+
|
|
20
|
+
log "Updating package lists…"
|
|
21
|
+
apt-get update -qq
|
|
22
|
+
|
|
23
|
+
log "Installing base packages…"
|
|
24
|
+
apt-get install -y -qq \
|
|
25
|
+
ca-certificates \
|
|
26
|
+
git \
|
|
27
|
+
curl \
|
|
28
|
+
wget \
|
|
29
|
+
build-essential \
|
|
30
|
+
pkg-config \
|
|
31
|
+
libgmp-dev \
|
|
32
|
+
libsqlite3-dev \
|
|
33
|
+
libev-dev \
|
|
34
|
+
cmake \
|
|
35
|
+
jq \
|
|
36
|
+
htop \
|
|
37
|
+
> /dev/null
|
|
38
|
+
|
|
39
|
+
log "Base packages installed"
|
|
40
|
+
|
|
41
|
+
# NOTE: Do NOT install Rust separately. The official install.sh
|
|
42
|
+
# --source-build installs a pinned Rust 1.88.0 toolchain into
|
|
43
|
+
# runtime_data/toolchains/ for the octra user. A separate rustup
|
|
44
|
+
# install in /root/.cargo causes permission conflicts.
|
|
45
|
+
|
|
46
|
+
# --- Create the octra system user --------------------------------
|
|
47
|
+
if ! id "${NODE_USER}" &>/dev/null; then
|
|
48
|
+
log "Creating system user '${NODE_USER}'…"
|
|
49
|
+
useradd -r -m -d "/home/${NODE_USER}" -s /bin/bash "${NODE_USER}"
|
|
50
|
+
log "User '${NODE_USER}' created"
|
|
51
|
+
else
|
|
52
|
+
log "User '${NODE_USER}' already exists"
|
|
53
|
+
fi
|
|
54
|
+
|
|
55
|
+
# --- Create the node source directory ------------------------------
|
|
56
|
+
log "Creating ${NODE_SRC_DIR}…"
|
|
57
|
+
mkdir -p "$(dirname "${NODE_SRC_DIR}")"
|
|
58
|
+
chown -R "${NODE_USER}:${NODE_USER}" "$(dirname "${NODE_SRC_DIR}")"
|
|
59
|
+
|
|
60
|
+
# --- Clone the lite_node repo (if not already present) ------------
|
|
61
|
+
if [[ ! -d "${NODE_SRC_DIR}/.git" ]]; then
|
|
62
|
+
log "Cloning lite_node repository…"
|
|
63
|
+
git clone --branch "${NODE_BRANCH}" --single-branch "${NODE_REPO}" "${NODE_SRC_DIR}"
|
|
64
|
+
chown -R "${NODE_USER}:${NODE_USER}" "${NODE_SRC_DIR}"
|
|
65
|
+
log "Repository cloned"
|
|
66
|
+
else
|
|
67
|
+
log "Repository already present at ${NODE_SRC_DIR}"
|
|
68
|
+
fi
|
|
69
|
+
|
|
70
|
+
# --- Run the official install.sh --source-build -------------------
|
|
71
|
+
# install.sh calls `opam switch link` itself, and opam 2.3 wipes the switch when
|
|
72
|
+
# <repo>/_opam already exists (see config.sh) - so clear the link first.
|
|
73
|
+
unlink_ocaml_switch_link "install.sh runs opam switch link next"
|
|
74
|
+
# This installs OCaml, Dune, builds all dependencies from source
|
|
75
|
+
log "Running official install.sh --source-build (this compiles OCaml + deps)…"
|
|
76
|
+
log "This may take 15–30 minutes on a 4-core VPS…"
|
|
77
|
+
|
|
78
|
+
cd "${NODE_SRC_DIR}"
|
|
79
|
+
export OCTRA_OPERATOR_USER="${NODE_USER}"
|
|
80
|
+
export OCTRA_DATA_ROOT="${NODE_DATA_ROOT}"
|
|
81
|
+
|
|
82
|
+
sh controls/install.sh --source-build
|
|
83
|
+
|
|
84
|
+
# --- Verify the build ---------------------------------------------
|
|
85
|
+
log "Running check.sh to verify the build…"
|
|
86
|
+
if su - "${NODE_USER}" -c "cd ${NODE_SRC_DIR} && sh controls/check.sh"; then
|
|
87
|
+
log "Build verification passed"
|
|
88
|
+
else
|
|
89
|
+
warn "check.sh reported issues — review the output above"
|
|
90
|
+
fi
|
|
91
|
+
|
|
92
|
+
echo
|
|
93
|
+
log "Dependencies installed. Next: run node-setup.sh to configure the node."
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# ===================================================================
|
|
3
|
+
# node-enroll.sh — join the Octra network as a validator
|
|
4
|
+
#
|
|
5
|
+
# Steps:
|
|
6
|
+
# 1. Join the active set (stake OCTRA tokens)
|
|
7
|
+
# 2. Check enrollment status
|
|
8
|
+
# 3. Show node status
|
|
9
|
+
#
|
|
10
|
+
# Usage:
|
|
11
|
+
# sudo bash node-enroll.sh # default stake (1000000)
|
|
12
|
+
# sudo bash node-enroll.sh 500000 # custom stake amount
|
|
13
|
+
# sudo bash node-enroll.sh exit # leave active set
|
|
14
|
+
# sudo bash node-enroll.sh withdraw # withdraw stake
|
|
15
|
+
#
|
|
16
|
+
# IMPORTANT: The node must be fully synced before enrolling.
|
|
17
|
+
# ===================================================================
|
|
18
|
+
|
|
19
|
+
set -euo pipefail
|
|
20
|
+
source "$(dirname "$0")/config.sh"
|
|
21
|
+
|
|
22
|
+
if [[ $EUID -ne 0 ]]; then
|
|
23
|
+
err "Run as root: sudo bash $0"
|
|
24
|
+
exit 1
|
|
25
|
+
fi
|
|
26
|
+
|
|
27
|
+
ACTION="${1:-join}"
|
|
28
|
+
STAKE_AMOUNT="${2:-1000000}"
|
|
29
|
+
|
|
30
|
+
case "${ACTION}" in
|
|
31
|
+
join)
|
|
32
|
+
log "Joining the network with stake ${STAKE_AMOUNT}…"
|
|
33
|
+
su - "${NODE_USER}" -c "cd ${NODE_SRC_DIR} && sh controls/enroll.sh join --amount ${STAKE_AMOUNT}"
|
|
34
|
+
log "Checking enrollment status…"
|
|
35
|
+
su - "${NODE_USER}" -c "cd ${NODE_SRC_DIR} && sh controls/enroll.sh status"
|
|
36
|
+
echo
|
|
37
|
+
log "Node status:"
|
|
38
|
+
su - "${NODE_USER}" -c "cd ${NODE_SRC_DIR} && sh controls/stat.sh"
|
|
39
|
+
;;
|
|
40
|
+
|
|
41
|
+
status)
|
|
42
|
+
log "Enrollment status:"
|
|
43
|
+
su - "${NODE_USER}" -c "cd ${NODE_SRC_DIR} && sh controls/enroll.sh status"
|
|
44
|
+
;;
|
|
45
|
+
|
|
46
|
+
exit)
|
|
47
|
+
warn "Leaving the active validator set…"
|
|
48
|
+
su - "${NODE_USER}" -c "cd ${NODE_SRC_DIR} && sh controls/enroll.sh exit"
|
|
49
|
+
su - "${NODE_USER}" -c "cd ${NODE_SRC_DIR} && sh controls/enroll.sh status"
|
|
50
|
+
log "Exited active set."
|
|
51
|
+
;;
|
|
52
|
+
|
|
53
|
+
withdraw)
|
|
54
|
+
warn "Withdrawing stake…"
|
|
55
|
+
su - "${NODE_USER}" -c "cd ${NODE_SRC_DIR} && sh controls/enroll.sh withdraw"
|
|
56
|
+
su - "${NODE_USER}" -c "cd ${NODE_SRC_DIR} && sh controls/enroll.sh status"
|
|
57
|
+
log "Stake withdrawn."
|
|
58
|
+
;;
|
|
59
|
+
|
|
60
|
+
*)
|
|
61
|
+
err "Unknown action: ${ACTION}"
|
|
62
|
+
echo "Usage: sudo bash node-enroll.sh [join|status|exit|withdraw] [amount]"
|
|
63
|
+
exit 1
|
|
64
|
+
;;
|
|
65
|
+
esac
|