Servers, routers and NAS boxes have no desktop, so installing Clash Verge there makes no sense. Run the Mihomo core instead — it is a single command-line binary.
This walks through the whole thing on Linux amd64.
1. Download and install
What we host is a .gz archive containing one executable:
# extract
gunzip mihomo-linux-amd64-v1.19.29.gz
# make it executable
chmod +x mihomo-linux-amd64-v1.19.29
# put it on PATH with a shorter name
sudo mv mihomo-linux-amd64-v1.19.29 /usr/local/bin/mihomo
# verify
mihomo -vYou should get a version string and build information.
2. Prepare a working directory
Mihomo needs somewhere to keep its config and data files:
sudo mkdir -p /etc/mihomo
cd /etc/mihomoPut your config.yaml in there. If you have a subscription URL, download it:
sudo curl -L -o /etc/mihomo/config.yaml \
-A "clash.meta" \
"your-subscription-url"At minimum the config needs these to work:
mixed-port: 7890 # combined HTTP + SOCKS5 port
allow-lan: true # let other LAN devices connect
bind-address: "*"
mode: rule
log-level: info
external-controller: 0.0.0.0:9090 # control API
secret: "set your own password" # API password, mandatory if reachable3. Run it in the foreground first
mihomo -d /etc/mihomo-d sets the working directory. A healthy start looks like:
INFO[0000] Start initial configuration in progress
INFO[0000] Geodata Loader mode: memconservative
INFO[0000] HTTP proxy listening at: [::]:7890
INFO[0000] RESTful API listening at: [::]:9090Once you see listening at, it is up.
Confirm it works, Ctrl+C to stop, then turn it into a service.
4. The systemd unit
Create /etc/systemd/system/mihomo.service:
[Unit]
Description=Mihomo Daemon
Documentation=https://wiki.metacubex.one
After=network.target nss-lookup.target
[Service]
Type=simple
User=root
LimitNPROC=500
LimitNOFILE=1000000
CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_RAW CAP_NET_BIND_SERVICE CAP_SYS_TIME CAP_SYS_PTRACE CAP_DAC_READ_SEARCH
AmbientCapabilities=CAP_NET_ADMIN CAP_NET_RAW CAP_NET_BIND_SERVICE CAP_SYS_TIME CAP_SYS_PTRACE CAP_DAC_READ_SEARCH
Restart=always
RestartSec=5
ExecStartPre=/usr/local/bin/mihomo -t -d /etc/mihomo
ExecStart=/usr/local/bin/mihomo -d /etc/mihomo
[Install]
WantedBy=multi-user.targetThe ExecStartPre line runs a config check (-t for test). A broken config then fails the check instead of taking down a running service — a small detail that saves a lot of grief.
sudo systemctl daemon-reload
sudo systemctl enable mihomo # start at boot
sudo systemctl start mihomo # start now
sudo systemctl status mihomo # checkactive (running) means you are done.
Day-to-day commands
sudo systemctl restart mihomo # after changing the config
sudo systemctl stop mihomo
journalctl -u mihomo -f # follow the log
journalctl -u mihomo -n 100 # last 100 lines5. Letting other devices use it
allow-lan: true already permits LAN access. Other devices just point their proxy at this machine's IP and port:
On the client devices:
- Windows: Settings → Network & Internet → Proxy → Manual → enter
192.168.1.10and7890 - Phone (Wi-Fi): long-press the current network → Modify → Advanced → Proxy: Manual → same address and port
- Router level: if the router itself is the gateway, you can pair this with TUN/TProxy for transparent proxying so every device is covered automatically (a more involved setup, not covered here)
6. The control API and a web panel
external-controller: 0.0.0.0:9090 exposes a RESTful API for switching nodes, inspecting connections and reloading the config.
Quick check:
curl -H "Authorization: Bearer your-secret" http://127.0.0.1:9090/versionUseful endpoints:
| Endpoint | Purpose |
|---|---|
GET /proxies | List all nodes and policy groups |
PUT /proxies/{group} | Switch the selected node in a group |
GET /connections | Current connections |
DELETE /connections | Close all connections |
GET /logs | Live log stream |
PUT /configs?force=true | Reload the config |
Paired with a web panel you get something close to a graphical client. Put the panel files in a local directory and point external-ui at it:
external-ui: /etc/mihomo/ui
external-ui-name: metacubexdThen visit http://server-ip:9090/ui in a browser.
7. Keeping the subscription updated
A headless deployment has no client to refresh the subscription, so use cron:
sudo crontab -eAdd a line (update at 4am and restart):
0 4 * * * curl -L -A "clash.meta" -o /etc/mihomo/config.yaml "your-subscription-url" && systemctl restart mihomoA safer version downloads to a temporary file, validates it, and only then replaces the live config:
#!/bin/bash
TMP=$(mktemp)
curl -fsSL -A "clash.meta" -o "$TMP" "your-subscription-url" || exit 1
# minimal sanity check: it must contain a proxies section
grep -q "^proxies:" "$TMP" || { rm -f "$TMP"; exit 1; }
mv "$TMP" /etc/mihomo/config.yaml
systemctl restart mihomoSave it as /usr/local/bin/update-mihomo.sh, chmod +x, and call it from cron. That way a temporarily broken subscription endpoint cannot overwrite a good config with an error page.
Common problems
Fails to start with unmarshal error The YAML is invalid, or uses a field this core version does not know. Run mihomo -t -d /etc/mihomo for a config check.
Port already in use sudo ss -tlnp | grep 7890 shows what has it. Change the port in the config or stop the other process.
GeoIP database will not download Fetch geoip.metadb and geosite.dat manually into the working directory, or disable auto-update:
geo-auto-update: falseIn short
Four steps: put the binary somewhere, put a config next to it, make it a systemd service, and firewall the port.
Once running it is a background service that needs essentially no maintenance — considerably less work than installing a client on every device.
Related: sharing a proxy across your LAN and installing Clash Verge on Linux.