/tmp/fix-splicevpn-handover-publish.sh
#!/usr/bin/env bash
set -euo pipefail
SRC="/opt/splicevpn/HANDOVER.md"
SCRIPTS="/opt/jfmsrv01/scripts"
PUBLIC_ROOT="/var/www/handoff/public"
DEFAULT_SLUG="vqngx6j8dc9q1lvt7g2a7a646q2t"
SITE_INDEX="/var/www/sites/splice/index.html"
STAMP="$(date +%Y%m%d-%H%M%S)"
BACKUP="/root/splicevpn-handover-fix-backup-$STAMP"
echo "=== SPLICEVPN HANDOVER REPAIR/PUBLISH ==="
date
echo "Source: $SRC"
echo "Backup: $BACKUP"
if [ ! -s "$SRC" ]; then
echo "ERROR: $SRC does not exist or is empty."
exit 1
fi
mkdir -p "$BACKUP" "$SCRIPTS"
backup_file() {
local f="$1"
if [ -e "$f" ]; then
mkdir -p "$BACKUP$(dirname "$f")"
cp -a "$f" "$BACKUP$f"
fi
}
SLUG="${HANDOFF_SLUG:-$DEFAULT_SLUG}"
if [ ! -d "$PUBLIC_ROOT/$SLUG" ]; then
SLUG="$(find "$PUBLIC_ROOT" -mindepth 1 -maxdepth 1 -type d -printf '%T@ %f\n' 2>/dev/null | sort -nr | awk 'NR==1{print $2}')"
fi
if [ -z "${SLUG:-}" ] || [ ! -d "$PUBLIC_ROOT/$SLUG" ]; then
echo "ERROR: Could not find public handoff directory under $PUBLIC_ROOT"
exit 1
fi
PUBLIC_BASE="$PUBLIC_ROOT/$SLUG"
PUBLIC_SERVER="$PUBLIC_BASE/server"
mkdir -p "$PUBLIC_SERVER"
for f in \
"$SCRIPTS/HANDOVER.md" \
"$SCRIPTS/CHANGELOG.md" \
"$SCRIPTS/SPLICEVPN_HANDOVER.md" \
"$SCRIPTS/SPLICEVPN_HANDOVER.html" \
"$PUBLIC_BASE/index.html" \
"$PUBLIC_SERVER/SPLICEVPN_HANDOVER.md" \
"$PUBLIC_SERVER/SPLICEVPN_HANDOVER.html" \
"$SITE_INDEX"
do
backup_file "$f"
done
echo
echo "=== CREATE HANDOVER FILES ==="
cp -a "$SRC" "$SCRIPTS/SPLICEVPN_HANDOVER.md"
python3 - "$SRC" "$SCRIPTS/SPLICEVPN_HANDOVER.html" <<'PY'
from pathlib import Path
import html
import sys
src = Path(sys.argv[1])
out = Path(sys.argv[2])
text = src.read_text(errors="replace")
escaped = html.escape(text)
out.write_text(f"""<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>SpliceVPN — Handover</title>
<style>
body{{font:15px/1.55 system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;max-width:980px;margin:2rem auto;padding:0 1rem;color:#111;background:#fff}}
h1{{font-size:1.55rem;margin-bottom:.25rem}}
p.meta{{color:#666;margin-top:0}}
pre{{white-space:pre-wrap;background:#f4f4f5;border:1px solid #ddd;border-radius:8px;padding:1rem;overflow:auto}}
a{{color:#075985}}
</style>
</head>
<body>
<h1>SpliceVPN — Handover</h1>
<p class="meta">Generated from <code>/opt/splicevpn/HANDOVER.md</code>.</p>
<pre>{escaped}</pre>
</body>
</html>
""")
print(f"Wrote {out}")
PY
install -m 0644 "$SCRIPTS/SPLICEVPN_HANDOVER.md" "$PUBLIC_SERVER/SPLICEVPN_HANDOVER.md"
install -m 0644 "$SCRIPTS/SPLICEVPN_HANDOVER.html" "$PUBLIC_SERVER/SPLICEVPN_HANDOVER.html"
echo
echo "=== UPDATE PUBLIC HANDOFF INDEX ==="
python3 - "$PUBLIC_BASE/index.html" <<'PY'
from pathlib import Path
import sys
p = Path(sys.argv[1])
if p.exists():
s = p.read_text(errors="replace")
else:
s = "<!doctype html><html><head><meta charset='utf-8'><title>Handoff</title></head><body><h1>Handoff</h1></body></html>"
start = "<!-- SPLICEVPN-HANDOVER-LINK-START -->"
end = "<!-- SPLICEVPN-HANDOVER-LINK-END -->"
block = f"""
{start}
<h2>SpliceVPN</h2>
<ul>
<li><a href="server/SPLICEVPN_HANDOVER.html">SPLICEVPN_HANDOVER.html</a></li>
<li><a href="server/SPLICEVPN_HANDOVER.md">SPLICEVPN_HANDOVER.md</a></li>
</ul>
{end}
"""
if start in s and end in s:
before = s.split(start)[0]
after = s.split(end, 1)[1]
s = before + block + after
elif "</body>" in s.lower():
idx = s.lower().rfind("</body>")
s = s[:idx] + block + "\n" + s[idx:]
else:
s += block
p.write_text(s)
print(f"Updated {p}")
PY
echo
echo "=== UPDATE MAIN JFMSRV01 HANDOVER + CHANGELOG ==="
python3 - "$SCRIPTS/HANDOVER.md" "$SCRIPTS/CHANGELOG.md" <<'PY'
from pathlib import Path
import sys
handover = Path(sys.argv[1])
changelog = Path(sys.argv[2])
def upsert(path, title, body):
start = f"<!-- {title}-START -->"
end = f"<!-- {title}-END -->"
block = f"\n{start}\n{body.rstrip()}\n{end}\n"
if path.exists():
s = path.read_text(errors="replace")
else:
s = "# jfmsrv01 handover\n"
if start in s and end in s:
s = s.split(start)[0] + block + s.split(end, 1)[1]
else:
s = s.rstrip() + "\n\n" + block
path.write_text(s)
upsert(handover, "SPLICEVPN-HANDOVER", """
## 2026-06-09 — SpliceVPN relay MVP handover
Dedicated SpliceVPN handover has been added.
Source of truth:
- `/opt/splicevpn/HANDOVER.md`
- `/opt/jfmsrv01/scripts/SPLICEVPN_HANDOVER.md`
- Public copy: `server/SPLICEVPN_HANDOVER.html`
Current architecture:
- Hub-and-spoke WireGuard relay MVP.
- Coordinator/control plane, agent/client, and WireGuard hub run on jfmsrv01.
- This is not true peer-to-peer yet.
- Public site wording must say traffic is relayed through the user's own SpliceVPN hub.
- Two-machine overlay ping test is still outstanding.
- Windows ZIP and Linux tarball still need refreshing because they may contain the older agent.
[REDACTED SECRET-LIKE LINE]
- Public handoff site still needs authentication.
""")
upsert(changelog, "SPLICEVPN-HANDOVER-CHANGELOG", """
## 2026-06-09 — SpliceVPN handover update
- Added SpliceVPN dedicated handover from `/opt/splicevpn/HANDOVER.md`.
- Published HTML and Markdown copies into the public handoff area.
- Documented hub-and-spoke relay architecture, coordinator, hub, agent, firewall rules, paths, status, tests, and MVP limitations.
- Recorded outstanding work:
- two-machine overlay ping test;
- public website wording correction;
- refresh Windows ZIP and Linux tarball;
[REDACTED SECRET-LIKE LINE]
- add authentication to handoff site.
""")
PY
echo
echo "=== PATCH SPLICEVPN PUBLIC SITE WORDING ==="
if [ -f "$SITE_INDEX" ]; then
python3 - "$SITE_INDEX" <<'PY'
from pathlib import Path
import re
import sys
p = Path(sys.argv[1])
s = p.read_text(errors="replace")
original = s
# Replace the most dangerous overclaims if they exist.
replacements = [
(
r"Every endpoint connects straight to every other\s*[—-]\s*a true peer-to-peer mesh\.",
"The current MVP creates a controlled hub-relayed WireGuard overlay between endpoints."
),
(
r"your traffic never detours through someone else[’']s cloud by default\.?",
"traffic is relayed through your own SpliceVPN hub in the current MVP."
),
(
r"Direct route first; punch through NAT and firewalls if needed; and if nothing else works, fall back to a relay we supply\. It never just gives up\.",
"The current MVP uses your own SpliceVPN hub relay so nodes can communicate without opening inbound client firewall rules. Direct traversal and hole-punching are planned for a later build."
),
(
r"When direct and traversal both fail, traffic routes through the SpliceVPN relay we operate\. The connection still comes up\s*[—-]\s*guaranteed\.",
"Current MVP traffic routes through your own SpliceVPN hub relay. Direct and traversal modes are planned for a later build."
),
]
for pattern, repl in replacements:
s = re.sub(pattern, repl, s, flags=re.I | re.S)
notice_start = "<!-- SPLICEVPN-MVP-NOTICE-START -->"
notice_end = "<!-- SPLICEVPN-MVP-NOTICE-END -->"
notice = f"""
{notice_start}
<div style="margin:1rem 0;padding:.85rem 1rem;border:1px solid #bae6fd;background:#f0f9ff;border-radius:10px;color:#0c4a6e">
<strong>Current MVP architecture:</strong>
SpliceVPN currently uses your own WireGuard hub relay. Direct peer-to-peer traversal and hole-punching are planned for a later build.
</div>
{notice_end}
"""
if notice_start in s and notice_end in s:
s = s.split(notice_start)[0] + notice + s.split(notice_end, 1)[1]
else:
m = re.search(r"<body[^>]*>", s, flags=re.I)
if m:
s = s[:m.end()] + notice + s[m.end():]
else:
s = notice + s
if s != original:
p.write_text(s)
print(f"Updated {p}")
else:
print("No website wording changes made.")
PY
else
echo "SKIP: $SITE_INDEX not found."
fi
echo
echo "=== CREATE SMALL REPUBLISH HELPER ==="
cat > "$SCRIPTS/publish_splicevpn_handover_extra.sh" <<'SH'
#!/usr/bin/env bash
set -euo pipefail
SRC="/opt/splicevpn/HANDOVER.md"
SCRIPTS="/opt/jfmsrv01/scripts"
PUBLIC_ROOT="/var/www/handoff/public"
DEFAULT_SLUG="vqngx6j8dc9q1lvt7g2a7a646q2t"
SLUG="${HANDOFF_SLUG:-$DEFAULT_SLUG}"
if [ ! -d "$PUBLIC_ROOT/$SLUG" ]; then
SLUG="$(find "$PUBLIC_ROOT" -mindepth 1 -maxdepth 1 -type d -printf '%T@ %f\n' 2>/dev/null | sort -nr | awk 'NR==1{print $2}')"
fi
PUBLIC_BASE="$PUBLIC_ROOT/$SLUG"
PUBLIC_SERVER="$PUBLIC_BASE/server"
mkdir -p "$PUBLIC_SERVER"
cp -a "$SRC" "$SCRIPTS/SPLICEVPN_HANDOVER.md"
python3 - "$SRC" "$SCRIPTS/SPLICEVPN_HANDOVER.html" <<'PY'
from pathlib import Path
import html
import sys
src = Path(sys.argv[1])
out = Path(sys.argv[2])
text = src.read_text(errors="replace")
out.write_text("<!doctype html><html><head><meta charset='utf-8'><title>SpliceVPN — Handover</title><style>body{font:15px/1.55 system-ui,sans-serif;max-width:980px;margin:2rem auto;padding:0 1rem}pre{white-space:pre-wrap;background:#f4f4f5;border:1px solid #ddd;border-radius:8px;padding:1rem}</style></head><body><h1>SpliceVPN — Handover</h1><pre>" + html.escape(text) + "</pre></body></html>")
PY
install -m 0644 "$SCRIPTS/SPLICEVPN_HANDOVER.md" "$PUBLIC_SERVER/SPLICEVPN_HANDOVER.md"
install -m 0644 "$SCRIPTS/SPLICEVPN_HANDOVER.html" "$PUBLIC_SERVER/SPLICEVPN_HANDOVER.html"
echo "Republished SpliceVPN handover:"
echo "$PUBLIC_SERVER/SPLICEVPN_HANDOVER.html"
SH
chmod +x "$SCRIPTS/publish_splicevpn_handover_extra.sh"
echo
echo "=== VERIFY ==="
echo "Backup: $BACKUP"
echo "Public slug: $SLUG"
echo
echo "--- Public files ---"
ls -l "$PUBLIC_SERVER/SPLICEVPN_HANDOVER."* || true
echo
echo "--- Public index link check ---"
grep -n "SPLICEVPN_HANDOVER" "$PUBLIC_BASE/index.html" || true
echo
echo "--- Site wording check ---"
if [ -f "$SITE_INDEX" ]; then
grep -nEi "never detours|someone else|true peer-to-peer|hub relay|hub-relayed|own SpliceVPN hub|hole-punch" "$SITE_INDEX" | head -40 || true
fi
echo
echo "Open this:"
echo "https://vqngx6j8dc9q1lvt7g2a7a646q2t.jfmcommunications.com.au/$SLUG/server/SPLICEVPN_HANDOVER.html"
echo
echo "Also check:"
echo "https://splicevpn.com.au/"
echo
echo "=== DONE ==="