amangs commited on
Commit
b557190
·
verified ·
1 Parent(s): 9edbb7f

Port Space to REA MCP Server + Caddy + code-server + goFiles + opencode-router (browser hard-blocked)

Browse files
Caddyfile ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ :7860 {
2
+ # 1. REA MCP Server (Streamable HTTP via supergateway)
3
+ handle /mcp* {
4
+ reverse_proxy 127.0.0.1:8093 {
5
+ flush_interval -1
6
+ }
7
+ }
8
+
9
+ handle /healthz {
10
+ reverse_proxy 127.0.0.1:8093
11
+ }
12
+
13
+ # 2. code-server routing (/code)
14
+ @code_noslash path /code
15
+ redir @code_noslash /code/ 308
16
+
17
+ handle_path /code/* {
18
+ reverse_proxy 127.0.0.1:8443
19
+ }
20
+
21
+ # 3. goFiles file manager (/files -> mounted at /data)
22
+ @files_noslash path /files
23
+ redir @files_noslash /files/ 308
24
+
25
+ handle_path /files/* {
26
+ reverse_proxy 127.0.0.1:8100 {
27
+ header_up X-Forwarded-Prefix /files
28
+ }
29
+ }
30
+
31
+ # 4. opencode-router (/opencode + root /v1, /api, /assets for its SPA)
32
+ @opencode_noslash path /opencode
33
+ redir @opencode_noslash /opencode/ 308
34
+
35
+ handle_path /opencode/* {
36
+ reverse_proxy 127.0.0.1:8787
37
+ }
38
+
39
+ handle /v1/* {
40
+ reverse_proxy 127.0.0.1:8787
41
+ }
42
+
43
+ handle /api/* {
44
+ reverse_proxy 127.0.0.1:8787
45
+ }
46
+
47
+ handle /assets/* {
48
+ reverse_proxy 127.0.0.1:8787
49
+ }
50
+
51
+ # 5. REA Doctor status JSON
52
+ handle /rea-status.json {
53
+ root * /data/logs
54
+ file_server
55
+ }
56
+
57
+ # 6. Main Status UI fallback
58
+ handle {
59
+ root * /opt/cbot-defaults/static
60
+ file_server
61
+ }
62
+ }
Dockerfile CHANGED
@@ -1,37 +1,169 @@
1
- FROM node:24-slim
 
 
 
 
2
 
3
- # 1. Install core system dependencies (pure CLI, zero browser packages)
4
- RUN apt-get update && apt-get install -y \
5
- git \
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
  curl \
 
7
  zip \
8
  unzip \
9
  tar \
10
  xz-utils \
11
  bzip2 \
 
 
 
 
 
 
 
 
 
 
12
  python3 \
13
  python3-pip \
 
14
  rsync \
 
 
 
 
 
 
 
 
 
 
15
  && rm -rf /var/lib/apt/lists/*
16
 
17
- # 2. Install OpenClaw CLI and pdfnano
18
- RUN npm install -g openclaw@latest pdfnano
 
 
19
 
20
- # 3. Install Hugging Face Hub (Python)
21
- RUN pip3 install --no-cache-dir --break-system-packages huggingface_hub
 
 
 
 
 
22
 
23
- # 4. Create directory structure
24
- RUN mkdir -p /root/.openclaw/agents/main/agent \
25
- /root/.openclaw/agents/main/sessions \
26
- /root/.openclaw/credentials \
27
- /root/.openclaw/workspace
28
 
29
- ENV PORT=7860
30
- ENV OPENCLAW_GATEWAY_MODE=local
31
- EXPOSE 7860
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
 
33
- # 5. Add and prepare start-openclaw runner script
 
 
 
 
 
 
 
34
  COPY start.sh /usr/local/bin/start.sh
35
- RUN chmod +x /usr/local/bin/start.sh
36
 
 
37
  CMD ["/usr/local/bin/start.sh"]
 
1
+ # ==========================================
2
+ # Stage 1: Build Binwalk 3.1.0 in Rust
3
+ # ==========================================
4
+ FROM rust:1-bookworm AS binwalk-builder
5
+ RUN cargo install binwalk --version 3.1.0 --root /install
6
 
7
+ # ==========================================
8
+ # Stage 2: Main Production Image
9
+ # ==========================================
10
+ FROM node:24-bookworm-slim
11
+
12
+ ENV DEBIAN_FRONTEND=noninteractive
13
+ ENV PORT=7860
14
+ EXPOSE 7860
15
+
16
+ # ------------------------------------------
17
+ # 1. Browser Hard-Block (APT Pinning)
18
+ # ------------------------------------------
19
+ RUN mkdir -p /etc/apt/preferences.d && \
20
+ printf 'Package: *chromium* *chrome* *firefox* *playwright* *puppeteer* *webkit* *geckodriver* *chromedriver* *electron*\nPin: release *\nPin-Priority: -1\n' > /etc/apt/preferences.d/99-block-browsers
21
+
22
+ # ------------------------------------------
23
+ # 2. System Dependencies (Zero Browser Packages)
24
+ # ------------------------------------------
25
+ RUN apt-get update && apt-get install -y --no-install-recommends \
26
+ ca-certificates \
27
  curl \
28
+ git \
29
  zip \
30
  unzip \
31
  tar \
32
  xz-utils \
33
  bzip2 \
34
+ zstd \
35
+ lz4 \
36
+ lzip \
37
+ lzop \
38
+ unar \
39
+ cabextract \
40
+ squashfs-tools \
41
+ cpio \
42
+ e2fsprogs \
43
+ p7zip-full \
44
  python3 \
45
  python3-pip \
46
+ python3-venv \
47
  rsync \
48
+ tshark \
49
+ wabt \
50
+ gdb \
51
+ binutils \
52
+ file \
53
+ patchelf \
54
+ procps \
55
+ util-linux \
56
+ liblz4-1 \
57
+ liblzo2-2 \
58
  && rm -rf /var/lib/apt/lists/*
59
 
60
+ ENV PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 \
61
+ PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=1 \
62
+ PUPPETEER_SKIP_DOWNLOAD=1 \
63
+ REA_BROWSER_EXECUTABLE=""
64
 
65
+ # ------------------------------------------
66
+ # 4. Adoptium Temurin JDK 21 (Full JDK)
67
+ # ------------------------------------------
68
+ RUN mkdir -p /opt/jdk-21 && \
69
+ curl -fsSL "https://github.com/adoptium/temurin21-binaries/releases/download/jdk-21.0.12.1%2B1/OpenJDK21U-jdk_x64_linux_hotspot_21.0.12.1_1.tar.gz" -o /tmp/jdk21.tar.gz && \
70
+ tar -xzf /tmp/jdk21.tar.gz -C /opt/jdk-21 --strip-components=1 && \
71
+ rm -f /tmp/jdk21.tar.gz
72
 
73
+ ENV JAVA_HOME="/opt/jdk-21"
74
+ ENV PATH="/opt/jdk-21/bin:${PATH}"
 
 
 
75
 
76
+ # ------------------------------------------
77
+ # 5. Ghidra 12.1.4 (Official Release)
78
+ # ------------------------------------------
79
+ RUN mkdir -p /opt/ghidra && \
80
+ curl -fsSL "https://github.com/NationalSecurityAgency/ghidra/releases/download/Ghidra_12.1.4_build/ghidra_12.1.4_PUBLIC_20260921.zip" -o /tmp/ghidra.zip && \
81
+ unzip -q /tmp/ghidra.zip -d /opt/ghidra && \
82
+ chmod +x /opt/ghidra/ghidra_12.1.4_PUBLIC/support/analyzeHeadless && \
83
+ rm -f /tmp/ghidra.zip
84
+
85
+ ENV GHIDRA_INSTALL_DIR="/opt/ghidra/ghidra_12.1.4_PUBLIC"
86
+ ENV REA_ANALYSIS_PROVIDER="ghidra"
87
+
88
+ # ------------------------------------------
89
+ # 6. Headless JADX MCP + JADX CLI + Apktool
90
+ # ------------------------------------------
91
+ RUN mkdir -p /opt/jadx /opt/jadx-cli && \
92
+ curl -fsSL "https://github.com/1013503897/jadx-headless-mcp/releases/download/v0.7.1/jadx-headless-mcp-0.7.1-all.jar" -o /opt/jadx/jadx-headless-mcp-0.7.1-all.jar && \
93
+ curl -fsSL "https://github.com/skylot/jadx/releases/download/v1.5.6/jadx-1.5.6.zip" -o /tmp/jadx.zip && \
94
+ unzip -q /tmp/jadx.zip -d /opt/jadx-cli && \
95
+ chmod +x /opt/jadx-cli/bin/jadx && \
96
+ ln -sf /opt/jadx-cli/bin/jadx /usr/local/bin/jadx && \
97
+ rm -f /tmp/jadx.zip && \
98
+ curl -fsSL "https://raw.githubusercontent.com/iBotPeaches/Apktool/master/scripts/linux/apktool" -o /usr/local/bin/apktool && \
99
+ chmod +x /usr/local/bin/apktool && \
100
+ curl -fsSL "https://github.com/iBotPeaches/Apktool/releases/download/v3.0.3/apktool_3.0.3.jar" -o /usr/local/bin/apktool.jar
101
+
102
+ ENV REA_JADX_MCP_JAR="/opt/jadx/jadx-headless-mcp-0.7.1-all.jar"
103
+ ENV REA_APKTOOL_COMMAND="/usr/local/bin/apktool"
104
+
105
+ # ------------------------------------------
106
+ # 7. Binwalk 3.1.0 & Unblob 26.6.4 & Pwntools
107
+ # ------------------------------------------
108
+ COPY --from=binwalk-builder /install/bin/binwalk /usr/local/bin/binwalk
109
+ RUN chmod +x /usr/local/bin/binwalk && \
110
+ pip3 install --no-cache-dir --break-system-packages unblob==26.6.4 pwntools
111
+
112
+ ENV REA_BINWALK_COMMAND="/usr/local/bin/binwalk"
113
+ ENV REA_UNBLOB_COMMAND="/usr/local/bin/unblob"
114
+ ENV REA_FIRMWARE_PRLIMIT_COMMAND="/usr/bin/prlimit"
115
+ ENV REA_PWNTOOLS_PYTHON="/usr/bin/python3"
116
+
117
+ # ------------------------------------------
118
+ # 8. Caddy Server
119
+ # ------------------------------------------
120
+ RUN curl -fsSL "https://caddyserver.com/api/download?os=linux&arch=amd64" -o /usr/local/bin/caddy && \
121
+ chmod +x /usr/local/bin/caddy
122
+
123
+ # ------------------------------------------
124
+ # 9. code-server
125
+ # ------------------------------------------
126
+ RUN curl -fsSL https://code-server.dev/install.sh | sh
127
+
128
+ # ------------------------------------------
129
+ # 10. goFiles & opencode-router
130
+ # ------------------------------------------
131
+ RUN mkdir -p /tmp/dl /opt/opencode-router && \
132
+ curl -fsSL "https://github.com/G-Aman/goFiles/releases/latest/download/gofiles-linux-amd64.zip" -o /tmp/dl/gf.zip && \
133
+ unzip -q /tmp/dl/gf.zip -d /tmp/dl/gf && \
134
+ mv /tmp/dl/gf/gofiles-linux-amd64/gofiles /usr/local/bin/gofiles && \
135
+ chmod +x /usr/local/bin/gofiles && \
136
+ curl -fsSL "https://github.com/G-Aman/opencode-router/releases/latest/download/opencode-router-linux-amd64.zip" -o /tmp/dl/ocr.zip && \
137
+ unzip -q /tmp/dl/ocr.zip -d /tmp/dl/ocr && \
138
+ cp -r /tmp/dl/ocr/opencode-router-linux-amd64/* /opt/opencode-router/ && \
139
+ chmod +x /opt/opencode-router/opencode-router && \
140
+ ln -sf /opt/opencode-router/opencode-router /usr/local/bin/opencode-router && \
141
+ rm -rf /tmp/dl
142
+
143
+ # ------------------------------------------
144
+ # 11. REA & supergateway + Browser Hard-Block
145
+ # ------------------------------------------
146
+ COPY stub-playwright-index.js /tmp/stub-pw.js
147
+ COPY stub-playwright-index.mjs /tmp/stub-pw.mjs
148
+ RUN npm install -g rea-agents@latest supergateway@latest && \
149
+ cp /tmp/stub-pw.js /usr/local/lib/node_modules/rea-agents/node_modules/playwright-core/index.js 2>/dev/null || true && \
150
+ cp /tmp/stub-pw.mjs /usr/local/lib/node_modules/rea-agents/node_modules/playwright-core/index.mjs 2>/dev/null || true && \
151
+ rm -f /tmp/stub-pw.* && \
152
+ for b in chromium chromium-browser google-chrome google-chrome-stable chrome firefox playwright playwright-core puppeteer chromedriver geckodriver msedge brave-browser webkit; do \
153
+ printf '#!/bin/sh\necho "ERROR: Browser engines and browser automation are strictly disabled by host security policy." >&2\nexit 126\n' > "/usr/local/bin/$b" && chmod 755 "/usr/local/bin/$b"; \
154
+ done && \
155
+ rm -rf /root/.npm
156
 
157
+ # ------------------------------------------
158
+ # 12. Copy CBot Repo Defaults & Runtime Runner
159
+ # ------------------------------------------
160
+ RUN mkdir -p /opt/cbot-defaults/init.d /opt/cbot-defaults/static /data
161
+ COPY Caddyfile /opt/cbot-defaults/Caddyfile
162
+ COPY init.d.sh /opt/cbot-defaults/init.d.sh
163
+ COPY init.d/ /opt/cbot-defaults/init.d/
164
+ COPY static/ /opt/cbot-defaults/static/
165
  COPY start.sh /usr/local/bin/start.sh
166
+ RUN chmod +x /usr/local/bin/start.sh /opt/cbot-defaults/init.d.sh /opt/cbot-defaults/init.d/*.sh
167
 
168
+ WORKDIR /data
169
  CMD ["/usr/local/bin/start.sh"]
README.md CHANGED
@@ -1,10 +1,33 @@
1
  ---
2
- title: CBot - OpenClaw
3
- emoji: 🦀
4
  colorFrom: purple
5
  colorTo: blue
6
  sdk: docker
7
  pinned: false
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
+ title: REA MCP Server & Workspace
3
+ emoji: 🔬
4
  colorFrom: purple
5
  colorTo: blue
6
  sdk: docker
7
  pinned: false
8
  ---
9
 
10
+ # REA MCP Server Space (`amangs/cbot`)
11
+
12
+ High-performance reverse-engineering server and persistent workspace backed by [REA](https://github.com/morluto/rea).
13
+
14
+ ## Architecture (`:7860` Caddy Gateway)
15
+
16
+ - **`/mcp`** → Streamable HTTP MCP endpoint (`supergateway` → `rea mcp`)
17
+ - **`/code/`** → In-browser VS Code Server bound to `/data/workspace`
18
+ - **`/files/`** → [goFiles](https://github.com/G-Aman/goFiles) File Manager & WebDAV server on `/data`
19
+ - **`/opencode/`** → [OpenCode Router](https://github.com/G-Aman/opencode-router) WebUI and `/v1` AI proxy
20
+ - **`/`** → System dashboard & analysis status
21
+
22
+ ## Included Engines
23
+
24
+ - **Ghidra 12.1.4 Headless** + **JDK 21**
25
+ - **JADX Headless MCP 0.7.1** + **JADX CLI 1.5.6** + **Apktool 3.0.3**
26
+ - **Binwalk 3.1.0 (Rust)** + **Unblob 26.6.4** + **Pwntools**
27
+ - **WABT** (WebAssembly WAT/WASM) + **TShark** (Packet capture)
28
+ - **Zero Browser Policy**: All browser packages, Playwright, and automation engines are strictly locked and restricted at the kernel, APT, and runtime level.
29
+
30
+ ## Storage & Persistence
31
+
32
+ All persistent data, code-server workspace, uploads, and runtime scripts live on the persistent storage volume mounted at `/data`.
33
+ Custom startup services can be placed into `/data/script/init.d/*.sh` to execute automatically on boot.
init.d.sh ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+ # ============================================================
3
+ # init.d - auto-start hook for persistent services
4
+ #
5
+ # Any executable script placed in /data/script/init.d runs on boot.
6
+ # - Source order: files run in sorted (alphabetical) order
7
+ # - A failing script logs and does NOT block the rest
8
+ # - Scripts are started in the background (setsid)
9
+ # ============================================================
10
+
11
+ INITD_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/init.d"
12
+ LOG="/data/script/init.d.log"
13
+
14
+ if [ ! -d "$INITD_DIR" ]; then
15
+ exit 0
16
+ fi
17
+
18
+ shopt -s nullglob
19
+ scripts=("$INITD_DIR"/*.sh)
20
+
21
+ if [ ${#scripts[@]} -eq 0 ]; then
22
+ exit 0
23
+ fi
24
+
25
+ echo "🧩 init.d: ${#scripts[@]} script(s) to run ($(date -Iseconds))" >> "$LOG"
26
+ for s in "${scripts[@]}"; do
27
+ name="$(basename "$s")"
28
+ chmod +x "$s" 2>/dev/null || true
29
+ echo " ▶️ $name" >> "$LOG"
30
+ setsid bash "$s" >> "$LOG" 2>&1 < /dev/null &
31
+ disown 2>/dev/null || true
32
+ done
33
+ exit 0
init.d/05-code-server.sh ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+ # 05-code-server.sh — code-server service on 127.0.0.1:8443
3
+ DIR="/data/script/code-server"
4
+ WORKSPACE="${CODE_WORKSPACE:-/data/workspace}"
5
+ USER_DATA="${CODE_USER_DATA:-/data/code-server}"
6
+ LOG="$DIR/code-server.log"
7
+
8
+ mkdir -p "$DIR" "$WORKSPACE" "$USER_DATA"
9
+
10
+ if [ -f /data/.env ]; then
11
+ set -a
12
+ . /data/.env
13
+ set +a
14
+ fi
15
+
16
+ export PASSWORD="${CODE_PASSWORD:-${AUTH_TOKEN:-aman@g}}"
17
+ rm -f "$HOME/.config/code-server/config.yaml" "$USER_DATA/config.yaml" 2>/dev/null || true
18
+
19
+ if pgrep -f "code-server.*8443" >/dev/null 2>&1; then
20
+ echo "code-server already running"
21
+ exit 0
22
+ fi
23
+
24
+ exec code-server \
25
+ --port 8443 \
26
+ --auth password \
27
+ --user-data-dir "$USER_DATA" \
28
+ --bind-addr 127.0.0.1:8443 \
29
+ --disable-telemetry \
30
+ --disable-update-check \
31
+ "$WORKSPACE" \
32
+ >> "$LOG" 2>&1
init.d/10-gofiles.sh ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+ # 10-gofiles.sh — goFiles file manager on 127.0.0.1:8100 serving /data
3
+ DIR="/data/script/gofiles"
4
+ CONFIG="$DIR/config.json"
5
+ LOG="$DIR/gofiles.log"
6
+
7
+ mkdir -p "$DIR"
8
+
9
+ if [ -f /data/.env ]; then
10
+ set -a
11
+ . /data/.env
12
+ set +a
13
+ fi
14
+
15
+ GOFILES_USER="${GOFILES_USER:-aman}"
16
+ GOFILES_PASS="${GOFILES_PASS:-${AUTH_TOKEN:-aman@g}}"
17
+
18
+ if [ ! -f "$CONFIG" ]; then
19
+ HASH="$(/usr/local/bin/gofiles -genpass "$GOFILES_PASS" 2>/dev/null | tr -d '\r\n')"
20
+ cat > "$CONFIG" <<EOF
21
+ {
22
+ "app_name": "goFiles",
23
+ "logo_url": "",
24
+ "listen": "127.0.0.1:8100",
25
+ "root": "/data",
26
+ "path_prefix": "",
27
+ "assets": "",
28
+ "users": [
29
+ {
30
+ "name": "${GOFILES_USER}",
31
+ "pass": "${HASH}",
32
+ "home": "/"
33
+ }
34
+ ],
35
+ "allow": {
36
+ "write": true,
37
+ "delete": true,
38
+ "upload": true,
39
+ "urlfetch": true,
40
+ "archive": true,
41
+ "extract": true,
42
+ "edit": true,
43
+ "chmod": true,
44
+ "hash": true,
45
+ "webdav": true
46
+ },
47
+ "max_upload_bytes": 50000000000,
48
+ "chunk_bytes": 4000000,
49
+ "theme": "auto",
50
+ "lang": "en",
51
+ "trust_proxy": true,
52
+ "session_name": "gofm_session"
53
+ }
54
+ EOF
55
+ fi
56
+
57
+ if pgrep -f "/usr/local/bin/gofiles" >/dev/null 2>&1; then
58
+ echo "gofiles already running"
59
+ exit 0
60
+ fi
61
+
62
+ cd "$DIR" || exit 1
63
+ exec /usr/local/bin/gofiles -config "$CONFIG" >> "$LOG" 2>&1
init.d/15-supergateway.sh ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+ # 15-supergateway.sh — REA MCP Server over Streamable HTTP on 127.0.0.1:8093
3
+ DIR="/data/script/rea-mcp"
4
+ LOG="$DIR/supergateway.log"
5
+
6
+ mkdir -p "$DIR" /data/workspace /data/tmp
7
+
8
+ if [ -f /data/.env ]; then
9
+ set -a
10
+ . /data/.env
11
+ set +a
12
+ fi
13
+
14
+ export JAVA_HOME="/opt/jdk-21"
15
+ export PATH="/opt/jdk-21/bin:/opt/jadx-cli/bin:/usr/local/bin:/usr/bin:/bin"
16
+ export GHIDRA_INSTALL_DIR="/opt/ghidra/ghidra_12.1.4_PUBLIC"
17
+ export REA_ANALYSIS_PROVIDER="ghidra"
18
+ export REA_JADX_MCP_JAR="/opt/jadx/jadx-headless-mcp-0.7.1-all.jar"
19
+ export REA_BINWALK_COMMAND="/usr/local/bin/binwalk"
20
+ export REA_UNBLOB_COMMAND="/usr/local/bin/unblob"
21
+ export REA_APKTOOL_COMMAND="/usr/local/bin/apktool"
22
+ export REA_FIRMWARE_PRLIMIT_COMMAND="/usr/bin/prlimit"
23
+ export REA_PWNTOOLS_PYTHON="/usr/bin/python3"
24
+ export REA_GHIDRA_STARTUP_TIMEOUT_MS="${REA_GHIDRA_STARTUP_TIMEOUT_MS:-600000}"
25
+ export TMPDIR="/data/tmp"
26
+ export PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1
27
+ export PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=1
28
+ export PUPPETEER_SKIP_DOWNLOAD=1
29
+
30
+ if pgrep -f "supergateway.*8093" >/dev/null 2>&1; then
31
+ echo "supergateway already running"
32
+ exit 0
33
+ fi
34
+
35
+ AUTH_ARGS=()
36
+ API_KEY="${REA_API_KEY:-${AUTH_TOKEN:-}}"
37
+ if [ -n "$API_KEY" ]; then
38
+ AUTH_ARGS=(--apiKey "$API_KEY")
39
+ fi
40
+
41
+ cd /data/workspace || exit 1
42
+ exec /usr/local/bin/supergateway \
43
+ --stdio "/usr/local/bin/rea mcp" \
44
+ --outputTransport streamableHttp \
45
+ --host 127.0.0.1 \
46
+ --port 8093 \
47
+ --streamableHttpPath /mcp \
48
+ --healthEndpoint /healthz \
49
+ --healthCheck server \
50
+ "${AUTH_ARGS[@]}" \
51
+ >> "$LOG" 2>&1
init.d/20-opencode-router.sh ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+ # 20-opencode-router.sh — OpenCode Router on 127.0.0.1:8787
3
+ DIR="/data/script/opencode-router"
4
+ CONFIG="$DIR/opencode-router.json"
5
+ LOG="$DIR/proxy.log"
6
+
7
+ mkdir -p "$DIR"
8
+
9
+ if [ -f /data/.env ]; then
10
+ set -a
11
+ . /data/.env
12
+ set +a
13
+ fi
14
+
15
+ # Copy bundled assets/public/defaults from /opt/opencode-router if missing
16
+ cp -rn /opt/opencode-router/* "$DIR/" 2>/dev/null || true
17
+
18
+ PROXY_KEY="${OCROUTER_KEY:-${AUTH_TOKEN:-aman@g}}"
19
+
20
+ if [ ! -f "$CONFIG" ]; then
21
+ cat > "$CONFIG" <<EOF
22
+ {
23
+ "host": "127.0.0.1",
24
+ "port": 8787,
25
+ "upstream": "https://opencode.ai/zen/v1",
26
+ "ua": "opencode/1.19.0 ai-sdk/provider-utils/4.0.23 runtime/bun/1.3.14",
27
+ "autoUA": true,
28
+ "injectSession": true,
29
+ "defaultModel": "nemotron-3.5-lightning-free",
30
+ "fallbackModels": [
31
+ "nemotron-3-ultra-free",
32
+ "muse-spark-1.3-contributor-free",
33
+ "mimo-v2.6-flash-free",
34
+ "longcat-2.5-preview-free",
35
+ "space-bunny-free"
36
+ ],
37
+ "disabledModels": [
38
+ "ling-3.0-flash-fin-free"
39
+ ],
40
+ "modelAliases": {},
41
+ "responsesModels": [
42
+ "gpt-5*",
43
+ "gpt-6*",
44
+ "grok-*",
45
+ "muse-spark-*"
46
+ ],
47
+ "rateLimitMax": 0,
48
+ "rateLimitWindowMs": 60000,
49
+ "proxyKey": "${PROXY_KEY}",
50
+ "defaultUpstreamKey": "",
51
+ "outboundProxy": "",
52
+ "trustForwarded": true,
53
+ "timeoutMs": 120000,
54
+ "cacheMs": 0,
55
+ "autoSync": false,
56
+ "autoSyncIntervalMs": 0
57
+ }
58
+ EOF
59
+ fi
60
+
61
+ if pgrep -f "$DIR/opencode-router" >/dev/null 2>&1; then
62
+ echo "opencode-router already running"
63
+ exit 0
64
+ fi
65
+
66
+ cd "$DIR" || exit 1
67
+ exec "$DIR/opencode-router" 8787 >> "$LOG" 2>&1
init.d/90-rea-doctor.sh ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+ # 90-rea-doctor.sh — Export REA readiness report to /data/logs/rea-status.json
3
+ mkdir -p /data/logs /data/tmp
4
+ export JAVA_HOME="/opt/jdk-21"
5
+ export PATH="/opt/jdk-21/bin:/opt/jadx-cli/bin:/usr/local/bin:/usr/bin:/bin"
6
+ export GHIDRA_INSTALL_DIR="/opt/ghidra/ghidra_12.1.4_PUBLIC"
7
+ export REA_ANALYSIS_PROVIDER="ghidra"
8
+ export REA_JADX_MCP_JAR="/opt/jadx/jadx-headless-mcp-0.7.1-all.jar"
9
+ export REA_BINWALK_COMMAND="/usr/local/bin/binwalk"
10
+ export REA_UNBLOB_COMMAND="/usr/local/bin/unblob"
11
+ export REA_APKTOOL_COMMAND="/usr/local/bin/apktool"
12
+ export REA_FIRMWARE_PRLIMIT_COMMAND="/usr/bin/prlimit"
13
+ export REA_PWNTOOLS_PYTHON="/usr/bin/python3"
14
+ export TMPDIR="/data/tmp"
15
+
16
+ /usr/local/bin/rea doctor --format json > /data/logs/rea-status.json 2>/data/logs/rea-doctor.err || true
start.sh CHANGED
@@ -1,59 +1,46 @@
1
  #!/bin/bash
2
  set -e
3
 
4
- OPENCLAW_DIR="/root/.openclaw"
5
- BUCKET_DIR="/data/openclaw"
6
- EXCLUDES=(
7
- --exclude="cache/"
8
- --exclude="logs/"
9
- --exclude="tmp/"
10
- --exclude="*.sock"
11
- --exclude="*.lock*"
12
- --exclude="*-wal"
13
- --exclude="*-shm"
14
- --exclude="*-journal"
15
- )
16
-
17
- # 1. Restore on boot
18
- if [ -d "$BUCKET_DIR" ] && [ "$(ls -A "$BUCKET_DIR" 2>/dev/null)" ]; then
19
- echo "[Storage] Restoring from $BUCKET_DIR..."
20
- rsync -a "${EXCLUDES[@]}" "$BUCKET_DIR/" "$OPENCLAW_DIR/"
21
- echo "[Storage] Restore completed."
22
- fi
23
 
24
- # 2. Database repair
25
- openclaw doctor --fix --yes 2>/dev/null || true
26
-
27
- # 3. Background sync to bucket every 30s
28
- if [ -d "/data" ]; then
29
- mkdir -p "$BUCKET_DIR"
30
- (
31
- set +e
32
- while true; do
33
- sleep 30
34
-
35
- # Flush SQLite WAL to main db files
36
- for db in "$OPENCLAW_DIR"/state/*.sqlite "$OPENCLAW_DIR"/agents/*/agent/*.sqlite; do
37
- if [ -f "$db" ]; then
38
- python3 -c "import sqlite3; c=sqlite3.connect('$db'); c.execute('PRAGMA wal_checkpoint(PASSIVE);'); c.close()" 2>/dev/null || true
39
- fi
40
- done
41
-
42
- # Sync state excluding runtime journals/locks
43
- rsync -a --delete "${EXCLUDES[@]}" "$OPENCLAW_DIR/" "$BUCKET_DIR/" 2>/dev/null || true
44
- done
45
- ) &
46
- fi
47
 
48
- # 4. Graceful shutdown sync
49
- sync_exit() {
50
- echo "[Storage] Container stopping, running final sync..."
51
- rsync -a --delete "${EXCLUDES[@]}" "$OPENCLAW_DIR/" "$BUCKET_DIR/" 2>/dev/null || true
52
- exit 0
53
- }
54
- trap sync_exit SIGTERM SIGINT
55
 
56
- chmod -R 700 "$OPENCLAW_DIR"
 
 
 
 
57
 
58
- # 5. Start gateway
59
- exec openclaw gateway run --port 7860
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  #!/bin/bash
2
  set -e
3
 
4
+ echo "🚀 Starting REA MCP Server Space..."
5
+ echo "=================================="
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ # 1. Directory Structure on Persistent Storage (/data)
8
+ mkdir -p /data/{workspace,logs,tmp,code-server,script/init.d}
9
+ chmod -R 755 /data/script
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
 
11
+ # 2. Seed Default Scripts & Caddyfile if not already customized
12
+ if [ ! -f /data/script/Caddyfile ]; then
13
+ echo "📋 Seeding default Caddyfile..."
14
+ cp /opt/cbot-defaults/Caddyfile /data/script/Caddyfile
15
+ fi
 
 
16
 
17
+ if [ ! -f /data/script/init.d.sh ]; then
18
+ echo "📋 Seeding init.d runner..."
19
+ cp /opt/cbot-defaults/init.d.sh /data/script/init.d.sh
20
+ chmod +x /data/script/init.d.sh
21
+ fi
22
 
23
+ for f in /opt/cbot-defaults/init.d/*.sh; do
24
+ target="/data/script/init.d/$(basename "$f")"
25
+ if [ ! -f "$target" ]; then
26
+ echo "📋 Seeding service script $(basename "$f")..."
27
+ cp "$f" "$target"
28
+ chmod +x "$target"
29
+ fi
30
+ done
31
+
32
+ # 3. Enforce Browser Hard-Block Policies
33
+ echo "🛡️ Verifying browser lockdown..."
34
+ rm -rf /root/.cache/ms-playwright /root/.cache/puppeteer /data/.cache/ms-playwright 2>/dev/null || true
35
+ mkdir -p /root/.cache /data/.cache
36
+ ln -sfn /dev/null /root/.cache/ms-playwright 2>/dev/null || true
37
+ ln -sfn /dev/null /root/.cache/puppeteer 2>/dev/null || true
38
+ echo "Browser lockdown verified: zero browser packages permitted." > /data/logs/browser-block.log
39
+
40
+ # 4. Run Persistent init.d Services
41
+ echo "🧩 Running init.d services..."
42
+ /data/script/init.d.sh
43
+
44
+ # 5. Run Caddy in Foreground on Port 7860
45
+ echo "🌐 Starting Caddy edge proxy on :7860..."
46
+ exec caddy run --config /data/script/Caddyfile --adapter caddyfile
static/index.html ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width,initial-scale=1">
6
+ <title>REA MCP Server &amp; Workspace</title>
7
+ <style>
8
+ :root{--bg:#0b0f19;--card:#131b2e;--border:#1e293b;--text:#e2e8f0;--muted:#94a3b8;--accent:#38bdf8;--ok:#10b981;--warn:#f59e0b}
9
+ *{box-sizing:border-box;margin:0;padding:0}
10
+ body{font-family:ui-sans-serif,system-ui,-apple-system,sans-serif;background:var(--bg);color:var(--text);padding:2rem;max-width:920px;margin:0 auto;line-height:1.5}
11
+ h1{font-size:1.5rem;margin-bottom:.25rem;display:flex;align-items:center;gap:.6rem}
12
+ p.sub{color:var(--muted);font-size:.9rem;margin-bottom:1.75rem}
13
+ .grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));gap:1rem;margin-bottom:1.75rem}
14
+ a.card{display:block;background:var(--card);border:1px solid var(--border);border-radius:10px;padding:1.1rem;text-decoration:none;color:var(--text);transition:border-color .15s}
15
+ a.card:hover{border-color:var(--accent)}
16
+ .card h3{font-size:1rem;margin-bottom:.3rem;color:var(--accent)}
17
+ .card p{font-size:.82rem;color:var(--muted)}
18
+ .panel{background:var(--card);border:1px solid var(--border);border-radius:10px;padding:1.1rem;margin-bottom:1rem}
19
+ .panel h2{font-size:.95rem;margin-bottom:.6rem;color:var(--muted);text-transform:uppercase;letter-spacing:.04em}
20
+ .badges{display:flex;flex-wrap:wrap;gap:.5rem}
21
+ .badge{background:#0f172a;border:1px solid var(--border);padding:.3rem .65rem;border-radius:6px;font-size:.8rem;font-family:ui-monospace,monospace}
22
+ .badge.ok{border-color:rgba(16,185,129,.4);color:#34d399}
23
+ .badge.lock{border-color:rgba(245,158,11,.4);color:#fbbf24}
24
+ code{font-family:ui-monospace,monospace;font-size:.82rem;background:#0f172a;padding:.15rem .4rem;border-radius:4px}
25
+ </style>
26
+ </head>
27
+ <body>
28
+ <h1>REA MCP Server <span id="health" class="badge">checking...</span></h1>
29
+ <p class="sub">Reverse Engineering MCP + Persistent Workspace on <code>/data</code></p>
30
+
31
+ <div class="grid">
32
+ <a class="card" href="/code/">
33
+ <h3>/code/ &rarr;</h3>
34
+ <p>VS Code Server bound to <code>/data/workspace</code></p>
35
+ </a>
36
+ <a class="card" href="/files/">
37
+ <h3>/files/ &rarr;</h3>
38
+ <p>goFiles File Manager &amp; WebDAV on <code>/data</code></p>
39
+ </a>
40
+ <a class="card" href="/opencode/">
41
+ <h3>/opencode/ &rarr;</h3>
42
+ <p>OpenCode Router Dashboard &amp; <code>/v1</code> API</p>
43
+ </a>
44
+ <a class="card" href="/rea-status.json">
45
+ <h3>/mcp &rarr;</h3>
46
+ <p>Streamable HTTP MCP endpoint + Doctor status</p>
47
+ </a>
48
+ </div>
49
+
50
+ <div class="panel">
51
+ <h2>Active Analysis Engines</h2>
52
+ <div class="badges">
53
+ <span class="badge ok">Node.js 24.x (SQLite ready)</span>
54
+ <span class="badge ok">Ghidra 12.1.4 Headless + JDK 21</span>
55
+ <span class="badge ok">JADX Headless MCP 0.7.1 + JADX 1.5.6</span>
56
+ <span class="badge ok">Apktool 3.0.3</span>
57
+ <span class="badge ok">Binwalk 3.1.0 + Unblob 26.6.4</span>
58
+ <span class="badge ok">Pwntools + WABT + TShark</span>
59
+ <span class="badge lock">Browser / Playwright Hard-Blocked</span>
60
+ </div>
61
+ </div>
62
+
63
+ <script>
64
+ fetch('/healthz').then(r=>r.ok?r.text():Promise.reject()).then(()=>{
65
+ const el=document.getElementById('health');
66
+ el.textContent='MCP Online';el.className='badge ok';
67
+ }).catch(()=>{
68
+ const el=document.getElementById('health');
69
+ el.textContent='Starting...';el.className='badge lock';
70
+ });
71
+ </script>
72
+ </body>
73
+ </html>
stub-playwright-index.js ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Strict Security Policy Stub — Playwright & Browser Automation are Prohibited
3
+ */
4
+ const denied = () => {
5
+ throw new Error("Browser engines and automation are strictly disabled on this system by host security policy.");
6
+ };
7
+
8
+ const pw = {
9
+ chromium: {
10
+ launch: denied,
11
+ launchPersistentContext: denied,
12
+ connect: denied,
13
+ connectOverCDP: denied,
14
+ executablePath: () => ""
15
+ },
16
+ firefox: {
17
+ launch: denied,
18
+ launchPersistentContext: denied,
19
+ connect: denied,
20
+ executablePath: () => ""
21
+ },
22
+ webkit: {
23
+ launch: denied,
24
+ launchPersistentContext: denied,
25
+ connect: denied,
26
+ executablePath: () => ""
27
+ },
28
+ _electron: {
29
+ launch: denied
30
+ },
31
+ _android: {},
32
+ selectors: {},
33
+ devices: {},
34
+ errors: {},
35
+ request: {}
36
+ };
37
+
38
+ module.exports = pw;
stub-playwright-index.mjs ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pw from './index.js';
2
+
3
+ export const chromium = pw.chromium;
4
+ export const firefox = pw.firefox;
5
+ export const webkit = pw.webkit;
6
+ export const _electron = pw._electron;
7
+ export const _android = pw._android;
8
+ export const selectors = pw.selectors;
9
+ export const devices = pw.devices;
10
+ export const errors = pw.errors;
11
+ export const request = pw.request;
12
+ export default pw;