Skip to content

Commit

Permalink
Merge pull request #287966 from Guanran928/clash-meta
Browse files Browse the repository at this point in the history
nixos/mihomo: init
  • Loading branch information
doronbehar authored Mar 21, 2024
2 parents 48895ec + 84bbdc7 commit 2897be3
Show file tree
Hide file tree
Showing 6 changed files with 172 additions and 0 deletions.
2 changes: 2 additions & 0 deletions nixos/doc/manual/release-notes/rl-2405.section.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ In addition to numerous new and upgraded packages, this release has the followin

- [ollama](https://ollama.ai), server for running large language models locally.

- [Mihomo](https://github.com/MetaCubeX/mihomo), a rule-based proxy in Go. Available as [services.mihomo.enable](#opt-services.mihomo.enable).

- [hebbot](https://github.com/haecker-felix/hebbot), a Matrix bot to generate "This Week in X" like blog posts. Available as [services.hebbot](#opt-services.hebbot.enable).

- [Python Matter Server](https://github.com/home-assistant-libs/python-matter-server), a
Expand Down
1 change: 1 addition & 0 deletions nixos/modules/module-list.nix
Original file line number Diff line number Diff line change
Expand Up @@ -1018,6 +1018,7 @@
./services/networking/lxd-image-server.nix
./services/networking/magic-wormhole-mailbox-server.nix
./services/networking/matterbridge.nix
./services/networking/mihomo.nix
./services/networking/minidlna.nix
./services/networking/miniupnpd.nix
./services/networking/miredo.nix
Expand Down
118 changes: 118 additions & 0 deletions nixos/modules/services/networking/mihomo.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
# NOTE:
# cfg.configFile contains secrets such as proxy servers' credential!
# we dont want plaintext secrets in world-readable `/nix/store`.

{ lib
, config
, pkgs
, ...
}:
let
cfg = config.services.mihomo;
in
{
options.services.mihomo = {
enable = lib.mkEnableOption "Mihomo, A rule-based proxy in Go.";

package = lib.mkPackageOption pkgs "mihomo" { };

configFile = lib.mkOption {
default = null;
type = lib.types.nullOr lib.types.path;
description = "Configuration file to use.";
};

webui = lib.mkOption {
default = null;
type = lib.types.nullOr lib.types.path;
description = ''
Local web interface to use.
You can also use the following website, just in case:
- metacubexd:
- https://d.metacubex.one
- https://metacubex.github.io/metacubexd
- https://metacubexd.pages.dev
- yacd:
- https://yacd.haishan.me
- clash-dashboard (buggy):
- https://clash.razord.top
'';
};

extraOpts = lib.mkOption {
default = null;
type = lib.types.nullOr lib.types.str;
description = "Extra command line options to use.";
};

tunMode = lib.mkEnableOption ''
necessary permission for Mihomo's systemd service for TUN mode to function properly.
Keep in mind, that you still need to enable TUN mode manually in Mihomo's configuration.
'';
};

config = lib.mkIf cfg.enable {
### systemd service
systemd.services."mihomo" = {
description = "Mihomo daemon, A rule-based proxy in Go.";
documentation = [ "https://wiki.metacubex.one/" ];
requires = [ "network-online.target" ];
after = [ "network-online.target" ];
wantedBy = [ "multi-user.target" ];
serviceConfig =
{
ExecStart = lib.concatStringsSep " " [
(lib.getExe cfg.package)
"-d /var/lib/private/mihomo"
(lib.optionalString (cfg.configFile != null) "-f \${CREDENTIALS_DIRECTORY}/config.yaml")
(lib.optionalString (cfg.webui != null) "-ext-ui ${cfg.webui}")
(lib.optionalString (cfg.extraOpts != null) cfg.extraOpts)
];

DynamicUser = true;
StateDirectory = "mihomo";
LoadCredential = "config.yaml:${cfg.configFile}";

### Hardening
AmbientCapabilities = "";
CapabilityBoundingSet = "";
DeviceAllow = "";
LockPersonality = true;
MemoryDenyWriteExecute = true;
NoNewPrivileges = true;
PrivateDevices = true;
PrivateMounts = true;
PrivateTmp = true;
PrivateUsers = true;
ProcSubset = "pid";
ProtectClock = true;
ProtectControlGroups = true;
ProtectHome = true;
ProtectHostname = true;
ProtectKernelLogs = true;
ProtectKernelModules = true;
ProtectKernelTunables = true;
ProtectProc = "invisible";
ProtectSystem = "strict";
RestrictRealtime = true;
RestrictSUIDSGID = true;
RestrictNamespaces = true;
RestrictAddressFamilies = "AF_INET AF_INET6";
SystemCallArchitectures = "native";
SystemCallFilter = "@system-service bpf";
UMask = "0077";
}
// lib.optionalAttrs cfg.tunMode {
AmbientCapabilities = "CAP_NET_ADMIN";
CapabilityBoundingSet = "CAP_NET_ADMIN";
PrivateDevices = false;
PrivateUsers = false;
RestrictAddressFamilies = "AF_INET AF_INET6 AF_NETLINK";
};
};
};

meta.maintainers = with lib.maintainers; [ Guanran928 ];
}
1 change: 1 addition & 0 deletions nixos/tests/all-tests.nix
Original file line number Diff line number Diff line change
Expand Up @@ -529,6 +529,7 @@ in {
memcached = handleTest ./memcached.nix {};
merecat = handleTest ./merecat.nix {};
metabase = handleTest ./metabase.nix {};
mihomo = handleTest ./mihomo.nix {};
mindustry = handleTest ./mindustry.nix {};
minecraft = handleTest ./minecraft.nix {};
minecraft-server = handleTest ./minecraft-server.nix {};
Expand Down
44 changes: 44 additions & 0 deletions nixos/tests/mihomo.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import ./make-test-python.nix ({ pkgs, ... }: {
name = "mihomo";
meta.maintainers = with pkgs.lib.maintainers; [ Guanran928 ];

nodes.machine = {
environment.systemPackages = [ pkgs.curl ];

services.nginx = {
enable = true;
statusPage = true;
};

services.mihomo = {
enable = true;
configFile = pkgs.writeTextFile {
name = "config.yaml";
text = ''
mixed-port: 7890
external-controller: 127.0.0.1:9090
authentication:
- "user:supersecret"
'';
};
};
};

testScript = ''
# Wait until it starts
machine.wait_for_unit("nginx.service")
machine.wait_for_unit("mihomo.service")
machine.wait_for_open_port(80)
machine.wait_for_open_port(7890)
machine.wait_for_open_port(9090)
# Proxy
machine.succeed("curl --fail --max-time 10 --proxy http://user:supersecret@localhost:7890 http://localhost")
machine.succeed("curl --fail --max-time 10 --proxy socks5://user:supersecret@localhost:7890 http://localhost")
machine.fail("curl --fail --max-time 10 --proxy http://user:supervillain@localhost:7890 http://localhost")
machine.fail("curl --fail --max-time 10 --proxy socks5://user:supervillain@localhost:7890 http://localhost")
# Web UI
machine.succeed("curl --fail http://localhost:9090") == '{"hello":"clash"}'
'';
})
6 changes: 6 additions & 0 deletions pkgs/by-name/mi/mihomo/package.nix
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{ lib
, fetchFromGitHub
, buildGoModule
, nixosTests
}:

buildGoModule rec {
Expand Down Expand Up @@ -31,6 +32,11 @@ buildGoModule rec {
# network required
doCheck = false;


passthru.tests = {
mihomo = nixosTests.mihomo;
};

meta = with lib; {
description = "A rule-based tunnel in Go";
homepage = "https://github.com/MetaCubeX/mihomo";
Expand Down

0 comments on commit 2897be3

Please sign in to comment.