Linux 下部署 mihomo:桌面图形客户端与 systemd 无界面运行

分别介绍 Linux 桌面安装图形客户端,以及服务器命令行下放置配置、编写 systemd 服务、开机自启与面板访问的完整流程。

1. 桌面选图形客户端,服务器选 systemd

Linux 上运行代理有两条常用路径。有桌面环境、需要托盘切换节点时,安装集成 mihomo 内核的图形客户端;只有 SSH 终端、需要退出登录后继续运行时,直接部署 mihomo 内核并交给 systemd 管理。两条路径使用的配置概念相同,但配置目录、订阅更新和权限管理方式不同。

ClashX 是 macOS 客户端,不是 Linux 安装包。Linux 桌面可按发行版选择 Clash Verge Rev 或 FlClash 等客户端的适配包。服务器不必为了使用代理安装桌面环境,也不必运行图形客户端的窗口进程。

使用场景建议方式配置与自启入口
个人 Linux 桌面图形客户端客户端配置页、桌面登录自启
SSH 服务器mihomo 与 systemd/etc/mihomo/config.yaml、系统服务
为个别命令提供代理本地 HTTP / SOCKS 监听应用参数或进程环境变量
需要接管更多系统流量确认权限后再配置 TUN内核配置、路由与 DNS

2. Linux 桌面安装与配置导入

确认架构和包格式

先执行以下命令确认系统。x86_64 通常对应 amd64 / x64 包,aarch64 通常对应 arm64 包;两者不能混用。Ubuntu、Debian 通常选择 DEB,Fedora 通常选择 RPM。发行版版本还会影响系统库兼容性,安装前应阅读所选客户端当前发行说明。

uname -m
cat /etc/os-release
  1. 进入安装包页面,选择 Linux,再按架构和包格式获取客户端。
  2. 在文件管理器中打开下载的 DEB 或 RPM,用系统的软件安装工具完成安装;如果依赖解析失败,先处理包管理器报告的依赖,不要强制忽略。
  3. 启动客户端,在“配置”或“Profiles”页面导入订阅地址或本地 YAML。入口名称随客户端与版本变化,以实际界面为准。
  4. 选中已导入的配置,确认节点列表与策略组存在,再查看“设置”中的代理端口,确认实际监听值。
  5. 先使用下面的显式代理命令测试,再考虑启用客户端的“系统代理”开关。
curl --proxy http://127.0.0.1:7890 \
  --connect-timeout 10 --max-time 20 \
  -I https://example.com/

这里的 7890 是本文示例值,不保证每个客户端都采用这个端口。能收到 HTTP 响应说明请求链路已经建立,但不能仅凭成功响应判断是否经过某个远端节点;若规则匹配到 DIRECT,请求仍是直连。应结合连接记录中的规则、策略组和出站节点一起确认。

桌面自启不等于系统服务

客户端“开机启动”通常依赖桌面会话,实际效果往往是用户登录桌面后启动。服务器重启后没有用户登录时,这类方式不适合承担后台代理。也不要让图形客户端和下文的 systemd 服务同时占用 127.0.0.1:7890;二选一运行,或者明确设置不同端口。

3. 放置 mihomo 内核与配置文件

以下流程面向使用 systemd 的 Linux 系统,命令以具备 sudo 权限的普通用户执行。示例使用 Debian / Ubuntu 常见的系统工具;其他发行版若缺少 useradd 等命令,应先通过发行版包管理器安装对应工具。容器与部分精简系统可能没有 systemd,不能直接套用本节服务配置。

安装可执行文件

从 mihomo 项目的官方发行页选择符合架构和 CPU 指令集要求的 Linux 构建,解压后将可执行文件放到 /tmp/mihomo。文件名应以实际下载内容为准,不能把压缩包直接当作可执行文件。旧 CPU 不应盲目选择要求更高指令集的构建。

file /tmp/mihomo
sudo install -m 0755 /tmp/mihomo /usr/local/bin/mihomo
/usr/local/bin/mihomo -v

-v 用于记录实际内核版本。出现 Exec format error 时先核对 CPU 架构;出现 Illegal instruction 时核对构建的指令集要求。本文不将某个固定版本号写进服务文件,后续升级仍沿用同一安装路径。

建立专用账户和目录

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

若账户已经存在,跳过创建步骤并检查其用户组;若发行版的 nologin 位于其他路径,先用 command -v nologin 确认后调整。配置放在 /etc/mihomo,缓存和运行数据放在 /var/lib/mihomo。服务账户只需读取配置,不需要修改订阅凭据所在的文件。

