Garden-Angel-Ai-35Bot / deploy /Caddyfile.example
Claude
Lock the bot to its operator, fix aws-secrets, and explain the no-trade
bf3ef55 unverified
Raw
History Blame Contribute Delete
3.47 kB
# deploy/Caddyfile.example — reference Caddy config for this box.
#
# The deployment runs TWO bots behind one Caddy:
#
# arb.elghaly.dev -> 127.0.0.1:8080 the Rust bot (basicauth, private)
# bot.elghaly.dev -> 127.0.0.1:8081 this Python bot (public, read-only)
#
# Copy to /etc/caddy/Caddyfile, adjust, then:
#
# sudo caddy validate --config /etc/caddy/Caddyfile
# sudo systemctl reload caddy
#
# ─────────────────────────────────────────────────────────────────────────
# THE PATH ALLOWLIST IS THE POINT OF THIS FILE
# ─────────────────────────────────────────────────────────────────────────
# A bare `reverse_proxy 127.0.0.1:8081` publishes EVERY route the Python
# bot serves, and two of them are not public routes:
#
# POST /command fund-moving. Runs /hunt, toggles ghost and mint mode.
# GET /logs operational detail — wallet addresses, tx signatures,
# route sizes, internal errors.
#
# Both are Bearer-token gated in the application (modules/bot_api_server.py)
# and both are rate-limited and lockout-protected (modules/http_guard.py),
# so a bare proxy is not an immediate compromise. It is still the wrong
# shape. Anything that can move funds should be unreachable for two
# independent reasons, so that no single mistake — a token in a shell
# history, a bad `git add`, a regression in the auth check — is sufficient
# on its own.
#
# So this config lists what MAY be reached and 404s everything else. Note
# the direction: an allowlist fails closed, so a new endpoint added to the
# Python server tomorrow is private until someone deliberately publishes
# it. A blocklist would fail open and publish it by default.
arb.elghaly.dev {
basicauth {
# Generate with: caddy hash-password
# The hash is not a password, but it is still an offline-crackable
# artifact — keep it out of screenshots and out of git.
admin REPLACE_WITH_BCRYPT_HASH
}
reverse_proxy 127.0.0.1:8080
}
bot.elghaly.dev {
encode gzip
# The public read-only surface. Nothing here can act, and nothing here
# returns a secret — see modules/bot_api_server.py's own audit note for
# the field-by-field reasoning.
@public {
path /
path /status
path /api/pnl
path /api/receipts
path /api/routes
path /api/nearmiss
path /api/engine
path /receipts.csv
}
handle @public {
reverse_proxy 127.0.0.1:8081
}
# Everything else, including /command and /logs, does not exist as far
# as the internet is concerned. 404 rather than 403: a 403 confirms the
# path is real and worth attacking, which is free reconnaissance.
handle {
respond "not found" 404
}
header {
# This page loads no external anything — no CDN, no fonts, no
# analytics — so the policy can be this tight honestly. 'unsafe-inline'
# covers the one inline <style> and <script> the page is built from.
Content-Security-Policy "default-src 'none'; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline'; connect-src 'self'; img-src 'self' data:; base-uri 'none'; form-action 'none'; frame-ancestors 'none'"
X-Content-Type-Options "nosniff"
Referrer-Policy "no-referrer"
X-Frame-Options "DENY"
-Server
}
}