main
1{
2 den,
3 lib,
4 ...
5}: {
6 den.aspects.services.mihomo = {
7 settings.host = {
8 autoStart = lib.mkEnableOption "Auto start mihomo service";
9 tailscaleWebControl = lib.mkEnableOption "Allow connect external controller from tailscale subnet";
10 interfaces = {
11 wan = lib.mkOption {
12 description = "The WAN interface to bind.";
13 type = lib.types.str;
14 default = null;
15 };
16 lan = lib.mkOption {
17 description = "The LAN interface to bind.";
18 type = lib.types.listOf lib.types.str;
19 default = [];
20 };
21 };
22 ports = {
23 controller = lib.mkOption {
24 type = lib.types.port;
25 default = 7900;
26 };
27 dns = lib.mkOption {
28 type = lib.types.port;
29 default = 1053;
30 };
31 mixed = lib.mkOption {
32 type = lib.types.port;
33 default = 7890;
34 };
35 tproxy = lib.mkOption {
36 type = lib.types.port;
37 default = 7894;
38 };
39 };
40 };
41
42 includes = with den.aspects.services.mihomo; [
43 dns
44 proxies
45 proxy-groups
46 rules
47 sniffer
48 grants
49 ];
50
51 cache = {
52 directories = [
53 {
54 directory = "/var/lib/mihomo";
55 user = "mihomo";
56 group = "mihomo";
57 }
58 ];
59 };
60
61 nixos = {
62 host,
63 pkgs,
64 ...
65 }: let
66 cfg = host.settings.services.mihomo;
67 in {
68 imports = [./_module.nix];
69
70 services.mihomo = {
71 enable = true;
72 webui = pkgs.metacubexd;
73 processesInfo = lib.mkDefault true;
74
75 config = {
76 mixed-port = cfg.ports.mixed;
77 mode = "rule";
78 ipv6 = false;
79 find-process-mode = lib.mkDefault "strict";
80 allow-lan = lib.mkDefault true;
81 bind-address = lib.mkDefault "*";
82 log-level = "warning";
83 interface-name = cfg.interfaces.wan;
84 unified-delay = true;
85 tcp-concurrent = true;
86 geodata-mode = true; # `.dat`
87 geox-url = {
88 geoip = "https://testingcf.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@release/geoip.dat";
89 geosite = "https://testingcf.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@release/geosite.dat";
90 };
91 external-controller = "${
92 if cfg.tailscaleWebControl
93 then host.address.ipv4.tailscale
94 else "127.0.0.1"
95 }:${toString cfg.ports.controller}";
96 external-controller-cors = {
97 allow-origins = ["*"];
98 allow-private-network = true;
99 };
100 };
101 };
102
103 systemd.services."mihomo" = {
104 wants = lib.optional (cfg.tailscaleWebControl) "tailscale-wait-online.service";
105 after = lib.optional (cfg.tailscaleWebControl) "tailscale-wait-online.service";
106 wantedBy = lib.mkIf (!cfg.autoStart) (lib.mkForce []);
107 };
108 };
109 };
110
111 den.aspects.services.mihomo.grants = {host, ...}: {
112 tailscaleGrant = lib.optional (host.settings.services.mihomo.tailscaleWebControl) {
113 src = ["autogroup:member"];
114 ip = ["tcp:${toString host.settings.services.mihomo.ports.controller}"];
115 };
116 };
117}