先用最小配置验证进程

sudo tee /etc/mihomo/config.yaml > /dev/null <<'YAML'
mixed-port: 7890
allow-lan: false
bind-address: 127.0.0.1
mode: rule
log-level: info
ipv6: false

rules:
  - MATCH,DIRECT
YAML

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

导入服务商配置时,先确认返回的是 mihomo 能读取的 YAML,而不是网页、登录提示或仅包含节点 URI 的文本。替换配置后,重新检查监听地址、控制端口以及规则末尾的兜底策略。订阅中的设置可能覆盖本文的本地监听限制。

-t 是配置检查,不代表远端节点、规则下载地址和目标网站一定可达。检查期间也可能涉及配置引用的数据文件,遇到失败要阅读具体日志,区分 YAML 语法错误、路径权限错误和资源获取错误。

4. 编写 systemd 服务并设置开机自启

先使用非 root 账户运行普通代理。监听 7890 这类高端口不需要 root 权限。下面的服务不配置 TUN 权限,适合显式 HTTP / SOCKS 代理,不适合直接承担透明网关。

sudo tee /etc/systemd/system/mihomo.service > /dev/null <<'UNIT'
[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
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
UNIT

sudo systemctl daemon-reload
sudo systemctl enable --now mihomo.service
sudo systemctl status mihomo.service --no-pager
sudo journalctl -u mihomo.service -b -n 80 --no-pager

enable --now 同时设置开机启动并立即启动服务。network-online.target 的实际等待效果取决于发行版是否配置了对应的网络等待服务,它不保证互联网或订阅地址已经可达。远程资源应有合理的重试与更新安排。

  • 修改 config.yaml:先执行配置检查,再运行 sudo systemctl restart mihomo。
  • 修改服务单元:先运行 sudo systemctl daemon-reload,再重启服务。
  • 只查看状态:运行 systemctl is-active mihomo 与 systemctl is-enabled mihomo。
  • 停止并取消开机启动:运行 sudo systemctl disable --now mihomo。

这份单元没有声明 ExecReload,因此不要把 systemctl reload mihomo 当成通用更新命令。使用重启方式最容易确认新配置是否加载,但现有连接可能中断。需要平滑更新时,应另行按当前内核的控制 API 文档设计流程。

5. 验证端口、代理链路与应用行为

sudo ss -lntp 'sport = :7890'

curl --proxy http://127.0.0.1:7890 \
  --connect-timeout 10 --max-time 20 \
  -I https://example.com/

curl --proxy socks5h://127.0.0.1:7890 \
  --connect-timeout 10 --max-time 20 \
  -I https://example.com/

混合端口可接收 HTTP 代理和 SOCKS 代理请求。上面的 socks5h 让 curl 把目标域名交给代理处理;socks5 则通常先在本机解析目标域名。两者会影响 DNS 排查结果,不能只看端口相同就认为行为完全相同。

仅让当前 shell 的部分程序使用代理

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

curl --connect-timeout 10 --max-time 20 -I https://example.com/

unset http_proxy https_proxy no_proxy

https_proxy 的值仍可使用 http://,表示通过 HTTP 代理建立 CONNECT 隧道,而不是要求本地代理端口自身提供 TLS。环境变量只对读取这些变量的程序及其子进程有效,不会自动覆盖浏览器、其他 systemd 服务或所有 UDP 流量。

包管理器、容器守护进程和后台服务可能使用独立代理设置。一个终端内的 curl 成功,不代表 Docker 拉取镜像或系统更新也已经走代理。应分别确认对应程序的代理入口;同样,不要把含凭据的代理变量随意写进所有用户都可读的文件。

6. 通过 SSH 隧道访问控制接口与面板

mihomo 的控制接口和代理端口是两件事。7890 接收代理请求,下面配置的 9090 用于控制 API。服务器面板建议走 SSH 本地转发,不要为了远程访问而把控制接口直接监听到公网。

启用本地控制接口

以下命令以此前最小配置为基础,只执行一次。若现有配置已经包含 external-controller 或 secret,应编辑原有字段,避免重复键。命令生成随机密钥并写入权限受限的配置,不在终端打印密钥。

controller_secret=$(openssl rand -hex 32)

printf '\nexternal-controller: 127.0.0.1:9090\nsecret: "%s"\n' \
  "$controller_secret" | \
  sudo tee -a /etc/mihomo/config.yaml > /dev/null

unset controller_secret

sudo -u mihomo /usr/local/bin/mihomo \
  -t -d /var/lib/mihomo -f /etc/mihomo/config.yaml
sudo systemctl restart mihomo

这一步需要系统已安装 OpenSSL。密钥属于控制凭据,输入面板前可通过受控的管理终端查看配置中的 secret 字段,不要将整个配置粘贴到公开工单。仅启用控制接口不会自动提供网页面板。

部署面板静态文件

从所选兼容面板项目的正式发行包取得已经构建的静态文件,将包含 index.html 的目录内容放到 /etc/mihomo/ui。不要把尚未构建的源代码目录当作静态页面目录,也不要多嵌套一层导致入口文件位于错误路径。

sudo install -d -o root -g mihomo -m 0750 /etc/mihomo/ui
sudoedit /etc/mihomo/config.yaml

在配置顶层添加以下字段,并确保服务账户能够读取面板目录中的文件:

external-ui: /etc/mihomo/ui

完成配置检查后重启服务。在本地电脑运行 SSH 命令,将本机 9090 转发到服务器回环地址的 9090。下面的 mihomo-server 是自行在 SSH 配置中建立的主机别名,应使用实际可连接的主机名称或已配置别名。

ssh -N -L 127.0.0.1:9090:127.0.0.1:9090 mihomo-server

保持 SSH 会话运行,再在本地浏览器打开 http://127.0.0.1:9090/ui/。面板后端填写 http://127.0.0.1:9090,密钥填写配置中的 secret。这里的本地地址指浏览器所在电脑,由 SSH 隧道连接到服务器;不是让浏览器直接访问服务器的回环地址。

7. TUN、订阅更新与常见故障边界

TUN 不能只改一个开关

Linux TUN 需要可用的 /dev/net/tun,通常还需要网络管理权限,并涉及自动路由、策略路由与 DNS 接管。本文的专用用户服务没有授予相关能力,直接追加 tun.enable: true 可能因权限失败。不要以长期使用 root 运行所有组件作为第一反应。

服务器尤其需要保护 SSH 管理通路。错误的默认路由、DNS 劫持或代理回环可能使连接中断。计划启用 TUN 时,先准备云控制台或串口恢复入口,核对当前内核文档的权限要求,再分别设计服务能力、路由排除和回滚步骤。桌面客户端提供的 TUN 服务模式也不等于这份普通代理单元。

订阅更新需要独立管理

把完整订阅 YAML 下载成 config.yaml,不等于内核会定时重新下载整个配置。图形客户端往往提供配置更新任务;无界面部署则应明确采用完整配置更新脚本,还是使用 proxy-providers 的 url、path 与 interval 更新节点提供者。

节点提供者文件与完整配置不是同一种结构,不能把任意订阅地址直接填进 provider。provider 的缓存路径应放在服务可写的 /var/lib/mihomo 下。更新完整配置时,先下载到临时文件、检查格式,再替换正式文件;不要直接用网络下载覆盖唯一可运行的配置。

现象优先检查处理方向
address already in usesudo ss -lntp确认是否有图形客户端或另一份内核占用 7890 / 9090。
permission denied配置可读性、缓存路径、systemd 写入限制保留配置只读,将缓存和 provider 文件移至可写数据目录。
服务反复重启journalctl -u mihomo -b先修复日志中的首个配置、资源或权限错误,再重新启动。
面板空白或 404/etc/mihomo/ui/index.html确认拿到的是构建产物,目录层级正确,服务账户可读取文件。
面板提示鉴权失败后端地址、SSH 转发端口、secret使用控制端口而非代理端口,核对当前配置中的密钥。
代理请求成功但仍是直连连接记录、规则匹配、策略组选项检查是否命中 DIRECT;最小测试配置本身只有直连。

升级与回滚检查

升级前保留旧二进制、配置和服务单元,并记录 mihomo -v 的输出。先用新二进制对现有配置执行 -t,再安排替换和重启。升级后依次确认服务状态、7890 监听、显式代理请求和面板连接;失败时恢复旧二进制与兼容配置,而不是连续修改多个网络选项。

部署完成的最低标准是:重启系统后服务为 active,代理端口只监听预期地址,应用能按规则发起请求,控制接口通过受保护的管理通路访问。把这四项分别验证,比只看到进程存在更可靠。

下载Clash