github MotherofallVPNs/MoaV v2.3.0

3 hours ago

[2.3.0] - 2026-10-21

sing-box 1.14, the new Snell protocol (on by default), opt-in Hysteria2 gecko obfuscation, component version bumps (incl. a Grafana security patch), a CDN flag fix so an upgrade no longer silently turns off a configured CDN, and a fix so moav update cleanly discards staged local changes. No breaking changes; keys, users, and certificates are untouched.

Added

  • Snell protocol (new sing-box inbound), on by default. A lightweight TCP proxy with HTTP obfuscation, no TLS/domain required (ENABLE_SNELL=true, PORT_SNELL=8389, SNELL_OBFS). Shared-key (one PSK for all users, like the DNS tunnels) — sing-box's multi-user snell has no client-compatible auth, so revoking a user needs a key rotation + re-issue. Needs a Snell v5 client (Surge 5 / Stash / Clash Mi / Mihomo / Clash Meta for Android / FlClash — not v2rayNG or Hiddify). Validated end-to-end against a real Mihomo client and the real sing-box 1.14 binary.
  • sing-box updated to 1.14.0. Our config is already on 1.14's modern surface, so no config change is required; validated by running the real 1.14 sing-box check against the live config (clean, no deprecation warnings). New CI gates render the config and run both a static compatibility check and the real sing-box check / format.
  • Opt-in Hysteria2 gecko obfuscation. HYSTERIA2_OBFS_TYPE (default salamander) can select the new gecko obfuscator, which fragments the QUIC handshake and resists Iran/CN/RU DPI better. Opt-in because gecko needs a client core of sing-box >= 1.14 or hysteria >= 2.9.2 — re-issue bundles and confirm your users' apps before enabling it.
  • --json output for automation (moav status, moav doctor [check], moav user list, moav user add, moav user remove|revoke; moav test --json unchanged in shape). One document on stdout, progress/logs on stderr, and secret-free by construction: no keys, passwords, share-links or server addresses — status only emits the dashboard URLs when they are domain-based, doctor details are colour-stripped and redacted (IPv4/IPv6, links, key-shaped tokens), user list carries names + service membership only. user remove --json reports a per-user result and exits non-zero on an unknown user (the text path still exits 0). Requested by the MoaV deploy app (moav-deploy-app#8).
  • Non-interactive install.sh: MOAV_NONINTERACTIVE=1 (or --non-interactive) with MOAV_DOMAIN, MOAV_EMAIL, MOAV_ADMIN_PASSWORD, MOAV_DOMAINLESS=1 and ENABLE_* toggles from the environment, or --answers FILE read from a regular file that must be mode 0600 and owned by the caller. Fails closed on any missing/invalid answer (weak or non-round-trippable passwords included), never accepts the password on the command line, never prints it, writes .env at 0600 without sed, only fills empty/placeholder values on an existing .env, derives DEFAULT_PROFILES from the toggles, and skips the swap / kernel-tuning host changes. MOAV_BOOTSTRAP=1 opts into running moav bootstrap --yes at the end.

Changed

  • Component version bumps (audit 2026-09-11):
    • Grafana 13.2.0 → 13.2.1 — upstream security fixes (CVE-2026-12704, CVE-2026-14199).
    • telemt 3.5.5 → 3.5.7 — install-probe fix, websocket-lane recovery, macOS status-schema fixes.
    • Xray-core v26.7.28 → v26.9.9.
    • slipstream 2026.02.22.1 → v2026.04.22.1 (server + client builds).
    • MasterDNS 2026.05.10 → v2026.06.13 (release SHA256SUMS still verified at build).
    • TrustTunnelClient held at 1.0.49. v1.1.5 swaps the QUIC stack (quiche → ngtcp2) while the server side stays 1.1.0, so it needs a live client/server compatibility test before bumping.
  • Client test tool: migrated the WireGuard path from the removed sing-box
    wireguard outbound to the 1.14 endpoint form.
  • Protocol count is now 18+ across the README, agent guide, and docs (Snell brought the transports to 18; the roster is 21 counting the 3 donation integrations).
  • Claude issue-triage --max-turns raised 6 → 15: the triage finished its work in ~8 turns, but the action failed a run that exceeded the cap. It no longer fails after completing.
  • moav bootstrap --yes honours the saved DEFAULT_PROFILES instead of entering the interactive service selection (which, without a TTY, fell through to "select later" and left a fresh install with nothing built or started).
  • moav test --json keeps stdout clean: the progress lines and the client image build now go to stderr, so the JSON no longer has to be scraped out of docker build output.
  • confirm() (CLI and installer) returns its default without opening /dev/tty when MOAV_NONINTERACTIVE=1.

Fixed

  • A configured CDN no longer needs a second toggle, and an upgrade no longer turns it off. ENABLE_CDN now ships unset (commented) in .env.example instead of =false, so cdn_enabled()'s rule governs everywhere: CDN is on exactly when CDN_SUBDOMAIN is set and proxied through Cloudflare, and off otherwise. Because the flag is unset, moav update no longer appends ENABLE_CDN=false onto an upgrading server — the append that could silently drop a working CDN at the next bootstrap. The compact moav:// bundle builder now gates on cdn_enabled as well, matching every other CDN path (it was the lone reader of the raw flag). An explicit ENABLE_CDN=true/false still wins.
  • moav update "Discard changes" now fully resets. The Discard option used git checkout -- ., which only clears unstaged edits; staged changes (git status MM / A, e.g. a hand-edited docker-compose.yml or added exporter files) survived and the pull still aborted with "local changes would be overwritten by merge" even after Discard reported success. It now uses git reset --hard, which clears the index too.
  • moav update -b <ref> now accepts a tag, not only a branch. Switching an install to a release candidate (moav update -b v2.3.0-rc.1) failed with "Branch '…' does not exist" because the target was validated against branch refs only. It now resolves tags too (fetching them first) and checks out a tag in detached HEAD without attempting a pull.
  • .env no longer carries inline comments on variable lines. moav update copied new options from .env.example verbatim, so a line like PORT_SNELL=8389 # Snell reached the live .env; a consumer reading the value with a raw grep|cut then folded the comment into it (the AmneziaWG port once became <ip>:51821 # AmneziaWG …, so clients connected but relayed nothing). Every note now sits on its own line in .env.example, the update path strips a trailing inline comment defensively, and a CI gate keeps it that way.
  • XDNS now carries VLESS Encryption (Xray >= 26.9 compatible). This release's Xray bump (v26.9.9) began rejecting a VLESS outbound with no TLS/encryption that dials a public IP, so xray refused to start and XDNS failed (caught by the rc.3 e2e). XDNS dials a public resolver/server over mKCP, so the VLESS layer now carries its own encryption: a server-wide X25519 keypair is minted at bootstrap (openssl, no extra binary; stored in state/keys/xdns.env), with decryption on the server XDNS inbound and encryption in every client bundle. This also hardens XDNS (its DNS-tunnelled VLESS was previously unencrypted) and unblocks it for anyone on an already-updated Xray client.
  • Telegram release notification pins its link preview to the release page. The preview showed whatever link appeared first in the notes body (e.g. a client's App Store page) instead of the release. It now sets link_preview_options.url to the release/issue URL. Same fix in moav-client.
  • moav status lost published ports when docker compose ps --format json returned an array: the array-to-lines split cut inside a container's Publishers list, so a service with two ports showed none and the next row was skipped. The split is now brace-depth aware.

Testing

  • tests/cli-json-test.sh — every --json shape (valid JSON, stdout-only, no planted secret substring), via the real dispatcher with a fake docker and fake provisioning scripts.
  • tests/install-noninteractive-test.sh — answers validation, 0600 / ownership checks, argv password refusal, .env rendering and re-run safety.

Quick Install

curl -fsSL https://moav.sh/install.sh | bash

This will install MoaV to /opt/moav and guide you through setup.

Documentation

moav.sh/docs — full documentation

Get started

Reference

Understand it

Help out

🤖 Running it with an AI agent? 🤖 moav.sh/llms.txt is a compact orientation for coding agents; llms-full.txt is the whole corpus. Both ship as release assets.

Community

Telegram · X · Issues · moav.sh

Don't miss a new MoaV release

NewReleases is sending notifications on new releases.