Monorepo for Aesthetic.Computer
aesthetic.computer
1#!/usr/bin/env node
2// help - reverse proxy to NanoClaw running on macbook
3//
4// Proxies all requests to a local port where an SSH reverse tunnel
5// from the macbook exposes NanoClaw's HTTP Help channel.
6//
7// SSH tunnel (run on macbook):
8// ssh -R 3005:localhost:3004 root@help.aesthetic.computer -N -o ServerAliveInterval=30
9//
10// This proxy: :3004 (Caddy) → :3005 (SSH tunnel → macbook NanoClaw)
11
12import "dotenv/config";
13import http from "http";
14
15const PORT = parseInt(process.env.PORT || "3004", 10);
16const BACKEND_PORT = parseInt(process.env.BACKEND_PORT || "3005", 10);
17const BACKEND_HOST = process.env.BACKEND_HOST || "127.0.0.1";
18
19const server = http.createServer((req, res) => {
20 const options = {
21 hostname: BACKEND_HOST,
22 port: BACKEND_PORT,
23 path: req.url,
24 method: req.method,
25 headers: req.headers,
26 };
27
28 const proxy = http.request(options, (proxyRes) => {
29 res.writeHead(proxyRes.statusCode, proxyRes.headers);
30 proxyRes.pipe(res, { end: true });
31 });
32
33 proxy.on("error", (err) => {
34 console.error(`proxy error: ${err.message}`);
35 if (!res.headersSent) {
36 res.writeHead(502, { "Content-Type": "application/json" });
37 res.end(JSON.stringify({ error: "NanoClaw backend unreachable. Is the SSH tunnel running?" }));
38 }
39 });
40
41 req.pipe(proxy, { end: true });
42});
43
44server.listen(PORT, () => {
45 console.log(`help proxy listening on :${PORT} → ${BACKEND_HOST}:${BACKEND_PORT}`);
46});