mirror of
https://github.com/NixOS/nixpkgs.git
synced 2025-07-13 21:50:33 +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).
|
- [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).
|
- [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).
|
- [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/dnsproxy.nix
|
||||||
./services/networking/doh-proxy-rust.nix
|
./services/networking/doh-proxy-rust.nix
|
||||||
./services/networking/doh-server.nix
|
./services/networking/doh-server.nix
|
||||||
|
./services/networking/easytier.nix
|
||||||
./services/networking/ejabberd.nix
|
./services/networking/ejabberd.nix
|
||||||
./services/networking/envoy.nix
|
./services/networking/envoy.nix
|
||||||
./services/networking/epmd.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;
|
fscrypt = runTest ./fscrypt.nix;
|
||||||
fastnetmon-advanced = runTest ./fastnetmon-advanced.nix;
|
fastnetmon-advanced = runTest ./fastnetmon-advanced.nix;
|
||||||
lauti = runTest ./lauti.nix;
|
lauti = runTest ./lauti.nix;
|
||||||
|
easytier = handleTest ./easytier.nix { };
|
||||||
ejabberd = runTest ./xmpp/ejabberd.nix;
|
ejabberd = runTest ./xmpp/ejabberd.nix;
|
||||||
elk = handleTestOn [ "x86_64-linux" ] ./elk.nix { };
|
elk = handleTestOn [ "x86_64-linux" ] ./elk.nix { };
|
||||||
emacs-daemon = runTest ./emacs-daemon.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,
|
fetchFromGitHub,
|
||||||
rustPlatform,
|
rustPlatform,
|
||||||
protobuf,
|
protobuf,
|
||||||
|
nixosTests,
|
||||||
nix-update-script,
|
nix-update-script,
|
||||||
withQuic ? false, # with QUIC protocol support
|
withQuic ? false, # with QUIC protocol support
|
||||||
}:
|
}:
|
||||||
|
@ -33,7 +34,10 @@ rustPlatform.buildRustPackage rec {
|
||||||
|
|
||||||
doCheck = false; # tests failed due to heavy rely on network
|
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 = {
|
meta = {
|
||||||
homepage = "https://github.com/EasyTier/EasyTier";
|
homepage = "https://github.com/EasyTier/EasyTier";
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue