Skip to content

Commit 33e87b5

Browse files
gmarzotclaude
andauthored
scripts & onboarding cleanup: README + no-sudo, bind-address knob, #441/#391 (#456)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 3fbe374 commit 33e87b5

8 files changed

Lines changed: 129 additions & 20 deletions

File tree

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,9 @@ DartConfiguration.tcl
1919
# CPack
2020
_CPack_Packages/
2121

22-
# Dependency scratch dir
22+
# Dependency scratch dirs
2323
/.scratch/
24+
/.docker-deps/
2425

2526
# OS
2627
.DS_Store
@@ -29,6 +30,7 @@ _CPack_Packages/
2930
.vscode/
3031
.claude/
3132
.cache/
33+
AGENTS.md
3234

3335
# Docker secrets (never commit)
3436
docker/.env

BUILD.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ formatting, and CI.
1919
Six steps. Each links to its detail section.
2020

2121
1. **Clone and init the moxygen submodule.**
22-
`git clone … && cd moqx && git submodule update --init`
22+
`git clone … && cd moqx && git submodule update --init --recursive`
2323
the submodule pins the exact moxygen commit the build will use
2424
(see [Dependency Modes](#dependency-modes)).
2525
2. **Ensure CMake 3.22+** is on `PATH`. All current targets ship a
@@ -100,7 +100,7 @@ docker run --rm -it -v "$PWD":/src -w /src ubuntu:22.04 bash
100100

101101
# Inside the container:
102102
apt-get update && apt-get install -y cmake ninja-build sudo git curl ca-certificates
103-
git submodule update --init
103+
git submodule update --init --recursive
104104
sudo deps/moxygen/standalone/install-system-deps.sh
105105
./scripts/build.sh setup --from-source # build from source (no release artifacts available offline)
106106
./scripts/build.sh

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ handler and create `MoQRelaySession` instances for incoming connections.
6565
6666
```bash
6767
git clone https://github.com/openmoq/moqx.git && cd moqx
68-
git submodule update --init
68+
git submodule update --init --recursive
6969
sudo deps/moxygen/standalone/install-system-deps.sh # system libs (both modes)
7070

7171
./scripts/build.sh setup # download prebuilt deps (~1 min)

scripts/README.md

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
# moqx scripts
2+
3+
Helper scripts for running and benchmarking a moqx relay. Run them from the
4+
repository root.
5+
6+
## Relay quickstart
7+
8+
Run a relay with [`moqx-run.sh`](moqx-run.sh). It fills
9+
[`config.bench.yaml`](config.bench.yaml) (a template with sensible defaults)
10+
and serves it. Override anything with a flag or env var — you rarely need to.
11+
12+
### Simplest possible
13+
14+
```bash
15+
# local dev relay — built-in self-signed cert, no root needed
16+
./scripts/moqx-run.sh --insecure
17+
```
18+
19+
Listens on **udp/4433** (MoQT), admin HTTP on **8000**, WebTransport endpoint
20+
**`/moq-relay`**. Offers MoQT drafts **16, 14, 18** (negotiates 16 with most
21+
clients; draft-18-only clients get 18).
22+
23+
### The handful of commands you'll actually use
24+
25+
```bash
26+
# 1. Local dev (insecure dev cert, no root needed)
27+
./scripts/moqx-run.sh --insecure
28+
29+
# 2. Real TLS — Let's Encrypt cert under DOMAIN (add --sudo if the key is root-owned 0600)
30+
DOMAIN=relay.example.com ./scripts/moqx-run.sh --sudo
31+
32+
# 3. Pin a single draft (e.g. force draft-18)
33+
./scripts/moqx-run.sh --insecure --moqt-versions 18
34+
35+
# 4. Different port / endpoint
36+
./scripts/moqx-run.sh --insecure --port 5433 --endpoint /relay
37+
38+
# 5. Validate the config without serving
39+
./scripts/moqx-run.sh --subcmd validate-config
40+
41+
# 6. Show the resolved config + exact command, run nothing
42+
./scripts/moqx-run.sh -n
43+
```
44+
45+
### Defaults (all overridable)
46+
47+
| knob | default | flag / env |
48+
|---|---|---|
49+
| QUIC stack | mvfst | `--quic-stack mvfst\|picoquic` |
50+
| listen port | 4433 | `--port` |
51+
| admin port | 8000 | `--admin-port` |
52+
| endpoint | `/moq-relay` | `--endpoint` |
53+
| MoQT drafts | 16,14,18 (server-pref order) | `--moqt-versions` |
54+
| IO threads | 4 | `--threads` |
55+
| congestion control | bbr | `--cc` |
56+
| object cache | on | `--cache` / `--no-cache` |
57+
| TLS | real cert under `DOMAIN`, else dev cert | `--insecure` / `--cert` / `--key` |
58+
| sudo | off (runs as you) | `--sudo` (only for a root-owned key) |
59+
60+
Full option list: `./scripts/moqx-run.sh --help`.
61+
62+
### Gotchas
63+
64+
- **picoquic needs a *real* cert** (no insecure dev cert): `--quic-stack picoquic`
65+
with `DOMAIN=...` (or `--cert/--key`).
66+
- Runs without sudo by default. If your TLS key is root-owned (e.g. a
67+
letsencrypt `0600 privkey.pem`), add `--sudo` so the relay can read it.
68+
- Check the relay is up: `curl http://localhost:8000/info`.
69+
70+
### Logging (if you need it)
71+
72+
- `-x ".=DBG4"` — verbose for **moqx's own** components (folly XLOG).
73+
- `-v 2` — verbose for the **QUIC/HTTP stack** underneath (mvfst/proxygen, glog).
74+
75+
## Other scripts
76+
77+
- [`perf-test.sh`](perf-test.sh) — relay throughput / subscriber-ramp perf test
78+
(drives the relay via `moqx-run.sh`). See `./scripts/perf-test.sh` header for
79+
options; short flags `-s`/`-d`/`-t`/`-l`/`-j` mirror the common ones.
80+
- [`config.bench.yaml`](config.bench.yaml) — the relay config template
81+
`moqx-run.sh` renders.

scripts/build.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ check_system_deps() {
180180
echo " sudo apt-get install -y build-essential cmake ninja-build \\"
181181
echo " libssl-dev libunwind-dev libgoogle-glog-dev libgflags-dev \\"
182182
echo " libdouble-conversion-dev libevent-dev libsodium-dev libzstd-dev \\"
183-
echo " libboost-all-dev libfmt-dev zlib1g-dev libc-ares-dev gperf"
183+
echo " libboost-all-dev libfmt-dev zlib1g-dev libc-ares-dev gperf libbrotli-dev"
184184
;;
185185
fedora|centos|rhel)
186186
echo "Install with:"

scripts/config.bench.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ listeners:
6767
moqt_versions: ${MOQX_MOQT_VERSIONS}
6868
udp:
6969
socket:
70-
address: "::"
70+
address: "${MOQX_BIND_ADDR}"
7171
port: ${MOQX_PORT}
7272
tls:
7373
cert_file: "${MOQX_CERT}"
@@ -106,5 +106,5 @@ service_defaults:
106106

107107
admin:
108108
port: ${MOQX_ADMIN_PORT}
109-
address: "::"
109+
address: "${MOQX_BIND_ADDR}"
110110
plaintext: true

scripts/moqx-run.sh

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,15 @@ usage() {
1515
Usage: $(basename "$0") [options] [-- <extra args to moqx>]
1616
1717
Logging (override .env/defaults):
18+
-x, --xlog SPEC folly XLOG config for moqx's own components, passed as
19+
--logging=SPEC. Primary logging (moqx standardizes on XLOG).
20+
The -v/-L/-m flags below tune the underlying QUIC/HTTP stack (mvfst/proxygen/
21+
fizz), which still logs via glog — kept until that stack moves to folly XLOG:
1822
-v, --verbose N GLOG_v (0=off, 1-4 increasing detail)
1923
-L, --log-level N GLOG_minloglevel (0=INFO 1=WARN 2=ERR 3=FATAL)
20-
-m, --vmodule SPEC GLOG_vmodule (e.g. MoQSession=4,MoQForwarder=3)
21-
-x, --xlog SPEC folly XLOG config (passed as --logging=SPEC)
24+
-m, --vmodule SPEC GLOG_vmodule — per-source-file glog VLOG for the stack
25+
(e.g. Acceptor=4,SSLContextManager=2). moqx/moxygen
26+
components log via XLOG: use -x for those, not -m.
2227
2328
Relay tuning (templated into the config; CLI > .env > default):
2429
--threads N IO worker threads, must be >= 1 (default 4)
@@ -38,6 +43,8 @@ Listener (templated into the config; CLI > .env > default):
3843
--moqt-versions LIST advertised MoQT drafts in server-preference order,
3944
e.g. 16,14,18 (default 16,14,18; first listed wins).
4045
Pass a single value (e.g. 18) to pin one draft.
46+
--bind ADDR bind address for the listener + admin (default 127.0.0.1;
47+
use :: or 0.0.0.0 to accept remote clients, e.g. cross-box bench)
4148
--port N UDP listen port (default 4433)
4249
--admin-port N admin HTTP port (default 8000)
4350
--endpoint PATH WebTransport endpoint path (default /moq-relay)
@@ -56,7 +63,9 @@ Execution:
5663
Bare flag auto-detects libjemalloc.so.2.
5764
--check-sysctl report current vs recommended UDP/network sysctls
5865
(with the commands to raise them) and exit
59-
--no-sudo run without sudo (cert files must be user-readable)
66+
--sudo run the relay under sudo (only needed to read a
67+
root-owned key, e.g. letsencrypt's 0600 privkey;
68+
default is no sudo)
6069
-n, --dry-run print resolved env + command, don't exec
6170
-h, --help this help
6271
@@ -65,7 +74,7 @@ Environment overrides (via .env or shell):
6574
MOQX_VERBOSE, MOQX_LOG_LEVEL, GLOG_vmodule, MOQX_JEMALLOC
6675
MOQX_THREADS, MOQX_UDP_BUFFER, MOQX_RECV_PKTS, MOQX_SEND_PKTS, MOQX_CC,
6776
MOQX_LOCAL_FWD, MOQX_CACHE, MOQX_BPF_STEERING, MOQX_IGNORE_PATH_MTU,
68-
MOQX_RELAY_THREAD, MOQX_STACK, MOQX_MOQT_VERSIONS, MOQX_PORT, MOQX_ADMIN_PORT, MOQX_ENDPOINT,
77+
MOQX_RELAY_THREAD, MOQX_STACK, MOQX_MOQT_VERSIONS, MOQX_BIND_ADDR, MOQX_PORT, MOQX_ADMIN_PORT, MOQX_ENDPOINT,
6978
MOQX_INSECURE, MOQX_CERT, MOQX_KEY, MOQX_MAX_TRACKS, MOQX_MAX_GROUPS,
7079
MOQX_RELAY_ID, MOQX_RESOLVED_CONFIG (env-only; no CLI flag)
7180
@@ -74,7 +83,8 @@ Examples:
7483
$0 --threads 8 --udp-buffer 16777216 # 8 IO threads, 16 MB socket buffer
7584
$0 --recv-pkts 256 -j # Alan's recv loop + jemalloc
7685
$0 --check-sysctl # audit kernel UDP buffers, then exit
77-
$0 --subcmd validate-config --no-sudo # just validate the config
86+
$0 --subcmd validate-config # just validate the config
87+
DOMAIN=relay.example.com $0 --sudo # real TLS, root-owned letsencrypt key
7888
$0 -n # show what would run
7989
EOF
8090
}
@@ -128,7 +138,7 @@ CLI_JEMALLOC="" # "" = unset; "auto" or explicit path
128138
CLI_THREADS="" CLI_UDP_BUFFER="" CLI_RECV_PKTS="" CLI_SEND_PKTS="" CLI_CC=""
129139
CLI_LOCAL_FWD="" CLI_CACHE="" CLI_RELAY_THREAD="" CLI_INSECURE="" # tri-state booleans
130140
CLI_IGNORE_PMTU="" CLI_BPF="" # tri-state booleans
131-
CLI_STACK="" CLI_MOQT_VERSIONS="" CLI_PORT="" CLI_ADMIN_PORT="" CLI_ENDPOINT="" CLI_CERT="" CLI_KEY=""
141+
CLI_STACK="" CLI_MOQT_VERSIONS="" CLI_BIND="" CLI_PORT="" CLI_ADMIN_PORT="" CLI_ENDPOINT="" CLI_CERT="" CLI_KEY=""
132142
CHECK_SYSCTL=0 DRY_RUN=0
133143
PASSTHRU=()
134144

@@ -153,6 +163,7 @@ while (($#)); do
153163
--bpf-steering) CLI_BPF=true; shift ;;
154164
--quic-stack) CLI_STACK="$2"; shift 2 ;;
155165
--moqt-versions) CLI_MOQT_VERSIONS="$2"; shift 2 ;;
166+
--bind) CLI_BIND="$2"; shift 2 ;;
156167
--port) CLI_PORT="$2"; shift 2 ;;
157168
--admin-port) CLI_ADMIN_PORT="$2"; shift 2 ;;
158169
--endpoint) CLI_ENDPOINT="$2"; shift 2 ;;
@@ -168,7 +179,7 @@ while (($#)); do
168179
if [[ -n "${2:-}" && "$2" != -* ]]; then CLI_JEMALLOC="$2"; shift 2
169180
else CLI_JEMALLOC="auto"; shift; fi ;;
170181
--check-sysctl) CHECK_SYSCTL=1; shift ;;
171-
--no-sudo) CLI_USE_SUDO=0; shift ;;
182+
--sudo) CLI_USE_SUDO=1; shift ;;
172183
-n|--dry-run) DRY_RUN=1; shift ;;
173184
-h|--help) usage; exit 0 ;;
174185
--) shift; PASSTHRU+=("$@"); break ;;
@@ -226,6 +237,9 @@ case "$MOQX_STACK" in mvfst|picoquic) ;; *) echo "invalid --quic-stack: $MOQX_ST
226237
# server-preference order — the relay picks the first listed version the client
227238
# also supports. Default offers d16, d14, then d18 as a fallback.
228239
export MOQX_MOQT_VERSIONS="$(norm_versions "${CLI_MOQT_VERSIONS:-${MOQX_MOQT_VERSIONS:-16,14,18}}")"
240+
# Bind address for the listener + admin. Local-safe default (127.0.0.1); set
241+
# :: / 0.0.0.0 (e.g. via perf-test.sh or --bind) to accept remote clients.
242+
export MOQX_BIND_ADDR="${CLI_BIND:-${MOQX_BIND_ADDR:-127.0.0.1}}"
229243
export MOQX_PORT="${CLI_PORT:-${MOQX_PORT:-4433}}"
230244
export MOQX_ADMIN_PORT="${CLI_ADMIN_PORT:-${MOQX_ADMIN_PORT:-8000}}"
231245
export MOQX_ENDPOINT="${CLI_ENDPOINT:-${MOQX_ENDPOINT:-/moq-relay}}"
@@ -268,11 +282,17 @@ RESOLVED_CONFIG="${MOQX_RESOLVED_CONFIG:-/tmp/moqx-resolved.yaml}"
268282
envsubst < "$CONFIG_TEMPLATE" > "$RESOLVED_CONFIG"
269283

270284
# ── GLOG — map MOQX_* → GLOG_* (matches docker/entrypoint.sh convention) ─
285+
# TODO(folly-xlog): drop this block once the QUIC/HTTP stack (mvfst/proxygen/
286+
# fizz) logging moves to folly XLOG and glog leaves the link. Load-bearing
287+
# until then — it's the only knob for stack-level diagnostics.
271288
export GLOG_logtostderr=1
272289
export GLOG_colorlogtostderr=1
273290
export GLOG_minloglevel="${CLI_LOG_LEVEL:-${MOQX_LOG_LEVEL:-0}}"
274291
export GLOG_v="${CLI_VERBOSE:-${MOQX_VERBOSE:-0}}"
275-
export GLOG_vmodule="${CLI_VMODULE:-${GLOG_vmodule:-MoqxRelay=3,MoQSession=3,MoQForwarder=3,MoqxCache=2}}"
292+
# Default empty: GLOG_v already sets global stack VLOG; vmodule only targets
293+
# specific stack source files (glog VLOG). The old default named moqx/moxygen
294+
# components, which log via folly XLOG (-x), so it filtered nothing.
295+
export GLOG_vmodule="${CLI_VMODULE:-${GLOG_vmodule:-}}"
276296

277297
# ── jemalloc resolution (CLI > env) ──────────────────────────────────────
278298
JEMALLOC_REQ="${CLI_JEMALLOC:-${MOQX_JEMALLOC:-}}"
@@ -301,12 +321,12 @@ fi
301321

