1. Why systemd for Clash on Linux
On a Linux desktop or server, people rarely want a proxy core sitting in an SSH session that dies when the terminal closes. You want something that starts after networking is up, survives reboots, and comes back when the process crashes. On Ubuntu 22.04, that “something” is almost always systemd: it supervises the process, records structured logs in the journal, and integrates with the same tooling you already use for nginx, Docker, or any other daemon.
This guide focuses on the Mihomo binary—the maintained Clash Meta core that speaks the same YAML vocabulary most subscription providers expect today. Treating it as a first-class service keeps your mental model simple: config.yaml lives in a fixed directory, the binary path never changes, and systemctl restart is the one knob you use after edits. That is the same operational pattern administrators expect from Clash Linux setups in homelabs and small VPS instances, even though graphical installers dominate on Windows and macOS.
If you are comparing platforms, our Windows 11 mixed-port guide covers LAN sharing and firewall rules; this article is the Linux complement—installation plus service ergonomics rather than GUI toggles.
2. Prerequisites and scope
You need a 64-bit Ubuntu 22.04 system (Jammy) with sudo access. Commands below assume a stock server or desktop install; cloud images and minimal containers work as long as systemd is PID 1 and you can create system users. ARM users should download the matching Mihomo build for arm64 instead of amd64; the file names on the release page spell out the architecture.
Bring a valid subscription or profile you are allowed to use. This walkthrough does not evaluate providers; it only ensures the engine starts, binds the ports you configured, and stays running. Legal and policy constraints are yours to verify for the network you operate on.
Optional but helpful: install curl, jq, and sudo apt install iproute2 if ss is missing in extremely trimmed images. You will use them when validating listeners and HTTP connectivity through the proxy.
3. Install the Mihomo binary
Download the latest Mihomo release archive for Linux from the project’s official GitHub Releases page, extract the single binary (often named mihomo or mihomo-linux-amd64), and install it to a standard location such as /usr/local/bin/mihomo. Make it executable with chmod +x. Placing the binary under /usr/local/bin keeps PATH predictable for root and for automation scripts without polluting /usr/bin, which package managers own.
Verify the version interactively before you daemonize:
/usr/local/bin/mihomo -v
If that prints a version string, your CPU architecture and libc match the build. When it fails with “Exec format error,” you grabbed the wrong archive—common when copying commands from an x86 tutorial onto an ARM SBC.
/etc/mihomo/README (or your chosen config root) documenting the exact release URL and checksum you installed. Future-you will thank you when debugging “it worked yesterday” incidents across kernel updates.
4. Directory layout and permissions
Do not run a network-facing proxy as root unless you have a specific reason. Create a dedicated system user and group, for example clash, with no login shell:
sudo useradd --system --home /etc/mihomo --shell /usr/sbin/nologin clash
sudo mkdir -p /etc/mihomo
sudo chown -R clash:clash /etc/mihomo
Store config.yaml and runtime artifacts (such as rule-provider caches) under /etc/mihomo. Tighten secrets: sudo chmod 600 /etc/mihomo/config.yaml if the file contains tokens. The directory itself can remain 750 so only root and the service account traverse it.
If you prefer a home-directory layout for an interactive user instead of a system account, the same permission ideas apply—just keep the User= and Group= fields in the unit file aligned with whoever should own the files. Mixed ownership (root-owned binary, user-owned config) is fine as long as the service user can read configs and write only where caches belong.
Choosing bind addresses
For a machine-local HTTP and SOCKS listener, 127.0.0.1 is the safest default on servers. If you intentionally expose the proxy to your LAN (similar to “Allow LAN” on desktop clients), set the appropriate keys in YAML to listen on 0.0.0.0 and tighten host firewalls (ufw) in a separate step. This guide does not open the port to the public internet; doing so without authentication is unsafe.
5. Minimal config.yaml checks
Your config.yaml should at least define port or mixed-port, a sane mode, DNS settings consistent with how you use fake-ip or redir-host, and proxies / proxy-groups fed by your subscription. Mihomo extends classic Clash syntax; if you import a profile from a provider, validate that the file parses: a stray tab or duplicate key prevents the service from starting and systemd will restart in a tight loop.
Point the daemon at the directory with -d (directory) or the explicit config path flag your build documents—Mihomo commonly uses -d /etc/mihomo so it loads /etc/mihomo/config.yaml by default. After any edit, prefer sudo systemctl restart mihomo over ad-hoc kill signals so restarts stay observable in the journal.
For a refresher on rule structure and modes, see our configuration documentation; it complements this Linux service layout without repeating every YAML knob.
6. systemd unit file
Create /etc/systemd/system/mihomo.service with a simple service type that runs Mihomo under the unprivileged account. The following example assumes binary at /usr/local/bin/mihomo and config root /etc/mihomo:
[Unit]
Description=Mihomo (Clash Meta) proxy
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=clash
Group=clash
ExecStart=/usr/local/bin/mihomo -d /etc/mihomo
Restart=on-failure
RestartSec=3
LimitNOFILE=1048576
# Hardening (adjust if you use features that need extra caps)
NoNewPrivileges=true
PrivateTmp=true
[Install]
WantedBy=multi-user.target
After=network-online.target reduces races where the daemon starts before DNS or routing is ready—especially on Wi-Fi or cloud instances with late DHCP. Restart=on-failure gives you crash restart without restarting on clean exits; pair it with sensible RestartSec to avoid hammering a bad config. LimitNOFILE raises the open-file ceiling for busy profiles with many concurrent streams.
If you enable TUN mode or other features that require elevated networking capabilities, you may need AmbientCapabilities=CAP_NET_ADMIN or a different user strategy. That is an advanced branch: start with userspace HTTP/SOCKS listeners on Ubuntu 22.04, validate stability, then layer TUN deliberately with documentation from your core version.
sudo systemctl daemon-reload before restart picks up changes. Forgetting reload is a frequent source of “I changed ExecStart but nothing happened.”
7. Enable, start, and logs
Reload systemd, enable the service for boot, and start it now:
sudo systemctl daemon-reload
sudo systemctl enable --now mihomo
sudo systemctl status mihomo --no-pager
Inspect logs with the journal—filtering by unit keeps noise down:
journalctl -u mihomo -e
journalctl -u mihomo --since "10 minutes ago"
Healthy output shows the core loading configuration, binding ports, and optionally syncing rule providers. Errors about YAML parsing or permission denied on the config path appear here first—fix the file, then restart again.
8. Boot order and crash recovery
Boot autostart comes from systemctl enable, which places a symlink in multi-user.target.wants. After a reboot, confirm the service is active with systemctl is-active mihomo and that listeners exist (next section). If your instance mounts network filesystems or waits on VPN interfaces, you may need additional After= dependencies—treat that as site-specific.
For crash restart, Restart=on-failure covers exits with non-zero status. If an upstream bug triggers segfaults, systemd will respawn the process with backoff defined by RestartSec. Watch for rapid restart loops in the journal; they usually mean configuration errors rather than transient network blips.
When you intentionally stop the service—maintenance window, subscription rotation—use sudo systemctl stop mihomo. That is cleaner than kill -9 because systemd records the stop in the journal and keeps enablement state predictable.
9. Verify ports and proxy path
Confirm the process listens where YAML says it should. Replace 7890 with your mixed-port or HTTP port:
sudo ss -tlnp | grep mihomo
curl -x http://127.0.0.1:7890 -I https://www.example.com
The ss line should show LISTEN on 127.0.0.1 (or 0.0.0.0 if you opened LAN access). The curl test validates the full client path through Mihomo to a remote TLS endpoint. If TCP connects but TLS fails, inspect DNS and rules before blaming systemd.
When something else on the host already occupies your chosen port, Mihomo fails early—free the port or change YAML, then reload the service. Port collisions are easy to miss when switching between manual runs and the supervised service because manual tests might use a different working directory.
| Symptom | Likely cause | First check |
|---|---|---|
| Active (running) but no listeners | Wrong -d path or config not loaded |
journalctl -u mihomo for parse errors |
| Permission denied on config | Ownership or mode bits | ls -l /etc/mihomo, fix chown/chmod |
| Restart loop every few seconds | Invalid YAML or missing files | Run mihomo manually once as clash user |
| Works manually, fails under systemd | Different user or environment | Match User= and working dir |
10. Security notes
Running Clash Linux infrastructure responsibly means limiting who can read secrets and who can reach open ports. Keep subscription URLs and API tokens in files readable only by the service account. If you must expose listeners beyond localhost, combine firewall rules with source IP constraints on trusted networks—never rely on “obscurity” of a high port number on the public internet.
Keep the Mihomo binary updated from trustworthy release artifacts. Verify checksums when the upstream publishes them. For transparency about licensing and source, the GitHub repository remains the canonical reference; separate that from day-to-day client downloads, which we centralize on the site for clarity.
Separate duties: SSH access to the host, sudo rights, and the ability to edit config.yaml should follow your organization’s least-privilege model. A read-only backup of known-good YAML saves recovery time when experiments go wrong.
11. Troubleshooting
When users search for Clash Linux and Ubuntu 22.04 together, they often already copied a unit file from a forum and hit subtle mismatches. Work through this sequence before reinstalling the binary:
- Validate YAML outside systemd. Switch to the service user with
sudo -u clash -Hand run Mihomo in the foreground once to surface errors immediately. - Confirm ExecStart matches reality. Paths are case-sensitive; a stale
-ddirectory breaks startup silently except in logs. - Compare file descriptors. Busy nodes can exhaust defaults; raise
LimitNOFILEcautiously and watch for leaks in custom scripts. - Check time sync. TLS failures on fresh VMs sometimes trace to incorrect clocks, not proxy rules.
- Review DNS mode. Fake-IP and redir-host interact with systemd-resolved or
resolv.confdifferently; align with the docs for your chosen mode.
If HTTP works on loopback but not from another host, re-evaluate bind addresses and host firewall—not Mihomo internals first.
12. Upstream and clients
The Mihomo project publishes source and release artifacts on GitHub; that is the right place to read changelogs, open issues, and verify signatures. This article’s install path is intentionally boring—stable paths, systemd supervision, predictable logs—so you can treat the proxy like any other infrastructure daemon.
Graphical Clash users on other platforms often manage YAML through a UI; on Linux servers you may pair this headless core with a separate panel or Git-driven configuration. Either way, keep a single source of truth for config.yaml and restart the unit after controlled changes.
When you also need desktop or mobile clients, browse the official download page for maintained builds across operating systems—use the same policy mindset even when the packaging differs from a bare systemd binary.
13. Summary
A solid Clash Linux deployment on Ubuntu 22.04 is less about secret flags and more about disciplined layout: a pinned Mihomo binary, a dedicated user, readable logs, and a systemd unit that handles boot autostart and crash restart without manual babysitting. Once ss and curl agree the listener and upstream path work, you can iterate on rules and DNS with confidence that operational issues will show up in journalctl instead of silent disconnects.
Compared with one-off shell wrappers, explicit service management makes the stack auditable—exactly what you want when the same host also runs backups, containers, or remote development environments. Pair this server story with our other platform guides and you cover Windows, macOS, Android, and Linux with consistent troubleshooting habits.
When you are ready to pick a client for interactive machines or refresh installers, start from the official site’s download flow so binaries match what maintainers ship—then map those clients back to the YAML patterns you already run under systemd.