Linux Deployment Options and Scope
For a desktop PC where you need to switch nodes regularly, start on the client downloads page: choose a Linux GUI client, then import the subscription from your provider. On a headless server accessed only over SSH, running mihomo directly and managing it with systemd is usually the better fit. The two approaches may use similar proxy configurations, but differ in installation, permissions, and how applications connect to the proxy. There’s no need to run both on the same machine.
Clash is a common name for this family of proxy tools and its configuration ecosystem; mihomo is a core that evolved from Clash Meta. A GUI client handles configuration, the system tray, and controls, while the core listens on ports, matches rules, and establishes connections. Downloading a core binary does not give you a desktop interface, and launching a GUI client does not automatically route every Linux application through the proxy.
| Environment | Recommended approach | Initial check |
|---|---|---|
| Ubuntu or Debian desktop | DEB GUI client for your architecture | Import a profile, then check the available nodes and local listening port |
| Fedora or another RPM-based desktop | RPM GUI client for your architecture | Check the core logs, then test an explicitly proxied request |
| Headless server | mihomo binary and systemd system service | Validate the configuration, then check the service and port 7890 |
Install a Desktop Client and Import a Subscription
System Architecture and Package Type
Run these two commands before downloading. x86_64 usually corresponds to an amd64 or x64 package; aarch64 usually corresponds to arm64. The package format must also match your distribution: DEB is for Debian-based systems, while RPM is for RPM-based distributions. Matching the architecture does not guarantee that all system dependencies are available, so check the client’s minimum requirements on older distributions.
uname -m
cat /etc/os-release
The downloads page lists Linux downloads and current support details for projects such as Clash Verge Rev and FlClash. The commands below use local filenames to demonstrate installation: rename the package you actually downloaded to client.deb or client.rpm, enter its directory, and run only the command for your distribution. These filenames are not download links.
# Debian / Ubuntu: install the DEB package in the current directory
sudo apt install ./client.deb
# Fedora: install the RPM package in the current directory
sudo dnf install ./client.rpm
Installing a local package with the package manager can also resolve dependencies available in your repositories. If it reports missing graphics libraries, WebKit, or runtime components, check your distribution version and the project documentation; don’t force the installation by skipping dependency checks. On a headless server, the command-line approach below is more straightforward.
Subscriptions, Profiles, and Node Selection
- In the client, open the “Subscriptions” or “Profiles” page and choose “Import” or “Add,” then paste the subscription URL from your provider. Labels vary between clients and versions. The key is to use the profile management page, not to paste the URL as a node name.
- Wait for the update to finish, then select the profile you just imported. Seeing a subscription card does not necessarily mean the core has loaded the profile.
- Open the “Proxies” page, start in rule mode, and select an available node in the relevant proxy group. If the subscription contains only a node list and no rules, use it with a complete configuration supported by the client or supplied by your provider.
- Find and enable the “System Proxy” toggle in “Settings,” then check whether your browser uses the desktop proxy settings. If the menu differs, search for the toggle by name instead of relying on a screenshot from a specific version.
Subscription URLs often contain account-identifying tokens and should be treated like credentials. When sharing troubleshooting screenshots, keep the error type and timestamp visible, but redact the full subscription URL, node passwords, and control interface keys. If an import fails, check the response first: a login page, HTML error page, or plain list of node URIs is not a complete mihomo YAML configuration.
System Proxy vs. TUN
The system proxy mainly affects applications that read the desktop proxy settings. Command-line tools, some games, and standalone network programs may bypass it. In GNOME, check “Settings” → “Network” → “Network Proxy”; in KDE, look under “System Settings” → “Network” → “Proxy.” Use the port shown by the client rather than assuming every client uses 7890.
TUN routes traffic through a virtual network interface, so it covers different traffic from the system proxy and also involves service modes, network administration permissions, and DNS settings. For a first desktop setup, verify the profile with the system proxy before enabling TUN according to the client’s documentation. Don’t let the desktop core and a separate systemd-managed core compete for the same port or both change the default route.
mihomo Binary and Service Account
For a command-line setup, choose a Linux binary that matches your CPU architecture. Some release assets distinguish instruction sets or compatibility levels in addition to amd64 and arm64. If an older processor reports Illegal instruction, check the release notes rather than repeatedly restarting the service. Download and extract the selected release asset, rename the executable to mihomo, then enter its directory.
chmod +x ./mihomo
./mihomo -v
sudo install -m 0755 ./mihomo /usr/local/bin/mihomo
/usr/local/bin/mihomo -v
The -v output shows the version of the installed core. Save it so you can check the matching documentation if configuration fields are incompatible later; don’t record only the GUI client version. If you see Exec format error, first check the architecture and make sure the file has been extracted. Don’t try to install the compressed archive as an executable.
Dedicated Account and Directory Permissions
A local HTTP/SOCKS proxy listening on port 7890 does not need root. The commands below create a dedicated system account, store the configuration in /etc/mihomo, and keep cache and runtime data in /var/lib/mihomo. The example uses /usr/sbin/nologin, common on Debian and Ubuntu. On other distributions, check the path with command -v nologin and adjust the commands as needed.
sudo useradd --system --user-group \
--home-dir /var/lib/mihomo \
--shell /usr/sbin/nologin mihomo
sudo install -d -o root -g mihomo -m 0750 /etc/mihomo
sudo install -d -o mihomo -g mihomo -m 0750 /var/lib/mihomo
Create the account only once. If an account with the same name already exists, check its purpose and group membership before making changes; don’t delete and recreate it blindly. Keeping the configuration root-managed and read-only to the service account reduces the risk of the running process accidentally changing subscription credentials. The data directory must be writable by the service account, or cache and rule resource updates may fail.
Configure config.yaml and Test in the Foreground
Minimal Configuration and Listening Scope
Create the configuration with sudoedit /etc/mihomo/config.yaml. The complete minimal example below is for checking that the service works: all rules use direct connections, so it can confirm that the process and port work, but not that remote proxy nodes are available. For actual use, replace it with a complete configuration from your provider that is compatible with your mihomo version, and keep appropriate limits on local listening.
mixed-port: 7890
allow-lan: false
bind-address: 127.0.0.1
mode: rule
log-level: info
ipv6: false
rules:
- MATCH,DIRECT
mixed-port accepts HTTP and SOCKS5 proxy requests on the same port. It is neither a DNS listening port nor a control panel port. LAN access is disabled here, and the proxy binds to the loopback address. Even if the server has a public IP, there’s no need to open port 7890 in the inbound firewall rules.
sudo chown root:mihomo /etc/mihomo/config.yaml
sudo chmod 0640 /etc/mihomo/config.yaml
sudo -u mihomo /usr/local/bin/mihomo \
-t -d /var/lib/mihomo -f /etc/mihomo/config.yaml
Use -t to test the configuration, -d to set the data directory, and -f to specify the configuration file. YAML indentation cannot use tabs. If an error points to a line number, first check the indentation, colons, and quotes on that line and the one above it. A successful test mainly confirms that the configuration can be parsed and loaded; it does not prove that nodes are reachable or that all rule resources will keep updating.
Migrate a Complete Subscription Configuration
If you already have a complete YAML file, save it locally as config.yaml, upload it to a directory on the server, then install it in the service directory. The commands below assume the uploaded file is in the current directory. Don’t put a tokenized subscription URL in a shared script or terminal screenshot, and don’t assume the contents are valid based only on the file extension.
sudo install -o root -g mihomo -m 0640 \
./config.yaml /etc/mihomo/config.yaml
sudo -u mihomo /usr/local/bin/mihomo \
-t -d /var/lib/mihomo -f /etc/mihomo/config.yaml
- Check
mixed-port,allow-lan, andbind-addressin the new configuration to avoid unintentionally expanding the listening scope when you replace the file. - If the configuration includes
proxy-providers,rule-providers, or relative-path resources, check their paths and directory permissions. This guide uses/var/lib/mihomoas the data directory. - If
external-controlleris enabled, confirm that you need the interface, bind it to loopback, and set a strong secret. You can also remove the control interface settings during the initial setup. - Check for
tun, automatic routing, or DNS hijacking settings. The regular service account setup in this guide does not grant the network administration permissions these features require.
Before handing control to systemd, start the core once in the foreground and inspect the logs. When the test is done, press Ctrl+C to exit and free port 7890, then start the service.
sudo -u mihomo /usr/local/bin/mihomo \
-d /var/lib/mihomo -f /etc/mihomo/config.yaml
Run mihomo as a systemd Service at Boot
Create /etc/systemd/system/mihomo.service. This system-level service does not depend on an SSH login session; systemd keeps managing it after the terminal disconnects. The unit below is for the standard proxy mode described earlier. It runs under a dedicated account and limits writable access to the data directory.
[Unit]
Description=mihomo local proxy service
Wants=network-online.target
After=network-online.target
[Service]
Type=simple
User=mihomo
Group=mihomo
WorkingDirectory=/var/lib/mihomo
ExecStartPre=/usr/local/bin/mihomo -t -d /var/lib/mihomo -f /etc/mihomo/config.yaml
ExecStart=/usr/local/bin/mihomo -d /var/lib/mihomo -f /etc/mihomo/config.yaml
Restart=on-failure
RestartSec=5s
UMask=0027
NoNewPrivileges=true
PrivateTmp=true
ProtectHome=true
ProtectSystem=strict
ReadWritePaths=/var/lib/mihomo
[Install]
WantedBy=multi-user.target
ExecStartPre tests the configuration before startup; if the test fails, the main process won’t start. Restart=on-failure restarts the process after an unexpected exit, but won’t fix an expired subscription or unreachable node. How network-online.target behaves also depends on the distribution’s network-wait service; it does not guarantee that remote nodes are available.
sudo systemctl daemon-reload
sudo systemctl enable --now mihomo.service
systemctl is-enabled mihomo.service
systemctl is-active mihomo.service
sudo systemctl status mihomo.service --no-pager
sudo journalctl -u mihomo.service -b -n 80 --no-pager
enabled means the service is set to start at boot; active means it is running now. Check both separately. After changing the service unit, run daemon-reload and restart the service. If you changed only the YAML, test it first, then run sudo systemctl restart mihomo.service. This guide does not set ExecReload, so don’t assume systemctl reload will reload the subscription.
Connect to the Proxy and Check Connectivity
Starting the service does not automatically make every Linux process use the proxy. Check the listening port first, then test a request with the proxy specified explicitly. This helps distinguish a core that hasn’t started from an application that isn’t using it. The example request uses example.com; response status and timing depend on the network and are not fixed test results.
sudo ss -lntp 'sport = :7890'
curl --connect-timeout 10 --max-time 30 \
--proxy http://127.0.0.1:7890 \
-I https://example.com
curl --connect-timeout 10 --max-time 30 \
--proxy socks5h://127.0.0.1:7890 \
-I https://example.com
The listening address should be 127.0.0.1:7890. For HTTPS through an HTTP proxy, curl uses a CONNECT tunnel. In the SOCKS example, socks5h means the proxy resolves the destination hostname. Actual resolution and forwarding still depend on the core configuration and matching rules; the command alone does not prove that the request went through a remote node.
Proxy Environment Variables for the Terminal
To use the proxy with compatible programs in the current terminal, set the variables below. They affect only this shell and its child processes, not other users, already-running programs, or existing systemd services. Some tools have their own proxy settings; follow the tool’s documentation.
export http_proxy=http://127.0.0.1:7890
export https_proxy=http://127.0.0.1:7890
export all_proxy=socks5h://127.0.0.1:7890
export no_proxy=localhost,127.0.0.1,::1
# Unset the proxy variables just set in this terminal
unset http_proxy https_proxy all_proxy no_proxy
The value of https_proxy still uses http:// because it connects to a local HTTP proxy; it does not mean the destination website uses an unencrypted connection. To set a proxy for an individual systemd service, add the environment variables to that service’s own configuration. Don’t change routing across the entire server just for one program.
Remote Access Scope
To temporarily connect your own computer to the server’s loopback proxy, set up SSH forwarding locally instead of opening port 7890 on the server. For example, after forwarding the server’s 127.0.0.1:7890 to a local port, local programs can connect to the forwarded port. Use the SSH hostname from your existing connection configuration; access remains subject to the SSH account’s permissions.
If you really need to share the proxy on a LAN, plan allow-lan, the listening address, authentication, and firewall source ranges separately. Binding to all interfaces only expands access; it is not a performance optimization. In particular, don’t expose a proxy on a public server without access controls.
Startup Failures and Maintenance Checks
| Symptom | Check first | What to do |
|---|---|---|
Exec format error | CPU architecture and binary format | Choose and extract the matching Linux release asset |
Permission denied | Executable bit, directory permissions, and file path | Make sure the service account can read the configuration and write to the data directory |
address already in use | Existing process listening on port 7890 | Exit the foreground test or stop the duplicate core |
| YAML parsing error | Log line number, indentation, and response content | Fix the configuration; make sure you didn’t import HTML or a node list by mistake |
| Port is open, but requests fail | Node status, matched rules, DNS, and outbound network access | Check the relevant request logs to distinguish direct connections from proxy traffic |
| Service repeatedly fails to start | Configuration test and logs from the latest startup attempt | Fix the cause, reset the failed state, then start the service |
During troubleshooting, keep the specific error in view and avoid changing the node, configuration, core, and port all at once. Run sudo journalctl -u mihomo.service --since "10 minutes ago" --no-pager to check recent logs. If systemd hits its start-rate limit, fix the configuration, then run sudo systemctl reset-failed mihomo.service and start the service again. Resetting the state without fixing the cause will only lead to another failure.
Updates and Rollbacks
- Record the current
mihomo -voutput and back up the binary and configuration in use. Restrict read access to the backup files as well. - Test the existing configuration with the new binary first, and review field and behavior changes between versions. If it uses relative-path resources, use the same data directory as the service.
- Schedule a short maintenance window. Stop the service, install the new binary, then start it and check the listener, logs, and an actual request.
- If the new version doesn’t work properly, restore the original binary and its matching configuration, then test again. Don’t restore only one of them.
Updating a complete YAML file is not the same as updating subscription providers. GUI clients usually have their own subscription refresh process. With a standalone mihomo setup, proxy-providers update behavior depends on the configuration; systemd does not automatically replace the entire config.yaml. If you add scheduled updates later, download to a temporary file and validate it before replacing the current one, keeping the old configuration available in case of failure.
For the desktop approach, focus on selecting the right profile and choosing how applications connect. For the command-line approach, focus on permissions, configuration paths, and process lifecycle. Verify the local loopback proxy first, then add rule providers, remote management, or TUN one step at a time to make issues easier to isolate. For more platform-specific checks, see the cross-platform troubleshooting guide; for first-time import steps, see Getting Started.