#!/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 </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 < $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