mirror of
https://relay.ngit.dev/npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr/ngit-grasp.git
synced 2026-10-05 15:08:24 +00:00
Production deployment previously depended on an illustrative Docker snippet and did not define which state or identity must survive replacement. Add a non-root runtime image, loopback-only Compose service, optional Caddy TLS overlay, shared /data layout, bounded public verifier, and an identity-persistence container test. Document backup, proxy, single-writer, upgrade, and rollback requirements as the contract for every environment. This assumes one ngit-grasp writer per state directory and a reverse proxy or platform edge for public TLS. Image publication and provider-specific control-plane setup are deliberately left to separate changes. Validated with sh -n, ShellCheck 0.11.0, locked Cargo metadata, YAML parsing, Docker Hub tag lookups, local input-failure checks, and git diff --check. Docker/Podman is unavailable in this VM, so the included end-to-end container test was not run here.
100 lines
2.3 KiB
Bash
Executable File
100 lines
2.3 KiB
Bash
Executable File
#!/bin/sh
|
|
set -eu
|
|
|
|
usage() {
|
|
echo "Usage: $0 <public-base-url>" >&2
|
|
echo "Example: $0 https://ngit.example.com" >&2
|
|
}
|
|
|
|
if [ "$#" -ne 1 ]; then
|
|
usage
|
|
exit 2
|
|
fi
|
|
|
|
base_url=${1%/}
|
|
case "${base_url}" in
|
|
http://*|https://*) ;;
|
|
*)
|
|
echo "public base URL must start with http:// or https://" >&2
|
|
exit 2
|
|
;;
|
|
esac
|
|
|
|
for required_command in curl grep mktemp; do
|
|
if ! command -v "${required_command}" >/dev/null 2>&1; then
|
|
echo "missing required command: ${required_command}" >&2
|
|
exit 2
|
|
fi
|
|
done
|
|
|
|
temporary_directory=$(mktemp -d)
|
|
cleanup() {
|
|
rm -rf -- "${temporary_directory}"
|
|
}
|
|
trap cleanup EXIT HUP INT TERM
|
|
|
|
nip11_body=${temporary_directory}/nip11.json
|
|
websocket_headers=${temporary_directory}/websocket.headers
|
|
|
|
curl \
|
|
--fail \
|
|
--silent \
|
|
--show-error \
|
|
--connect-timeout 5 \
|
|
--max-time 15 \
|
|
--retry 20 \
|
|
--retry-all-errors \
|
|
--retry-max-time 120 \
|
|
--header 'Accept: application/nostr+json' \
|
|
--output "${nip11_body}" \
|
|
"${base_url}"
|
|
|
|
if command -v jq >/dev/null 2>&1; then
|
|
jq -e '
|
|
(.pubkey | type == "string" and length == 64) and
|
|
(.supported_nips | type == "array")
|
|
' "${nip11_body}" >/dev/null
|
|
else
|
|
grep -q '"pubkey"' "${nip11_body}"
|
|
grep -q '"supported_nips"' "${nip11_body}"
|
|
fi
|
|
echo "ok: NIP-11 relay information"
|
|
|
|
set +e
|
|
curl \
|
|
--http1.1 \
|
|
--silent \
|
|
--show-error \
|
|
--connect-timeout 5 \
|
|
--max-time 5 \
|
|
--dump-header "${websocket_headers}" \
|
|
--output /dev/null \
|
|
--header 'Connection: Upgrade' \
|
|
--header 'Upgrade: websocket' \
|
|
--header 'Sec-WebSocket-Version: 13' \
|
|
--header 'Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==' \
|
|
"${base_url}"
|
|
websocket_curl_status=$?
|
|
set -e
|
|
|
|
if ! grep -Eq '^HTTP/[0-9.]+ 101([[:space:]]|$)' "${websocket_headers}"; then
|
|
echo "WebSocket upgrade failed (curl status ${websocket_curl_status})" >&2
|
|
cat "${websocket_headers}" >&2
|
|
exit 1
|
|
fi
|
|
echo "ok: WebSocket upgrade"
|
|
|
|
if [ "${VERIFY_METRICS:-true}" = true ]; then
|
|
curl \
|
|
--fail \
|
|
--silent \
|
|
--show-error \
|
|
--connect-timeout 5 \
|
|
--max-time 15 \
|
|
--output /dev/null \
|
|
"${base_url}/metrics"
|
|
echo "ok: Prometheus metrics"
|
|
fi
|
|
|
|
echo "deployment verified: ${base_url}"
|