Custom header X-Proxy-Provider is not sent by ClashMi and other clients
that don't support header: in proxy-providers. URL query param works in
all clients universally.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
include-all is Mihomo-only; explicit use: [sub] works in all Clash clients.
Also remove empty proxies blocks and non-standard remnawave field.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When Mihomo fetches proxy-providers it sends a Clash UA, causing nginx to
return clash.yaml instead of the actual proxy list — resulting in empty groups.
Fix: proxy-providers in clash.yaml now send X-Proxy-Provider: true header.
nginx map checks combined key "$is_clash_ua:$http_x_proxy_provider":
- Clash UA with no header ("1:") → serve clash.yaml (initial import)
- Clash UA with header present → pass through to x-ui sub port (provider refresh)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Regex location only matches single-segment paths (subscription IDs).
Deep asset paths like /sub_path/static/js/main.js fall through to the
prefix location /sub_path/ which proxies them to x-ui sub port normally.
Nginx regex > prefix priority ensures Clash UA detection still works for IDs.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
proxy_pass with URI component is forbidden inside if blocks and regex locations.
Use rewrite ^ /__clash_api?sub_id=$clash_sub_id last; inside if (safe),
then proxy_pass with URI lives in location = /__clash_api (exact match, internal).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
expected-status: 204 ended up after the rules section instead of
inside proxy-providers.sub.health-check where it belongs.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- clash.yaml template (proxy-providers -> x-ui base64 sub URL) in assets/clash/
- install_clash_sub() downloads and substitutes domain/sub_path at install time
- nginx: map $http_user_agent $is_clash_client detects Clash/Mihomo/Stash/Surfboard
- sub_path locations rewrite to internal /__clash_sub on UA match
- /__clash_sub serves /var/www/subpage/clash.yaml as text/yaml
- Regular clients still proxy to x-ui sub port unchanged
- Uninstall cleans /var/www/subpage/
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Download uses fetch() with streaming progress on 100MB test file.
Upload sends 25MB to /api/upload on mtr-backend which reads the full
body before responding, giving accurate client-side timing.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>