File size: 4,934 Bytes
afd9806 de83fbe afd9806 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 | #!/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
|