Deploy Clash on Linux: Desktop Clients, mihomo CLI, and systemd Autostart
A practical guide to config directories, launch commands, systemd services, and terminal proxy variables—from desktop Linux to headless servers.
Choose a deployment path first: desktop, CLI, or background service
There is no single best way to deploy Clash on Linux. Personal computers running GNOME, KDE, Xfce, or another desktop environment are well suited to a graphical client. Remote servers, development container hosts, and machines managed only over SSH are better served by running the mihomo core directly. If a machine must start on boot and provide local proxy ports continuously, add a systemd service on top of the command-line setup.
mihomo is the actively maintained core associated with Clash Meta. It reads YAML configuration, establishes proxy connections, matches rules, and listens on HTTP, SOCKS, or mixed ports. Graphical clients typically provide subscription management, proxy switching, log viewing, and system-proxy controls on top of the core. In short, the desktop client handles interaction while the core processes traffic. When connections fail, determine whether the cause is the interface state, the configuration, or the core itself.
| Environment | Recommended approach | Primary management interface |
|---|---|---|
| Everyday use on a Linux desktop | Graphical client | Tray menu, client settings, and log view |
| Headless server | mihomo CLI | SSH, configuration files, and runtime logs |
| Workstation or server running continuously | mihomo with systemd | systemctl and journalctl |
| Need to handle traffic from more applications | TUN mode | Configuration, routing, and permission settings |
Before deploying, confirm the CPU architecture. Most personal computers and cloud servers use amd64, while some development boards, routers, and ARM cloud instances use arm64. Run uname -m to see the system report: x86_64 maps to amd64, and aarch64 maps to arm64. A binary built for the wrong architecture will usually produce an execution or format error in the shell.
Linux desktop clients: packages, config directories, and proxy controls
On a desktop system, start with a graphical client that is actively maintained and explicitly supports mihomo. Common release formats include AppImage, Debian-family .deb packages, and .rpm packages for Fedora, openSUSE, and similar systems. Choose the format that matches your distribution’s package workflow; there is no need to change system repositories just to install a client.
Running an AppImage
An AppImage is usually distributed as a single file, but it must be made executable after download. The commands below assume the file is in the current directory; replace the example with the complete filename you downloaded:
chmod +x Clash-Linux.AppImage
./Clash-Linux.AppImage
If double-clicking does not open a window, launch it once from a terminal and read the output. Newer distributions may be missing the FUSE compatibility component required by AppImage, or startup may be blocked by a desktop sandbox, display server, or permission setting. Terminal output is usually far more useful for diagnosis than a brief desktop notification.
Installing deb and rpm packages
Debian, Ubuntu, and their derivatives can install a local deb file through the package manager, allowing the system to resolve dependencies:
sudo apt install ./clash-client-linux-amd64.deb
On Fedora, use:
sudo dnf install ./clash-client-linux-x86_64.rpm
After installation, launch the client from the application menu. The first run usually involves three steps: import a subscription or YAML configuration, select an available proxy from a policy group, and enable the system proxy. The system-proxy setting affects only applications that honor the desktop proxy configuration. Some terminal programs, containers, games, and software with its own networking stack will not read it automatically.
A graphical client’s config directory varies by project. Common locations include an app-specific directory under ~/.config/ and a data directory under ~/.local/share/. Do not overwrite its database or managed configuration while the client is running. For migration, quit the client first and back up its application directory. If the client offers an export function, use that workflow whenever possible.
After enabling the desktop proxy, first check the client log for a successful listener message, then test access in a browser. If the browser works but terminal commands fail, the terminal program probably is not reading the system proxy—not that the core or proxy is broken.
mihomo CLI deployment: directories, configuration, and startup checks
On a headless system, keep the executable, configuration, and runtime data under separate paths. A system-wide installation can place the binary at /usr/local/bin/mihomo and the config directory at /etc/mihomo. For the current user only, use ~/.config/mihomo. The account running the core must be able to read and write the config directory because mihomo may store caches, rule data, and runtime state there.
After installing the binary, first verify that it runs:
mihomo -v
mihomo -h
If the shell says the command cannot be found, check that the file is in a directory included in PATH and that it is executable. When the binary is in the current directory, use ./mihomo; the shell does not search the current directory by default.
mihomo uses YAML configuration. The minimal example below verifies the listener ports and rule engine. It sends all traffic directly and contains no remote proxies:
mixed-port: 7890
allow-lan: false
mode: rule
log-level: info
ipv6: false
proxies: []
proxy-groups: []
rules:
- MATCH,DIRECT
Save the file as config.yaml, then run a configuration check. Supported options may vary slightly by version, so follow the output of mihomo -h; a common check looks like this:
mihomo -t -d /etc/mihomo
Once the check passes, start it in the foreground:
mihomo -d /etc/mihomo
-d sets the working directory, from which the core reads its main configuration and related data. On a first deployment, do not send it to the background immediately. Watch the startup log to confirm that the YAML parses, the ports are free, and rule files can be read. Once the mixed port is listening successfully, open another SSH session to test the proxy:
curl --proxy http://127.0.0.1:7890 https://example.com/
A production subscription usually includes proxy nodes, policy groups, rules, DNS settings, and rule providers. When updating it, do more than validate YAML syntax: check that every node or provider referenced by a policy group exists, that the rules end with a sensible fallback, and that all fields are supported by the installed mihomo version.
systemd autostart: service accounts, restart policies, and logs
For long-running deployments, register mihomo as a systemd system service. This is suitable for machines that must provide proxy ports immediately after boot and makes exit states and runtime logs easy to review consistently. Before creating the service, prepare a dedicated account and configuration directory:
sudo useradd --system --home-dir /var/lib/mihomo --create-home --shell /usr/sbin/nologin mihomo
sudo mkdir -p /etc/mihomo
sudo chown -R mihomo:mihomo /etc/mihomo /var/lib/mihomo
sudo chmod 750 /etc/mihomo
Then create /etc/systemd/system/mihomo.service:
[Unit]
Description=mihomo proxy service
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=mihomo
Group=mihomo
WorkingDirectory=/etc/mihomo
ExecStart=/usr/local/bin/mihomo -d /etc/mihomo
Restart=on-failure
RestartSec=5
LimitNOFILE=1048576
[Install]
WantedBy=multi-user.target
After saving the unit file, reload the systemd configuration and start the service:
sudo systemctl daemon-reload
sudo systemctl enable --now mihomo
sudo systemctl status mihomo
View logs from the current boot with:
sudo journalctl -u mihomo -b
sudo journalctl -u mihomo -f
-b limits the output to records from the current boot, while -f follows new entries continuously. After editing YAML, run a standalone configuration check before restarting the service:
sudo -u mihomo /usr/local/bin/mihomo -t -d /etc/mihomo
sudo systemctl restart mihomo
If it should run only after the current user logs in, use a systemd user service. Place the unit file in ~/.config/systemd/user/ and manage it with systemctl --user. A user service needs no dedicated system account, but by default it follows the lifetime of the user session. To keep it running after logout, evaluate linger settings along with the required permissions and maintenance process.
Do not configure the service to restart rapidly without conditions. YAML errors, port conflicts, and file-permission problems will not fix themselves through repeated restarts and may generate a flood of duplicate logs. Restart=on-failure with a delay of a few seconds is better suited to occasional process exits.
Terminal proxy variables: HTTP_PROXY, ALL_PROXY, and NO_PROXY
Linux desktop “system proxy” settings usually do not cover every shell command. curl, Git, some package managers, and developer tools read environment variables, so the command-line environment needs its own settings. Assuming mihomo’s mixed port is 7890, run this in the current terminal:
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
Set both uppercase and lowercase variables for compatibility with more tools:
export http_proxy="$HTTP_PROXY"
export https_proxy="$HTTPS_PROXY"
export all_proxy="$ALL_PROXY"
export no_proxy="$NO_PROXY"
In socks5h, the h means hostname resolution is also delegated to the SOCKS proxy, which is useful when you want to reduce differences in the local DNS path. However, proxy protocols and variable precedence are implemented differently across tools. When something fails, test with curl and an explicitly specified proxy first, then consult the documentation for the affected tool.
For persistent use, add the export commands to your shell configuration, such as Bash’s ~/.bashrc or Zsh’s ~/.zshrc. A safer approach is to define toggle functions so you do not forget to disable the proxy when accessing local services or troubleshooting the network:
proxy_on() {
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
export http_proxy="$HTTP_PROXY"
export https_proxy="$HTTPS_PROXY"
export all_proxy="$ALL_PROXY"
export no_proxy="$NO_PROXY"
}
proxy_off() {
unset HTTP_PROXY HTTPS_PROXY ALL_PROXY NO_PROXY
unset http_proxy https_proxy all_proxy no_proxy
}
When you run sudo, environment variables are usually filtered. A proxy enabled in a regular user’s terminal therefore does not mean programs launched by sudo will use it. Rather than preserving the entire environment for convenience, configure the proxy explicitly for the package manager or command that supports it.
Containers also do not automatically inherit a host proxy at 127.0.0.1. Inside a container, the loopback address points to the container itself, not the host. To let a container reach the host proxy, configure a reachable host address according to Docker, Podman, and the network mode, then verify mihomo’s bind address, LAN access settings, and firewall rules. Before exposing a proxy port to the LAN, restrict the permitted source networks.
TUN mode: coordinating permissions, routes, and DNS
System proxy settings and environment variables work only for applications that actively read proxy configuration. For programs without proxy support, mihomo can capture traffic through a virtual TUN interface. TUN mode changes routes and handles more connections, so it is more complex than a conventional port-based proxy.
Linux must provide /dev/net/tun first. Check it with:
ls -l /dev/net/tun
In a container or restricted virtual environment, this device may not be mapped in. Even when it exists, the account running mihomo needs network-management capabilities. Add capability settings to the systemd service as needed:
CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE
AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE
Place these two lines in the service file’s [Service] section. After editing, run systemctl daemon-reload and restart the service. A regular proxy port above 1024 generally does not need CAP_NET_BIND_SERVICE; retain it only if the actual listening port requires it.
When configuring TUN, pay attention to auto routes, automatic egress-interface detection, DNS hijacking, and IPv6 behavior. Supported fields evolve across mihomo versions, so follow the documentation and startup logs for the installed version. After deployment, verify at least the following:
- After mihomo stops, do the system’s default route and DNS settings recover?
- Does the current SSH connection remain stable, and is the remote management address kept out of the proxy?
- Do LAN subnets, gateways, NAS devices, and development services connect directly as expected?
- Do IPv4 and IPv6 follow consistent policies, preventing only one traffic family from bypassing the rules?
- After suspend/resume, a network change, or a VPN connection, does the TUN route need to be rebuilt?
Troubleshooting: check layer by layer from process to port, config, and rules
On Linux, troubleshoot connection problems layer by layer instead of immediately switching proxies or reinstalling the client. Confirm that the process exists, then verify the listening port, proxy requests, DNS, and rule matches.
The process exits immediately after startup
With systemd, start with systemctl status mihomo and journalctl -u mihomo -b. Common causes include incorrect YAML indentation, fields unsupported by the current core, a non-writable working directory, or a missing referenced rule file. Running mihomo -t -d /etc/mihomo manually usually shows the configuration error location more directly.
The port is already in use
Check which process is listening on port 7890:
ss -lntp | grep 7890
An old instance, another proxy client, or a service started twice may be holding the same port. Stop the unnecessary instance or change the port in the configuration, then update the terminal proxy variables as well. Changing only one side leaves programs pointed at the old port.
Works locally but not from other devices
Check allow-lan, the bind address, and the host firewall first. If the service listens only on 127.0.0.1, it accepts local connections only. After enabling LAN access, restrict the firewall’s source range and avoid exposing the control interface to untrusted networks. If external-controller is configured, bind it to a loopback address and set access credentials.
Works in the browser but not in Git or curl
This usually means the system proxy and terminal environment are separate. Run env | grep -i proxy to inspect the current variables, then compare with a curl test using --proxy. Also check whether the tool has an old proxy saved in its own settings; Git’s global proxy configuration, for example, can override the current environment.
The proxy is connected, but traffic uses the wrong policy
Temporarily increase the log level and inspect which rules and policy groups match each request. Clash rules are evaluated in order, so a broad rule near the top may capture traffic prematurely. Check the ordering of domain rules, IP rules, GEOIP, and rule sets, and confirm that the list ends with an explicit fallback. After changing rules, validate the configuration before a graceful reload or service restart.
A safe order for updating the core and configuration
Update the core and configuration separately. Keep a copy of the working binary and configuration, then replace one item and verify it before changing the other. After updating mihomo, run its version command and a configuration check to confirm existing fields still parse. After updating a subscription, focus on policy-group references, rule providers, and node names. Change one critical variable at a time so failures are easier to roll back and diagnose.
For long-running servers, periodically review the service exit state, log size, and configuration update time. Automatic subscription updates do not necessarily reload the core; confirm whether the client or script you use triggers a configuration reload when the file changes. When replacing a configuration that is being read, write to a temporary file, complete the syntax check, and atomically replace the live file to reduce the risk of a partially written file being loaded.
Post-deployment checklist
- Confirm that the downloaded build matches the processor architecture reported by
uname -m. - Confirm that the runtime account owns the configuration directory and that sensitive settings cannot be read by other local users.
- During foreground startup, complete YAML validation, listener-port checks, and a basic proxy request test.
- The systemd service uses an explicit working directory, runtime account, and failure-restart policy.
- Terminal proxy variables match mihomo’s actual port, with sensible direct-access ranges for local and LAN addresses.
- Before enabling TUN, check the device node, network capabilities, SSH management path, and route recovery procedure.
- Validate each change to subscriptions, rules, or the core version separately; avoid changing multiple runtime conditions at once.
Graphical clients, the mihomo CLI, and systemd are not mutually exclusive. A personal workstation can use a graphical client for everyday node management while retaining CLI methods for log diagnosis. A headless server can combine mihomo with systemd for stable, auditable operation. Once the deployment method is chosen, decide between environment variables and TUN based on whether applications read system proxy settings, keeping the overall setup clearer.