Tutorial · Estimated reading 12 mins

Install Mihomo on Linux with systemd:
Minimal YAML for daily use

You do not need a desktop environment to run a solid Clash-compatible proxy on Linux. This walkthrough covers binary install on Debian/Ubuntu-style hosts, a small production-minded YAML, and a systemd unit so Mihomo starts on boot and recovers from crashes.

Linux · Mihomo · systemd · Clash · VPS

1 Why run Mihomo on Linux

If you administer a Debian or Ubuntu server, maintain a Fedora workstation, or rent a small VPS for development, you often need a proxy layer that stays out of the way: low memory footprint, no mandatory GUI, and reliable restarts after upgrades or kernel panics. Mihomo, the community continuation of the Clash.Meta core, fits that role well. It speaks the same YAML dialect as mainstream Clash clients, supports modern transports such as Hysteria2 and TUIC v5, and can grow from a tiny mixed-port setup to full TUN-based transparent routing when you are ready.

Desktop Linux users sometimes install a graphical Clash front-end, but on headless machines or minimal cloud images the usual pattern is a single static binary plus a configuration directory. Pairing that binary with systemd gives you process supervision, journal integration, and the ability to enable the service at boot without cron hacks or screen sessions. This guide targets that stack: install Mihomo on amd64 (typical for most VPS plans), drop in a Clash-compatible minimal YAML you can extend later, and register a systemd unit so the daemon survives reboots and crashes.

The configuration below is intentionally conservative. It exposes a mixed HTTP and SOCKS listener on port 7890, enables LAN access so other devices on the same network can point to your machine, and turns on DNS handling with FakeIP to reduce leakage. You should treat the proxy list as a placeholder: paste nodes from your provider or merge a subscription URL using a converter workflow you already trust. Nothing here replaces your provider's security obligations; you remain responsible for keys, endpoints, and compliance with local policy.

2 Download and install the binary

Start by identifying your CPU architecture. Cloud vendors overwhelmingly ship x86_64 images, which Mihomo labels as amd64. ARM64 devices, including many Raspberry Pi OS 64-bit installs and Ampere VPS plans, need the arm64 artifact instead. If you are unsure, run uname -m: outputs such as x86_64 map to amd64, while aarch64 maps to arm64.

The project publishes compressed binaries on GitHub Releases. Pick the latest stable tag, copy the correct asset name, and download with curl or wget. The snippet below illustrates amd64 version 1.18.0; replace the URL when a newer release ships. Keeping the binary under /usr/local/bin follows Filesystem Hierarchy Standard expectations for locally managed software and keeps your PATH tidy for manual troubleshooting.

Create layout directories

Store configuration under /etc/mihomo and logs under /var/log/mihomo. Both paths are arbitrary but conventional; adjust if your distribution prefers /usr/local/etc.

Bash
sudo mkdir -p /etc/mihomo
sudo mkdir -p /var/log/mihomo

Fetch and install Mihomo

After downloading, decompress, move the binary into place, and mark it executable. Verify with mihomo -v before you wire up systemd.

Bash
# Replace URL with the latest amd64 release asset
wget https://github.com/MetaCubeX/Mihomo/releases/download/v1.18.0/mihomo-linux-amd64-v1.18.0.gz

gunzip mihomo-linux-amd64-v1.18.0.gz
sudo mv mihomo-linux-amd64-v1.18.0 /usr/local/bin/mihomo
sudo chmod +x /usr/local/bin/mihomo
/usr/local/bin/mihomo -v
Package managers: Some distributions or third-party repositories ship Mihomo or Clash.Meta packages. Those can speed up updates, but manual installs remain portable across Ubuntu, Debian, Arch, and RHEL derivatives. Pick whichever matches your change-management rules.

3 Minimal Clash-compatible YAML

Mihomo reads config.yaml from the directory passed to -d. The file is largely compatible with Clash Premium schemas, so snippets from older tutorials usually work after minor key renames. This template focuses on daily mixed-port usage: local applications and containers can set http_proxy to http://127.0.0.1:7890 without TUN drivers. The DNS section enables FakeIP and upstream resolvers; tune nameserver and fallback to match your region and threat model.

Populate the proxies list with real nodes or reference a proxy-providers block if you load remote subscriptions. Until you add outbound servers, keep proxy-groups pointing at DIRECT so the parser stays valid. After you insert nodes, extend the selector group with their names and adjust rules for streaming or LAN exceptions as needed. For converting non-Clash subscription URLs into YAML, many teams use a self-hosted subconverter; the important part is to audit the generated file before deploying it to production hosts.

YAML (/etc/mihomo/config.yaml)
# External controller (dashboard / API)
external-controller: 0.0.0.0:9090
secret: "change_me_strong_password"

# Mixed HTTP + SOCKS listener
mixed-port: 7890
allow-lan: true
mode: rule
log-level: info
ipv6: false

dns:
  enable: true
  listen: 0.0.0.0:1053
  enhanced-mode: fake-ip
  fake-ip-range: 198.18.0.1/16
  nameserver:
    - 223.5.5.5
    - 119.29.29.29
  fallback:
    - https://8.8.8.8/dns-query
    - https://1.1.1.1/dns-query

# Replace with your real proxies or proxy-providers
proxies: []

proxy-groups:
  - name: Proxy
    type: select
    proxies:
      - DIRECT

rules:
  - GEOIP,CN,DIRECT
  - MATCH,Proxy

Lock down permissions on the file because it contains secrets: sudo chown root:root /etc/mihomo/config.yaml && sudo chmod 600 /etc/mihomo/config.yaml. If you expose external-controller on all interfaces, firewall the management port or bind it to localhost only. The sample uses 0.0.0.0 for remote dashboards—convenient on a VPS, risky without packet filtering.

