1{
2 config,
3 lib,
4 pkgs,
5 ...
6}:
7
8{
9 imports = [
10 ];
11 options.programs.clash-verge = {
12 enable = lib.mkEnableOption "Clash Verge";
13 package = lib.mkOption {
14 type = lib.types.package;
15 description = ''
16 The clash-verge package to use. Available options are
17 clash-verge-rev and clash-nyanpasu, both are forks of
18 the original clash-verge project.
19 '';
20 default = pkgs.clash-verge-rev;
21 defaultText = lib.literalExpression "pkgs.clash-verge-rev";
22 };
23 serviceMode = lib.mkEnableOption "Service Mode";
24 tunMode = lib.mkEnableOption "Setcap for TUN Mode. DNS settings won't work on this way";
25 autoStart = lib.mkEnableOption "Clash Verge auto launch";
26 };
27
28 config =
29 let
30 cfg = config.programs.clash-verge;
31 in
32 lib.mkIf cfg.enable {
33
34 environment.systemPackages = [
35 cfg.package
36 (lib.mkIf cfg.autoStart (
37 pkgs.makeAutostartItem {
38 name = "clash-verge";
39 package = cfg.package;
40 }
41 ))
42 ];
43
44 security.wrappers.clash-verge = lib.mkIf cfg.tunMode {
45 owner = "root";
46 group = "root";
47 capabilities = "cap_net_bind_service,cap_net_raw,cap_net_admin=+ep";
48 source = "${lib.getExe cfg.package}";
49 };
50
51 systemd.services.clash-verge = lib.mkIf cfg.serviceMode {
52 enable = true;
53 description = "Clash Verge Service Mode";
54 serviceConfig = {
55 ExecStart = "${cfg.package}/bin/clash-verge-service";
56 Restart = "on-failure";
57 ProtectSystem = "strict";
58 NoNewPrivileges = true;
59 ProtectHostname = true;
60 ProtectProc = "invisible";
61 ProcSubset = "pid";
62 SystemCallArchitectures = "native";
63 PrivateTmp = true;
64 PrivateMounts = true;
65 ProtectKernelTunables = true;
66 ProtectKernelModules = true;
67 ProtectKernelLogs = true;
68 ProtectControlGroups = true;
69 LockPersonality = true;
70 RestrictRealtime = true;
71 RuntimeDirectory = "clash-verge-rev";
72 ProtectClock = true;
73 MemoryDenyWriteExecute = true;
74 RestrictSUIDSGID = true;
75 RestrictNamespaces = [ "~user cgroup mnt uts" ];
76 RestrictAddressFamilies = [
77 "AF_INET AF_INET6 AF_NETLINK AF_PACKET AF_UNIX"
78 ];
79 CapabilityBoundingSet = [
80 "CAP_NET_ADMIN CAP_NET_RAW CAP_SYS_ADMIN CAP_DAC_OVERRIDE CAP_SETUID CAP_SETGID CAP_CHOWN CAP_MKNOD"
81 ];
82 SystemCallFilter = [
83 "~@aio @chown @clock @cpu-emulation @debug @keyring @memlock @module @mount @obsolete @pkey @privileged @raw-io @reboot @sandbox @setuid @swap @timer"
84 ];
85 SystemCallErrorNumber = "EPERM";
86 };
87 wantedBy = [ "multi-user.target" ];
88 };
89 };
90
91 meta.maintainers = with lib.maintainers; [
92 bot-wxt1221
93 Guanran928
94 ];
95}