302322
# ── Run ──────────────────────────────────────────────────────────────────
303323
SUBCMD="${CLI_SUBCMD:-${MOQX_SUBCMD:-serve}}"
304-
USE_SUDO="${CLI_USE_SUDO:-${MOQX_USE_SUDO:-1}}"
324+
USE_SUDO="${CLI_USE_SUDO:-${MOQX_USE_SUDO:-0}}"
305325
CMD=("$MOQX_BIN" "$SUBCMD" --config "$RESOLVED_CONFIG" "${PASSTHRU[@]}")
306326

307327
if (( DRY_RUN )); then
308328
echo "# relay knobs (templated into config)"
309-
echo "relay_id=$MOQX_RELAY_ID stack=$MOQX_STACK moqt_versions=$MOQX_MOQT_VERSIONS port=$MOQX_PORT admin_port=$MOQX_ADMIN_PORT endpoint=$MOQX_ENDPOINT insecure=$MOQX_INSECURE"
329+
echo "relay_id=$MOQX_RELAY_ID stack=$MOQX_STACK moqt_versions=$MOQX_MOQT_VERSIONS bind=$MOQX_BIND_ADDR port=$MOQX_PORT admin_port=$MOQX_ADMIN_PORT endpoint=$MOQX_ENDPOINT insecure=$MOQX_INSECURE"
310330
echo "resolved_config=$RESOLVED_CONFIG"
311331
echo "threads=$MOQX_THREADS relay_thread=$MOQX_RELAY_THREAD local_fwd=$MOQX_LOCAL_FWD bpf_steering=$MOQX_BPF_STEERING cache=$MOQX_CACHE"
312332
echo "cc=$MOQX_CC send_pkts=$MOQX_SEND_PKTS recv_pkts=$MOQX_RECV_PKTS udp_buffer=$MOQX_UDP_BUFFER ignore_path_mtu=$MOQX_IGNORE_PATH_MTU"
@@ -341,6 +361,10 @@ if [[ "$SUBCMD" == serve && "$MOQX_INSECURE" == false ]]; then
341361
for f in "$MOQX_CERT" "$MOQX_KEY"; do
342362
"${probe[@]}" "$f" 2>/dev/null || {
343363
echo "error: TLS cert/key not readable: $f" >&2
364+
if [[ -e "$f" ]]; then
365+
echo " - file exists but isn't readable as $(id -un); if it's root-owned (e.g." >&2
366+
echo " letsencrypt's 0600 privkey), re-run with --sudo" >&2
367+
fi
344368
echo " - check DOMAIN spelling — it names the /etc/letsencrypt/live/<dir>, not the served host" >&2
345369
echo " (a wildcard *.example.com cert lives under the 'example.com' dir)" >&2
346370
echo " - or pass --cert/--key explicitly, or --insecure for the built-in dev cert" >&2

scripts/perf-test.sh

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -244,11 +244,13 @@ echo ""
244244
ulimit -n 65536 2>/dev/null || true
245245
echo "Starting relay (use_relay_thread=$USE_RELAY_THREAD, local_forwarders=$USE_LOCAL_FORWARDERS, io_threads=$IO_THREADS, transport=$TRANSPORT, mvfst_bpf_steering=$BPF_STEERING)..."
246246

247-
# Map perf knobs -> moqx-run.sh. --no-sudo is REQUIRED: moqx-run execs the relay,
248-
# so under sudo $! would be the sudo PID and perf -p would profile sudo, not moqx.
247+
# Map perf knobs -> moqx-run.sh. moqx-run runs without sudo by default (do NOT
248+
# set MOQX_USE_SUDO=1 / pass --sudo here): it execs the relay, so under sudo $!
249+
# would be the sudo PID and perf -p would profile sudo, not moqx.
249250
RELAY_RUN_ARGS=(
250-
--no-sudo --insecure --no-cache --ignore-path-mtu
251+
--insecure --no-cache --ignore-path-mtu
251252
--bin "$BINARY"
253+
--bind "::" # all interfaces: the perf client may run on another box
252254
--port "$RELAY_PORT"
253255
--admin-port "$RELAY_ADMIN_PORT"
254256
--endpoint "$ENDPOINT"

0 commit comments

Comments
 (0)