mirror of
https://github.com/NixOS/nixpkgs.git
synced 2025-07-13 13:40:28 +03:00
nixos/easytier: init module
This commit is contained in:
parent
4206c4cb56
commit
725a756dbb
6 changed files with 422 additions and 1 deletions
|
@ -88,6 +88,8 @@ Alongside many enhancements to NixOS modules and general system improvements, th
|
|||
|
||||
- [Readeck](https://readeck.org/), a read-it later web-application. Available as [services.readeck](#opt-services.readeck.enable).
|
||||
|
||||
- [EasyTier](https://github.com/EasyTier/EasyTier), a decentralized VPN solution. Available as [services.easytier](#opt-services.easytier.enable).
|
||||
|
||||
- [Traccar](https://www.traccar.org/), a modern GPS Tracking Platform. Available as [services.traccar](#opt-services.traccar.enable).
|
||||
|
||||
- [Schroot](https://codeberg.org/shelter/reschroot), a lightweight virtualisation tool. Securely enter a chroot and run a command or login shell. Available as [programs.schroot](#opt-programs.schroot.enable).
|
||||
|
|
|
@ -1115,6 +1115,7 @@
|
|||
./services/networking/dnsproxy.nix
|
||||
./services/networking/doh-proxy-rust.nix
|
||||
./services/networking/doh-server.nix
|
||||
./services/networking/easytier.nix
|
||||
./services/networking/ejabberd.nix
|
||||
./services/networking/envoy.nix
|
||||
./services/networking/epmd.nix
|
||||
|
|
292
nixos/modules/services/networking/easytier.nix
Normal file
292
nixos/modules/services/networking/easytier.nix
Normal file
|
@ -0,0 +1,292 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
|
||||
with lib;
|
||||
let
|
||||
cfg = config.services.easytier;
|
||||
settingsFormat = pkgs.formats.toml { };
|
||||
|
||||
genFinalSettings =
|
||||
inst:
|
||||
attrsets.filterAttrsRecursive (_: v: v != { }) (
|
||||
attrsets.filterAttrsRecursive (_: v: v != null) (
|
||||
{
|
||||
inherit (inst.settings)
|
||||
instance_name
|
||||
hostname
|
||||
ipv4
|
||||
dhcp
|
||||
listeners
|
||||
;
|
||||
network_identity = {
|
||||
inherit (inst.settings) network_name network_secret;
|
||||
};
|
||||
peer = map (p: { uri = p; }) inst.settings.peers;
|
||||
}
|
||||
// inst.extraSettings
|
||||
)
|
||||
);
|
||||
|
||||
genConfigFile =
|
||||
name: inst:
|
||||
if inst.configFile == null then
|
||||
settingsFormat.generate "easytier-${name}.toml" (genFinalSettings inst)
|
||||
else
|
||||
inst.configFile;
|
||||
|
||||
activeInsts = filterAttrs (_: inst: inst.enable) cfg.instances;
|
||||
|
||||
settingsModule = name: {
|
||||
options = {
|
||||
instance_name = mkOption {
|
||||
type = types.str;
|
||||
default = name;
|
||||
description = "Identify different instances on same host";
|
||||
};
|
||||
|
||||
hostname = mkOption {
|
||||
type = with types; nullOr str;
|
||||
default = null;
|
||||
description = "Hostname shown in peer list and web console.";
|
||||
};
|
||||
|
||||
network_name = mkOption {
|
||||
type = with types; nullOr str;
|
||||
default = null;
|
||||
description = "EasyTier network name.";
|
||||
};
|
||||
|
||||
network_secret = mkOption {
|
||||
type = with types; nullOr str;
|
||||
default = null;
|
||||
description = ''
|
||||
EasyTier network credential used for verification and
|
||||
encryption. It can also be set in environmentFile.
|
||||
'';
|
||||
};
|
||||
|
||||
ipv4 = mkOption {
|
||||
type = with types; nullOr str;
|
||||
default = null;
|
||||
description = ''
|
||||
IPv4 cidr address of this peer in the virtual network. If
|
||||
empty, this peer will only forward packets and no TUN device
|
||||
will be created.
|
||||
'';
|
||||
example = "10.144.144.1/24";
|
||||
};
|
||||
|
||||
dhcp = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Automatically determine the IPv4 address of this peer based on
|
||||
existing peers on network.
|
||||
'';
|
||||
};
|
||||
|
||||
listeners = mkOption {
|
||||
type = with types; listOf str;
|
||||
default = [
|
||||
"tcp://0.0.0.0:11010"
|
||||
"udp://0.0.0.0:11010"
|
||||
];
|
||||
description = ''
|
||||
Listener addresses to accept connections from other peers.
|
||||
Valid format is: `<proto>://<addr>:<port>`, where the protocol
|
||||
can be `tcp`, `udp`, `ring`, `wg`, `ws`, `wss`.
|
||||
'';
|
||||
};
|
||||
|
||||
peers = mkOption {
|
||||
type = with types; listOf str;
|
||||
default = [ ];
|
||||
description = ''
|
||||
Peers to connect initially. Valid format is: `<proto>://<addr>:<port>`.
|
||||
'';
|
||||
example = [
|
||||
"tcp://example.com:11010"
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
instanceModule =
|
||||
{ name, ... }:
|
||||
{
|
||||
options = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Enable the instance.";
|
||||
};
|
||||
|
||||
configServer = mkOption {
|
||||
type = with types; nullOr str;
|
||||
default = null;
|
||||
description = ''
|
||||
Configure the instance from config server. When this option
|
||||
set, any other settings for configuring the instance manually
|
||||
except `hostname` will be ignored. Valid formats are:
|
||||
|
||||
- full uri for custom server: `udp://example.com:22020/<token>`
|
||||
- username only for official server: `<token>`
|
||||
'';
|
||||
example = "udp://example.com:22020/myusername";
|
||||
};
|
||||
|
||||
configFile = mkOption {
|
||||
type = with types; nullOr path;
|
||||
default = null;
|
||||
description = ''
|
||||
Path to easytier config file. Setting this option will
|
||||
override `settings` and `extraSettings` of this instance.
|
||||
'';
|
||||
};
|
||||
|
||||
environmentFiles = mkOption {
|
||||
type = with types; listOf path;
|
||||
default = [ ];
|
||||
description = ''
|
||||
Environment files for this instance. All command-line args
|
||||
have corresponding environment variables.
|
||||
'';
|
||||
example = literalExpression ''
|
||||
[
|
||||
/path/to/.env
|
||||
/path/to/.env.secret
|
||||
]
|
||||
'';
|
||||
};
|
||||
|
||||
settings = mkOption {
|
||||
type = types.submodule (settingsModule name);
|
||||
default = { };
|
||||
description = ''
|
||||
Settings to generate {file}`easytier-${name}.toml`
|
||||
'';
|
||||
};
|
||||
|
||||
extraSettings = mkOption {
|
||||
type = settingsFormat.type;
|
||||
default = { };
|
||||
description = ''
|
||||
Extra settings to add to {file}`easytier-${name}.toml`.
|
||||
'';
|
||||
};
|
||||
|
||||
extraArgs = mkOption {
|
||||
type = with types; listOf str;
|
||||
default = [ ];
|
||||
description = ''
|
||||
Extra args append to the easytier command-line.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
in
|
||||
{
|
||||
options.services.easytier = {
|
||||
enable = mkEnableOption "EasyTier daemon";
|
||||
|
||||
package = mkPackageOption pkgs "easytier" { };
|
||||
|
||||
allowSystemForward = mkEnableOption ''
|
||||
Allow the system to forward packets from easytier. Useful when
|
||||
`proxy_forward_by_system` enabled.
|
||||
'';
|
||||
|
||||
instances = mkOption {
|
||||
description = ''
|
||||
EasyTier instances.
|
||||
'';
|
||||
type = types.attrsOf (types.submodule instanceModule);
|
||||
default = { };
|
||||
example = {
|
||||
settings = {
|
||||
network_name = "easytier";
|
||||
network_secret = "easytier";
|
||||
ipv4 = "10.144.144.1/24";
|
||||
peers = [
|
||||
"tcp://public.easytier.cn:11010"
|
||||
"wss://example.com:443"
|
||||
];
|
||||
};
|
||||
extraSettings = {
|
||||
flags.dev_name = "tun1";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
environment.systemPackages = [ cfg.package ];
|
||||
|
||||
systemd.services = mapAttrs' (
|
||||
name: inst:
|
||||
let
|
||||
configFile = genConfigFile name inst;
|
||||
in
|
||||
nameValuePair "easytier-${name}" {
|
||||
description = "EasyTier Daemon - ${name}";
|
||||
wants = [
|
||||
"network-online.target"
|
||||
"nss-lookup.target"
|
||||
];
|
||||
after = [
|
||||
"network-online.target"
|
||||
"nss-lookup.target"
|
||||
];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
path = with pkgs; [
|
||||
cfg.package
|
||||
iproute2
|
||||
bash
|
||||
];
|
||||
restartTriggers = inst.environmentFiles ++ (optionals (inst.configServer == null) [ configFile ]);
|
||||
serviceConfig = {
|
||||
Type = "simple";
|
||||
Restart = "on-failure";
|
||||
EnvironmentFile = inst.environmentFiles;
|
||||
StateDirectory = "easytier/easytier-${name}";
|
||||
StateDirectoryMode = "0700";
|
||||
WorkingDirectory = "/var/lib/easytier/easytier-${name}";
|
||||
ExecStart = escapeShellArgs (
|
||||
[
|
||||
"${cfg.package}/bin/easytier-core"
|
||||
]
|
||||
++ optionals (inst.configServer != null) (
|
||||
[
|
||||
"-w"
|
||||
"${inst.configServer}"
|
||||
]
|
||||
++ (optionals (inst.settings.hostname != null) [
|
||||
"--hostname"
|
||||
"${inst.settings.hostname}"
|
||||
])
|
||||
)
|
||||
++ optionals (inst.configServer == null) [
|
||||
"-c"
|
||||
"${configFile}"
|
||||
]
|
||||
++ inst.extraArgs
|
||||
);
|
||||
};
|
||||
}
|
||||
) activeInsts;
|
||||
|
||||
boot.kernel.sysctl = mkIf cfg.allowSystemForward {
|
||||
"net.ipv4.conf.all.forwarding" = mkOverride 97 true;
|
||||
"net.ipv6.conf.all.forwarding" = mkOverride 97 true;
|
||||
};
|
||||
};
|
||||
|
||||
meta.maintainers = with maintainers; [
|
||||
ltrump
|
||||
];
|
||||
}
|
|
@ -433,6 +433,7 @@ in
|
|||
fscrypt = runTest ./fscrypt.nix;
|
||||
fastnetmon-advanced = runTest ./fastnetmon-advanced.nix;
|
||||
lauti = runTest ./lauti.nix;
|
||||
easytier = handleTest ./easytier.nix { };
|
||||
ejabberd = runTest ./xmpp/ejabberd.nix;
|
||||
elk = handleTestOn [ "x86_64-linux" ] ./elk.nix { };
|
||||
emacs-daemon = runTest ./emacs-daemon.nix;
|
||||
|
|
121
nixos/tests/easytier.nix
Normal file
121
nixos/tests/easytier.nix
Normal file
|
@ -0,0 +1,121 @@
|
|||
import ./make-test-python.nix (
|
||||
{ lib, ... }:
|
||||
{
|
||||
name = "easytier";
|
||||
meta.maintainers = with lib.maintainers; [ ltrump ];
|
||||
|
||||
nodes =
|
||||
let
|
||||
genPeer =
|
||||
hostConfig: settings:
|
||||
lib.mkMerge [
|
||||
{
|
||||
services.easytier = {
|
||||
enable = true;
|
||||
instances.default = {
|
||||
settings = {
|
||||
network_name = "easytier_test";
|
||||
network_secret = "easytier_test_secret";
|
||||
} // settings;
|
||||
};
|
||||
};
|
||||
|
||||
networking.useDHCP = false;
|
||||
networking.firewall.allowedTCPPorts = [
|
||||
11010
|
||||
11011
|
||||
];
|
||||
networking.firewall.allowedUDPPorts = [
|
||||
11010
|
||||
11011
|
||||
];
|
||||
}
|
||||
hostConfig
|
||||
];
|
||||
in
|
||||
{
|
||||
relay =
|
||||
genPeer
|
||||
{
|
||||
virtualisation.vlans = [
|
||||
1
|
||||
2
|
||||
];
|
||||
|
||||
networking.interfaces.eth1.ipv4.addresses = [
|
||||
{
|
||||
address = "192.168.1.11";
|
||||
prefixLength = 24;
|
||||
}
|
||||
];
|
||||
|
||||
networking.interfaces.eth2.ipv4.addresses = [
|
||||
{
|
||||
address = "192.168.2.11";
|
||||
prefixLength = 24;
|
||||
}
|
||||
];
|
||||
}
|
||||
{
|
||||
ipv4 = "10.144.144.1";
|
||||
listeners = [
|
||||
"tcp://0.0.0.0:11010"
|
||||
"wss://0.0.0.0:11011"
|
||||
];
|
||||
};
|
||||
|
||||
peer1 =
|
||||
genPeer
|
||||
{
|
||||
virtualisation.vlans = [ 1 ];
|
||||
}
|
||||
{
|
||||
ipv4 = "10.144.144.2";
|
||||
peers = [ "tcp://192.168.1.11:11010" ];
|
||||
};
|
||||
|
||||
peer2 =
|
||||
genPeer
|
||||
{
|
||||
virtualisation.vlans = [ 2 ];
|
||||
}
|
||||
{
|
||||
ipv4 = "10.144.144.3";
|
||||
peers = [ "wss://192.168.2.11:11011" ];
|
||||
};
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
start_all()
|
||||
|
||||
relay.wait_for_unit("easytier-default.service")
|
||||
peer1.wait_for_unit("easytier-default.service")
|
||||
peer2.wait_for_unit("easytier-default.service")
|
||||
|
||||
# relay is accessible by the other hosts
|
||||
peer1.succeed("ping -c5 192.168.1.11")
|
||||
peer2.succeed("ping -c5 192.168.2.11")
|
||||
|
||||
# The other hosts are in separate vlans
|
||||
peer1.fail("ping -c5 192.168.2.11")
|
||||
peer2.fail("ping -c5 192.168.1.11")
|
||||
|
||||
# Each host can ping themselves through EasyTier
|
||||
relay.succeed("ping -c5 10.144.144.1")
|
||||
peer1.succeed("ping -c5 10.144.144.2")
|
||||
peer2.succeed("ping -c5 10.144.144.3")
|
||||
|
||||
# Relay is accessible by the other hosts through EasyTier
|
||||
peer1.succeed("ping -c5 10.144.144.1")
|
||||
peer2.succeed("ping -c5 10.144.144.1")
|
||||
|
||||
# Relay can access the other hosts through EasyTier
|
||||
relay.succeed("ping -c5 10.144.144.2")
|
||||
relay.succeed("ping -c5 10.144.144.3")
|
||||
|
||||
# The other hosts in separate vlans can access each other through EasyTier
|
||||
peer1.succeed("ping -c5 10.144.144.3")
|
||||
peer2.succeed("ping -c5 10.144.144.2")
|
||||
'';
|
||||
}
|
||||
)
|
|
@ -4,6 +4,7 @@
|
|||
fetchFromGitHub,
|
||||
rustPlatform,
|
||||
protobuf,
|
||||
nixosTests,
|
||||
nix-update-script,
|
||||
withQuic ? false, # with QUIC protocol support
|
||||
}:
|
||||
|
@ -33,7 +34,10 @@ rustPlatform.buildRustPackage rec {
|
|||
|
||||
doCheck = false; # tests failed due to heavy rely on network
|
||||
|
||||
passthru.updateScript = nix-update-script { };
|
||||
passthru = {
|
||||
tests = { inherit (nixosTests) easytier; };
|
||||
updateScript = nix-update-script { };
|
||||
};
|
||||
|
||||
meta = {
|
||||
homepage = "https://github.com/EasyTier/EasyTier";
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue