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