Merge pull request #287966 from Guanran928/clash-meta

nixos/mihomo: init
This commit is contained in:
Doron Behar 2024-03-21 10:40:10 +02:00 committed by GitHub
commit 2897be360b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 172 additions and 0 deletions

View File

@ -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

View File

@ -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

View File

@ -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 ];
}

View File

@ -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 {};

44
nixos/tests/mihomo.nix Normal file
View File

@ -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"}'
'';
})

View File

@ -1,6 +1,7 @@
{ lib
, fetchFromGitHub
, buildGoModule
, nixosTests
}:
buildGoModule rec {
@ -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";