What this guide covers (and what it assumes)
You are on Fedora Workstation because you want a rolling-but-stable desktop with modern kernels, sensible defaults, and first-class dnf packaging—but the same reasons that make Fedora pleasant also change how you install Clash Meta compared with Debian or Ubuntu. SELinux is usually enforcing, firewalld owns the user-facing firewall story, and NetworkManager still negotiates DHCP while Mihomo tries to insert routes. None of that is impossible; it simply means you should not paste an Ubuntu-only checklist and expect Linux TUN permissions, DNS, and systemd autostart to line up without a second pass.
This article assumes you already have permission to use the subscription or profile you load into Mihomo, that you can keep YAML indentation honest, and that you understand the difference between a mixed port listener and TUN capture. It focuses on Fedora-specific sequencing: prepare packages with dnf, place files where SELinux will not surprise you, prove listeners, wire a systemd unit with the right capability bounding set, align resolvers, and only then flip tun.enable with auto-route. If the capture concepts feel fuzzy, read the Clash TUN mode guide first; the mental model is identical, only the plumbing differs. For a Debian-oriented baseline you can still borrow directory ideas from the Ubuntu Clash Meta install article, then return here for the Fedora deltas.
Step 1: dnf prep, kernel modules, and the tools Mihomo expects
Before you download a binary, make sure the workstation profile actually contains the tiny utilities you will use for debugging. Fedora splits packages aggressively; it is normal to discover that dig, tcpdump, or ss live in optional components you have not installed yet. A pragmatic first pass is:
sudo dnf install -y bind-utils iproute nftables /usr/sbin/sestatus
That line is intentionally boring. You are not “installing Clash from dnf” here—upstream Mihomo builds are still delivered as archives you place yourself—but you are guaranteeing that when TUN misbehaves you can answer whether the tunnel exists, whether routes duplicated, and whether packets leave the expected interface. Confirm the tun kernel interface class is available; on stock Fedora Workstation it already is, yet verifying with modinfo tun costs nothing and saves a long night when you accidentally booted a custom kernel flavor without the module bundle you expected.
Keep your firmware and kernel reasonably current. Mihomo’s system stack expects sane netlink behavior; chasing proxy bugs on a months-old crashy wireless driver is a different project. If you live on Fedora Silverblue or another rpm-ostree image, treat /usr as read-only: place the binary under /var/usrlocal/bin or another writable layer your compositor documents, and adjust the unit paths accordingly. The rest of this guide assumes a classic mutable Workstation install, but the ordering—listeners, systemd, TUN—still applies.
Step 2: Directory layout, ownership, and SELinux-friendly placement
Fedora’s hardened posture means “drop a random binary in /usr/local/bin and hope” sometimes works, and sometimes you get an execmem or mis-labeled file that fails only under specific transitions. A calmer layout mirrors what administrators already do on RHEL: keep configuration under /etc/mihomo, state under /var/lib/mihomo, and the executable somewhere predictable such as /usr/local/bin/mihomo with an explicit chcon or a relocation into /opt/mihomo/bin that you label once. After copying files, run sudo restorecon -RFv /usr/local/bin/mihomo /etc/mihomo /var/lib/mihomo (adjust paths) so contexts match your chosen tree.
Create a service user if you want isolation:
sudo useradd --system --home /var/lib/mihomo --shell /sbin/nologin mihomo
sudo chown -R mihomo:mihomo /var/lib/mihomo
On a single-user laptop you may run as your own UID instead; the trade-off is that any application running as you can hit the external controller or signal the process. Either way, avoid world-readable secrets: chmod 600 /etc/mihomo/config.yaml is a good habit.
Fetch a maintained Linux build from the official Clash download page instead of random social links. Smoke-test interactively before systemd:
sudo -u mihomo /usr/local/bin/mihomo -d /var/lib/mihomo -f /etc/mihomo/config.yaml
You should see listener lines without instant YAML fatals. If this step fails, fix the profile while stderr is attached to your terminal; journalctl can wait.
Step 3: Minimal listener configuration before you touch TUN
Carry the same discipline you would on any distribution: prove mixed-port (or explicit HTTP and SOCKS ports), a controller socket or REST address you actually intend to protect, and DNS behavior that matches whether you run fake-ip or redir-host. Fedora ships systemd-resolved and stub listening patterns that look a lot like Ubuntu’s, so the failure mode is identical even if the control commands differ: once auto-route toggles on, latent DNS loops become visible.
Checklist before tun.enable: true:
- Listeners bound to
127.0.0.1unless you explicitly want LAN exposure. - Controller authentication or binding restricted to loopback.
- DNS inbound that will not fight the stub resolver unless you intend to replace it.
When migrating profiles from another core, walk the field renames in the Clash Meta (Mihomo) upgrade guide so you are not blending deprecated keys with modern defaults.
Step 4: systemd unit with NetworkManager ordering and Linux capabilities
Fedora boots quickly; services that race ahead of DHCP can look “flaky” even when YAML is perfect. A conservative unit depends on network-online.target and keeps restart policy honest. Capabilities are the heart of Linux TUN permission ergonomics: grant CAP_NET_ADMIN to the service user so Mihomo can create the tunnel without setuid root.
[Unit]
Description=Mihomo (Clash Meta) for Fedora
After=network-online.target NetworkManager-wait-online.service
Wants=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=3
AmbientCapabilities=CAP_NET_BIND_SERVICE CAP_NET_ADMIN
CapabilityBoundingSet=CAP_NET_BIND_SERVICE CAP_NET_ADMIN
NoNewPrivileges=true
LimitNOFILE=1048576
[Install]
WantedBy=multi-user.target
Apply it:
sudo systemctl daemon-reload
sudo systemctl enable --now mihomo.service
systemctl status mihomo.service --no-pager
If the daemon exits immediately, read journalctl -u mihomo -e --no-pager. Typical Fedora-specific wrinkles include SELinux denials (look for avc: denied), wrong labels on the binary, or a state directory still owned by root. Resolve those before enabling TUN; otherwise you will misattribute routing failures to Mihomo when the service never stayed up long enough to program the stack.
Step 5: Enable TUN after listeners succeed—stack, auto-route, and firewalld awareness
When applications ignore environment variables or open UDP flows that bypass SOCKS, TUN mode is the right layer. On Fedora kernels, start with the system stack unless you have a measured reason to prefer gvisor; it integrates with the same netlink paths ip route already shows you. A conservative tun stanza looks like:
tun:
enable: true
stack: system
auto-route: true
auto-detect-interface: true
strict-route: false
Flip one knob at a time. Restart the service, confirm a device such as Meta or tun0 appears in ip link, then inspect ip route show table all for duplicate defaults. Because firewalld maintains zones, aggressive local rules can still interfere even when Mihomo thinks it owns policy. If you previously punched custom rich rules, temporarily simplify while you validate TUN, then reintroduce constraints deliberately.
Remember the capability story: without CAP_NET_ADMIN, TUN creation fails with permission errors that look like generic “operation not permitted” messages. The sample unit above uses AmbientCapabilities so a non-root service user retains them. setcap cap_net_admin,cap_net_bind_service+ep /usr/local/bin/mihomo is an alternative some admins prefer; pick one strategy and document it for your future self.
Step 6: systemd-resolved, NetworkManager, and DNS order on Fedora
Fedora Workstation still routes many desktops through the stub resolver at 127.0.0.53. Mihomo may want to become the upstream for captured clients once TUN hijacks traffic. The failure pattern is universal: names resolve outside Mihomo while packets follow the tunnel, or every name flows through Mihomo while RFC1918 split zones silently break.
Practical steps:
- Decide who owns upstream DNS for captured applications, then draw it.
- Use
resolvectl statusandnmcli dev showto see which interface and DNS servers NetworkManager actually advertised. - Test both a public hostname and a LAN hostname that must stay direct before you declare victory.
For deeper fake-ip interplay, reuse the troubleshooting map in the TUN guide; Fedora differs from Windows in resolver plumbing, not in the requirement that DNS and routing agree.
Step 7: GNOME, KDE, and “TUN plus mixed port” ergonomics
Fedora ships multiple desktop spins, yet the advice stays consistent: if TUN capture works, you may still keep the mixed port for diagnostics or for CLI tools that speak SOCKS explicitly. Avoid configuring GNOME’s manual HTTP proxy and TUN in conflicting ways unless you enjoy duplicated flows inside Chromium. If another VPN already owns the default route, either disable it or split responsibilities; two stacks fighting for the same default is a recipe for intermittent “half the internet works” bugs.
Step 8: dnf, git, and shell automation around the mixed port
Even with TUN, many engineers still export http_proxy and https_proxy for dnf operations that must traverse a corporate forwarder, or conversely set no_proxy for local mirrors. Fedora’s dnf.conf supports proxy= directives if you prefer file-level configuration over environment variables. Keep the story consistent: either the mixed port handles dnf traffic, or TUN captures it without extra exports, but do not stack contradictory overrides and then wonder why only one terminal session behaves.
Step 9: Verification checklist tuned for Fedora
systemctl is-active mihomoreturnsactiveafter a reboot, not only after manual starts.ss -lntplists your loopback listeners with the UID you expect.ip linkshows the Mihomo tunnel device when TUN is enabled.resolvectl query example.comreflects the resolver path you designed.curl --ipv4 https://example.com(and an IPv6 variant if you use it) succeeds for both direct and policy cases.- Optional:
ausearch -m avc -ts recentafter first TUN boot confirms SELinux is quiet.
Only after those pass should you tune rich rules or zone assignments in firewalld. Debugging YAML, netfilter, and provider routing at the same time is expensive.
Common Fedora pitfalls and how to escape them
- SELinux denials on the binary or state dir: check
ausearch, apply a targeted context withsemanage fcontextif you insist on exotic paths, or relocate into/optwith documented labels. - TUN works once, fails after reboot: usually a racing unit without
network-online.target, or capabilities dropped because the service file changed withoutdaemon-reload. - DNS works in curl but browsers stall: split-brain between stub resolver and fake-ip; isolate with
resolvectland Mihomo DNS logs. - firewalld surprises: verify zones with
firewall-cmd --list-all; remember that user-space helpers can reorder rules independently of nftables intuition. - Silverblue layering: if you cannot write to
/etc/systemd/system, userpm-ostree initramfsworkflows or place units in the paths ostree documents—do not treat immutability as optional.
Where to go next in the documentation set
Installation is scaffolding; routing policy is the product. After the unit is stable, spend time in the Clash documentation hub for rule ordering, provider refresh cadence, and performance habits that matter more than any single Fedora tweak. Keep Mihomo updated on a schedule you can defend; the upgrade guide captures the silent behavior changes that bite people who only bump binaries without reading release notes.
Closing: treat Fedora like the serious network OS it is
Fedora Workstation does not hide complexity—it exposes enough rope to hang interesting routing experiments, then gives you SELinux, firewalld, and modern kernels to keep you honest. Clash Meta fits that culture well when you respect the order: prove YAML on a mixed port, install a systemd unit that preserves CAP_NET_ADMIN, align DNS with NetworkManager reality, and only then enable TUN auto-route. Compared with ad-hoc per-app proxy toggles, Mihomo rewards the same discipline Red Hat users already associate with long-running services.
When the checklist passes twice—once before lunch and once after a cold boot—you can trust the stack more than any single speedtest screenshot. Curated installers and documentation-first workflows beat chasing random nightly artifacts, especially on a distribution that updates frequently. If you want a polished entry point while you experiment with advanced rules, start from the official download page, keep your Fedora system current, and treat every routing change like a production change because, on your laptop, it is.