All notable changes to MoaV will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
1.4.5 - 2026-03-09
- Snowflake build failing in Russia —
git clonefromgitlab.torproject.orgtimes out in countries where it's blocked; replaced withgo installvia Go module proxy (proxy.golang.org, Google CDN) which bypasses the block. Applies to bothDockerfile.snowflake(proxy) andDockerfile.client(snowflake-client)
- DNS documentation refreshed — New "Do I Need a Domain?" section, domain-less mode guide, split port forwarding tables (domain-less vs with domain), all protocols/ports updated, Raspberry Pi tips, CGNAT troubleshooting
- telemt updated to 3.3.14
- TrustTunnel updated to 1.0.13
- TrustTunnel Client updated to 1.0.19
1.4.4 - 2026-03-03
- Auto-detect missing
.envvariables —moav updatenow compares your.envwith.env.exampleand offers to auto-add new variables with defaults (timestamped separator for easy review) - CDN WS path auto-generation — Bootstrap generates a random realistic API-like path (e.g.,
/api/v3/storage/download/update-bundle-4821.bin) instead of the obvious/ws, persisted in state for consistency across regenerations - HTTPUpgrade as default CDN transport — Less fingerprinted by DPI than WebSocket; configurable via
CDN_TRANSPORTenv var (httpupgradeorws) - TLS fingerprint randomization — All protocols now use
fp=random(rotates real browser fingerprints: Chrome, Firefox, Safari, Edge) instead of hardcodedchrome - Domain naming strategy guide — New section in DNS docs with good/bad domain name examples and CDN subdomain advice for DPI evasion
- CDN split SNI/Address/Host — Client configs now use root domain as TLS SNI (less suspicious to DPI than
cdn.domain.com), with CDN subdomain only in the encrypted Host header for Cloudflare routing. OptionalCDN_ADDRESSfor full domain separation (CDN_SNI,CDN_ADDRESSenv vars) - Cloudflare SSL Flexible requirement — Added clear documentation about SSL mode requirement across DNS, Setup, and Troubleshooting docs (prevents 525 errors)
- Shell autocompletion —
moav installnow installs bash/zsh completions for all commands, subcommands, services, profiles, and protocols;moav uninstallremoves them - Admin dashboard redesign — Services displayed as cards with auto-fill grid layout, green border for running services; favicon and logo in browser tab/header; centered footer with version and GitHub link
moav user revoketelemt support — Revoking a user now removes their MTProxy secret from all three telemt config sections and restarts telemt
moav updatecrashing silently —check_component_versions()failed underset -euo pipefailwhen version variables (e.g.,TELEMT_VERSION,SLIPSTREAM_VERSION) were missing from older.envfiles; grep returning exit code 1 killed the script before reachingcheck_env_additions()moav logs <service>showing all containers — Service names likeslipstreamwere resolved as profile aliases (→dnstunnel), causing--profile dnstunnelto show all DNS tunnel services; now checks exact profile names first, then falls back to service resolution- Domainless mode
unbound variablecrash —TROJAN_LINK,HY2_LINK, and their IPv6 variants were referenced unconditionally but only set when a domain is configured; all references now guarded with[[ -n "${VAR:-}" ]] moav uninstallaborting on root-owned files — Docker-created files underconfigs/,state/,outputs/are owned by root;set -euo pipefail+rm= permission denied = script abort; now uses_wrm()helper with sudo fallback- Permission denied on
state/users/andconfigs/— Docker containers create directories as root; non-root users couldn't write when adding/revoking users; added sudo mkdir/chmod fallback in user-add and user-revoke scripts mvinteractive prompt on Debian/Ubuntu — Defaultmv -ialias caused scripts to hang waiting for confirmation; allmvcalls now usemv -facross all scriptsxxd: command not foundon minimal systems — Replaced allxxd -pusage with POSIX-portableod -An -tx1 | tr -d ' \n'(xxd requires vim package, not installed on minimal Raspberry Pi OS)- Docker Compose service status checks always returning true —
docker compose ps --status runningreturns exit code 0 with only a header row even when no containers match; all service-running checks now usetail -n +2 | grep -q .to skip the header and verify actual container output exists - User add failing when WireGuard not running — Config file existing was enough to trigger WireGuard peer add attempt; now checks if the Docker service is actually running first, skips gracefully with info message if not
- Snowflake dashboard false positive —
check_service_status("snowflake")was hardcoded to return"running"; changed to"unknown"with distinct?indicator and hover tooltip explaining host networking limitation - AmneziaWG
awgbinary missing from Docker image — Built in multi-stage builder but never copied to final image; addedCOPY --from=builder /usr/bin/awg /usr/bin/awg - Grafana dashboard starring silently failing —
star_dashboards()used GNU wget flags (--user,--password,--auth-no-challenge) unsupported by BusyBox wget in the official Grafana Alpine image; replaced with--header "Authorization: Basic ..."which works everywhere. Also added missingmoav-amneziawgto star list - Dashboard user protocol tags incomplete — telemt detection checked wrong filename (
telegram-mtproxy.txtinstead oftelegram-proxy-link.txt); added missing dnstt and Slipstream protocol detection
- CDN bundle files renamed —
cdn-vless-ws-singbox.json→cdn-vless-singbox.json,cdn-vless-ws.txt→cdn-vless.txt(reflects transport-agnostic naming)
1.4.1 - 2026-03-02
- Telegram MTProxy (telemt) — Rust-based MTProxy with Fake-TLS V2 for direct Telegram access in censored regions
- New
telemtservice on port 993/tcp (IMAPS port — blends with expected TLS traffic) - Fake-TLS V2: real certificate emulation, timing simulation, ALPN enforcement (mimics
dl.google.com) - Per-user 32-hex secrets with configurable connection limits (
TELEMT_MAX_TCP_CONNS,TELEMT_MAX_UNIQUE_IPS) tg://proxyandhttps://t.me/proxylinks auto-generated in user bundles with QR codes- No domain required — works with IP address only (fake-TLS domain is for DPI evasion, not DNS)
- No client binary needed — users connect via official Telegram app
- Profile:
telegram(aliases:tg,mtproxy,telemt) ENABLE_TELEMT=trueby default
- New
- Telegram MTProxy Grafana Dashboard — Per-user connection monitoring
- Active Users, Total/Bad Connections, Handshake Timeouts, Uptime stat panels
- Connection Rate, Active Connections & Users, Bandwidth Rate time series
- Per-user breakdown: Active Connections by User, Unique IPs by User
- Per-User Details table and ME Health (Messaging Engine) charts
moav user addtelemt integration — New users automatically get MTProxy secrets andtg://proxylinks
- Grafana proxy 502 errors — Race condition where grafana-proxy started before Grafana was ready; added readiness wait loop
- Grafana dashboard starring fails on HTTPS —
star_dashboards()was usinghttp://but Grafana runs HTTPS when certs are found; now uses matching protocol with--no-check-certificate - dnstt/Slipstream "cannot resolve sing-box" warning — Race condition where DNS tunnels started before sing-box was registered in Docker DNS; added
depends_on: sing-box: condition: service_healthy - telemt metrics not scraped by Prometheus — telemt's
metrics_whitelistdefaults to localhost-only; addedmetrics_whitelist = ["0.0.0.0/0"]to generated config moav restart grafanarestarting entire monitoring stack — Service names likegrafana,prometheuswere being resolved as profile aliases tomonitoring;restart/stopnow only match exact profile names- Slipstream build arguments — Fixed build failures from incorrect argument passing
- Fake-TLS default domain — Changed from
www.google.comtodl.google.com(whitelisted during Iran's Jan-Feb 2026 shutdowns, less commonly used as proxy SNI fingerprint) - telemt per-user limits configurable —
TELEMT_MAX_TCP_CONNS(default: 100) andTELEMT_MAX_UNIQUE_IPS(default: 10) via.env
1.4.0 - 2026-03-01
- Slipstream DNS Tunnel — QUIC-over-DNS protocol (1.5-5x faster than dnstt)
- New
slipstreamservice using pre-built Rust binaries from slipstream-rust - Resolver mode (default, ~63 KB/s, stealthier) and authoritative mode (~3.9 MB/s, exposes server IP)
- ECDSA P-256 self-signed certificate generated during bootstrap
- Full client support: cert distribution, client instructions, client-test, client-connect
- Client guide (EN/FA) with protocol description and setup instructions
- New
- DNS Router — Lightweight Go UDP forwarder for running multiple DNS tunnels on port 53
- Routes DNS queries by domain suffix to dnstt or Slipstream backends
- Supports single-backend mode (routes all traffic when only one tunnel is enabled)
dnstunnelProfile — Unified profile for all DNS tunnel services (dns-router + dnstt + Slipstream)- Profile aliases:
dnstt,dns,slip,slipstreamall resolve todnstunnel - Individual toggles:
ENABLE_DNSTTandENABLE_SLIPSTREAMcontrol which backends are active
- Profile aliases:
moav logsProfile Support —moav logs dnstunnelnow shows logs for all services in a profile (was silently failing for profile names)
- Decoy Container Profile Mismatch —
certbotdepends ondecoy, butdecoywas missing profiles (wireguard,dnstunnel,trusttunnel) causinginvalid compose projecterrors when starting non-proxy profiles - Slipstream Binary on Alpine — Pre-built Rust binaries are glibc-linked; Slipstream server switched to
debian:bookworm-slim, client container usesgcompat+libgcc+libc6-compat
dnsttProfile Renamed —dnsttprofile renamed todnstunnel(backwards-compatible via alias)- dnstt Port Mapping — dnstt no longer binds host port 53 directly; dns-router handles port 53 and routes to backends
1.3.8 - 2026-02-27
- Decoy Website — Interactive backgammon game replaces "Under Construction" page
- Anti-fingerprinting: randomized titles, headings, footers, and color themes on each container start
- 8 distinct color palettes, random hex comment to change file hash per deployment
- Uses nginx
docker-entrypoint.dmechanism with tmpfs for ephemeral randomized content
- Connection Optimization Tips in User Bundle — Inline per-protocol optimization guidance in README.html
- Reality: TLS Fragment tip with Hiddify/v2rayNG settings, MUX warning (incompatible with Vision)
- Trojan: TLS Fragment + MUX tips with app-specific values
- CDN VLESS+WS: MUX tip, note that Fragment doesn't help (TLS at Cloudflare)
- Hysteria2: no tips (QUIC, nothing to tweak)
- Multi-user Revoke —
moav user revokenow accepts multiple usernames in one command - AmneziaWG Revoke — User revoke now properly removes AmneziaWG peers
- CDN Domain Empty in User Bundle —
{{CDN_DOMAIN}}in README.html was replaced with empty string- Root cause:
user-add.shandgenerate-user.shdidn't constructCDN_DOMAINfromCDN_SUBDOMAIN+DOMAIN singbox-user-add.shhad the construction logic but it didn't propagate to the README generation
- Root cause:
- Certbot Port 80 Conflict — Certbot standalone mode conflicted with decoy website on port 80
- Switched certbot from
--standaloneto--webrootmode with shared ACME challenge volume
- Switched certbot from
- Decoy Container Not Picking Up Config —
docker compose restartdoesn't apply compose file changes; documented need for--force-recreate
- sing-box — Updated to v1.12.23
- Decoy Website — Now accessible on HTTP port 80 (was only internal)
- Client Guide Docs — Added Connection Optimization section to
docs/CLIENTS.md(Fragment & MUX per-protocol table)
1.3.7 - 2026-02-27
- Conduit v2.0.0 Upgrade — Upgraded Psiphon Conduit to v2.0.0 with native Prometheus metrics
- Native
/metricsendpoint replaces custom log-parsing exporter and tcpdump-based GeoIP collector - Per-region client breakdown (
conduit_region_connected_clients,conduit_region_bytes_downloaded/uploaded) - Ryve deep link displayed in container logs on startup for easy mobile import
- Slimmed Dockerfile: removed
geoip-bin,tcpdump,iproute2,procps(no longer needed)
- Native
- Conduit Grafana Dashboard — New panels for v2 native metrics
- Live status panel (
conduit_is_live), max clients panel (conduit_max_common_clients) - Connected clients by region timeseries chart
- Live status panel (
- Build Optimization — BuildKit cache mounts for Go compilation services
- Go module and build caches persist across rebuilds (amneziawg, dnstt, snowflake, clash-exporter, client)
- pip cache mount for admin image
- Build Reliability — Fixed Go services failing during parallel
moav build --no-cache- Root cause: 13+ parallel builds saturated network, causing TLS handshake timeouts on Go module downloads
- Fix: two-phase build — Go services built sequentially first, then remaining services in parallel
- Phase 2 now filters to only buildable services (skips image-only services like certbot, grafana)
- Go Version Pinning — Fixed Dockerfile.amneziawg and Dockerfile.dnstt build failures
- Pinned amneziawg-go to tag v0.2.16 (was cloning unpinned default branch)
- Updated dnstt builder from
golang:1.21-alpinetogolang:1.24-alpineto match upstreamgo.mod
- Conduit Environment Variables —
CONDUIT_MAX_CLIENTSrenamed toCONDUIT_MAX_COMMON_CLIENTS(backwards-compatible fallback in entrypoint) - Prometheus Scrape Target — Conduit metrics now scraped directly from
psiphon-conduit:9090(wasconduit-exporter:9101) - Admin Dashboard — Conduit stats section now shows per-region data from native metrics endpoint
- Component Versions — Updated Prometheus default to 3.10.0, sing-box 1.12.22, AmneziaWG tools 1.0.20260223
- conduit-exporter service — Replaced by Conduit v2 native Prometheus endpoint
exporters/conduit/main.pyandexporters/conduit/Dockerfile— Custom log parser no longer neededscripts/conduit-stats-collector.sh— tcpdump-based GeoIP collector replaced by native per-region metricsscripts/conduit-stats.sh— Live CLI viewer replaced by Grafana dashboard
1.3.6 - 2026-02-19
- Admin Dashboard User Creation - Create users directly from the web dashboard
- "Create User" button in User Bundles section with collapsible form
- Single user creation by username
- Batch mode with checkbox: enter username + count to create
name_01,name_02, etc. - Real-time script output log with dismiss button
- Auto-refresh paused during user creation to prevent timeouts on batch operations
- Scalable timeout: 60s per user in batch mode
- Admin Dashboard Docker Enhancements - Admin container can now run user management scripts
- Full project mount (
/project) for runninguser-add.shvia API - Docker socket mount for
docker compose execcommands within scripts qrencodeinstalled for QR code generation in user bundles
- Full project mount (
- AmneziaWG Grafana Dashboard - Monitoring panel for AmneziaWG connections
- Bootstrap Key Preservation - Bootstrap no longer regenerates existing keys on re-run
- Reality, WireGuard, and AmneziaWG keys preserved across re-bootstrap
- Prevents breaking existing user configs when re-bootstrapping
- WireGuard/AmneziaWG User Addition - Fixed multiple bugs in user-add flow
- AWG peers now hot-reloaded into running container (previously required restart)
- AWG IP allocation uses actual IPs from config + running interface (prevents collisions)
- WG IP allocation checks both config file and running interface
- Fixed stale peers with
allowed ips: (none)after re-bootstrap
- Reality Public Key Derivation - Fixed empty
pbk=in Reality client configs- Bootstrap no longer clobbers public key when
sing-box generate reality-keypair --private-keyis unavailable - Falls back to
wg pubkeyfor x25519 key derivation (same curve as WireGuard) singbox-user-add.shauto-derives and saves public key if missing from state
- Bootstrap no longer clobbers public key when
- dnstt Public Key in README.html - Fixed empty dnstt pubkey in generated README.html
generate-user.shwas reading fromdnstt-server.pubinstead ofdnstt-server.pub.hex
- User Regeneration - Fixed WG/AWG config regeneration after re-bootstrap
- Admin Dashboard UI - Create User form moved from separate card to inline toggle in User Bundles header
- Documentation - Added admin dashboard user creation to SETUP.md and CLI.md
1.3.5 - 2026-02-18
- AmneziaWG protocol - DPI-resistant WireGuard fork with packet-level obfuscation (#48)
- New
amneziawgDocker service and profile (port 51821/udp) - Userspace Go implementation (
amneziawg-go) for Docker compatibility - Random obfuscation parameters (Jc/Jmin/Jmax junk packets, S1/S2 padding, H1-H4 headers)
- Separate subnet (10.67.67.0/24) from WireGuard (10.66.66.0/24)
- Full client support: config generation, QR codes, client guide (EN/FA)
awgalias formoav start amneziawg- Client container includes
awg-toolsfor AmneziaWG connections
- New
- Protocol Integration Checklist - Developer documentation for adding new protocols to MoaV
- Version Bump Checklist - Developer documentation for release process
- WireGuard MTU - Added
MTU = 1280to all WireGuard configs (server + client)- Fixes poor upload speeds on mobile networks behind CGNAT (e.g., Iranian carriers)
- Applied to: direct, IPv6, and wstunnel-wrapped configs
- Grafana local build edge case fix
- DNS check before dnstt startup
- First start profile selection fix
- Bugfix #38
- Bugfix #44
- Local building bugfix
- Default Snowflake/Conduit bandwidth lowered (due to high usage)
awg-toolsupdated to v1.0.20250903- Developer checklists moved to
docs/devdocs/
1.3.4 - 2026-02-14
- Local Image Building - Build container images locally for regions with blocked registries
moav build --local- builds commonly blocked images (cAdvisor, clash-exporter)moav build --local SERVICE- builds specific image (prometheus, grafana, etc.)moav build --local all- builds ALL images locally (docker-compose + external)- Automatically updates .env to use local images
- Available images: cadvisor, clash-exporter, prometheus, grafana, node-exporter, nginx, certbot
- Uses pre-built binaries from GitHub releases (avoids compilation, works on 1GB servers)
- Version control via
.envvariables (PROMETHEUS_VERSION, GRAFANA_VERSION, etc.)
- Configurable Container Images - All external images now configurable via .env
IMAGE_PROMETHEUS,IMAGE_GRAFANA,IMAGE_NODE_EXPORTER,IMAGE_CADVISOR, etc.- Allows use of mirror registries when default registries are blocked
- Registry Troubleshooting Guide - New section in TROUBLESHOOTING.md for blocked registries
- Dockerfile Organization - All Dockerfiles moved to
dockerfiles/directory- Cleaner root directory structure
- All docker compose commands work unchanged
- Alpine Base Image - Updated all Dockerfiles to Alpine 3.21 (from 3.19/3.20)
- Profile Support for Build -
moav build monitoringnow works (builds all monitoring services)
- Uninstall --wipe - Now properly removes all Docker images
- Fixed: images with non-default tags (e.g.,
moav-nginx:local) were not being removed - Now removes external images (prometheus, grafana, cadvisor, etc.)
- Shows both built and pulled images before removal
- Fixed: images with non-default tags (e.g.,
- Build Counter Bug - Fixed
moav build --localstopping after first image due toset -ewith arithmetic
1.3.3 - 2026-02-13
- Grafana CDN Proxy - Access Grafana through Cloudflare CDN for faster loading
- New
grafana-proxynginx service on port 2083 (Cloudflare-supported HTTPS port) - Configure with
GRAFANA_SUBDOMAINin .env (e.g.,grafana.yourdomain.com:2083) - Dynamic SSL certificate detection (Let's Encrypt or self-signed fallback)
- New
- Grafana MoaV Branding - Custom logo, favicon, and app title
- Replaces default Grafana branding with MoaV logo/favicon
- Dynamic app title: "MoaV - {DOMAIN}" or "MoaV - {SERVER_IP}" for PWA home screen
- Note: Uses file replacement since GF_BRANDING_* is Grafana Enterprise-only
- Dashboard Auto-Starring - All MoaV dashboards automatically starred on Grafana startup
- Conduit Peak Clients - New stat panel showing maximum concurrent clients in time range
- Subdomain Configuration - Cleaner .env format for CDN settings
GRAFANA_ROOT_URL→GRAFANA_SUBDOMAIN(just subdomain, URL constructed automatically)CDN_DOMAIN→CDN_SUBDOMAIN(just subdomain, URL constructed automatically)
- Monitoring Default -
ENABLE_MONITORINGno longer set in .env.example- Users are now prompted when selecting "all" services
- Prevents accidental monitoring on low-RAM servers
- Service URLs in output -
moav startnow shows Grafana CDN URL and VLESS+WS CDN URL when configured
- Domainless Mode - Fixed bootstrap failing when running without a domain
- Now properly disables all TLS protocols including TrustTunnel
- Handles missing ENABLE_* vars in .env (adds them if not present)
- CLASH_API_SECRET Flow - Fixed monitoring setup during bootstrap
- Secret is now properly copied from state volume to .env
ensure_clash_api_secret()runs before starting services after bootstrap
- Entrypoint Permissions - Added missing executable bit to entrypoint scripts
- Fixes "modified files" warning during
moav update
- Fixes "modified files" warning during
- sing-box User Connections Table - Fixed column display
- Shows: User, Connections, Active (in correct order)
- Hides metadata fields: name, instance, job
- Snowflake Bandwidth Clarification - Added tooltips explaining why container metrics (cAdvisor) show higher values than Snowflake dashboard (WebSocket/TLS overhead, broker connections)
1.3.1 - 2026-02-11
- Conduit Exporter - Custom Prometheus exporter for Psiphon Conduit metrics
- Parses
[STATS]lines from conduit logs - Exposes: connected/connecting clients, upload/download totals, uptime
- New Grafana dashboard: MoaV - Conduit
- Parses
- Sing-box User Exporter - Custom Prometheus exporter for user tracking
- Parses sing-box logs for
[username]connection patterns - Tracks active users (5-minute window), total users, per-user connections
- Protocol breakdown (Reality, Trojan, Hysteria2, etc.)
- Updated sing-box dashboard with user metrics table and protocol pie chart
- Parses sing-box logs for
- Monitoring intervals reduced - Less CPU overhead
- cAdvisor housekeeping: 10s → 30s
- Prometheus scrape interval: 15s → 30s
- Snowflake dashboard fixed - Deduplicated metrics using
max()aggregation - Container dashboard improved - Network traffic now excludes monitoring containers
- Filters out: prometheus, grafana, cadvisor, node-exporter, all exporters
- Shows only actual proxy/service traffic
- Snowflake/WireGuard exporters now only run with
monitoringprofile (not standalone) - Removed
docker compose psoutput after start commands (cleaner output)
- Conduit exporter no longer has cross-profile
depends_onissue - Fixed duplicate metrics in Snowflake Grafana dashboard (3x values shown)
- Snowflake exporter replaced - Custom optimized version instead of third-party
- Fixes high CPU usage (20-90%) from inefficient log parsing
- Uses file position tracking instead of constant re-reading
- Adaptive sleep intervals (1s when active, 5s when idle)
- Snowflake dashboard labels fixed - Now shows user perspective:
- "Users Downloaded" = bandwidth users received (was confusingly labeled "Upload")
- "Users Uploaded" = bandwidth users sent (was confusingly labeled "Download")
1.3.0 - 2026-02-10
- Monitoring Stack - Optional Grafana + Prometheus observability (
monitoringprofile)- Grafana dashboards on port 9444 (configurable via
PORT_GRAFANA) - Prometheus with 15-day retention (internal only, port 9091)
- Node Exporter for system metrics (CPU, RAM, disk, network)
- cAdvisor for container metrics (per-container CPU, memory, network)
- Clash Exporter for sing-box proxy metrics (connections, traffic)
- WireGuard Exporter for VPN peer statistics (peers, handshakes, traffic)
- Snowflake Exporter for Tor donation metrics (people served, bandwidth donated)
- Pre-built dashboards: System, Containers, sing-box, WireGuard, Snowflake
- Uses existing
ADMIN_PASSWORDfor Grafana authentication moav start monitoringor combine with other profiles
- Grafana dashboards on port 9444 (configurable via
PORT_GRAFANAenvironment variable (default: 9444)ENABLE_MONITORINGtoggle in .env- Batch user creation - Create multiple users at once:
moav user add alice bob charlie- Add multiple named usersmoav user add --batch 5- Create user01, user02, ..., user05moav user add --batch 10 --prefix team- Create team01..team10- Smart numbering: skips existing users (if user01-03 exist, creates user04, user05)
- Services reload once at the end (not after each user) for efficiency
--packageflag works with batch mode
- Admin dashboard simplified (connection/memory metrics moved to Grafana):
- Removed Active Connections card
- Removed Memory Usage card
- Removed Active Connections table
- Added Grafana link button in header
- Kept: Conduit stats, User bundles, Service status, Total upload/download
moav user revokemenu crash - User list script was crashing when listing WireGuard peers after a user was revoked- Fixed grep pattern to only extract usernames from [Peer] blocks
- Added proper error handling for missing peer IPs
- Added
docs/MONITORING.mdwith complete monitoring stack guide - Documented: TrustTunnel and dnstt do not have metrics APIs (container metrics still available via cAdvisor)
- Added "Apply .env changes" section to TROUBLESHOOTING.md explaining that containers must be recreated (not just restarted) to pick up
.envchanges
- Batch user creation - Create multiple users at once:
moav user add alice bob charlie- Add multiple named usersmoav user add --batch 5- Create user01, user02, ..., user05moav user add --batch 10 --prefix team- Create team01..team10- Smart numbering: skips existing users (if user01-03 exist, creates user04, user05)
- Services reload once at the end (not after each user) for efficiency
--packageflag works with batch mode
moav user revokemenu crash - User list script was crashing when listing WireGuard peers after a user was revoked- Fixed grep pattern to only extract usernames from [Peer] blocks
- Added proper error handling for missing peer IPs
- Added "Apply .env changes" section to TROUBLESHOOTING.md explaining that containers must be recreated (not just restarted) to pick up
.envchanges
1.2.5 - 2026-02-07
moav uninstallcommand - Clean uninstallation with two modes:moav uninstall- Remove containers, keep data (.env, keys, bundles)moav uninstall --wipe- Complete removal including all configs, keys, and user data- Optional Docker images cleanup prompt during --wipe
- Verbose output showing each file/directory being removed
- Component version update checking -
moav updatenow compares versions:- Compares .env with .env.example after git pull
- Shows available updates for sing-box, wstunnel, conduit, snowflake, trusttunnel
- Prompts to update versions in .env
- Shows rebuild command:
moav build <services> --no-cache
- Unified service selection menu - Beautiful table-based menu for start/stop/restart
- Consistent UI across all service operations
- "ALL" option highlighted as "(Recommended)" in green
- Shows v2ray app compatibility for proxy protocols
moav build --no-cacheflag for forcing container rebuilds- Logs menu "Last 100 lines + follow" option (shows tail then continues following)
- Cloudflare Origin Rule documentation for CDN mode (required for port 2082 routing)
- Service selection menu improvements:
- Proxy description: "Reality, Trojan, Hysteria2 (v2ray apps)"
- TrustTunnel description: "TrustTunnel VPN (HTTP/2 + QUIC)"
- Donation services: "Donate bandwidth via Psiphon/Tor"
- Cancel option dimmed to de-emphasize
- Start/stop/restart now use unified menu instead of separate implementations
- dnstt auto-dependency (adding proxy) only applies to start, not stop/restart operations
- WireGuard key generation permissions warning - Now uses
umask 077to create private keys with secure permissions (owner-only read) - Bootstrap missing python3 - Added python3 to Dockerfile.bootstrap for placeholder replacement
- Stop/restart stopping extra services - Auto-adding proxy for dnstt now only happens during start
- Complete CLI.md reference with all moav commands and options
- SETUP.md: Added "Uninstalling MoaV" section, expanded "Breaking Changes" guidance
- TROUBLESHOOTING.md: Added "Breaking changes after update" section with solutions
- DNS.md: Added Cloudflare Origin Rule setup for CDN mode (fixes 521 errors)
- Updated uninstall documentation across all relevant docs
1.2.4 - 2026-02-06
- TrustTunnel VPN protocol integration - Modern VPN protocol from AdGuard using HTTP/2 and HTTP/3 (QUIC)
- New
trusttunnelDocker service and profile - TrustTunnel endpoint on port 4443 (TCP+UDP)
- Full TOML config generation for CLI client
- TrustTunnel section in client guide (HTML) with all app fields
- Admin dashboard: TrustTunnel service status and "TT" protocol tag for users
- New
- TrustTunnel CLI client (
trusttunnel_client) in client container for testing moav start trusttunneland service menu option- User bundles now include
trusttunnel.toml,trusttunnel.txt, andtrusttunnel.json
- Client test gracefully falls back to endpoint reachability check when TUN device unavailable
- TrustTunnel app store links updated to correct URLs
- README.html placeholder replacement broken - Multiple issues fixed:
localvariable used outside function causing script exit withset -e- sed
&character interpreted as "matched pattern" in replacement strings - awk escape sequence warnings (
\&treated as plain&) - Multiline WireGuard configs breaking sed commands
- Now uses Python-based replacement for reliable handling of special characters and multiline content
- TrustTunnel CLI client requires
--configflag (was missing) - TrustTunnel credentials format:
[[client]]not[[credentials]],[[main_hosts]]not[[hosts]]
1.2.3 - 2026-02-06
- CDN-fronted VLESS+WebSocket inbound - New protocol for Cloudflare CDN-proxied connections
- sing-box
vless-ws-ininbound on port 2082 (plain HTTP, Cloudflare terminates TLS) - Uses same user UUIDs as Reality (no extra credentials)
- Client links generated when
CDN_DOMAINis set in.env
- sing-box
CDN_DOMAINconfig option - Set to your Cloudflare-proxied subdomain (e.g.,cdn.yourdomain.com)CDN_WS_PATHconfig option - WebSocket path (default:/ws)PORT_CDNconfig option - CDN inbound port (default:2082, a Cloudflare-allowed HTTP port)- User bundles now include
cdn-vless-ws.txt,cdn-vless-ws-singbox.json, and QR code when CDN is configured - Documentation: "Adding a Domain After Domainless Setup" guide in SETUP.md
- Documentation: Full CDN setup guide with Cloudflare configuration steps
moav statusnow displays CDN domain when configured- User add message now mentions CDN VLESS+WS
- DNS.md Cloudflare section now includes optional
cdnA record (Proxied)
moav client connectfailing whilemoav testworks - Connect mode was missing IPv6 URI parsing, causing "invalid address" errors when IPv6 configs were presentextract_host()andextract_port()now handle IPv6 URIs (@[addr]:portformat)- Config file discovery now prefers IPv4 configs (
reality.txt) before falling back to globs (reality*.txt) - WireGuard endpoint parsing now handles IPv6 addresses
- Added field validation with debug logging for all protocols
- Added port numeric validation for Reality and Trojan (was only in test mode)
1.2.2 - 2026-02-04
- Fresh setup required: This version includes protocol changes (Hysteria2 obfuscation, Reality target) that require regenerating both server configuration and all user configs. Existing users must receive new config files.
- Hysteria2 Salamander obfuscation - Disguises QUIC traffic as random UDP to bypass Iranian/Chinese censorship
HYSTERIA2_OBFS_PASSWORDconfig option (auto-generated if empty)moav config rebuild- Regenerates server config and all users with new credentials- Update available notification in CLI header and admin dashboard
- Admin dashboard: User bundles table now shows creation date, sorted newest first
- Internet accessibility check (exit IP verification) for all protocol tests
- Component version management via
.envfile
- Default Reality target changed from
www.microsoft.comtodl.google.com(less fingerprinted in censored regions) - DNS fallback servers: removed Cloudflare DoH (failing), added Google UDP and Quad9 UDP
moav config rebuildsimplified - cleanly regenerates everything instead of complex state preservation- Admin dashboard UI improvements
- Critical: dnstt traffic not routing - sing-box mixed inbound was localhost-only
- Critical: Client container architecture mismatch - Fixed arm64/amd64 binary downloads
- Admin dashboard crash on load (
connection_statsundefined) moav logsCtrl+C now returns to menu instead of exitingmoav logs proxyandmoav logs realityaliases for sing-boxmoav regenerate-usersnow passes Hysteria2 obfuscation passwordmoav testvarious fixes for dnstt and validationmoav updateconflicts from generated files
- Hysteria2 obfuscation helps bypass QUIC fingerprinting and blocking in Iran/China
1.2.0 - 2026-02-03
moav update -b BRANCH- switch git branches during update (e.g.,moav update -b dev)- Profile aliases for
moav start:sing-box,singbox,reality,trojan,hysteria→proxy - Service aliases for restart/stop/logs:
proxy,reality→sing-box - Branch display in header and status when not on
mainbranch moav testverbose flag (-vor--verbose) for debugging connection issues- Multiple fallback DNS servers in sing-box config (Google, Cloudflare, Quad9 UDP)
moav updatenow shows help with--helpflagmoav testnow prefers IPv4 configs over IPv6 (testsreality.txtbeforereality-ipv6.txt)moav testtreats IPv6 network failures as warnings instead of errors (IPv6 may not be available in container)- Improved gitignore for generated WireGuard and dnstt files
moav update -b BRANCHarguments not being passed correctly- Double header display when running
moavinteractive menu - Script permissions (755) for all shell scripts in repository
- Generated files (server.pub, wg_confs/, coredns/) no longer trigger update conflicts
- WireGuard-wstunnel not forwarding traffic - wstunnel was trying to forward to localhost instead of wireguard container (changed
127.0.0.1:51820tomoav-wireguard:51820) moav testnow correctly parses IPv6 addresses in URIs (e.g.,[2400:6180::1]:443)moav testnow validates parsed URI fields before generating configmoav testnow shows actual sing-box error messages instead of generic "failed to start"moav testnow validates generated JSON config before running sing-box
1.1.2 - 2026-02-02
- One-click VPS deployment buttons for Hetzner, Linode, Vultr, DigitalOcean
- Cloud-init script for automated VPS provisioning
- First-login welcome prompt for cloud-deployed servers
- Home VPN server documentation (Raspberry Pi, ARM64 support)
- Dynamic DNS (DDNS) guide for home servers (DuckDNS, Cloudflare)
- VPS deployment guide (docs/DEPLOY.md)
- Bootstrap confirmation prompt before running
- Domain-less mode support (WireGuard, Conduit, Snowflake without TLS)
- First-run loading indicator ("First run - checking prerequisites...")
- Disabled service indicators in status display (
*suffix with legend) - Disabled service indicators in service selection menu (
(disabled)text) - Install script
-b BRANCHflag for testing feature branches - Admin dashboard: User Bundles section with download functionality
moav updatenow shows current branch and warns if not on main/master- Admin dashboard URL shown in menu, status, and after starting services
- Admin dashboard now works in domain-less mode using self-signed certificates
- Certbot status explanation in
moav status(clarifies "Exited (0)" is expected) - Admin URL now shows server public IP instead of localhost
- Bootstrap now auto-detects and saves SERVER_IP to .env if not set
- Improved sing-box performance: disabled
sniff_override_destination, disabled multiplex padding, enabled TCP Fast Open, use local DNS by default - WireGuard entrypoint bypasses wg-quick to avoid Docker 29 compatibility issues
- WireGuard peer IP assignment now based on peer count (fixes demouser getting server IP)
- Service selection "ALL" now respects ENABLE_* settings (only starts enabled services)
moav stopnow usesdocker compose stopinstead ofdown(preserves container state)- Certbot exits gracefully when no domain configured (domain-less mode)
- Admin dashboard using self-signed cert instead of Let's Encrypt (now waits for certbot)
- Admin dashboard "sing-box API timeout" error (memory endpoint is streaming, now reads first line only)
- WireGuard traffic not flowing (missing iptables FORWARD rule for return traffic)
- WireGuard "Permission denied" error on Docker 29 with Alpine
- WireGuard config parsing stripping trailing "=" from base64 keys
- WireGuard QR code showing "Invalid QR Code" in app due to non-hex IPv6 address (
fd00:moav:wg::→fd00:cafe:beef::) - WireGuard-wstunnel QR code not being generated in wg-user-add.sh (missing in README.html)
- Conduit status showing "never" even when running (#7)
- Reality URL
&characters replaced with placeholder in README.html (#8) - Architecture mismatch in Dockerfile.client - now uses TARGETARCH for multi-arch support (#4)
- Bootstrap failing in domain-less mode (missing ENABLE_* exports, conditional config generation)
- generate-user.sh unconditionally sourcing reality.env (now conditional on ENABLE_REALITY)
- generate-user.sh peer count calculation failing when grep returns no matches
1.1.1 - 2025-01-31
- Website link badge in README
- GitHub issue templates (bug reports, feature requests)
- "Your Protocol?" CTA card in Multi-Protocol Arsenal section
- Server Management demo on website
- Status table column widths to accommodate longer service names
1.0.2 - 2025-01-31
- Ctrl+C handler with friendly goodbye message
- README.html generation in user bundles using client-guide-template
- Demo user notice (bilingual EN/FA) for bootstrap demouser
- Server Management demo on website
- Support for comma separator in multi-option selection (e.g.,
1,2,4)
- Bootstrap now creates "demouser" when INITIAL_USERS=1 (instead of user01)
- User management menu now loops back after listing users
- Package command now places zip files in
outputs/bundles/consistently - Status table widened to accommodate longer service names (psiphon-conduit)
- Removed README.md from user bundles (HTML-only now)
- Export and regenerate-users now correctly find users from bundles directory
- Demo notice placeholders properly removed from non-demo user HTML
- Awk escape sequence warnings in HTML generation
- Package user menu option creating zip in wrong directory
1.0.1 - 2025-01-30
- Minor bug fixes and improvements
1.0.0 - 2025-01-28
- Initial release of MoaV multi-protocol circumvention stack
- Protocols:
- Reality (VLESS) - Primary protocol with TLS camouflage
- Trojan - TLS-based fallback on port 8443
- Hysteria2 - QUIC/UDP-based for fast connections
- WireGuard - Full VPN mode (direct and wstunnel-wrapped)
- DNS Tunnel (dnstt) - Last resort for restrictive networks
- Tor/Snowflake - Standalone fallback via Tor network
- Server features:
- Docker Compose-based deployment
- Multi-user management with per-user credentials
- Automatic TLS certificate management via Caddy
- Decoy website for traffic camouflage
- Admin dashboard for monitoring
- Psiphon Conduit for bandwidth donation
- Snowflake proxy for Tor network contribution
- Client features:
- Built-in client container for Linux/Docker
- Test mode for connectivity verification
- Connect mode with local SOCKS5/HTTP proxy
- Auto protocol fallback
- CLI tool (moav.sh):
- Interactive menu and command-line interface
- User management (add/list/revoke)
- Service management (start/stop/restart/logs)
- Global installation support
- Documentation:
- Setup guide with prerequisites
- Client configuration guides for all platforms
- Troubleshooting guide
- Farsi (Persian) README
- Per-user UUID and password generation
- Reality protocol with XTLS Vision flow
- uTLS fingerprint spoofing (Chrome)
- Automatic short ID generation for Reality