diff --git a/ops/README.md b/ops/README.md index 7c5e6c4..09fedb9 100644 --- a/ops/README.md +++ b/ops/README.md @@ -125,7 +125,7 @@ If you'd rather understand each piece, see [MANUAL.md](MANUAL.md) — same steps |---|---| | `push.sh` | **Routine deploy from the dev box** — build, ship web bundle and/or daemon sources, restart, verify (see Production layout) | | `nginx-digibyte-x.conf` | Mirror of the live nginx vhost for digibyte.x (`@NOWNODES_API_KEY@` placeholder; render with `sed` as the file header shows) | -| `blockbook-upstream.sh` | `atomic` or `nownodes` — repoint the live `/blockbook/` proxy, test, reload, verify | +| `blockbook-upstream.sh` / `.ps1` | `atomic` or `nownodes` — repoint the live `/blockbook/` proxy, test, reload, verify (`.ps1` from PowerShell, where `bash` is the WSL launcher; both pipe `blockbook-upstream.remote.sh` over ssh) | | `setup.sh` | RPC-VPS bootstrap (Core + Caddy in front of it) — optional Core backend, not deployed | | `deploy-wallet.sh` | Wallet-site VPS bootstrap (web bundle at `/` + P2P daemon reverse-proxy) | | `deploy-wallet-web.sh` | Wallet-subpath bootstrap — plain production build (relative `./` base), ships bundle to `/web/`, renders Caddy import snippet | diff --git a/ops/blockbook-upstream.ps1 b/ops/blockbook-upstream.ps1 new file mode 100644 index 0000000..d9559e2 --- /dev/null +++ b/ops/blockbook-upstream.ps1 @@ -0,0 +1,18 @@ +# Point the live digibyte.x vhost's /blockbook/ proxy at a Blockbook +# upstream (PowerShell entry point; same job as blockbook-upstream.sh). +# +# ops/blockbook-upstream.ps1 atomic # Atomic Wallet's public Blockbook (no key) +# ops/blockbook-upstream.ps1 nownodes # NOWNodes, key from /etc/dgb-core/nownodes.env on the VPS +# +# Pipes blockbook-upstream.remote.sh through `ssh silentmode`; the +# previous vhost is kept under /etc/nginx/sites-enabled-stale-baks/. +param([Parameter(Mandatory = $true)][ValidateSet('atomic', 'nownodes')][string]$Target) +$ErrorActionPreference = 'Stop' +switch ($Target) { + 'atomic' { $upstream = 'digibyte.atomicwallet.io'; $keyhdr = 0 } + 'nownodes' { $upstream = 'dgbbook.nownodes.io'; $keyhdr = 1 } +} +$remote = Join-Path $PSScriptRoot 'blockbook-upstream.remote.sh' +# -Raw keeps the script one string; ssh's stdin gets LF line endings. +((Get-Content -Raw $remote) -replace "`r`n", "`n") | ssh silentmode "HOST=$upstream KEYHDR=$keyhdr bash -s" +if ($LASTEXITCODE -ne 0) { throw "remote script failed (exit $LASTEXITCODE)" } diff --git a/ops/blockbook-upstream.remote.sh b/ops/blockbook-upstream.remote.sh new file mode 100644 index 0000000..49aa1d2 --- /dev/null +++ b/ops/blockbook-upstream.remote.sh @@ -0,0 +1,37 @@ +#!/usr/bin/env bash +# Runs ON the VPS (piped through `ssh silentmode 'HOST=… KEYHDR=… bash -s'` +# by blockbook-upstream.sh / .ps1). Repoints the digibyte.x vhost's +# /blockbook/ proxy at $HOST, with the NOWNodes api-key header when +# KEYHDR=1, tests the config, reloads nginx and proves the route works. +set -euo pipefail +: "${HOST:?HOST (upstream hostname) is required}" +KEYHDR="${KEYHDR:-0}" +F=/etc/nginx/sites-enabled/digibyte-x +mkdir -p /etc/nginx/sites-enabled-stale-baks +cp "$F" "/etc/nginx/sites-enabled-stale-baks/digibyte-x.bak.$(date +%s)" +KEY="" +if [ "$KEYHDR" = 1 ]; then + KEY="$(. /etc/dgb-core/nownodes.env; printf %s "$NOWNODES_API_KEY" | tr -d '\r\n ')" + [ -n "$KEY" ] || { echo "no NOWNODES_API_KEY in /etc/dgb-core/nownodes.env" >&2; exit 1; } +fi +HOST="$HOST" KEY="$KEY" python3 - "$F" <<'PY' +import os, re, sys +p = sys.argv[1]; s = open(p).read() +host, key = os.environ['HOST'], os.environ['KEY'] +a = s.index(' location /blockbook/ {'); b = s.index('\n }\n', a) + 7 +blk = s[a:b] +blk = re.sub(r'proxy_pass https://[^/]+/api/v2/;', f'proxy_pass https://{host}/api/v2/;', blk) +blk = re.sub(r'proxy_ssl_name [^;]+;', f'proxy_ssl_name {host};', blk) +blk = re.sub(r'proxy_set_header Host [^;]+;', f'proxy_set_header Host {host};', blk) +blk = re.sub(r'\n proxy_set_header api-key "[^"]*";', '', blk) +if key: + blk = blk.replace(' proxy_set_header X-Real-IP "";\n', f' proxy_set_header X-Real-IP "";\n proxy_set_header api-key "{key}";\n') +open(p, 'w').write(s[:a] + blk + s[b:]) +print('vhost now proxies /blockbook/ ->', host, '(api-key header)' if key else '(no key)') +PY +nginx -t +systemctl reload nginx +sleep 1 +code=$(curl -sk -o /dev/null -w '%{http_code}' --resolve digibyte.x:443:127.0.0.1 'https://digibyte.x/blockbook/') +echo "GET /blockbook/ via vhost -> HTTP $code" +[ "$code" = 200 ] || { echo "upstream not answering 200 — check the key / host" >&2; exit 1; } diff --git a/ops/blockbook-upstream.sh b/ops/blockbook-upstream.sh index a971353..6ffd67e 100644 --- a/ops/blockbook-upstream.sh +++ b/ops/blockbook-upstream.sh @@ -5,46 +5,18 @@ # ops/blockbook-upstream.sh atomic # Atomic Wallet's public Blockbook (no key) # ops/blockbook-upstream.sh nownodes # NOWNodes, key from /etc/dgb-core/nownodes.env on the VPS # -# Runs over `ssh silentmode`; the previous vhost is kept under +# From PowerShell use ops/blockbook-upstream.ps1 — there `bash` is the +# WSL launcher, not Git Bash, and this file would never reach the VPS. +# +# The work happens in blockbook-upstream.remote.sh, piped over +# `ssh silentmode`; the previous vhost is kept under # /etc/nginx/sites-enabled-stale-baks/. The repo mirror # ops/nginx-digibyte-x.conf documents the same two blocks. set -euo pipefail -target="${1:-}" -case "$target" in +here="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +case "${1:-}" in atomic) host=digibyte.atomicwallet.io; keyhdr=0 ;; nownodes) host=dgbbook.nownodes.io; keyhdr=1 ;; *) echo "usage: $0 atomic|nownodes" >&2; exit 2 ;; esac - -ssh silentmode "HOST=$host KEYHDR=$keyhdr bash -s" <<'REMOTE' -set -euo pipefail -F=/etc/nginx/sites-enabled/digibyte-x -mkdir -p /etc/nginx/sites-enabled-stale-baks -cp "$F" "/etc/nginx/sites-enabled-stale-baks/digibyte-x.bak.$(date +%s)" -KEY="" -if [ "$KEYHDR" = 1 ]; then - KEY="$(. /etc/dgb-core/nownodes.env; printf %s "$NOWNODES_API_KEY" | tr -d '\r\n ')" - [ -n "$KEY" ] || { echo "no NOWNODES_API_KEY in /etc/dgb-core/nownodes.env" >&2; exit 1; } -fi -HOST="$HOST" KEY="$KEY" python3 - "$F" <<'PY' -import os, re, sys -p = sys.argv[1]; s = open(p).read() -host, key = os.environ['HOST'], os.environ['KEY'] -a = s.index(' location /blockbook/ {'); b = s.index('\n }\n', a) + 7 -blk = s[a:b] -blk = re.sub(r'proxy_pass https://[^/]+/api/v2/;', f'proxy_pass https://{host}/api/v2/;', blk) -blk = re.sub(r'proxy_ssl_name [^;]+;', f'proxy_ssl_name {host};', blk) -blk = re.sub(r'proxy_set_header Host [^;]+;', f'proxy_set_header Host {host};', blk) -blk = re.sub(r'\n proxy_set_header api-key "[^"]*";', '', blk) -if key: - blk = blk.replace(' proxy_set_header X-Real-IP "";\n', f' proxy_set_header X-Real-IP "";\n proxy_set_header api-key "{key}";\n') -open(p, 'w').write(s[:a] + blk + s[b:]) -print('vhost now proxies /blockbook/ ->', host, '(api-key header)' if key else '(no key)') -PY -nginx -t -systemctl reload nginx -sleep 1 -code=$(curl -sk -o /dev/null -w '%{http_code}' --resolve digibyte.x:443:127.0.0.1 'https://digibyte.x/blockbook/') -echo "GET /blockbook/ via vhost -> HTTP $code" -[ "$code" = 200 ] || { echo "upstream not answering 200 — check the key / host" >&2; exit 1; } -REMOTE +ssh silentmode "HOST=$host KEYHDR=$keyhdr bash -s" < "$here/blockbook-upstream.remote.sh"