ovtools 0.0.0-stage → 1.0.0

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.
Files changed (198) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +121 -2
  3. package/assets/common/bond-inspect.sh +368 -0
  4. package/assets/common/config.sh +263 -0
  5. package/assets/common/extract-data.sh +197 -0
  6. package/assets/common/harden-host.sh +37 -0
  7. package/assets/common/install-deps.sh +93 -0
  8. package/assets/common/node-enroll.sh +65 -0
  9. package/assets/common/node-setup.sh +150 -0
  10. package/assets/common/node-start.sh +90 -0
  11. package/assets/common/node-stop.sh +18 -0
  12. package/assets/common/node-upgrade.sh +45 -0
  13. package/assets/common/pre-run.sh +497 -0
  14. package/assets/common/promote-validator.sh +104 -0
  15. package/assets/deploy/10-prepare-host.sh +98 -0
  16. package/assets/deploy/20-install-toolchain.sh +93 -0
  17. package/assets/deploy/30-setup-node.sh +82 -0
  18. package/assets/deploy/40-start-node.sh +75 -0
  19. package/assets/deploy/50-verify.sh +259 -0
  20. package/assets/deploy/60-enroll.sh +304 -0
  21. package/assets/deploy/70-promote.sh +152 -0
  22. package/assets/deploy/lib.sh +398 -0
  23. package/assets/manage/10-bond-increase.sh +149 -0
  24. package/assets/manage/10-diagnose-node.sh +169 -0
  25. package/assets/manage/20-exit-validator.sh +259 -0
  26. package/assets/manage/25-recover-node.sh +291 -0
  27. package/assets/manage/30-status.sh +64 -0
  28. package/assets/manage/40-exit-withdraw.sh +133 -0
  29. package/assets/manage/bond_inc.sh +318 -0
  30. package/assets/manage/dashboard_monitor/app.js +1544 -0
  31. package/assets/manage/dashboard_monitor/assets/v2.2/css/base.css +113 -0
  32. package/assets/manage/dashboard_monitor/assets/v2.2/css/components/content.css +133 -0
  33. package/assets/manage/dashboard_monitor/assets/v2.2/css/components/controls.css +229 -0
  34. package/assets/manage/dashboard_monitor/assets/v2.2/css/components/data.css +374 -0
  35. package/assets/manage/dashboard_monitor/assets/v2.2/css/components/icons.css +35 -0
  36. package/assets/manage/dashboard_monitor/assets/v2.2/css/components/motion.css +57 -0
  37. package/assets/manage/dashboard_monitor/assets/v2.2/css/components/shell.css +51 -0
  38. package/assets/manage/dashboard_monitor/assets/v2.2/css/components/sidebar.css +242 -0
  39. package/assets/manage/dashboard_monitor/assets/v2.2/css/components/topbar.css +138 -0
  40. package/assets/manage/dashboard_monitor/assets/v2.2/css/fonts.css +30 -0
  41. package/assets/manage/dashboard_monitor/assets/v2.2/css/synteq-ui-v2.css +25 -0
  42. package/assets/manage/dashboard_monitor/assets/v2.2/css/theme-dark.css +38 -0
  43. package/assets/manage/dashboard_monitor/assets/v2.2/css/theme-light.css +36 -0
  44. package/assets/manage/dashboard_monitor/assets/v2.2/css/tokens.css +61 -0
  45. package/assets/manage/dashboard_monitor/assets/v2.2/fonts/GoogleSansCode-Medium.ttf +0 -0
  46. package/assets/manage/dashboard_monitor/assets/v2.2/fonts/GoogleSansCode-Regular.ttf +0 -0
  47. package/assets/manage/dashboard_monitor/assets/v2.2/fonts/GoogleSansCode-SemiBold.ttf +0 -0
  48. package/assets/manage/dashboard_monitor/assets/v2.2/js/synteq-ui-v2.js +869 -0
  49. package/assets/manage/dashboard_monitor/deploy-dashboard.sh +230 -0
  50. package/assets/manage/dashboard_monitor/favicon.svg +13 -0
  51. package/assets/manage/dashboard_monitor/index.html +1197 -0
  52. package/assets/manage/dashboard_monitor/nginx-octra.conf +76 -0
  53. package/assets/manage/dashboard_monitor/octra-dashboard.service +29 -0
  54. package/assets/manage/dashboard_monitor/octra-node-prune.cron +12 -0
  55. package/assets/manage/dashboard_monitor/octra-node-prune.service +16 -0
  56. package/assets/manage/dashboard_monitor/octra-node-prune.timer +12 -0
  57. package/assets/manage/dashboard_monitor/prune-node-junk.sh +329 -0
  58. package/assets/manage/dashboard_monitor/server.py +1887 -0
  59. package/assets/manage/dashboard_monitor/ssl-certbot.sh +90 -0
  60. package/assets/manage/dashboard_monitor/styles.css +327 -0
  61. package/assets/manage/lib.sh +347 -0
  62. package/assets/manifest.json +143 -0
  63. package/assets/migrate/00-backup-identity.sh +67 -0
  64. package/assets/migrate/01-prepare-target.sh +145 -0
  65. package/assets/migrate/02-authorize-pull.sh +43 -0
  66. package/assets/migrate/03-pull-state.sh +102 -0
  67. package/assets/migrate/04-stop-source.sh +85 -0
  68. package/assets/migrate/05-finalize-target.sh +140 -0
  69. package/assets/migrate/06-start-target.sh +57 -0
  70. package/assets/migrate/07-verify.sh +237 -0
  71. package/assets/migrate/08-rollback.sh +54 -0
  72. package/assets/migrate/lib.sh +149 -0
  73. package/assets/upgrade/10-preflight.sh +120 -0
  74. package/assets/upgrade/20-upgrade.sh +142 -0
  75. package/assets/upgrade/30-manual-upgrade.sh +129 -0
  76. package/assets/upgrade/40-storage-prune.sh +65 -0
  77. package/assets/upgrade/50-status.sh +58 -0
  78. package/assets/upgrade/lib.sh +232 -0
  79. package/bin/ovtools.js +32 -0
  80. package/dist/api/checks.d.ts +6 -0
  81. package/dist/api/checks.d.ts.map +1 -0
  82. package/dist/api/checks.js +173 -0
  83. package/dist/api/checks.js.map +1 -0
  84. package/dist/api/hostkeys.d.ts +10 -0
  85. package/dist/api/hostkeys.d.ts.map +1 -0
  86. package/dist/api/hostkeys.js +58 -0
  87. package/dist/api/hostkeys.js.map +1 -0
  88. package/dist/api/jobs.d.ts +33 -0
  89. package/dist/api/jobs.d.ts.map +1 -0
  90. package/dist/api/jobs.js +483 -0
  91. package/dist/api/jobs.js.map +1 -0
  92. package/dist/api/nodes.d.ts +16 -0
  93. package/dist/api/nodes.d.ts.map +1 -0
  94. package/dist/api/nodes.js +126 -0
  95. package/dist/api/nodes.js.map +1 -0
  96. package/dist/api/server.d.ts +3 -0
  97. package/dist/api/server.d.ts.map +1 -0
  98. package/dist/api/server.js +443 -0
  99. package/dist/api/server.js.map +1 -0
  100. package/dist/cli.d.ts +3 -0
  101. package/dist/cli.d.ts.map +1 -0
  102. package/dist/cli.js +301 -0
  103. package/dist/cli.js.map +1 -0
  104. package/dist/constants.d.ts +76 -0
  105. package/dist/constants.d.ts.map +1 -0
  106. package/dist/constants.js +150 -0
  107. package/dist/constants.js.map +1 -0
  108. package/dist/index.d.ts +18 -0
  109. package/dist/index.d.ts.map +1 -0
  110. package/dist/index.js +60 -0
  111. package/dist/index.js.map +1 -0
  112. package/dist/orchestrator/base.d.ts +52 -0
  113. package/dist/orchestrator/base.d.ts.map +1 -0
  114. package/dist/orchestrator/base.js +219 -0
  115. package/dist/orchestrator/base.js.map +1 -0
  116. package/dist/orchestrator/deploy.d.ts +33 -0
  117. package/dist/orchestrator/deploy.d.ts.map +1 -0
  118. package/dist/orchestrator/deploy.js +313 -0
  119. package/dist/orchestrator/deploy.js.map +1 -0
  120. package/dist/orchestrator/manage.d.ts +28 -0
  121. package/dist/orchestrator/manage.d.ts.map +1 -0
  122. package/dist/orchestrator/manage.js +267 -0
  123. package/dist/orchestrator/manage.js.map +1 -0
  124. package/dist/orchestrator/migrate.d.ts +31 -0
  125. package/dist/orchestrator/migrate.d.ts.map +1 -0
  126. package/dist/orchestrator/migrate.js +442 -0
  127. package/dist/orchestrator/migrate.js.map +1 -0
  128. package/dist/ssh/client.d.ts +39 -0
  129. package/dist/ssh/client.d.ts.map +1 -0
  130. package/dist/ssh/client.js +418 -0
  131. package/dist/ssh/client.js.map +1 -0
  132. package/dist/test/core.test.d.ts +2 -0
  133. package/dist/test/core.test.d.ts.map +1 -0
  134. package/dist/test/core.test.js +188 -0
  135. package/dist/test/core.test.js.map +1 -0
  136. package/dist/types.d.ts +267 -0
  137. package/dist/types.d.ts.map +1 -0
  138. package/dist/types.js +3 -0
  139. package/dist/types.js.map +1 -0
  140. package/dist/utils/assets.d.ts +28 -0
  141. package/dist/utils/assets.d.ts.map +1 -0
  142. package/dist/utils/assets.js +583 -0
  143. package/dist/utils/assets.js.map +1 -0
  144. package/dist/utils/browser.d.ts +2 -0
  145. package/dist/utils/browser.d.ts.map +1 -0
  146. package/dist/utils/browser.js +23 -0
  147. package/dist/utils/browser.js.map +1 -0
  148. package/dist/utils/dashboard.d.ts +16 -0
  149. package/dist/utils/dashboard.d.ts.map +1 -0
  150. package/dist/utils/dashboard.js +177 -0
  151. package/dist/utils/dashboard.js.map +1 -0
  152. package/dist/utils/helpers.d.ts +29 -0
  153. package/dist/utils/helpers.d.ts.map +1 -0
  154. package/dist/utils/helpers.js +204 -0
  155. package/dist/utils/helpers.js.map +1 -0
  156. package/dist/utils/scripts.d.ts +60 -0
  157. package/dist/utils/scripts.d.ts.map +1 -0
  158. package/dist/utils/scripts.js +174 -0
  159. package/dist/utils/scripts.js.map +1 -0
  160. package/dist/utils/state.d.ts +12 -0
  161. package/dist/utils/state.d.ts.map +1 -0
  162. package/dist/utils/state.js +44 -0
  163. package/dist/utils/state.js.map +1 -0
  164. package/dist/utils/tar.d.ts +11 -0
  165. package/dist/utils/tar.d.ts.map +1 -0
  166. package/dist/utils/tar.js +93 -0
  167. package/dist/utils/tar.js.map +1 -0
  168. package/dist/utils/update.d.ts +9 -0
  169. package/dist/utils/update.d.ts.map +1 -0
  170. package/dist/utils/update.js +134 -0
  171. package/dist/utils/update.js.map +1 -0
  172. package/dist/utils/websocket.d.ts +10 -0
  173. package/dist/utils/websocket.d.ts.map +1 -0
  174. package/dist/utils/websocket.js +203 -0
  175. package/dist/utils/websocket.js.map +1 -0
  176. package/package.json +55 -4
  177. package/public/app.js +2712 -0
  178. package/public/assets/v2.2/css/base.css +113 -0
  179. package/public/assets/v2.2/css/components/content.css +133 -0
  180. package/public/assets/v2.2/css/components/controls.css +229 -0
  181. package/public/assets/v2.2/css/components/data.css +373 -0
  182. package/public/assets/v2.2/css/components/icons.css +35 -0
  183. package/public/assets/v2.2/css/components/motion.css +57 -0
  184. package/public/assets/v2.2/css/components/shell.css +51 -0
  185. package/public/assets/v2.2/css/components/sidebar.css +242 -0
  186. package/public/assets/v2.2/css/components/topbar.css +138 -0
  187. package/public/assets/v2.2/css/fonts.css +30 -0
  188. package/public/assets/v2.2/css/synteq-ui-v2.css +25 -0
  189. package/public/assets/v2.2/css/theme-dark.css +38 -0
  190. package/public/assets/v2.2/css/theme-light.css +36 -0
  191. package/public/assets/v2.2/css/tokens.css +61 -0
  192. package/public/assets/v2.2/fonts/GoogleSansCode-Medium.ttf +0 -0
  193. package/public/assets/v2.2/fonts/GoogleSansCode-Regular.ttf +0 -0
  194. package/public/assets/v2.2/fonts/GoogleSansCode-SemiBold.ttf +0 -0
  195. package/public/assets/v2.2/js/synteq-ui-v2.js +869 -0
  196. package/public/favicon.svg +7 -0
  197. package/public/index.html +1080 -0
  198. package/public/styles.css +552 -0
