Garden-Angel-Ai-35Bot / scripts /setup_nginx.sh
Claude
Failure-mode logging, drawdown alerts, route transparency, HTTP guard
de83fbe unverified
Raw
History Blame Contribute Delete
4.93 kB
#!/usr/bin/env bash
# scripts/setup_nginx.sh — publish the dashboard at bot.elghaly.dev.
#
# ONE command, because this box is administered from a phone browser
# terminal where multi-line pastes get truncated and interactive editors
# are unusable.
#
# sudo ./scripts/setup_nginx.sh
#
# What it does: installs nginx, copies deploy/nginx-bot.elghaly.dev.conf
# into place, disables the default site, tests the config, reloads, and
# verifies the four public routes answer while /command and /logs do not.
#
# It does NOT touch TLS — run certbot afterwards (it prints the command).
# And it cannot do the two things that are not on this box: the DNS A
# record, and opening ports 80/443 in the EC2 security group. It checks
# both and tells you plainly if they are missing, rather than appearing to
# succeed and leaving you wondering why the site does not load.
set -euo pipefail
DOMAIN="${DOMAIN:-bot.elghaly.dev}"
REPO="$(cd "$(dirname "$0")/.." && pwd)"
CONF="$REPO/deploy/nginx-$DOMAIN.conf"
if [ "$(id -u)" -ne 0 ]; then
echo "run with sudo: sudo ./scripts/setup_nginx.sh" >&2
exit 1
fi
[ -f "$CONF" ] || { echo "missing $CONF" >&2; exit 1; }
# ── 0/5 is something ELSE already serving :80? ──────────────────────────
#
# This box runs Caddy, which already fronts arb.elghaly.dev for the Rust
# bot. Two web servers cannot both bind :80, so the earlier version of this
# script installed a valid nginx config, then failed at the last step with
# "nginx.service is not active, cannot reload" — leaving a config on disk
# that looked installed and served nothing.
#
# That is the worst possible outcome: a half-applied change that reports a
# syntax success. Detect the conflict up front and point at the script that
# actually fits this deployment, rather than fighting Caddy for the port.
if ss -lntp 2>/dev/null | grep ':80 ' | grep -qv nginx; then
OWNER="$(ss -lntp 2>/dev/null | grep ':80 ' | grep -o 'users:((\"[^\"]*\"' | head -1 | tr -d '"' | sed 's/users:((//')"
if [ "${OWNER:-}" != "nginx" ] && [ -n "${OWNER:-}" ]; then
cat >&2 <<EOF
⛔ Port 80 is already served by: ${OWNER}
nginx cannot bind a port another web server holds, so installing this
config would leave a file on disk that serves nothing — which is worse
than doing nothing, because it looks like it worked.
This box uses Caddy. Use the Caddy script instead — it publishes the
same allowlist and leaves every other site block untouched:
sudo ./scripts/setup_caddy.sh
Set FORCE_NGINX=1 to override this check if you really mean to switch.
EOF
[ "${FORCE_NGINX:-}" = "1" ] || exit 1
fi
fi
echo "── 1/5 is the bot actually listening on 8081?"
if ss -lnt 2>/dev/null | grep -q ':8081'; then
echo " ok"
else
echo " WARNING: nothing on :8081 — start the bot first, or the site will 502."
fi
echo "── 2/5 does $DOMAIN point at this box?"
MYIP="$(curl -s --max-time 5 https://checkip.amazonaws.com || echo unknown)"
DNSIP="$(getent hosts "$DOMAIN" | awk '{print $1; exit}' || true)"
if [ -n "$DNSIP" ] && [ "$DNSIP" = "$MYIP" ]; then
echo " ok — $DOMAIN -> $DNSIP"
else
echo " NOT YET: $DOMAIN resolves to '${DNSIP:-nothing}', this box is $MYIP."
echo " Add an A record for $DOMAIN pointing at $MYIP at your DNS provider."
echo " (Continuing — nginx will be configured and ready for when it does.)"
fi
echo "── 3/5 installing nginx"
if ! command -v nginx >/dev/null; then
apt-get update -qq && apt-get install -y -qq nginx
fi
echo "── 4/5 installing the site config"
cp "$CONF" "/etc/nginx/sites-available/$DOMAIN"
ln -sf "/etc/nginx/sites-available/$DOMAIN" "/etc/nginx/sites-enabled/$DOMAIN"
rm -f /etc/nginx/sites-enabled/default
nginx -t
systemctl reload nginx
echo " ok"
echo "── 5/5 verifying the public surface (locally, via the Host header)"
check() {
local path="$1" want="$2"
local got
got="$(curl -s -o /dev/null -w '%{http_code}' -H "Host: $DOMAIN" "http://127.0.0.1$path" || echo 000)"
if [ "$got" = "$want" ]; then
printf ' %-16s %s ok\n' "$path" "$got"
else
printf ' %-16s %s EXPECTED %s\n' "$path" "$got" "$want"
fi
}
check / 200
check /api/pnl 200
check /api/receipts 200
check /receipts.csv 200
# These MUST be refused at the edge. A 401 here would mean they are
# reachable and merely password-protected, which is a much weaker position
# for an endpoint that can move funds.
check /command 404
check /logs 404
cat <<EOF
Done. Remaining, in order:
1. DNS: A record for $DOMAIN -> $MYIP (at your DNS provider)
2. EC2 security group: allow inbound 80 and 443 from 0.0.0.0/0
DO NOT open 8081 — /command and /logs live there.
3. TLS, once DNS resolves:
sudo certbot --nginx -d $DOMAIN --agree-tos --redirect -m you@example.com
Then open https://$DOMAIN
EOF