Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions docs/VPS_DEPLOYMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,18 @@ curl http://127.0.0.1:3000/api/health

A healthy app should return a JSON response.

Run the VPS smoke test script to verify the homepage, health endpoint, and token-protected admin API endpoints without printing the admin token:

```bash
BASE_URL=http://127.0.0.1:3000 ADMIN_EXPORT_TOKEN="..." bash scripts/vps-smoke-test.sh
```

If you only want to verify public endpoints, omit `ADMIN_EXPORT_TOKEN` and the admin checks will be skipped:

```bash
BASE_URL=http://127.0.0.1:3000 bash scripts/vps-smoke-test.sh
```

## 9. Reverse proxy with Caddy

Use a reverse proxy so visitors reach the app over HTTPS. Caddy is beginner-friendly because it can automatically request and renew TLS certificates.
Expand Down
88 changes: 88 additions & 0 deletions scripts/vps-smoke-test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
#!/usr/bin/env bash
set -euo pipefail

BASE_URL="${BASE_URL:-http://127.0.0.1:3000}"
BASE_URL="${BASE_URL%/}"
ADMIN_EXPORT_TOKEN="${ADMIN_EXPORT_TOKEN:-}"

failures=0

print_pass() {
printf 'PASS: %s\n' "$1"
}

print_fail() {
printf 'FAIL: %s\n' "$1"
failures=$((failures + 1))
}

http_get() {
local url="$1"
local output_file="$2"
shift 2

local status
if ! status=$(curl --silent --show-error --location --output "$output_file" --write-out '%{http_code}' "$@" "$url"); then
printf '000'
return 0
fi

printf '%s' "$status"
}

check_status() {
local label="$1"
local url="$2"
shift 2

local response_file
response_file=$(mktemp)
local status
status=$(http_get "$url" "$response_file" "$@")
rm -f "$response_file"

if [[ "$status" == "200" ]]; then
print_pass "$label returned HTTP 200"
else
print_fail "$label returned HTTP $status (expected 200)"
fi
}

check_health() {
local response_file
response_file=$(mktemp)
local status
status=$(http_get "$BASE_URL/api/health" "$response_file")

if [[ "$status" == "200" ]]; then
print_pass "GET $BASE_URL/api/health returned HTTP 200"
else
print_fail "GET $BASE_URL/api/health returned HTTP $status (expected 200)"
fi

if [[ -s "$response_file" ]] && LC_ALL=C grep -Eq '^[[:space:]]*[{[]' "$response_file"; then
print_pass "GET $BASE_URL/api/health returned JSON-like text"
else
print_fail "GET $BASE_URL/api/health did not return JSON-like text"
fi

rm -f "$response_file"
}

check_status "GET $BASE_URL/" "$BASE_URL/"
check_health

if [[ -n "$ADMIN_EXPORT_TOKEN" ]]; then
auth_header="Authorization: Bearer ${ADMIN_EXPORT_TOKEN}"
check_status "GET $BASE_URL/api/admin/diagnostics" "$BASE_URL/api/admin/diagnostics" --header "$auth_header"
check_status "GET $BASE_URL/api/admin/stats" "$BASE_URL/api/admin/stats" --header "$auth_header"
else
printf 'SKIP: ADMIN_EXPORT_TOKEN is not set; skipping admin diagnostics and stats checks\n'
fi

if (( failures > 0 )); then
printf 'FAIL: VPS smoke test completed with %d failure(s)\n' "$failures"
exit 1
fi

printf 'PASS: VPS smoke test completed successfully\n'