🚀 herald: production hardening — SOLARGOD_READONLY gates /snap; unit adapted to the tunnel topology (fable)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
03f1c009f2
commit
a6538fee1c
@ -1,5 +1,7 @@
|
|||||||
# HERALD — systemd unit for SOLARGOD. serve.py binds 127.0.0.1 only; nginx
|
# HERALD — systemd unit for SOLARGOD on the botchat VPS. serve.py binds
|
||||||
# reverse-proxies the public domain to it (mirror of the godstrument.pro shape).
|
# 127.0.0.1 only; the cloudflared tunnel's ingress rule for
|
||||||
|
# solargod.godstrument.pro forwards to it (same shape as godstrument.pro —
|
||||||
|
# no nginx in this topology; nginx-solargod.conf is the alternative shape).
|
||||||
# Install: sudo cp deploy/solargod.service /etc/systemd/system/ && sudo systemctl enable --now solargod
|
# Install: sudo cp deploy/solargod.service /etc/systemd/system/ && sudo systemctl enable --now solargod
|
||||||
[Unit]
|
[Unit]
|
||||||
Description=SOLARGOD orrery — serve.py (static + JPL Horizons/SBDB/CAD proxy + disk cache)
|
Description=SOLARGOD orrery — serve.py (static + JPL Horizons/SBDB/CAD proxy + disk cache)
|
||||||
@ -7,9 +9,10 @@ After=network.target
|
|||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
Type=simple
|
Type=simple
|
||||||
User=www-data
|
User=humanjing
|
||||||
WorkingDirectory=/opt/solargod
|
WorkingDirectory=/home/humanjing/solargod
|
||||||
ExecStart=/usr/bin/python3 /opt/solargod/serve.py 8147
|
Environment=SOLARGOD_READONLY=1
|
||||||
|
ExecStart=/usr/bin/python3 /home/humanjing/solargod/serve.py 8147
|
||||||
Restart=on-failure
|
Restart=on-failure
|
||||||
RestartSec=3
|
RestartSec=3
|
||||||
# serve.py writes its disk cache under WorkingDirectory/cache — keep it writable.
|
# serve.py writes its disk cache under WorkingDirectory/cache — keep it writable.
|
||||||
|
|||||||
8
serve.py
8
serve.py
@ -32,6 +32,9 @@ PORT = int(sys.argv[1]) if len(sys.argv) > 1 else 8147
|
|||||||
ROOT = Path(__file__).resolve().parent
|
ROOT = Path(__file__).resolve().parent
|
||||||
CACHE_DIR = ROOT / "cache"
|
CACHE_DIR = ROOT / "cache"
|
||||||
CACHE_TTL_SEC = 24 * 3600
|
CACHE_TTL_SEC = 24 * 3600
|
||||||
|
# Production (HERALD): SOLARGOD_READONLY=1 disables the dev-only /snap write
|
||||||
|
# endpoint — behind a public tunnel, the server must accept no writes at all.
|
||||||
|
READONLY = os.environ.get("SOLARGOD_READONLY") == "1"
|
||||||
|
|
||||||
UPSTREAMS = {
|
UPSTREAMS = {
|
||||||
"horizons": "https://ssd.jpl.nasa.gov/api/horizons.api",
|
"horizons": "https://ssd.jpl.nasa.gov/api/horizons.api",
|
||||||
@ -182,7 +185,10 @@ class Handler(SimpleHTTPRequestHandler):
|
|||||||
def do_POST(self):
|
def do_POST(self):
|
||||||
# Dev-only screenshot sink: POST /snap?name=<n> with base64 PNG (or a
|
# Dev-only screenshot sink: POST /snap?name=<n> with base64 PNG (or a
|
||||||
# data:image/png;base64,... URL) → docs/<n>.png. Bound to 127.0.0.1; the
|
# data:image/png;base64,... URL) → docs/<n>.png. Bound to 127.0.0.1; the
|
||||||
# name is sanitized so the write can never escape docs/.
|
# name is sanitized so the write can never escape docs/. Disabled entirely
|
||||||
|
# in production (SOLARGOD_READONLY=1) — a tunneled deploy must not write.
|
||||||
|
if READONLY:
|
||||||
|
return self.send_error(403, "read-only deployment")
|
||||||
if not (self.path == "/snap" or self.path.startswith("/snap?")):
|
if not (self.path == "/snap" or self.path.startswith("/snap?")):
|
||||||
return self.send_error(404, "not found")
|
return self.send_error(404, "not found")
|
||||||
_, _, query = self.path.partition("?")
|
_, _, query = self.path.partition("?")
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user