nixos/frp: add 'extraConfig' option

This feature allows for unparsable settings (by nix) to be used, such as Go templates. It is needed to configure port ranges (https://github.com/fatedier/frp?tab=readme-ov-file#port-range-mapping).
This commit is contained in:
Edgar Pireyn
2026-06-13 23:00:12 +02:00
parent 75ee9bdeef
commit 3716f2e811
2 changed files with 65 additions and 5 deletions
+32 -1
View File
@@ -76,6 +76,26 @@ in
];
};
};
extraConfig = lib.mkOption {
type = lib.types.lines;
default = "";
description = ''
Extra frp TOML configuration included at the end of the generated configuration file.
Especially useful for [port range mapping].
[port range mapping]: https://github.com/fatedier/frp#port-range-mapping
'';
example = ''
{{- range $_, $v := parseNumberRangePair "6000-6006,6007" "6000-6006,6007" }}
[[proxies]]
name = "tcp-{{ $v.First }}"
type = "tcp"
localPort = {{ $v.First }}
remotePort = {{ $v.Second }}
{{- end }}
'';
};
};
}
);
@@ -94,7 +114,18 @@ in
instance: options:
let
serviceName = "frp" + lib.optionalString (instance != "") ("-" + instance);
configFile = settingsFormat.generate "${serviceName}.toml" options.settings;
baseConfigFile = settingsFormat.generate "${serviceName}-base.toml" options.settings;
configFile =
if options.extraConfig == "" then
baseConfigFile
else
pkgs.writeText "${serviceName}.toml" ''
# Nixos Module settings
${builtins.readFile baseConfigFile}
# Nixos Module extraConfig
${options.extraConfig}
'';
isClient = (options.role == "client");
isServer = (options.role == "server");
serviceCapability = lib.optionals isServer [ "CAP_NET_BIND_SERVICE" ];
+33 -4
View File
@@ -9,6 +9,7 @@ let
name = "secrets";
text = "token=${token}";
};
portRange = 6003;
in
{
name = "frp";
@@ -56,14 +57,25 @@ in
services.httpd = {
enable = true;
adminAddr = "admin@example.com";
virtualHosts."test-appication" =
virtualHosts =
let
testdir = pkgs.writeTextDir "web/index.php" "<?php phpinfo();";
in
{
documentRoot = "${testdir}/web";
locations."/" = {
index = "index.php index.html";
"test-appication" = {
documentRoot = "${testdir}/web";
locations."/" = {
index = "index.php index.html";
};
};
"test-range" = {
documentRoot = "${testdir}/web";
listen = [
{ port = portRange; }
];
locations."/" = {
index = "index.php index.html";
};
};
};
phpPackage = pkgs.php84;
@@ -87,6 +99,15 @@ in
}
];
};
extraConfig = ''
{{- range $_, $v := parseNumberRangePair "6000-6006,6007" "6000-6006,6007" }}
[[proxies]]
name = "tcp-{{ $v.First }}"
type = "tcp"
localPort = {{ $v.First }}
remotePort = {{ $v.Second }}
{{- end }}
'';
};
};
};
@@ -96,9 +117,17 @@ in
frps.wait_for_unit("frp-server.service")
frps.wait_for_open_port(80)
frpc.wait_for_unit("frp-client.service")
# Test config written in Nix
response = frpc.succeed("curl -fvvv -s http://127.0.0.1/")
assert "PHP Version ${pkgs.php84.version}" in response, "PHP version not detected"
response = frpc.succeed("curl -fvvv -s http://10.0.0.1/")
assert "PHP Version ${pkgs.php84.version}" in response, "PHP version not detected"
# Test `extraConfig` option with port range
response = frpc.succeed("curl -fvvv -s http://127.0.0.1:${toString portRange}/")
assert "PHP Version ${pkgs.php84.version}" in response, "PHP version not detected"
response = frpc.succeed("curl -fvvv -s http://10.0.0.1:${toString portRange}/")
assert "PHP Version ${pkgs.php84.version}" in response, "PHP version not detected"
'';
}