Our own keyless Bun service (not Linky's): watches relays for kind-1059 wraps
carrying the plaintext marker ["skatespots","push"] on the recipient copy,
extracts only {recipient, wrapId}, and sends a Web Push. NEVER decrypts - the
client fetches + decrypts the named wrap itself.
Endpoints: GET /health, GET /vapid-public-key, POST /auth/challenge ->
/subscribe|/unsubscribe with a one-time NIP-98 (kind 27235) challenge proof.
State is a JSON file; VAPID keys from env. Wired like the other standalone
servers (typecheck:push + check:push in npm test, deploy:push, Caddyfile +
systemd unit). Verified locally end-to-end: auth -> subscribe -> marked wrap ->
watcher -> push attempt, and proof replay rejected.
Client half (service worker, subscribe hook + Settings toggle, marker on DM
sends) is the next step.
70 lines
3 KiB
Bash
70 lines
3 KiB
Bash
#!/usr/bin/env bash
|
|
#
|
|
# Deploy the SkateSpots push service to the CVM host (same box as the CVM server
|
|
# and the AI proxy). Same class of service: a Bun process under systemd,
|
|
# reachable only via Caddy (TLS) on the public side.
|
|
#
|
|
# Config/host come from ~/.config/skatespots/cvm.env (never committed).
|
|
#
|
|
# npm run deploy:push # or: bash scripts/deploy-push.sh
|
|
# bash scripts/deploy-push.sh --logs
|
|
#
|
|
# On first deploy it generates VAPID keys ON THE HOST and writes .env, so the
|
|
# private key never leaves the server. Changing those keys invalidates all
|
|
# existing subscriptions.
|
|
set -euo pipefail
|
|
|
|
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
|
|
CONF="${HOME}/.config/skatespots/cvm.env"
|
|
if [[ -f "$CONF" ]]; then
|
|
# shellcheck disable=SC1090
|
|
source "$CONF"
|
|
fi
|
|
|
|
: "${CVM_HOST:?Set CVM_HOST (e.g. in ~/.config/skatespots/cvm.env) — the host is never committed}"
|
|
CVM_SSH_KEY="${CVM_SSH_KEY:-$HOME/.ssh/skatespots-new}"
|
|
PUSH_DIR="${PUSH_DIR:-/home/ubuntu/skatespots-push}"
|
|
PUSH_SERVICE="${PUSH_SERVICE:-skatespots-push}"
|
|
|
|
SSH=(ssh -i "$CVM_SSH_KEY" -o BatchMode=yes -o ConnectTimeout=12 "$CVM_HOST")
|
|
|
|
if [[ "${1:-}" == "--logs" ]]; then
|
|
"${SSH[@]}" "journalctl -u $PUSH_SERVICE -n 60 --no-pager"
|
|
exit 0
|
|
fi
|
|
|
|
echo "→ Ensuring $PUSH_DIR exists"
|
|
"${SSH[@]}" "mkdir -p $PUSH_DIR"
|
|
|
|
echo "→ Uploading push-service/{server.ts,package.json,tsconfig.json,skatespots-push.service}"
|
|
scp -i "$CVM_SSH_KEY" -o BatchMode=yes \
|
|
"$REPO_ROOT/push-service/server.ts" \
|
|
"$REPO_ROOT/push-service/package.json" \
|
|
"$REPO_ROOT/push-service/tsconfig.json" \
|
|
"$REPO_ROOT/push-service/skatespots-push.service" \
|
|
"$CVM_HOST:$PUSH_DIR/"
|
|
|
|
echo "→ Creating .env with fresh VAPID keys if missing (private key stays on the host)"
|
|
"${SSH[@]}" "cd $PUSH_DIR && if [ ! -f .env ]; then \
|
|
~/.bun/bin/bun -e \"import wp from 'web-push'; const k=wp.generateVAPIDKeys(); \
|
|
console.log(['PUSH_VAPID_SUBJECT=mailto:owner@skate-spots.org','PUSH_VAPID_PUBLIC_KEY='+k.publicKey,'PUSH_VAPID_PRIVATE_KEY='+k.privateKey,'PUSH_RELAYS=wss://goskatespots.nostr1.com','PUSH_MARKER=skatespots','PUSH_STORAGE_PATH=$PUSH_DIR/push-state.json','PUSH_ALLOWED_ORIGINS=https://skate-spots.org,http://localhost:8080','PORT=8788'].join('\\n'))\" > .env && chmod 600 .env && echo 'created .env'; \
|
|
else echo '.env already exists (leaving keys untouched)'; fi"
|
|
|
|
echo "→ bun install"
|
|
"${SSH[@]}" "cd $PUSH_DIR && ~/.bun/bin/bun install --silent 2>&1 | tail -3 || true"
|
|
|
|
echo "→ Installing the unit and (re)starting $PUSH_SERVICE"
|
|
"${SSH[@]}" "sudo cp $PUSH_DIR/skatespots-push.service /etc/systemd/system/ \
|
|
&& sudo systemctl daemon-reload \
|
|
&& sudo systemctl enable --now $PUSH_SERVICE >/dev/null 2>&1 || true; \
|
|
sudo systemctl restart $PUSH_SERVICE \
|
|
&& sleep 2 && echo \"active: \$(systemctl is-active $PUSH_SERVICE)\""
|
|
|
|
echo "→ Health check"
|
|
"${SSH[@]}" "curl -s http://127.0.0.1:8788/health || true; echo"
|
|
|
|
echo "→ Recent log:"
|
|
"${SSH[@]}" "journalctl -u $PUSH_SERVICE -n 15 --no-pager | tail -8"
|
|
|
|
echo "✅ Push service deployed. Public TLS via Caddy — see push-service/README.md."
|