Files
vpn-proxy/docs/superpowers/specs/2026-05-19-macos-client-design.md

2.1 KiB

macOS Docker Client Design

Goal

Add a simple macOS-friendly Docker client that behaves like the previous local proxy product: the user runs one container, opens a web UI, loads a subscription, chooses a server, and points macOS apps at 127.0.0.1:8080.

Product Shape

The client is not a transparent gateway. It must not require router changes, host networking, NET_ADMIN, iptables, ipset, or TProxy. The first-screen UI should explain the current proxy state, active server, and exact local proxy addresses. Gateway-only controls remain available only when the app runs in gateway mode.

Runtime Architecture

APP_MODE=client switches the config generator to proxy-only sing-box config:

  • one mixed inbound on PROXY_PORT;
  • no tproxy inbound;
  • custom routing rules still apply before fallback;
  • proxyDefaultMode controls the mixed proxy fallback and defaults to VPN;
  • generated configs still pass sing-box check before restart.

The client Docker image builds the React frontend inside Docker so macOS installation does not require local Node.js. Docker publishes only loopback ports:

  • 127.0.0.1:3456 for the UI;
  • 127.0.0.1:8080 for HTTP/SOCKS proxy.

Installer

The macOS installer is a curl-friendly shell script. It checks macOS, Docker, Docker Compose, and Git, clones or updates the repository under ~/.vpn-proxy-client, then runs the client compose file with --build. It prints the UI URL, proxy URLs, and optional networksetup commands, but does not change system proxy settings automatically.

UI

Client mode gets a user-facing overview based on the old workflow:

  • status: ready, stopped, not configured, applying, error;
  • active server and traffic quota;
  • copyable HTTP and SOCKS5 proxy URLs;
  • short macOS setup commands;
  • primary actions: load subscription, choose server, restart, stop.

Gateway terminology such as TProxy, devices, router, transparent fallback, and direct bypass cache is hidden in client mode.

Verification

Use node:test for server config behavior, then run:

  • npm test;
  • npm run build;
  • docker compose -f docker-compose.client.yml config.