Update from update-inputs-2024-10-02-04-20
This commit is contained in:
commit
a4d0125e29
5 changed files with 406 additions and 315 deletions
|
@ -7,6 +7,7 @@
|
||||||
../../services/nginx.nix
|
../../services/nginx.nix
|
||||||
../../services/uptime-kuma.nix
|
../../services/uptime-kuma.nix
|
||||||
../../services/vaultwarden.nix
|
../../services/vaultwarden.nix
|
||||||
|
../../services/librespeed.nix
|
||||||
./disko.nix
|
./disko.nix
|
||||||
./hardware-configuration.nix
|
./hardware-configuration.nix
|
||||||
];
|
];
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
../../services/nginx.nix
|
../../services/nginx.nix
|
||||||
../../services/hydra
|
../../services/hydra
|
||||||
../../services/update-nixfiles.nix
|
../../services/update-nixfiles.nix
|
||||||
../../services/librespeed.nix
|
|
||||||
];
|
];
|
||||||
boot.binfmt.emulatedSystems = [ "aarch64-linux" ];
|
boot.binfmt.emulatedSystems = [ "aarch64-linux" ];
|
||||||
|
|
||||||
|
|
|
@ -155,11 +155,11 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1727531434,
|
"lastModified": 1727809780,
|
||||||
"narHash": "sha256-b+GBgCWd2N6pkiTkRZaMFOPztPO4IVTaclYPrQl2uLk=",
|
"narHash": "sha256-7W5HE2IRiZglMBKcn9JtC6bveE6/F7IzQyV2XDanGFA=",
|
||||||
"owner": "nix-community",
|
"owner": "nix-community",
|
||||||
"repo": "disko",
|
"repo": "disko",
|
||||||
"rev": "b709e1cc33fcde71c7db43850a55ebe6449d0959",
|
"rev": "6c5ba9ec9d470c1ca29e7735762c9c366e28f7f5",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
|
@ -1,337 +1,427 @@
|
||||||
{ config, lib, pkgs, ... }:
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}:
|
||||||
let
|
let
|
||||||
cfg = config.services.librespeed;
|
cfg = config.services.librespeed;
|
||||||
in {
|
in
|
||||||
options.services.librespeed = let
|
{
|
||||||
inherit (lib) mkOption types;
|
options.services.librespeed =
|
||||||
in {
|
let
|
||||||
enable = lib.mkEnableOption "LibreSpeed server";
|
inherit (lib) mkOption types;
|
||||||
package = lib.mkPackageOption pkgs "librespeed-rust" {};
|
in
|
||||||
domain = mkOption {
|
{
|
||||||
description = ''
|
enable = lib.mkEnableOption "LibreSpeed server";
|
||||||
If not `null`, this will add an entry to `services.librespeed.servers` and
|
package = lib.mkPackageOption pkgs "librespeed-rust" { };
|
||||||
configure librespeed to use TLS.
|
domain = mkOption {
|
||||||
'';
|
|
||||||
default = null;
|
|
||||||
type = with types; nullOr nonEmptyStr;
|
|
||||||
};
|
|
||||||
downloadIPDB = mkOption {
|
|
||||||
description = ''
|
|
||||||
Whether to download the IP info database before starting librespeed.
|
|
||||||
Disable this if you want to use the Go implementation.
|
|
||||||
'';
|
|
||||||
default = (!cfg.secrets ? "ipinfo_api_key");
|
|
||||||
type = types.bool;
|
|
||||||
};
|
|
||||||
openFirewall = mkOption {
|
|
||||||
description = ''
|
|
||||||
Whether to open the firewall for the specified port.
|
|
||||||
'';
|
|
||||||
default = false;
|
|
||||||
type = types.bool;
|
|
||||||
};
|
|
||||||
secrets = mkOption {
|
|
||||||
description = ''
|
|
||||||
Attribute set of filesystem paths.
|
|
||||||
The contents of the specified paths will be read at service start time and merged with the attributes provided in `settings`.
|
|
||||||
'';
|
|
||||||
default = {};
|
|
||||||
type = with types; nullOr (attrsOf path);
|
|
||||||
};
|
|
||||||
settings = mkOption {
|
|
||||||
description = ''
|
|
||||||
LibreSpeed configuration written as Nix expression.
|
|
||||||
All values set to `null` will be excluded from the evaluated config.
|
|
||||||
This is useful if you want to omit certain defaults when using a different LibreSpeed implementation.
|
|
||||||
|
|
||||||
See [github.com/librespeed][librespeed] for configuration help.
|
|
||||||
|
|
||||||
[librespeed]: https://github.com/librespeed/speedtest-rust
|
|
||||||
'';
|
|
||||||
default = {};
|
|
||||||
type = with types; nullOr (attrsOf (oneOf [
|
|
||||||
(nullOr bool)
|
|
||||||
int
|
|
||||||
str
|
|
||||||
package
|
|
||||||
]));
|
|
||||||
};
|
|
||||||
frontend = {
|
|
||||||
enable = lib.mkEnableOption "LibreSpeed frontend.";
|
|
||||||
contactEmail = mkOption {
|
|
||||||
description = "Email address listed in the privacy policy.";
|
|
||||||
default = if (cfg.domain != null) then "webmaster@${cfg.domain}" else "webmaster@${config.networking.fqdn}";
|
|
||||||
type = types.str;
|
|
||||||
};
|
|
||||||
pageTitle = mkOption {
|
|
||||||
description = "Title of the webpage.";
|
|
||||||
default = "LibreSpeed";
|
|
||||||
type = types.str;
|
|
||||||
};
|
|
||||||
useNginx = mkOption {
|
|
||||||
description = ''
|
description = ''
|
||||||
Configure nginx for the LibreSpeed frontend.
|
If not `null`, this will add an entry to `services.librespeed.servers` and
|
||||||
This will only create a virtual host for the frontend and won't proxy all requests because,
|
configure librespeed to use TLS.
|
||||||
the reported upload and download speeds are inaccurate if proxied.
|
|
||||||
'';
|
'';
|
||||||
default = cfg.domain != null;
|
default = null;
|
||||||
|
type = with types; nullOr nonEmptyStr;
|
||||||
|
};
|
||||||
|
downloadIPDB = mkOption {
|
||||||
|
description = ''
|
||||||
|
Whether to download the IP info database before starting librespeed.
|
||||||
|
Disable this if you want to use the Go implementation.
|
||||||
|
'';
|
||||||
|
default = !(cfg.secrets ? "ipinfo_api_key");
|
||||||
|
defaultText = lib.literalExpression ''!(cfg.secrets ? "ipinfo_api_key")'';
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
};
|
};
|
||||||
|
openFirewall = mkOption {
|
||||||
|
description = ''
|
||||||
|
Whether to open the firewall for the specified port.
|
||||||
|
'';
|
||||||
|
default = false;
|
||||||
|
type = types.bool;
|
||||||
|
};
|
||||||
|
secrets = mkOption {
|
||||||
|
description = ''
|
||||||
|
Attribute set of filesystem paths.
|
||||||
|
The contents of the specified paths will be read at service start time and merged with the attributes provided in `settings`.
|
||||||
|
'';
|
||||||
|
default = { };
|
||||||
|
type = with types; nullOr (attrsOf path);
|
||||||
|
};
|
||||||
settings = mkOption {
|
settings = mkOption {
|
||||||
description = ''
|
description = ''
|
||||||
Override default test parameters.
|
LibreSpeed configuration written as Nix expression.
|
||||||
See [speedtest_worker.js][link] for a list of possible values.
|
All values set to `null` will be excluded from the evaluated config.
|
||||||
|
This is useful if you want to omit certain defaults when using a different LibreSpeed implementation.
|
||||||
|
|
||||||
[link]: https://github.com/librespeed/speedtest/blob/master/speedtest_worker.js#L39
|
See [github.com/librespeed][librespeed] for configuration help.
|
||||||
|
|
||||||
|
[librespeed]: https://github.com/librespeed/speedtest-rust
|
||||||
'';
|
'';
|
||||||
default = {};
|
default = { };
|
||||||
type = with types; nullOr (attrsOf (oneOf [
|
type =
|
||||||
bool
|
with types;
|
||||||
int
|
nullOr (
|
||||||
str
|
attrsOf (oneOf [
|
||||||
float
|
(nullOr bool)
|
||||||
]));
|
int
|
||||||
|
str
|
||||||
|
package
|
||||||
|
])
|
||||||
|
);
|
||||||
};
|
};
|
||||||
servers = mkOption {
|
frontend = {
|
||||||
description = "LibreSpeed servers that should apper in the server list.";
|
enable = lib.mkEnableOption ''
|
||||||
type = types.listOf (types.submodule {
|
Enables the LibreSpeed frontend and adds a nginx virtual host if
|
||||||
options = let
|
not explicetly disabled and `services.librespeed.domain` is not `null`.
|
||||||
inherit (types) nonEmptyStr;
|
'';
|
||||||
in {
|
contactEmail = mkOption {
|
||||||
name = mkOption {
|
description = "Email address listed in the privacy policy.";
|
||||||
description = "Name shown in the server list.";
|
default =
|
||||||
type = nonEmptyStr;
|
if (cfg.domain != null) then "webmaster@${cfg.domain}" else "webmaster@${config.networking.fqdn}";
|
||||||
};
|
defaultText = lib.literalExpression ''
|
||||||
server = mkOption {
|
if (config.services.librespeed.domain != null) then
|
||||||
description = "URL to the server. You may use `//` instead of `http://` or `https://`.";
|
"webmaster@''${config.services.librespeed.domain}"
|
||||||
type = nonEmptyStr;
|
else
|
||||||
};
|
"webmaster@''${config.networking.fqdn}";
|
||||||
dlURL = mkOption {
|
'';
|
||||||
description = ''
|
type = types.str;
|
||||||
URL path to download test on this server.
|
};
|
||||||
Append `.php` to the default value if the server uses the php implementation.
|
pageTitle = mkOption {
|
||||||
'';
|
description = "Title of the webpage.";
|
||||||
default = "backend/garbage";
|
default = "LibreSpeed";
|
||||||
type = nonEmptyStr;
|
type = types.str;
|
||||||
};
|
};
|
||||||
ulURL = mkOption {
|
useNginx = mkOption {
|
||||||
description = ''
|
description = ''
|
||||||
URL path to upload test on this server.
|
Configure nginx for the LibreSpeed frontend.
|
||||||
Append `.php` to the default value if the server uses the php implementation.
|
This will only create a virtual host for the frontend and won't proxy all requests because
|
||||||
'';
|
the reported upload and download speeds are inaccurate if proxied.
|
||||||
default = "backend/empty";
|
'';
|
||||||
type = nonEmptyStr;
|
default = cfg.domain != null;
|
||||||
};
|
defaultText = lib.literalExpression "config.services.librespeed.domain != null";
|
||||||
pingURL = mkOption {
|
type = types.bool;
|
||||||
description = ''
|
};
|
||||||
URL path to latency/jitter test on this server.
|
settings = mkOption {
|
||||||
Append `.php` to the default value if the server uses the php implementation.
|
description = ''
|
||||||
'';
|
Override default settings of the speedtest web client.
|
||||||
default = "backend/empty";
|
See [speedtest_worker.js][link] for a list of possible values.
|
||||||
type = nonEmptyStr;
|
|
||||||
};
|
[link]: https://github.com/librespeed/speedtest/blob/master/speedtest_worker.js#L39
|
||||||
getIpURL = mkOption {
|
'';
|
||||||
description = ''
|
default = {
|
||||||
URL path to IP lookup on this server.
|
telemetry_level = "basic";
|
||||||
Append `.php` to the default value if the server uses the php implementation.
|
|
||||||
'';
|
|
||||||
default = "backend/getIP";
|
|
||||||
type = nonEmptyStr;
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
});
|
type =
|
||||||
|
with types;
|
||||||
|
nullOr (
|
||||||
|
attrsOf (oneOf [
|
||||||
|
bool
|
||||||
|
int
|
||||||
|
str
|
||||||
|
float
|
||||||
|
])
|
||||||
|
);
|
||||||
|
};
|
||||||
|
servers = mkOption {
|
||||||
|
description = "LibreSpeed servers that should apper in the server list.";
|
||||||
|
type = types.listOf (
|
||||||
|
types.submodule {
|
||||||
|
options =
|
||||||
|
let
|
||||||
|
inherit (types) nonEmptyStr;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
name = mkOption {
|
||||||
|
description = "Name shown in the server list.";
|
||||||
|
type = nonEmptyStr;
|
||||||
|
};
|
||||||
|
server = mkOption {
|
||||||
|
description = "URL to the server. You may use `//` instead of `http://` or `https://`.";
|
||||||
|
type = nonEmptyStr;
|
||||||
|
};
|
||||||
|
dlURL = mkOption {
|
||||||
|
description = ''
|
||||||
|
URL path to download test on this server.
|
||||||
|
Append `.php` to the default value if the server uses the php implementation.
|
||||||
|
'';
|
||||||
|
default = "backend/garbage";
|
||||||
|
type = nonEmptyStr;
|
||||||
|
};
|
||||||
|
ulURL = mkOption {
|
||||||
|
description = ''
|
||||||
|
URL path to upload test on this server.
|
||||||
|
Append `.php` to the default value if the server uses the php implementation.
|
||||||
|
'';
|
||||||
|
default = "backend/empty";
|
||||||
|
type = nonEmptyStr;
|
||||||
|
};
|
||||||
|
pingURL = mkOption {
|
||||||
|
description = ''
|
||||||
|
URL path to latency/jitter test on this server.
|
||||||
|
Append `.php` to the default value if the server uses the php implementation.
|
||||||
|
'';
|
||||||
|
default = "backend/empty";
|
||||||
|
type = nonEmptyStr;
|
||||||
|
};
|
||||||
|
getIpURL = mkOption {
|
||||||
|
description = ''
|
||||||
|
URL path to IP lookup on this server.
|
||||||
|
Append `.php` to the default value if the server uses the php implementation.
|
||||||
|
'';
|
||||||
|
default = "backend/getIP";
|
||||||
|
type = nonEmptyStr;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
config = lib.mkIf cfg.enable (
|
||||||
config = lib.mkIf cfg.enable (let
|
let
|
||||||
librespeedAssets = pkgs.runCommand "librespeed-assets" (let
|
librespeedAssets =
|
||||||
mapValue = arg: if (lib.isBool arg) then
|
pkgs.runCommand "librespeed-assets"
|
||||||
lib.boolToString arg
|
(
|
||||||
else if ((lib.isInt arg) || (lib.isFloat arg)) then
|
let
|
||||||
toString arg
|
mapValue =
|
||||||
else
|
arg:
|
||||||
"\"${lib.escape [ "\"" ] (toString arg)}\"";
|
if (lib.isBool arg) then
|
||||||
|
lib.boolToString arg
|
||||||
|
else if ((lib.isInt arg) || (lib.isFloat arg)) then
|
||||||
|
toString arg
|
||||||
|
else
|
||||||
|
"\"${lib.escape [ "\"" ] (toString arg)}\"";
|
||||||
|
|
||||||
mapSettings = lib.pipe cfg.frontend.settings [
|
mapSettings = lib.pipe cfg.frontend.settings [
|
||||||
(lib.mapAttrs (name: val: " s.setParameter(\"${lib.escape [ "\"" ] name}\",${mapValue val});"))
|
(lib.mapAttrs (name: val: " s.setParameter(\"${lib.escape [ "\"" ] name}\",${mapValue val});"))
|
||||||
(lib.attrValues)
|
(lib.attrValues)
|
||||||
(lib.concatLines)
|
(lib.concatLines)
|
||||||
];
|
];
|
||||||
in {
|
in
|
||||||
preferLocal = true;
|
{
|
||||||
|
preferLocal = true;
|
||||||
|
|
||||||
serversList = ''
|
serversList = ''
|
||||||
function get_servers() {
|
function get_servers() {
|
||||||
return ${builtins.toJSON cfg.frontend.servers}
|
return ${builtins.toJSON cfg.frontend.servers}
|
||||||
|
}
|
||||||
|
function override_settings () {
|
||||||
|
${mapSettings}
|
||||||
|
}
|
||||||
|
'';
|
||||||
|
}
|
||||||
|
)
|
||||||
|
''
|
||||||
|
cp -r ${pkgs.librespeed-rust}/assets $out
|
||||||
|
chmod 666 $out/servers_list.js
|
||||||
|
cat >$out/servers_list.js <<<"$serversList"
|
||||||
|
substitute ${pkgs.librespeed-rust}/assets/index.html $out/index.html \
|
||||||
|
--replace-fail "s.setParameter(\"telemetry_level\",\"basic\"); //enable telemetry" "override_settings();" \
|
||||||
|
--replace-fail "LibreSpeed Example" ${lib.escapeShellArg (lib.escapeXML cfg.frontend.pageTitle)} \
|
||||||
|
--replace-fail "PUT@YOUR_EMAIL.HERE" ${lib.escapeShellArg (lib.escapeXML cfg.frontend.contactEmail)} \
|
||||||
|
--replace-fail "TO BE FILLED BY DEVELOPER" ${lib.escapeShellArg (lib.escapeXML cfg.frontend.contactEmail)}
|
||||||
|
'';
|
||||||
|
in
|
||||||
|
{
|
||||||
|
assertions = [
|
||||||
|
{
|
||||||
|
assertion = cfg.frontend.useNginx -> cfg.domain != null;
|
||||||
|
message = ''
|
||||||
|
`services.librespeed.frontend.useNginx` requires `services.librespeed.frontend.domain` to be set.
|
||||||
|
'';
|
||||||
}
|
}
|
||||||
function override_settings () {
|
|
||||||
${mapSettings}
|
|
||||||
}
|
|
||||||
'';
|
|
||||||
}) ''
|
|
||||||
cp -r ${pkgs.librespeed-rust}/assets $out
|
|
||||||
chmod 666 $out/servers_list.js
|
|
||||||
cat >$out/servers_list.js <<<"$serversList"
|
|
||||||
substitute ${pkgs.librespeed-rust}/assets/index.html $out/index.html \
|
|
||||||
--replace-fail "s.setParameter(\"telemetry_level\",\"basic\"); //enable telemetry" "override_settings();" \
|
|
||||||
--replace-fail "LibreSpeed Example" ${lib.escapeShellArg (lib.escapeXML cfg.frontend.pageTitle)} \
|
|
||||||
--replace-fail "PUT@YOUR_EMAIL.HERE" ${lib.escapeShellArg (lib.escapeXML cfg.frontend.contactEmail)} \
|
|
||||||
--replace-fail "TO BE FILLED BY DEVELOPER" ${lib.escapeShellArg (lib.escapeXML cfg.frontend.contactEmail)}
|
|
||||||
'';
|
|
||||||
in {
|
|
||||||
assertions = [
|
|
||||||
{
|
|
||||||
assertion = cfg.frontend.useNginx -> cfg.domain != null;
|
|
||||||
message = ''
|
|
||||||
`services.librespeed.frontend.useNginx` requires `services.librespeed.frontend.domain` to be set.
|
|
||||||
'';
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
networking.firewall = lib.mkIf cfg.openFirewall {
|
|
||||||
allowedTCPPorts = [ cfg.settings.listen_port ];
|
|
||||||
};
|
|
||||||
services.nginx.virtualHosts = lib.mkIf (cfg.frontend.enable && cfg.frontend.useNginx) {
|
|
||||||
${cfg.domain} = {
|
|
||||||
locations."/".root = librespeedAssets;
|
|
||||||
locations."/backend/".extraConfig = "return 301 https://$host:${toString cfg.settings.listen_port}$request_uri;";
|
|
||||||
enableACME = true;
|
|
||||||
forceSSL = true;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
security.acme.certs = lib.mkIf (cfg.domain != null) {
|
|
||||||
${cfg.domain} = {
|
|
||||||
reloadServices = [ "librespeed.service" ];
|
|
||||||
webroot = "/var/lib/acme/acme-challange";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
services.librespeed.frontend.servers = lib.mkIf (cfg.frontend.enable && (cfg.domain != null)) [
|
|
||||||
{
|
|
||||||
name = cfg.domain;
|
|
||||||
server = "//${cfg.domain}:${toString cfg.settings.listen_port}";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
services.librespeed.frontend.settings = lib.mkIf cfg.frontend.enable {
|
|
||||||
telemetry_level = lib.mkDefault "basic";
|
|
||||||
};
|
|
||||||
|
|
||||||
services.librespeed.settings = let
|
|
||||||
inherit (lib) mkDefault mkIf;
|
|
||||||
in {
|
|
||||||
assets_path = if (cfg.frontend.enable && !cfg.frontend.useNginx) then librespeedAssets
|
|
||||||
else pkgs.writeTextDir "index.html" "";
|
|
||||||
|
|
||||||
bind_address = mkDefault "::";
|
|
||||||
listen_port = mkDefault 8989;
|
|
||||||
base_url = mkDefault "backend";
|
|
||||||
worker_threads = mkDefault "auto";
|
|
||||||
|
|
||||||
database_type = mkDefault "none";
|
|
||||||
database_file = mkDefault "/var/lib/librespeed/speedtest.sqlite";
|
|
||||||
|
|
||||||
#librespeed-rust will fail to start if the following config parameters are omitted.
|
|
||||||
ipinfo_api_key = mkIf (!cfg.secrets ? "ipinfo_api_key") "";
|
|
||||||
stats_password = mkIf (!cfg.secrets ? "stats_password") "";
|
|
||||||
tls_cert_file = if (cfg.domain != null) then (mkDefault "/run/credentials/librespeed.service/cert.pem") else (mkDefault "");
|
|
||||||
tls_key_file = if (cfg.domain != null) then (mkDefault "/run/credentials/librespeed.service/key.pem") else (mkDefault "");
|
|
||||||
|
|
||||||
enable_tls = mkDefault (cfg.domain != null);
|
|
||||||
};
|
|
||||||
|
|
||||||
systemd.services = let
|
|
||||||
configFile = let
|
|
||||||
mapValue = arg: if (lib.isBool arg) then
|
|
||||||
lib.boolToString arg
|
|
||||||
else if (lib.isInt arg) then
|
|
||||||
toString arg
|
|
||||||
else "\"${lib.escape [ "\"" ] (toString arg)}\"";
|
|
||||||
in
|
|
||||||
with lib; pipe cfg.settings [
|
|
||||||
(filterAttrs (_: val: val != null))
|
|
||||||
(mapAttrs (name: val: "${name}=${mapValue val}"))
|
|
||||||
(attrValues)
|
|
||||||
(concatLines)
|
|
||||||
(pkgs.writeText "${cfg.package.name}-config.toml")
|
|
||||||
];
|
];
|
||||||
in {
|
|
||||||
librespeed-secrets = lib.mkIf (cfg.secrets != {}) {
|
|
||||||
description = "LibreSpeed secret helper";
|
|
||||||
|
|
||||||
ExecStart = let
|
networking.firewall = lib.mkIf cfg.openFirewall {
|
||||||
script = pkgs.writeShellApplication {
|
allowedTCPPorts = [ cfg.settings.listen_port ];
|
||||||
name = "librespeed-secrets";
|
};
|
||||||
runtimeInputs = [ pkgs.coreutils ];
|
services.nginx.virtualHosts = lib.mkIf (cfg.frontend.enable && cfg.frontend.useNginx) {
|
||||||
text = ''
|
${cfg.domain} = {
|
||||||
cp ${configFile} ''${RUNTIME_DIRECTORY%%:*}/config.toml
|
locations."/".root = librespeedAssets;
|
||||||
'' + lib.pipe cfg.secrets [
|
locations."/backend/" = {
|
||||||
(lib.mapAttrs (name: file: ''
|
proxyPass = "http://${cfg.settings.bind_address}:${toString cfg.settings.listen_port}/backend/";
|
||||||
cat >>''${RUNTIME_DIRECTORY%%:*}/config.toml <<EOF
|
extraConfig = ''
|
||||||
${name}="$(<${lib.escapeShellArg file})"
|
# add_header Cache-Control 'no-store, no-cache, max-age=0, no-transform';
|
||||||
EOF
|
# add_header Last-Modified $date_gmt;
|
||||||
''))
|
if_modified_since off;
|
||||||
(lib.concatLines lib.attrValues)
|
expires off;
|
||||||
|
etag off;
|
||||||
|
|
||||||
|
access_log off;
|
||||||
|
gzip off;
|
||||||
|
log_not_found off;
|
||||||
|
server_tokens off;
|
||||||
|
tcp_nodelay on;
|
||||||
|
tcp_nopush on;
|
||||||
|
sendfile on;
|
||||||
|
client_max_body_size 50M;
|
||||||
|
proxy_read_timeout 999;
|
||||||
|
proxy_buffers 16 128k;
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
enableACME = true;
|
||||||
|
forceSSL = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
security.acme.certs = lib.mkIf (cfg.domain != null) {
|
||||||
|
${cfg.domain} = lib.mkIf (!cfg.frontend.useNginx) {
|
||||||
|
reloadServices = [ "librespeed.service" ];
|
||||||
|
webroot = "/var/lib/acme/acme-challenge";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
services.librespeed.frontend.servers = lib.mkIf (cfg.frontend.enable && (cfg.domain != null)) [
|
||||||
|
{
|
||||||
|
name = cfg.domain;
|
||||||
|
server = "//${cfg.domain}${lib.optionalString (!cfg.frontend.useNginx) ":${toString cfg.settings.listen_port}"}";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
services.librespeed.settings =
|
||||||
|
let
|
||||||
|
inherit (lib) mkDefault mkIf;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
assets_path =
|
||||||
|
if (cfg.frontend.enable && !cfg.frontend.useNginx) then
|
||||||
|
librespeedAssets
|
||||||
|
else
|
||||||
|
pkgs.writeTextDir "index.html" "";
|
||||||
|
|
||||||
|
bind_address = mkDefault "127.0.0.1";
|
||||||
|
listen_port = mkDefault 8989;
|
||||||
|
base_url = mkDefault "backend";
|
||||||
|
worker_threads = mkDefault "auto";
|
||||||
|
|
||||||
|
database_type = mkDefault "none";
|
||||||
|
database_file = mkDefault "/var/lib/librespeed/speedtest.sqlite";
|
||||||
|
|
||||||
|
#librespeed-rust will fail to start if the following config parameters are omitted.
|
||||||
|
ipinfo_api_key = mkIf (!cfg.secrets ? "ipinfo_api_key") "";
|
||||||
|
stats_password = mkIf (!cfg.secrets ? "stats_password") "";
|
||||||
|
tls_cert_file =
|
||||||
|
if (cfg.domain != null && !cfg.frontend.useNginx) then
|
||||||
|
(mkDefault "/run/credentials/librespeed.service/cert.pem")
|
||||||
|
else
|
||||||
|
(mkDefault "");
|
||||||
|
tls_key_file =
|
||||||
|
if (cfg.domain != null && !cfg.frontend.useNginx) then
|
||||||
|
(mkDefault "/run/credentials/librespeed.service/key.pem")
|
||||||
|
else
|
||||||
|
(mkDefault "");
|
||||||
|
|
||||||
|
enable_tls = mkDefault (cfg.domain != null && !cfg.frontend.useNginx);
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.services =
|
||||||
|
let
|
||||||
|
configFile =
|
||||||
|
let
|
||||||
|
mapValue =
|
||||||
|
arg:
|
||||||
|
if (lib.isBool arg) then
|
||||||
|
lib.boolToString arg
|
||||||
|
else if (lib.isInt arg) then
|
||||||
|
toString arg
|
||||||
|
else
|
||||||
|
"\"${lib.escape [ "\"" ] (toString arg)}\"";
|
||||||
|
in
|
||||||
|
with lib;
|
||||||
|
pipe cfg.settings [
|
||||||
|
(filterAttrs (_: val: val != null))
|
||||||
|
(mapAttrs (name: val: "${name}=${mapValue val}"))
|
||||||
|
(attrValues)
|
||||||
|
(concatLines)
|
||||||
|
(pkgs.writeText "${cfg.package.name}-config.toml")
|
||||||
];
|
];
|
||||||
|
in
|
||||||
|
{
|
||||||
|
librespeed-secrets = lib.mkIf (cfg.secrets != { }) {
|
||||||
|
description = "LibreSpeed secret helper";
|
||||||
|
|
||||||
|
ExecStart =
|
||||||
|
let
|
||||||
|
script = pkgs.writeShellApplication {
|
||||||
|
name = "librespeed-secrets";
|
||||||
|
runtimeInputs = [ pkgs.coreutils ];
|
||||||
|
text =
|
||||||
|
''
|
||||||
|
cp ${configFile} ''${RUNTIME_DIRECTORY%%:*}/config.toml
|
||||||
|
''
|
||||||
|
+ lib.pipe cfg.secrets [
|
||||||
|
(lib.mapAttrs (
|
||||||
|
name: file: ''
|
||||||
|
cat >>''${RUNTIME_DIRECTORY%%:*}/config.toml <<EOF
|
||||||
|
${name}="$(<${lib.escapeShellArg file})"
|
||||||
|
EOF
|
||||||
|
''
|
||||||
|
))
|
||||||
|
(lib.concatLines lib.attrValues)
|
||||||
|
];
|
||||||
|
};
|
||||||
|
in
|
||||||
|
lib.getExe script;
|
||||||
|
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "oneshot";
|
||||||
|
RemainAfterExit = true;
|
||||||
|
RuntimeDirectory = "librespeed";
|
||||||
|
UMask = "u=rw";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
in lib.getExe script;
|
librespeed = {
|
||||||
|
description = "LibreSpeed server daemon";
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
wants = [ "network-online.target" ];
|
||||||
|
requires = lib.optionals (cfg.secrets != { }) [ "librespeed-secrets.service" ];
|
||||||
|
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
Type = "oneshot";
|
Type = "simple";
|
||||||
RemainAfterExit = true;
|
Restart = "always";
|
||||||
RuntimeDirectory = "librespeed";
|
|
||||||
UMask = "u=rw";
|
DynamicUser = true;
|
||||||
|
|
||||||
|
LoadCredential = lib.mkIf (cfg.domain != null && !cfg.frontend.useNginx) [
|
||||||
|
"cert.pem:${config.security.acme.certs.${cfg.domain}.directory}/cert.pem"
|
||||||
|
"key.pem:${config.security.acme.certs.${cfg.domain}.directory}/key.pem"
|
||||||
|
];
|
||||||
|
|
||||||
|
ExecStartPre = lib.mkIf cfg.downloadIPDB "${lib.getExe cfg.package} --update-ipdb";
|
||||||
|
ExecStart = "${lib.getExe cfg.package} -c ${
|
||||||
|
if (cfg.secrets == { }) then configFile else "\${RUNTIME_DIRECTORY%%:*}/config.toml"
|
||||||
|
}";
|
||||||
|
WorkingDirectory = "/var/cache/librespeed";
|
||||||
|
RuntimeDirectory = "librespeed";
|
||||||
|
RuntimeDirectoryPreserve = true;
|
||||||
|
StateDirectory = "librespeed";
|
||||||
|
CacheDirectory = "librespeed";
|
||||||
|
SyslogIdentifier = "librespeed";
|
||||||
|
|
||||||
|
ReadOnlyPaths = [ cfg.package ];
|
||||||
|
RestrictSUIDSGID = true;
|
||||||
|
RestrictNamespaces = true;
|
||||||
|
PrivateTmp = true;
|
||||||
|
PrivateDevices = true;
|
||||||
|
PrivateUsers = true;
|
||||||
|
ProtectHostname = true;
|
||||||
|
ProtectClock = true;
|
||||||
|
ProtectKernelTunables = true;
|
||||||
|
ProtectKernelModules = true;
|
||||||
|
ProtectKernelLogs = true;
|
||||||
|
ProtectControlGroups = true;
|
||||||
|
ProtectSystem = "strict";
|
||||||
|
ProtectHome = true;
|
||||||
|
ProtectProc = "invisible";
|
||||||
|
SystemCallArchitectures = "native";
|
||||||
|
SystemCallFilter = "@system-service";
|
||||||
|
SystemCallErrorNumber = "EPERM";
|
||||||
|
LockPersonality = true;
|
||||||
|
NoNewPrivileges = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
}
|
||||||
librespeed = {
|
);
|
||||||
description = "LibreSpeed server daemon";
|
|
||||||
wantedBy = [ "multi-user.target" ];
|
|
||||||
wants = [ "network-online.target" ];
|
|
||||||
requires = lib.optionals (cfg.secrets != {}) [ "librespeed-secrets.service" ];
|
|
||||||
|
|
||||||
serviceConfig = {
|
|
||||||
Type = "simple";
|
|
||||||
Restart = "always";
|
|
||||||
|
|
||||||
DynamicUser = true;
|
|
||||||
|
|
||||||
LoadCredential = lib.mkIf (cfg.domain != null) [
|
|
||||||
"cert.pem:${config.security.acme.certs.${cfg.domain}.directory}/cert.pem"
|
|
||||||
"key.pem:${config.security.acme.certs.${cfg.domain}.directory}/key.pem"
|
|
||||||
];
|
|
||||||
|
|
||||||
ExecStartPre = lib.mkIf cfg.downloadIPDB "${lib.getExe cfg.package} --update-ipdb";
|
|
||||||
ExecStart = "${lib.getExe cfg.package} -c ${if (cfg.secrets == {}) then configFile else "\${RUNTIME_DIRECTORY%%:*}/config.toml"}";
|
|
||||||
WorkingDirectory = "/var/cache/librespeed";
|
|
||||||
RuntimeDirectory = "librespeed";
|
|
||||||
RuntimeDirectoryPreserve = true;
|
|
||||||
StateDirectory = "librespeed";
|
|
||||||
CacheDirectory = "librespeed";
|
|
||||||
SyslogIdentifier = "librespeed";
|
|
||||||
|
|
||||||
ReadOnlyPaths = [ cfg.package ];
|
|
||||||
RestrictSUIDSGID = true;
|
|
||||||
RestrictNamespaces = true;
|
|
||||||
PrivateTmp = true;
|
|
||||||
PrivateDevices = true;
|
|
||||||
PrivateUsers = true;
|
|
||||||
ProtectHostname = true;
|
|
||||||
ProtectClock = true;
|
|
||||||
ProtectKernelTunables = true;
|
|
||||||
ProtectKernelModules = true;
|
|
||||||
ProtectKernelLogs = true;
|
|
||||||
ProtectControlGroups = true;
|
|
||||||
ProtectSystem = "strict";
|
|
||||||
ProtectHome = true;
|
|
||||||
ProtectProc = "invisible";
|
|
||||||
SystemCallArchitectures = "native";
|
|
||||||
SystemCallFilter = "@system-service";
|
|
||||||
SystemCallErrorNumber = "EPERM";
|
|
||||||
LockPersonality = true;
|
|
||||||
NoNewPrivileges = true;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
meta.maintainers = with lib.maintainers; [ snaki ];
|
meta.maintainers = with lib.maintainers; [ snaki ];
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
rustPlatform,
|
rustPlatform,
|
||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
|
# https://github.com/librespeed/speedtest-rust/pull/7
|
||||||
version = "unstable-2024-09-28";
|
version = "unstable-2024-09-28";
|
||||||
src = fetchFromGitHub {
|
src = fetchFromGitHub {
|
||||||
owner = "librespeed";
|
owner = "librespeed";
|
||||||
|
|
Loading…
Reference in a new issue