patches on sxsw ai working api key working container hardened plus many more

This commit is contained in:
Dorian
2026-03-12 22:19:04 +00:00
parent 73e0a1b74d
commit 5e6aaa74aa
14 changed files with 625 additions and 46 deletions

View File

@@ -1153,6 +1153,78 @@ RestartSec=5
WantedBy=multi-user.target
SERVICE
# Claude API proxy — middleware that injects max_tokens, strips invalid fields
# API key must be set after install via setup-aiui-server.sh or manually
cat > /mnt/target/opt/archipelago/claude-api-proxy.py <<'CLAUDEPROXY'
#!/usr/bin/env python3
import http.server, json, ssl, sys, os, urllib.request, urllib.error
API_KEY = os.environ.get("ANTHROPIC_API_KEY", "")
PORT = 3142
class Handler(http.server.BaseHTTPRequestHandler):
def do_POST(self):
if self.path == "/health":
self.send_response(200); self.send_header("Content-Type","application/json"); self.end_headers()
self.wfile.write(b'{"status":"ok"}'); return
cl = int(self.headers.get("Content-Length", 0))
body = self.rfile.read(cl)
try: data = json.loads(body)
except: data = {}
if "max_tokens" not in data: data["max_tokens"] = 8096
for f in ["webSearch","web_search"]: data.pop(f, None)
body = json.dumps(data).encode()
headers = {"Content-Type":"application/json","x-api-key":API_KEY,"anthropic-version":"2023-06-01","anthropic-dangerous-direct-browser-access":"true"}
for h in ["anthropic-version","anthropic-beta"]:
if self.headers.get(h): headers[h] = self.headers[h]
req = urllib.request.Request("https://api.anthropic.com"+self.path, data=body, headers=headers, method="POST")
try:
ctx = ssl.create_default_context()
resp = urllib.request.urlopen(req, context=ctx, timeout=300)
self.send_response(resp.status)
is_stream = "text/event-stream" in (resp.headers.get("Content-Type","") or "")
for k,v in resp.headers.items():
if k.lower() not in ("transfer-encoding","connection"): self.send_header(k,v)
if is_stream: self.send_header("Transfer-Encoding","chunked")
self.end_headers()
if is_stream:
while True:
chunk = resp.read(4096)
if not chunk: break
self.wfile.write(b"%x\r\n" % len(chunk)); self.wfile.write(chunk); self.wfile.write(b"\r\n"); self.wfile.flush()
self.wfile.write(b"0\r\n\r\n"); self.wfile.flush()
else: self.wfile.write(resp.read())
except urllib.error.HTTPError as e:
self.send_response(e.code); self.send_header("Content-Type","application/json"); self.end_headers(); self.wfile.write(e.read())
except Exception as e:
self.send_response(502); self.send_header("Content-Type","application/json"); self.end_headers(); self.wfile.write(json.dumps({"error":str(e)}).encode())
def do_GET(self):
if self.path == "/health":
self.send_response(200); self.send_header("Content-Type","application/json"); self.end_headers(); self.wfile.write(b'{"status":"ok"}')
else: self.send_response(404); self.end_headers()
def log_message(self, fmt, *args): pass
if not API_KEY: print("ERROR: ANTHROPIC_API_KEY not set — configure via setup-aiui-server.sh"); sys.exit(1)
server = http.server.HTTPServer(("127.0.0.1", PORT), Handler)
print(f"Claude API proxy on port {PORT}")
server.serve_forever()
CLAUDEPROXY
chmod +x /mnt/target/opt/archipelago/claude-api-proxy.py
# Claude API proxy systemd service (disabled by default — enabled after API key is configured)
cat > /mnt/target/etc/systemd/system/claude-api-proxy.service <<'CLAUDESVC'
[Unit]
Description=Claude API Proxy
After=network.target
[Service]
Type=simple
Environment=ANTHROPIC_API_KEY=
ExecStart=/usr/bin/python3 /opt/archipelago/claude-api-proxy.py
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
CLAUDESVC
# Install GRUB
echo " [6/6] Installing bootloader..."
mount --bind /dev /mnt/target/dev

View File

@@ -0,0 +1,87 @@
# External web-only apps — reverse proxy to strip X-Frame-Options for iframe embedding
# Used by appLauncher.ts EXTERNAL_PROXY_PORT mapping
# Deployed to /etc/nginx/conf.d/external-app-proxies.conf
resolver 1.1.1.1 8.8.8.8 valid=300s;
resolver_timeout 5s;
# BotFights (botfights.net) → port 8901
server {
listen 8901;
server_name _;
location / {
set $upstream_botfights https://botfights.net;
proxy_pass $upstream_botfights;
proxy_http_version 1.1;
proxy_set_header Host botfights.net;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Accept-Encoding "";
proxy_ssl_server_name on;
proxy_ssl_name botfights.net;
proxy_hide_header X-Frame-Options;
proxy_hide_header Content-Security-Policy;
proxy_connect_timeout 60s;
proxy_read_timeout 60s;
proxy_redirect https://botfights.net/ /;
sub_filter_once off;
sub_filter_types text/html text/css application/javascript;
}
}
# 484 Kitchen (484.kitchen) → port 8902
server {
listen 8902;
server_name _;
location / {
set $upstream_484 https://484.kitchen;
proxy_pass $upstream_484;
proxy_http_version 1.1;
proxy_set_header Host 484.kitchen;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Accept-Encoding "";
proxy_ssl_server_name on;
proxy_ssl_name 484.kitchen;
proxy_hide_header X-Frame-Options;
proxy_hide_header Content-Security-Policy;
proxy_connect_timeout 60s;
proxy_read_timeout 60s;
proxy_redirect https://484.kitchen/ /;
sub_filter_once off;
sub_filter_types text/html text/css application/javascript;
}
}
# Arch Presentation (present.l484.com) → port 8903
server {
listen 8903;
server_name _;
location / {
set $upstream_present https://present.l484.com;
proxy_pass $upstream_present;
proxy_http_version 1.1;
proxy_set_header Host present.l484.com;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Accept-Encoding "";
proxy_ssl_server_name on;
proxy_ssl_name present.l484.com;
proxy_hide_header X-Frame-Options;
proxy_hide_header Content-Security-Policy;
proxy_connect_timeout 60s;
proxy_read_timeout 60s;
proxy_redirect https://present.l484.com/ /;
sub_filter_once off;
sub_filter_types text/html text/css application/javascript;
}
}

View File

@@ -28,7 +28,7 @@ server {
if ($cookie_session = "") {
return 401 '{"error":"Unauthorized"}';
}
proxy_pass http://127.0.0.1:3141/;
proxy_pass http://127.0.0.1:3142/;
proxy_http_version 1.1;
proxy_set_header Host $host;
# Connection header managed by nginx default
@@ -511,7 +511,7 @@ server {
if ($cookie_session = "") {
return 401 '{"error":"Unauthorized"}';
}
proxy_pass http://127.0.0.1:3141/;
proxy_pass http://127.0.0.1:3142/;
proxy_http_version 1.1;
proxy_set_header Host $host;
# Connection header managed by nginx default