4 systemd unit file

systemd supervises long-running daemons better than nohup scripts. A Type=simple service works because Mihomo stays in the foreground. Restart=always handles crashes; combine with RestartSec to avoid tight restart loops while you fix configuration mistakes. Logging via StandardOutput and StandardError append lines to files under /var/log/mihomo, which complements journalctl if you prefer centralized logs.

The unit below runs as root for simplicity. Root is often required when you later enable TUN or bind privileged ports. For a least-privilege deployment limited to high ports, create a dedicated mihomo user, grant read rights to /etc/mihomo, and drop User= accordingly. TUN mode typically demands capabilities such as CAP_NET_ADMIN; consult Mihomo documentation when you graduate beyond mixed-port mode.

Bash
sudo nano /etc/systemd/system/mihomo.service

Paste the following unit definition:

Service file
[Unit]
Description=Mihomo Daemon, A rule-based tunnel in Go.
After=network.target network-online.target nss-lookup.target

[Service]
Type=simple
User=root
ExecStart=/usr/local/bin/mihomo -d /etc/mihomo
Restart=always
RestartSec=5
StandardOutput=append:/var/log/mihomo/output.log
StandardError=append:/var/log/mihomo/error.log

[Install]
WantedBy=multi-user.target
Security note: Running as root broadens the blast radius if the binary or config is compromised. Prefer a dedicated service account when high ports are enough, and keep the management API off the public internet unless you fully understand the exposure.

5 Enable and manage the service

After saving the unit, reload systemd's configuration cache, start the daemon, and enable it for multi-user boot. Use status to confirm the main process is active, and follow with journalctl -u mihomo -f during your first edits to catch YAML mistakes immediately.

Bash
sudo systemctl daemon-reload
sudo systemctl enable --now mihomo
sudo systemctl status mihomo --no-pager

Routine maintenance commands include sudo systemctl restart mihomo after configuration changes, sudo systemctl stop mihomo for maintenance windows, and sudo systemctl disable mihomo if you need to pause autostart. Pair these with configuration backups so rollback stays simple when experimenting with new rule providers.

6 Point shells and apps at the mixed port

Mihomo does not alter global desktop settings automatically. Applications must opt in via environment variables or explicit proxy configuration. The mixed port accepts both HTTP and SOCKS clients; most CLI tools understand uppercase http_proxy and https_proxy variables pointing to an HTTP proxy URI.

Temporary session exports

Shell
export http_proxy="http://127.0.0.1:7890"
export https_proxy="http://127.0.0.1:7890"
export all_proxy="socks5://127.0.0.1:7890"

Persistent user defaults

Append the same exports to ~/.bashrc, ~/.zshrc, or systemd user environment drop-ins for GUI sessions, then open a new shell. Remember to define no_proxy for local addresses so internal APIs stay on the LAN path.

Bash
cat >> ~/.bashrc <<'EOF'
export http_proxy="http://127.0.0.1:7890"
export https_proxy="http://127.0.0.1:7890"
export no_proxy="localhost,127.0.0.1,::1"
EOF
source ~/.bashrc

Smoke test

Bash
curl -I https://www.example.com

Expect a quick TLS handshake and an HTTP status line if routing and DNS succeed. If the command hangs, verify Mihomo is running, confirm the selector group actually includes a working outbound, and ensure firewall rules allow forwarded DNS queries on port 1053 when you query through Mihomo’s DNS listener.

7 Troubleshooting checklist

  • Unit fails immediately: Run journalctl -u mihomo -n 100 --no-pager. Indentation errors in YAML and missing proxies references inside groups are frequent culprits.
  • Port already in use: Change mixed-port or stop conflicting services with sudo ss -lntp to identify listeners.
  • Dashboard unreachable remotely: Open the management port in ufw, firewalld, or your cloud security group, or bind external-controller to 127.0.0.1 and tunnel via SSH.
  • DNS oddities: Another resolver may already bind port 53. Keeping Mihomo’s DNS on 1053 avoids collisions; align your rules accordingly.
  • Permission errors after hardening: Confirm the service account can read /etc/mihomo and write log files; use systemd-tmpfiles or ACLs if you split users.

8 Wrap-up

You now have a reproducible pattern for Linux hosts: drop the Mihomo binary under /usr/local/bin, keep declarative config in /etc/mihomo, and let systemd handle boot ordering and restarts. The YAML stays compatible with the broader Clash ecosystem, so you can reuse snippets from desktop clients or community rule sets without reinventing structure. Compared with ad hoc scripts, this setup survives unattended reboots and surfaces failures through familiar tooling.

When you outgrow manual environment variables, consider transparent routing. Our Clash Verge Rev TUN mode guide walks through full-stack takeover on desktop operating systems; many of the same YAML concepts apply once you enable TUN inside Mihomo on Linux. For a polished GUI on your workstation, a dedicated client often beats hand-edited files, even though servers still shine with the lean stack described here.

Clash-compatible clients generally offer smoother onboarding than stitching together unrelated tools: unified rule editing, built-in DNS helpers, and healthier defaults for mixed networks. If you want that experience without living inside a terminal editor, pick a maintained build for your platform from our downloads page.

→ Download Clash for free and experience the difference

Tags: Linux Mihomo systemd Clash VPS YAML
Clash client logo

Clash Verge Rev

Next-gen Clash client · Free and open source

Built on the Mihomo core with optional TUN mode, subscription import, and Linux desktop packages alongside Windows and macOS—handy when you want a GUI on top of the same rules you run on servers.

TUN full traffic takeover Mihomo high-performance core Precise rule routing DNS leak helpers Multi-subscription management

Related reading