@@ -0,0 +1,230 @@
1
+ #!/usr/bin/env bash
2
+ # ===================================================================
3
+ # deploy-dashboard.sh — install / refresh the Octra live monitor
4
+ #
5
+ # Idempotent. Run from the VPS after pushing dashboard files:
6
+ # bash /root/dashboard/deploy-dashboard.sh
7
+ #
8
+ # Steps
9
+ # 1. install nginx + python3 when missing
10
+ # 2. sync files into /opt/octra/dashboard
11
+ # 3. install + restart the systemd backend (port 9090)
12
+ # 4. install the nginx site and reload
13
+ # 5. verify /api/ping locally
14
+ # ===================================================================
15
+ set -euo pipefail
16
+
17
+ DASH_SRC="${DASH_SRC:-/root/dashboard}"
18
+ DASH_DIR="/opt/octra/dashboard"
19
+ SERVICE_NAME="octra-dashboard"
20
+ SERVICE_FILE="/etc/systemd/system/${SERVICE_NAME}.service"
21
+ NGINX_SITE="/etc/nginx/sites-available/${SERVICE_NAME}"
22
+ NGINX_LINK="/etc/nginx/sites-enabled/${SERVICE_NAME}"
23
+
24
+ GREEN='\033[0;32m'; YELLOW='\033[1;33m'; RED='\033[0;31m'; NC='\033[0m'
25
+ log() { echo -e "${GREEN}[dashboard]${NC} $*"; }
26
+ warn() { echo -e "${YELLOW}[warn]${NC} $*"; }
27
+ die() { echo -e "${RED}[err]${NC} $*" >&2; exit 1; }
28
+
29
+ [[ $EUID -eq 0 ]] || die "run as root: sudo bash $0"
30
+
31
+ # ── 1. Prerequisites ──────────────────────────────────────────────
32
+ log "Checking prerequisites…"
33
+ if ! command -v nginx >/dev/null 2>&1; then
34
+ log "Installing nginx…"
35
+ apt-get update -qq && apt-get install -y -qq nginx >/dev/null
36
+ fi
37
+ if ! command -v python3 >/dev/null 2>&1; then
38
+ log "Installing python3…"
39
+ apt-get update -qq && apt-get install -y -qq python3 >/dev/null
40
+ fi
41
+ log "nginx: $(nginx -v 2>&1 | cut -d/ -f2) · python: $(python3 --version 2>&1 | cut -d' ' -f2)"
42
+
43
+ # ── 2. Sync files ─────────────────────────────────────────────────
44
+ [[ -d "$DASH_SRC" ]] || die "source folder not found: $DASH_SRC"
45
+ log "Syncing $DASH_SRC → $DASH_DIR"
46
+ mkdir -p "$DASH_DIR"
47
+ if command -v rsync >/dev/null 2>&1; then
48
+ rsync -a --delete --exclude 'dev/' --exclude '__pycache__/' "$DASH_SRC"/ "$DASH_DIR"/
49
+ else
50
+ find "$DASH_DIR" -mindepth 1 -maxdepth 1 -exec rm -rf {} +
51
+ cp -r "$DASH_SRC"/. "$DASH_DIR"/
52
+ rm -rf "$DASH_DIR/dev" "$DASH_DIR/__pycache__"
53
+ fi
54
+
55
+ for f in index.html app.js styles.css server.py assets/v2.2/css/synteq-ui-v2.css assets/v2.2/js/synteq-ui-v2.js \
56
+ prune-node-junk.sh octra-node-prune.cron octra-node-prune.service octra-node-prune.timer; do
57
+ [[ -f "$DASH_DIR/$f" ]] || die "missing file: $DASH_DIR/$f"
58
+ done
59
+ log "Files verified"
60
+
61
+ chown -R root:root "$DASH_DIR"
62
+ find "$DASH_DIR" -type d -exec chmod 755 {} +
63
+ find "$DASH_DIR" -type f -exec chmod 644 {} +
64
+ chmod 755 "$DASH_DIR/server.py" 2>/dev/null || true
65
+
66
+ # ── 3. Backend service ────────────────────────────────────────────
67
+ log "Installing systemd unit ${SERVICE_NAME}…"
68
+ install -m 644 "$DASH_DIR/octra-dashboard.service" "$SERVICE_FILE"
69
+ systemctl daemon-reload
70
+ systemctl enable "$SERVICE_NAME" >/dev/null 2>&1 || true
71
+ systemctl restart "$SERVICE_NAME"
72
+
73
+ for _ in $(seq 1 15); do
74
+ if curl -fsS -m 2 http://127.0.0.1:9090/api/ping >/dev/null 2>&1; then break; fi
75
+ sleep 1
76
+ done
77
+
78
+ if ! curl -fsS -m 3 http://127.0.0.1:9090/api/ping >/dev/null 2>&1; then
79
+ warn "backend did not answer /api/ping"
80
+ journalctl -u "$SERVICE_NAME" --no-pager -n 25 || true
81
+ die "backend failed to start"
82
+ fi
83
+ log "Backend healthy on 127.0.0.1:9090"
84
+
85
+ # ── 3b. Wallet reward baseline ────────────────────────────────────
86
+ # Captured once (at setup) and kept across redeploys: it is the reference
87
+ # point for the wallet panel's reward cross-check. The log index itself is
88
+ # rebuilt incrementally by the backend, so this only ever runs once.
89
+ WALLET_STATE_DIR="/var/lib/octra/dashboard"
90
+ install -d -m 755 "$WALLET_STATE_DIR"
91
+ if [[ -f "$WALLET_STATE_DIR/wallet_state.json" ]]; then
92
+ log "Wallet baseline already captured — keeping $WALLET_STATE_DIR/wallet_state.json"
93
+ else
94
+ log "Capturing wallet reward baseline..."
95
+ if ! python3 "$DASH_DIR/server.py" --init-wallet; then
96
+ warn "wallet baseline not captured (node RPC offline?) — the backend retries on first poll"
97
+ fi
98
+ fi
99
+
100
+ # ── 3c. Daily prune job (node logs & junk) ────────────────────────
101
+ # The monitor is the natural owner of this: it already runs on the node, and a
102
+ # growing operator log is what eventually starves the box (a 211 MB log with
103
+ # the node leaving it open). The program itself is policy-free enough to be
104
+ # safe: it only rotates/trims logs and removes junk, never chain data.
105
+ PRUNE_BIN="/usr/local/sbin/octra-node-prune"
106
+ PRUNE_CRON="/etc/cron.d/octra-node-prune"
107
+ PRUNE_LOG="/var/log/octra-node-prune.log"
108
+ PRUNE_UNIT="octra-node-prune.service"
109
+ PRUNE_TIMER="octra-node-prune.timer"
110
+
111
+ install -m 755 "$DASH_DIR/prune-node-junk.sh" "$PRUNE_BIN"
112
+ touch "$PRUNE_LOG" && chmod 644 "$PRUNE_LOG"
113
+ log "Prune program installed: $PRUNE_BIN"
114
+
115
+ # cron is the requested scheduler; a minimal Debian image may lack the
116
+ # package, so install it when apt is available and fall back to a systemd
117
+ # timer otherwise (same cadence, no extra package).
118
+ have_cron=0
119
+ if command -v cron >/dev/null 2>&1 || command -v crond >/dev/null 2>&1; then
120
+ have_cron=1
121
+ elif command -v apt-get >/dev/null 2>&1; then
122
+ log "Installing cron (scheduler for the daily prune)..."
123
+ if DEBIAN_FRONTEND=noninteractive apt-get install -y -qq cron >/dev/null 2>&1; then
124
+ have_cron=1
125
+ fi
126
+ fi
127
+
128
+ if [[ "$have_cron" -eq 1 ]]; then
129
+ cron_changed=1
130
+ [[ -f "$PRUNE_CRON" ]] && cmp -s "$DASH_DIR/octra-node-prune.cron" "$PRUNE_CRON" && cron_changed=0
131
+ install -m 644 "$DASH_DIR/octra-node-prune.cron" "$PRUNE_CRON"
132
+ # cron parses this as bytes: a stray CR (Windows checkout) makes it reject
133
+ # the whole file with "bad minute", silently skipping every run.
134
+ sed -i 's/\r$//' "$PRUNE_CRON"
135
+ chown root:root "$PRUNE_CRON"
136
+ chmod 644 "$PRUNE_CRON"
137
+ if command -v systemctl >/dev/null 2>&1; then
138
+ systemctl disable --now "$PRUNE_TIMER" >/dev/null 2>&1 || true
139
+ systemctl enable --now cron >/dev/null 2>&1 || systemctl enable --now crond >/dev/null 2>&1 || true
140
+ fi
141
+ rm -f "/etc/systemd/system/$PRUNE_UNIT" "/etc/systemd/system/$PRUNE_TIMER"
142
+ log "Daily prune scheduled via cron: $PRUNE_CRON (03:40)"
143
+ # cron re-reads /etc/cron.d once a minute and logs "bad minute" when a file
144
+ # is malformed (CRLF, non-ASCII, bad fields) - it then ignores the file
145
+ # silently. Prove it was accepted instead of trusting the exit code.
146
+ if [[ "$cron_changed" -eq 1 ]] && command -v journalctl >/dev/null 2>&1; then
147
+ log "Waiting for cron to re-read the schedule (~60s)..."
148
+ sleep 62
149
+ if journalctl -u cron --since '-2 min' --no-pager 2>/dev/null | grep -qi 'bad minute.*octra-node-prune'; then
150
+ warn "cron REJECTED $PRUNE_CRON ('bad minute') - the daily prune will not run"
151
+ else
152
+ log "cron accepted $PRUNE_CRON"
153
+ fi
154
+ fi
155
+ else
156
+ install -m 644 "$DASH_DIR/$PRUNE_UNIT" "/etc/systemd/system/$PRUNE_UNIT"
157
+ install -m 644 "$DASH_DIR/$PRUNE_TIMER" "/etc/systemd/system/$PRUNE_TIMER"
158
+ sed -i 's/\r$//' "/etc/systemd/system/$PRUNE_UNIT" "/etc/systemd/system/$PRUNE_TIMER"
159
+ systemctl daemon-reload
160
+ systemctl enable --now "$PRUNE_TIMER" >/dev/null 2>&1 \
161
+ || warn "could not enable $PRUNE_TIMER (run: systemctl enable --now $PRUNE_TIMER)"
162
+ rm -f "$PRUNE_CRON"
163
+ log "Daily prune scheduled via systemd timer: $PRUNE_TIMER (03:40)"
164
+ fi
165
+
166
+ # Prove the program runs on this box before the first scheduled night:
167
+ # a dry run only reads and reports.
168
+ if "$PRUNE_BIN" --dry-run >/tmp/octra-prune-dryrun.txt 2>&1; then
169
+ log "Prune dry-run OK ($(grep -c . /tmp/octra-prune-dryrun.txt) line(s), see $PRUNE_LOG)"
170
+ else
171
+ warn "prune dry-run failed - check 'octra-node-prune --status' (nothing was deleted)"
172
+ fi
173
+ rm -f /tmp/octra-prune-dryrun.txt
174
+ if [[ -x "$PRUNE_BIN" ]]; then
175
+ "$PRUNE_BIN" --status 2>/dev/null | sed -n '1,6p' | sed 's/^/[prune] /'
176
+ fi
177
+
178
+ # ── 4. Nginx ──────────────────────────────────────────────────────
179
+ log "Applying nginx site..."
180
+ rm -f /etc/nginx/sites-enabled/default 2>/dev/null || true
181
+ rm -f /etc/nginx/sites-enabled/octra-dashboard-old 2>/dev/null || true
182
+
183
+ # The checked-in site file carries one default server_name, but every VPS is
184
+ # published under its own subdomain. Remember the host that is already live
185
+ # here, install the fresh file, then point it back at that host and strip CRLF
186
+ # (a Windows checkout can leave it behind, which breaks the awk match below).
187
+ #
188
+ # NOTE: on a FRESH host $NGINX_SITE does not exist yet, so awk exits 2. With
189
+ # `set -euo pipefail` that aborted the whole deploy before the site was even
190
+ # installed — `|| true` keeps the first-install path working.
191
+ existing_name=$(awk '/^[[:space:]]*server_name/ {gsub(/;/,"");print $2; exit}' "$NGINX_SITE" 2>/dev/null | tr -d '\r' || true)
192
+ source_name=$(awk '/^[[:space:]]*server_name/ {gsub(/;/,"");print $2; exit}' "$DASH_DIR/nginx-octra.conf" 2>/dev/null | tr -d '\r' || true)
193
+
194
+ install -m 644 "$DASH_DIR/nginx-octra.conf" "$NGINX_SITE"
195
+ sed -i 's/\r$//' "$NGINX_SITE"
196
+ ln -sfn "$NGINX_SITE" "$NGINX_LINK"
197
+
198
+ if [[ -n "$existing_name" && -n "$source_name" && "$existing_name" != "$source_name" ]]; then
199
+ log "Keeping this host's server_name: $existing_name"
200
+ sed -i "s|${source_name}|${existing_name}|g" "$NGINX_SITE"
201
+ sed -i "s|^# Domain : .*|# Domain : ${existing_name} (edit server_name to your domain)|" "$NGINX_SITE"
202
+ fi
203
+
204
+ if ! nginx -t 2>&1; then
205
+ die "nginx config test failed"
206
+ fi
207
+ systemctl reload nginx
208
+ log "nginx reloaded"
209
+
210
+ # ── 5. Report ──────────────────────────────────────────────────────
211
+ # The live host name is what nginx actually serves, not a placeholder: the report
212
+ # used to print `https://<server_name>/` as if the deploy had failed to fill it in
213
+ # (2026-11-04 operator report).
214
+ live_name=$(awk '/^[[:space:]]*server_name/ {gsub(/;/,"");print $2; exit}' "$NGINX_SITE" 2>/dev/null | tr -d '\r' || true)
215
+ if [[ -z "$live_name" ]]; then
216
+ live_name="$(hostname 2>/dev/null || echo localhost)"
217
+ fi
218
+ echo
219
+ log "Live monitor deployed"
220
+ echo " UI : https://${live_name}/"
221
+ echo " API : https://${live_name}/api/status"
222
+ echo " Backend : systemctl status ${SERVICE_NAME}"
223
+ echo " Logs : journalctl -u ${SERVICE_NAME} -f"
224
+ echo " Nginx log : tail -f /var/log/nginx/error.log"
225
+ if [[ -f "$PRUNE_CRON" ]]; then
226
+ echo " Prune : daily 03:40 via cron ($PRUNE_CRON)"
227
+ elif [[ -f "/etc/systemd/system/$PRUNE_TIMER" ]]; then
228
+ echo " Prune : daily 03:40 via systemd timer ($PRUNE_TIMER)"
229
+ fi
230
+ echo " Prune log : ${PRUNE_LOG} · status: octra-node-prune --status · dry-run: --dry-run"
@@ -0,0 +1,13 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 50" fill="none" role="img" aria-label="Octra Node">
2
+ <style>
3
+ /* Octra mark — ring, same geometry as docs.octra.org/favicon.svg.
4
+ currentColor keeps the glyph reusable when inlined; setting it here
5
+ makes the standalone favicon render brand green and follow the
6
+ browser colour scheme. */
7
+ svg { color: #00e599; }
8
+ @media (prefers-color-scheme: light) { svg { color: #059669; } }
9
+ circle { stroke: currentColor; }
10
+ </style>
11
+ <circle cx="25" cy="25" r="21" stroke-width="8"/>
12
+ </svg>
13
+