Proxy Group Types and Practical Use
Proxy groups choose an outbound route after a rule matches traffic; they don’t determine which website the traffic belongs to. In the configuration, proxies defines the actual nodes, proxy-groups organizes nodes or other groups into selectable routes, and rules references those route names. Names must match across all three layers. Renaming a node to something similar won’t make existing rules find it automatically.
Before making changes, check which subscription is active on the Profiles page, then review the existing groups on the Proxies page. Providers may already define nested groups for automatic selection, regions, and app-specific routing. Adding a group with a duplicate name can cause conflicts; replacing the entire list may leave existing rules without a target. Note the names and references first—it’s easier to spot problems than by copying a whole configuration upfront.
Manual Selection, Latency Testing, and Failover
Use select to choose an outbound route manually. It’s useful for apps that need a consistent region or login environment. The client’s saved selection may also depend on persistence settings, so the first item in the YAML list may not be the active one. To troubleshoot, expand the group on the Proxies page and check the selected item. If it references another group, keep expanding until you reach the node actually in use.
Use url-test to select a route based on probe results. It works well with nodes serving similar purposes. Results depend on whether the test URL is stable, the nodes can reach it, and the interval is reasonable. A fast probe reflects only that request; it doesn’t mean every site will load faster. Downloads, video, and work services may take different routes, so don’t treat probe results as a throughput ranking.
fallback prefers the first available member in the list, making it suitable for a defined primary and backup route. load-balance distributes connections according to the selected strategy; it doesn’t split one download across multiple nodes to combine their bandwidth. For accounts tied to a region, payment verification, or source-IP restrictions, frequent route changes may trigger extra checks. Start with a manual or primary/backup group to confirm how the service behaves.
| Type | Selection basis | Best suited for |
|---|---|---|
select | User selection | A fixed route and reproducible troubleshooting |
url-test | Health probe results | Similar candidate nodes where automatic switching is acceptable |
fallback | Member order and availability | A clearly defined primary and backup |
load-balance | Connection distribution strategy | Workloads that can use multiple outbound routes |
Start with a clear, easy-to-understand routing layer
This snippet shows how a rule can reference a proxy group; it doesn’t include any proxy servers. The two built-in outbound options are already available, so there’s no need to invent node details. When merging it into an existing configuration, combine the lists instead of adding a second top-level key with the same name. The example defaults to direct access. To use a proxy, add real nodes from an imported subscription or existing groups to the member list, then select one in the client.
proxy-groups:
- name: Manual route
type: select
proxies:
- DIRECT
- REJECT
rules:
- DOMAIN-SUFFIX,example.org,Manual route
- MATCH,DIRECT
For automatic groups, you can set url, interval, and tolerance. The interval is in seconds; tolerance helps prevent repeated switching over minor differences. Shorter intervals aren’t always better, especially on mobile or metered connections, where multiple groups probing at once can generate extra requests. Start with a moderate frequency and use the logs to determine whether you need to adjust it.
Groups can reference other groups, but avoid circular dependencies. For example, a “Work route” that references an “Auto route” is a clear one-way structure. If the auto group also lists the work group as a member, the core can’t resolve the dependency. This is more likely after merging subscriptions, since different providers often use the same group names. Give locally maintained groups stable, purpose-based prefixes rather than relying on display names that may change with subscription updates.
To verify a proxy group, keep rule mode enabled, visit a domain that should match a specific rule, then check the matched rule, proxy chain, and actual route on the Connections page. If there’s no connection record, first check whether traffic reached the core. If there is a record but the wrong group was used, review rule order. Don’t change the mode, node, and DNS settings all at once; otherwise, it’s hard to tell what caused the result.
Managing Rules with Rule Providers
Rule providers move frequently changing match conditions out of the main configuration, leaving only references and ordering there. This means you can update website domain lists without repeatedly editing proxy groups or port settings. A rule provider is not a node subscription: node subscriptions supply outbound routes, while rule providers supply match conditions. The route is still determined by the policy specified in the RULE-SET rule.
Before managing rule providers, organize existing rules by purpose. Device and LAN exceptions usually need higher priority, followed by specific site-routing rules, then geographic and fallback rules. Mihomo typically evaluates rules from top to bottom and stops at the first match. A broad rule above a more specific one won’t be overridden automatically. Rule order matters just as much as the domains in each list.
Choose the Behavior First, Then the File Format
behavior describes what the rule content means. domain handles domain lists, ipcidr handles address ranges, and classical can contain rule conditions with type prefixes. format describes how the file is encoded, such as YAML, plain text, or a supported binary rule format. A valid format doesn’t guarantee the behavior is correct; both must match the source content.
The examples below use local files and don’t depend on remote URLs. Create each file in a configuration directory the client can access, then merge the provider and rule references into the main configuration. Relative paths are based on the working directory the client passes to the core, not your browser’s download folder. If the logs say a file is missing, check the configuration directory and runtime environment instead of repeatedly changing the domains.
rule-providers:
local-direct:
type: file
behavior: classical
format: yaml
path: ./rules/local-direct.yaml
rules:
- RULE-SET,local-direct,DIRECT
- MATCH,Manual route
The corresponding local-direct.yaml file contains the following. It keeps the rule conditions separate from the outbound policy, which is specified centrally in the main configuration. The trailing no-resolve means this address rule won’t trigger a DNS lookup; it does not disable DNS for the whole client. “Manual route” should refer to the group created in the previous section, or be replaced with the name of an existing group.
payload:
- DOMAIN-SUFFIX,example.org
- IP-CIDR,192.168.0.0/16,no-resolve
- IP-CIDR,10.0.0.0/8,no-resolve
To switch to a remote provider, set it to type: http and specify an accessible url, a local cache path, and an interval in seconds. Don’t infer the content from the file extension alone: if the server returns a login page, an access restriction message, or a regular webpage, it can’t be parsed as a rule set—even if the URL ends in .yaml. Check the response body before reviewing the configuration fields.
Treat Update Failures and Rule Misses Separately
If an update fails, first check whether the download path is reachable. Updating a rule provider also requires network access, so don’t make your only working route depend entirely on a resource that hasn’t downloaded yet. If a cache exists, the client may continue using old content; continued connectivity doesn’t prove that new rules have loaded. Check the provider status and logs to confirm the update completed, then inspect the cached content.
If the update succeeds but a rule doesn’t match, check whether an earlier, broader rule already matched—for example, a rule sending the same domain suffix direct, or an earlier IP rule. Then check whether the connection uses a domain or an IP address: a connection made by IP without a domain mapping may not match a domain rule. Finally, test with a new connection; the browser’s connection pool may keep an old one alive.
As rule sets grow, avoid stacking every source together. Providers may overlap, update on different schedules, or classify the same site differently. A more maintainable approach is to pick one base set of categories and add a small number of local exceptions. Document each provider’s purpose, source, behavior, and references. When removing one, delete its references first, then its provider definition.
Keep local exceptions narrowly scoped. If you need to change the route for one domain, don’t include the entire top-level domain or a broad address range. For IP rules, check whether they trigger DNS lookups; avoid unnecessary queries just to match a wide subnet. The more specific the reason a rule matches, the less you’ll need to inspect when troubleshooting misrouted traffic.
Remote rules are part of your configuration supply chain, so choose sources with a clear purpose and reviewable content. Keep the last working file before an update, then check the proxy chain for a few representative domains afterward. For an overview of top-level fields and indentation, see A Section-by-Section Guide to Clash YAML Configuration. Don’t try to fix merge issues by adding duplicate fields.
Optimizing DNS
The goal of DNS configuration is to keep name resolution consistent with the route used for connections, not simply to add more servers. A request may involve an app’s own resolver, the system resolver, the core’s DNS, and DNS lookups for proxy server names. First identify which layer is handling the query. That’s the key to understanding why a browser works while a command-line tool fails, or why switching routes still connects to the old address.
In the client, dns.enable enables DNS in the core, but doesn’t guarantee that every app uses it. The system proxy generally handles connections from apps that support proxy settings; it doesn’t necessarily intercept system DNS. TUN DNS hijacking follows a different path. Apps with built-in encrypted DNS may also bypass regular queries over port 53, so an enabled setting alone doesn’t prove that all DNS traffic is using the same resolver.
Separate Bootstrap, Regular, and Policy-Based DNS
default-nameserver resolves the hostnames of upstream DNS servers and should generally use IP addresses that are directly reachable. nameserver is the regular upstream list. nameserver-policy lets you assign upstream servers to specific domain patterns. It controls where DNS queries go; rules controls where application connections go. Check the two separately.
The snippet below shows a standard DNS mode with a policy for selected domains. The listener is limited to the loopback interface, and the high-numbered port helps avoid conflicts with system services. This snippet won’t change the operating system’s DNS settings or enable TUN. First, query the listener directly to confirm the core responds, then consider routing app traffic through it. When merging, replace or combine the existing DNS object; don’t append a second one at the end of the file.
dns:
enable: true
listen: 127.0.0.1:1053
ipv6: false
enhanced-mode: redir-host
default-nameserver:
- 223.5.5.5
nameserver:
- https://dns.alidns.com/dns-query
nameserver-policy:
"+.example.org":
- 223.5.5.5
The domain policy in the example illustrates matching syntax; it doesn’t mean that domain must use the specified upstream. Internal company domains need an internal DNS server that can resolve them—not a public resolver copied from an example. If you use an internal server, also check the network interface and route used for the request. It may be unreachable outside the company network, so hard-coding it can cause intermittent failures.
When enabling rule-based DNS routing, also check how respect-rules and proxy-server-nameserver work together. If a proxy server is specified by hostname, the core must resolve it before connecting. You can’t require that lookup to go through a proxy that hasn’t been established yet. Keep a separate, reachable resolution path for proxy hostnames to avoid this startup dependency loop.
Fallback Isn’t a Second Set of Servers for Redundancy
Understand fallback and fallback-filter together. The latter determines which results use fallback DNS; it doesn’t simply try every backup server in sequence when the primary times out. Adding fallback servers without checking the filter conditions may produce unexpected address choices for the same domain. Start with a minimal configuration to confirm basic resolution, then add routing conditions to address specific pollution or regional issues.
Encrypted DNS protects queries in transit to the upstream server, but doesn’t guarantee that the returned addresses suit your current route. A remote resolver may return a content delivery address in another region, making the connection take a longer path. If a site loads slowly, compare the DNS response, actual connection address, and outbound route. Don’t assume every performance issue is caused by the proxy node, or create a separate policy for every domain.
Evaluate IPv6 across the entire connection path. Having an IPv6 address on the system doesn’t mean the proxy node, TUN routes, and destination all have working IPv6 paths. Disabling IPv6 DNS responses can narrow the scope of troubleshooting, but it doesn’t replace checking system routes. Apps may keep using cached addresses after a change. Close the relevant connections, then resolve and test again for comparable results.
On systems with dig, use the command below to test the example listener. Check whether it responds, whether the latency is unusual, and whether the address type matches the current mode. A successful query only confirms that this direct request to the core’s DNS worked; test from the actual app too, to make sure it isn’t using a different resolver. You don’t need to change the system-wide DNS settings just because a query tool isn’t installed.
dig @127.0.0.1 -p 1053 example.org A
dig @127.0.0.1 -p 1053 example.org AAAA
Troubleshoot DNS caches layer by layer: browsers, operating systems, and the core may all cache results. After changing a policy, start a new connection and clear the relevant cache only if needed—you don’t have to restart the computer every time. If the logs show repeated resolution failures, note the domains and upstream server. For a single affected site, check its domain policy and app settings first. See Understanding Log Messages and Troubleshooting Them for help reading errors.
TUN and Fake-IP
TUN receives traffic through a virtual network interface, which is useful for apps that ignore system proxy settings. Fake-IP is a DNS mode: the core returns an address used for internal mapping, then restores the domain information when the connection is made. They’re often used together, but they’re separate features and don’t have to be enabled together in every environment. First identify whether you need to capture traffic or preserve domain mapping, then adjust the relevant layer.
If the system proxy already meets your needs, leave TUN off for now. Enable it when you need to capture traffic from command-line tools, games, or other apps that connect directly, and check the required system permissions. Clash Verge Rev’s service mode, operating system permissions, and other networking software can all affect virtual interface setup. An enabled toggle doesn’t confirm that the interface, routes, and connection records are working.
Set Up Traffic Capture Before Changing DNS Mode
The snippet below shows a common combination of TUN auto-routing and Fake-IP. It requires permission to create a virtual interface and configure routes; use the client’s settings to check permission status. Support for network stacks and interfaces varies by platform, so don’t assume a value used on another platform is optimal. If you encounter compatibility issues, restore the original stack first.
tun:
enable: true
stack: mixed
auto-route: true
auto-detect-interface: true
dns-hijack:
- any:53
dns:
enable: true
enhanced-mode: fake-ip
fake-ip-range: 198.18.0.1/16
fake-ip-filter:
- "*.lan"
- "*.local"
nameserver:
- https://dns.alidns.com/dns-query
auto-route adds the necessary routes, while auto-detect-interface identifies the outbound interface. Neither guarantees the correct route when multiple network adapters, VM bridges, or corporate VPNs are involved. If traffic stops after switching Wi-Fi, connecting Ethernet, or starting another tunnel, check the outbound interface and route changes first. Don’t immediately rebuild the subscription.
Using regular DNS hijacking in dns-hijack doesn’t intercept every kind of name resolution. An app’s built-in HTTPS DNS request is encrypted application traffic and usually can’t be handled like a regular DNS packet. Some systems also have their own local DNS forwarding path. When testing, check both the query result and the domain shown on the Connections page. A rule for port 53 doesn’t prove that every app is under control.
Fake-IP Addresses Are Mappings, Not Remote Servers
In Fake-IP mode, seeing an address from a reserved range is expected; it doesn’t indicate a problem with the destination site. For the connection to work, it must return to the core that maintains the mapping. If an app gets a mapped address but bypasses the core when connecting, the request will usually fail. DNS interception and traffic routing need to work together; pointing system DNS at the core alone may not be enough.
Use fake-ip-filter to return real DNS results for selected domains, often local device names or app domains with confirmed compatibility issues. A longer list isn’t necessarily more reliable: excluding too many domains reduces available mapping information and can change how later rules match. Identify the specific failing app or domain first, then add the narrowest exception that addresses it. Avoid excluding an entire public domain space upfront.
Exceptions for local domain suffixes don’t replace support for device discovery protocols. Printers, casting, and file sharing may also rely on multicast, broadcast, or operating system services. Successful name resolution doesn’t guarantee discovery will work. Test IP reachability, name resolution, and service ports separately before deciding whether to exclude a route. Don’t force all private network traffic through a proxy just to fix one device.
| Environment | Check first | Then verify |
|---|---|---|
| Windows | Service status and virtual interface permissions | Conflicts with other VPNs, the system firewall, or routes |
| macOS | Client authorization and network interfaces | System proxy, routes, and other network extensions |
| Linux | TUN device and route management permissions | Network management services, firewall, and policy routing |
When using a corporate VPN alongside TUN, preserve the routes required for the corporate network first. If both tools try to control the default route, traffic may loop between tunnels or internal services may become unreachable. Record the route table before and after enabling TUN, then test public addresses, internal addresses, and the proxy server address separately. Decide whether to exclude an interface or subnet based on the core’s current capabilities and the system’s routing design.
After disabling Fake-IP or switching configurations, an app may still have an old mapped address cached, while the new core has no record of it. Close the app’s connections and resolve the name again; clear its cache if needed. Don’t attribute every failure to a disconnected proxy node. Persistent mappings may help keep addresses consistent across some restarts, but won’t fix DNS requests handled by another resolver or traffic bypassing the core.
Use a consistent verification order: first confirm a regular proxy connection works, then enable TUN and test an app that normally bypasses the proxy, and finally switch to Fake-IP and check domain matching. Keep a working configuration at each step. If enabling TUN cuts off all network access, disable it and restore connectivity before checking permissions and routes. Switching nodes repeatedly won’t fix a virtual interface that was never created.
Domain Sniffing
Domain sniffing supplements connection details with protocol information visible at the start of a connection, such as the Host header in an HTTP request or the server name in a TLS handshake. It can improve domain-rule matching when only a destination IP is available, but it can’t recover the domain for every connection and doesn’t decrypt HTTPS. Results depend on the protocol used, whether the handshake name is hidden, and whether traffic reaches the core.
Before enabling sniffing, confirm that the domain is actually missing. If Fake-IP already provides the correct domain, sniffing may not add anything. If the connection never reaches the core, enabling sniffing won’t help. A typical case worth investigating is when the Connections page shows a destination IP and port but no domain, so a rule for the site’s domain suffix doesn’t match.
Start with a Narrow Set of Protocols and Ports
The snippet below attempts to sniff HTTP, TLS, and QUIC on common web ports and allows processing connections without existing domain information. It doesn’t start TUN, replace DNS settings, or change every app’s proxy behavior. After merging it, create a new connection. A long-lived connection that has already completed its handshake usually won’t provide the initial protocol details again just because sniffing was enabled.
sniffer:
enable: true
parse-pure-ip: true
sniff:
HTTP:
ports:
- 80
- 8080-8880
override-destination: false
TLS:
ports:
- 443
- 8443
QUIC:
ports:
- 443
parse-pure-ip tells the core to try handling connections that have only an IP address; it doesn’t mean arbitrary binary protocols can be identified. Port ranges define where the core attempts identification, not which protocol is actually running on a port. Adding every port and protocol usually only broadens the scope—it can’t reveal a readable domain when the handshake contains none.
override-destination controls whether sniffed destination information replaces the original connection target. That’s separate from whether a domain can be identified. Some apps rely on the actual connection address, and overriding it may change which service is selected or conflict with the app’s cache. The example explicitly disables overrides for HTTP so you can first observe domain detection, then decide whether to adjust it for compatibility.
Compare Sniffed Results with the Original Destination
CDNs, shared IP addresses, and app-embedded address lists can all make the relationship between an IP and a domain ambiguous. One IP may serve many websites, so reverse DNS or address ownership alone can’t identify the domain for a particular request. A protocol name obtained through sniffing is more specific than an address-based guess, but still needs to be checked against the app’s actual behavior, especially when redirects and multiple background requests are involved.
For testing, choose a request you can reproduce reliably, close the relevant connections, and visit the site again. On the Connections page, check the destination domain, matched rule, and outbound chain. If the domain appears but the rule doesn’t match, check rule order and match type. If the rule is correct but the service fails, check the route, DNS result, and destination override behavior. Successful sniffing doesn’t prove the entire connection is working.
Temporarily raise the log level enough to observe the connection, capture one complete reproduction, then restore your usual level. Detailed logs may contain visited domains and connection metadata, so don’t store or publish them casually. Before sharing troubleshooting details, remove subscription URLs, account information, and controller credentials. Include only the relevant lines and the necessary configuration structure.
QUIC uses UDP, so HTTP/3 also depends on UDP support from the proxy node and network path. If a connection fails, first determine whether the transport failed or domain identification did. Disabling QUIC sniffing won’t force an app to switch to TCP; fallback behavior depends on the app. This setting isn’t a general-purpose protocol converter.
Some TLS connections use encrypted handshake name mechanisms or travel through another tunnel. In those cases, less information is visible, and sniffing can’t reconstruct the original domain. A more reliable approach is to give the app a DNS path you can control, preserve Fake-IP mappings, or add IP- or process-based rules once you understand their scope. Don’t keep expanding the sniffing port list indefinitely.
For a compatibility issue affecting one app, consider using exceptions such as skip-domain, if supported by your core version. Exclude the specific domain and test again. The exception must match what was actually identified: if the logs show only an IP, an unseen domain may not help. If disabling sniffing restores the app, compare the protocol scope and destination override settings one at a time instead of removing the entire rule set.
Take extra care with enterprise apps, fixed-IP services, and device management pages. They may send hostnames that don’t match the address’s intended use, or depend on gateway-specific mappings. Keep LAN direct-access rules in place so sniffed results don’t send internal requests through a public route. For a breakdown of the Connections, Rules, and Logs pages, see A Quick Tour of the Client Interface.
Local Overrides and Subscription Merging
Subscription content is usually maintained remotely, while your local preferences need to survive updates. Editing YAML downloaded from a remote subscription may work temporarily, but an update can overwrite your changes. Local overrides separate stable personal settings from regularly updated remote content. The important questions aren’t what the editing option is called, but when it runs, which fields it affects, and what the final configuration contains.
In Clash Verge Rev, manage local changes through the extensions, merge, or script options on the Profiles page; names vary by interface version. Some settings are also written to the runtime configuration by the client’s global settings, so the value in the subscription file may not be the final one. Check client settings, then inspect the runtime configuration and logs. That’s more effective than repeatedly adding the same field to the original file.
Verify Object Merging and List Replacement Separately
Different merge mechanisms may handle objects and arrays differently. Objects may merge by key, while lists such as rules and proxy-groups may be replaced entirely, prepended, or appended. Don’t assume that because a DNS field was preserved, the rules list will behave the same way. Test the actual behavior with one easy-to-identify local rule before expanding the changes.
This snippet expresses the intent to “save proxy group selections”; it isn’t a universal merge directive. After placing it in a merge entry supported by the client, confirm that the runtime configuration still contains the other fields required by the subscription. If a script rebuilds the entire profile object, a later step may overwrite earlier settings. Check the final output instead of relying on a successful save in the editor.
profile:
store-selected: true
store-fake-ip: true
When adding local rules, pay close attention to where they’re inserted. A rule that changes routing for a specific site should appear near the top. If it’s appended after an existing MATCH, it will usually never run. Keep one clear fallback rule; you don’t need to append a separate one for each subscription. Every line in the merged list should have a clear purpose. Too many duplicate rules make troubleshooting harder.
Two Subscriptions Don’t Make a Valid Configuration by Concatenation
A complete configuration often includes ports, DNS, proxy groups, and rules; don’t simply concatenate two files. Duplicate top-level YAML keys may cause a parser error or make one value overwrite the other, depending on the tool. If you only need to combine nodes, consider using subscriptions as proxy providers and maintaining groups and rules centrally in a local configuration. This avoids multiple remote sources competing over the same base settings.
The example below uses two local proxy providers to make the structure easy to verify. You must supply both files, and each must contain a valid proxies list; arbitrary Base64-encoded node strings won’t work. The snippet doesn’t invent server details—it only references the providers and adds a direct-access fallback member. Before testing the combined selection group, confirm that each file works on its own.
proxy-providers:
source-a:
type: file
path: ./providers/source-a.yaml
source-b:
type: file
path: ./providers/source-b.yaml
proxy-groups:
- name: Combined subscriptions
type: select
use:
- source-a
- source-b
proxies:
- DIRECT
Proxy provider files can retain valid node definitions, but remove full rules and global settings that don’t belong in the provider format. For remote providers, add the actual subscription URL, cache path, and update interval. If the formats are incompatible, use a trusted local method or a compatible option provided by the service. See Subscription Import Methods and URL Formats for details.
Another issue with multiple sources is duplicate node names. Even with different provider names, nodes shown together in a proxy group may be hard to tell apart, and scripts that filter by name may select the wrong one. Use source prefixes or name-handling features supported by the current core to keep names stable. Don’t rely on a region flag, temporary promotion label, or traffic notice as the only long-term identifier.
Filtering expressions also need a fallback. If you filter by region keywords, a provider rename could leave a group empty. Check whether the client reports empty groups clearly and keep a usable selection path. Before using a regular expression, test it against a small number of nodes. Don’t apply a complex, untested expression to every proxy group and then guess why members are missing.
Scripts are useful for predictable, repeatable transformations such as standardizing names or inserting a few rules. They shouldn’t hide large, undocumented configuration changes. Keep the input before running a script and inspect the output afterward, with a clear way to revert to the original subscription if something goes wrong. If the script comes from someone else, review whether it accesses external URLs, reads local data, or changes the controller interface. “It connects to the internet” isn’t proof that it’s safe for ongoing use.
External Controllers
An external controller API lets you query core status, inspect connections, and change proxy selections. A dashboard is the front end that calls this API. It isn’t the same as the HTTP proxy port used by a browser. The mixed port handles proxy traffic; the controller port handles management requests. If you enter the mixed port as the dashboard URL, you’ll usually get a connection error, not the client’s proxy page.
Clash Verge Rev includes interfaces for common proxy, connection, and log tasks, so you can usually use the client directly for local work. Configure an external controller only if you need a separate dashboard, remote device management, or automated queries. Controller access can affect all current connections and route selections, so consider the listening address and who can connect before opening a port to your LAN.
For Local Use, Start with Loopback
The example below listens only on the loopback address and references a local directory for static dashboard files. You’ll need to provide the directory, using a path relative to the core’s actual working directory. The example password is an explicit teaching placeholder. Replace it with a long, randomly generated value before use. Never put a real password in a public configuration, screenshot, share link, or version-controlled repository.
external-controller: 127.0.0.1:9090
secret: "example-only-change-before-use"
external-ui: ./ui
Troubleshoot controller and mixed port conflicts separately. If the logs report a listener error after saving, check whether another client or core process already occupies the port. Don’t switch to listening on all interfaces just to work around a conflict. Update the dashboard connection settings when you change the port. See How to Diagnose a Busy Mixed Port, replacing the port being checked with the current controller port.
The dashboard needs the controller address and authentication details, but it may not run on the same device as the core. In a dashboard page, 127.0.0.1 points to the device running the browser. If you open the dashboard on a phone, it’s the phone’s loopback address, not the desktop’s. This commonly explains remote connection failures; enabling “Allow LAN connections” in the desktop settings alone won’t fix it.
For Cross-Device Access, Check the Boundaries—Not Just the Address
If you need remote management, use a trusted network, explicit firewall rules, and an authenticated access path. Binding to 0.0.0.0 only accepts connections on multiple interfaces; it doesn’t create a security boundary. A device connected to a public network, virtual network, or guest Wi-Fi may expose the controller more widely than expected. Check each interface before making this change.
Browser access to the API may also be affected by same-origin policy, CORS settings, and mixed content restrictions. A browser may block a request from an HTTPS dashboard to an HTTP API; that doesn’t mean the core failed to start. First verify that the API responds locally, then check the exact error in the browser’s developer tools. Don’t use permissive wildcard CORS settings to conceal an address or protocol misconfiguration.
Use local dashboard files from a project you can review and that’s compatible with the API, and deploy them according to its instructions. A directory existing doesn’t mean the files are complete, and a page loading doesn’t mean API authentication succeeded. Troubleshoot in four separate steps: static page loads, API is reachable, authentication succeeds, and the requested action works. Confirm each step before moving on; a blank page and an authentication failure aren’t the same problem.
Automation should follow the same principle of minimizing exposure. If a script only needs local access, don’t publish the controller to the internet for convenience. Provide credentials securely through the runtime environment; never hard-code them in browser scripts. Any JavaScript available to a browser visitor can be read—minification and renaming the file won’t protect a password. Remove sensitive request headers and connection details from troubleshooting materials too.
Use a Fixed Verification Sequence After Changes
First, check that the runtime configuration contains the expected listening address and that the logs show no port conflict or parsing error. Second, verify API reachability and authentication from the same device. Third, load the dashboard and confirm it’s connected to the core currently in use, not another process left running in the background. Finally, change an easily restored proxy selection and check whether the client interface updates.
If the API is reachable but the dashboard shows no proxy groups, confirm that the current configuration loaded them, then check dashboard/API compatibility. If you can view status but can’t change selections, check whether the group allows manual selection and review authentication and request errors. Don’t reinstall the client instead of checking these layers; a reinstall won’t fix an incorrect target address or duplicate background process.
When finished, restore your usual log level, close any temporary listeners, remove local dashboard files or automation jobs you no longer need, and keep a working configuration backup. Separate shareable configuration structure from private subscription details; share only the necessary snippets. After updating the client or core, repeat the same checks to identify whether any change came from the configuration, dashboard, or runtime environment.