Compare commits

...

3 commits

Author SHA1 Message Date
Update Bot a4d0125e29
Update from update-inputs-2024-10-02-04-20 2024-10-02 04:20:27 +02:00
Update Bot 8a687c5308
flake.lock: Update
Flake lock file updates:

• Updated input 'disko':
    'github:nix-community/disko/67dc29be3036cc888f0b9d4f0a788ee0f6768700' (2024-09-26)
  → 'github:nix-community/disko/6c5ba9ec9d470c1ca29e7735762c9c366e28f7f5' (2024-10-01)
• Updated input 'nixos-hardware':
    'github:nixos/nixos-hardware/d830ad47cc992b4a46b342bbc79694cbd0e980b2' (2024-09-27)
  → 'github:nixos/nixos-hardware/11c43c830e533dad1be527ecce379fcf994fbbb5' (2024-09-30)
• Updated input 'nixpkgs':
    'github:nixos/nixpkgs/1925c603f17fc89f4c8f6bf6f631a802ad85d784' (2024-09-26)
  → 'github:nixos/nixpkgs/06cf0e1da4208d3766d898b7fdab6513366d45b9' (2024-09-29)
• Updated input 'nixvim':
    'github:nix-community/nixvim/b5c19b6abb0fb0156b1cb76793b363e430e2cb47' (2024-09-27)
  → 'github:nix-community/nixvim/5f4a4b47597d3b9ac26c41ff4e8da28fa662f200' (2024-09-29)
• Updated input 'nixvim/git-hooks':
    'github:cachix/git-hooks.nix/4e743a6920eab45e8ba0fbe49dc459f1423a4b74' (2024-09-19)
  → 'github:cachix/git-hooks.nix/85f7a7177c678de68224af3402ab8ee1bcee25c8' (2024-09-28)
• Updated input 'nixvim/nix-darwin':
    'github:lnl7/nix-darwin/bd7d1e3912d40f799c5c0f7e5820ec950f1e0b3d' (2024-09-22)
  → 'github:lnl7/nix-darwin/f2e1c4aa29fc211947c3a7113cba1dd707433b70' (2024-09-28)
• Updated input 'nixvim/nuschtosSearch':
    'github:NuschtOS/search/3b7dd61b365ca45380707453758a45f2e9977be3' (2024-09-22)
  → 'github:NuschtOS/search/9f7426e532ef8dfc839c4a3fcc567b13a20a70d3' (2024-09-27)
• Updated input 'nixvim/treefmt-nix':
    'github:numtide/treefmt-nix/1bff2ba6ec22bc90e9ad3f7e94cca0d37870afa3' (2024-09-25)
  → 'github:numtide/treefmt-nix/879b29ae9a0378904fbbefe0dadaed43c8905754' (2024-09-27)
• Updated input 'sops-nix':
    'github:Mic92/sops-nix/127a96f49ddc377be6ba76964411bab11ae27803' (2024-09-27)
  → 'github:Mic92/sops-nix/3198a242e547939c5e659353551b0668ec150268' (2024-09-30)
• Updated input 'stylix':
    'github:danth/stylix/e3eb7fdf8d129ff3676dfbc84ee1262322ca6fb4' (2024-09-26)
  → 'github:danth/stylix/e7e97059776da7e34b739415a7bc8f80f606b803' (2024-09-30)
2024-10-02 04:20:25 +02:00
emily a1f06c7b22
librespeed: Fixes 2024-10-01 13:45:37 +02:00
5 changed files with 406 additions and 315 deletions

View file

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

View file

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

View file

@ -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": {

View file

@ -1,10 +1,18 @@
{ config, lib, pkgs, ... }: {
config,
lib,
pkgs,
...
}:
let let
cfg = config.services.librespeed; cfg = config.services.librespeed;
in { in
options.services.librespeed = let {
options.services.librespeed =
let
inherit (lib) mkOption types; inherit (lib) mkOption types;
in { in
{
enable = lib.mkEnableOption "LibreSpeed server"; enable = lib.mkEnableOption "LibreSpeed server";
package = lib.mkPackageOption pkgs "librespeed-rust" { }; package = lib.mkPackageOption pkgs "librespeed-rust" { };
domain = mkOption { domain = mkOption {
@ -20,7 +28,8 @@ in {
Whether to download the IP info database before starting librespeed. Whether to download the IP info database before starting librespeed.
Disable this if you want to use the Go implementation. Disable this if you want to use the Go implementation.
''; '';
default = (!cfg.secrets ? "ipinfo_api_key"); default = !(cfg.secrets ? "ipinfo_api_key");
defaultText = lib.literalExpression ''!(cfg.secrets ? "ipinfo_api_key")'';
type = types.bool; type = types.bool;
}; };
openFirewall = mkOption { openFirewall = mkOption {
@ -49,18 +58,32 @@ in {
[librespeed]: https://github.com/librespeed/speedtest-rust [librespeed]: https://github.com/librespeed/speedtest-rust
''; '';
default = { }; default = { };
type = with types; nullOr (attrsOf (oneOf [ type =
with types;
nullOr (
attrsOf (oneOf [
(nullOr bool) (nullOr bool)
int int
str str
package package
])); ])
);
}; };
frontend = { frontend = {
enable = lib.mkEnableOption "LibreSpeed frontend."; enable = lib.mkEnableOption ''
Enables the LibreSpeed frontend and adds a nginx virtual host if
not explicetly disabled and `services.librespeed.domain` is not `null`.
'';
contactEmail = mkOption { contactEmail = mkOption {
description = "Email address listed in the privacy policy."; description = "Email address listed in the privacy policy.";
default = if (cfg.domain != null) then "webmaster@${cfg.domain}" else "webmaster@${config.networking.fqdn}"; default =
if (cfg.domain != null) then "webmaster@${cfg.domain}" else "webmaster@${config.networking.fqdn}";
defaultText = lib.literalExpression ''
if (config.services.librespeed.domain != null) then
"webmaster@''${config.services.librespeed.domain}"
else
"webmaster@''${config.networking.fqdn}";
'';
type = types.str; type = types.str;
}; };
pageTitle = mkOption { pageTitle = mkOption {
@ -71,33 +94,43 @@ in {
useNginx = mkOption { useNginx = mkOption {
description = '' description = ''
Configure nginx for the LibreSpeed frontend. Configure nginx for the LibreSpeed frontend.
This will only create a virtual host for the frontend and won't proxy all requests because, 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. the reported upload and download speeds are inaccurate if proxied.
''; '';
default = cfg.domain != null; default = cfg.domain != null;
defaultText = lib.literalExpression "config.services.librespeed.domain != null";
type = types.bool; type = types.bool;
}; };
settings = mkOption { settings = mkOption {
description = '' description = ''
Override default test parameters. Override default settings of the speedtest web client.
See [speedtest_worker.js][link] for a list of possible values. See [speedtest_worker.js][link] for a list of possible values.
[link]: https://github.com/librespeed/speedtest/blob/master/speedtest_worker.js#L39 [link]: https://github.com/librespeed/speedtest/blob/master/speedtest_worker.js#L39
''; '';
default = {}; default = {
type = with types; nullOr (attrsOf (oneOf [ telemetry_level = "basic";
};
type =
with types;
nullOr (
attrsOf (oneOf [
bool bool
int int
str str
float float
])); ])
);
}; };
servers = mkOption { servers = mkOption {
description = "LibreSpeed servers that should apper in the server list."; description = "LibreSpeed servers that should apper in the server list.";
type = types.listOf (types.submodule { type = types.listOf (
options = let types.submodule {
options =
let
inherit (types) nonEmptyStr; inherit (types) nonEmptyStr;
in { in
{
name = mkOption { name = mkOption {
description = "Name shown in the server list."; description = "Name shown in the server list.";
type = nonEmptyStr; type = nonEmptyStr;
@ -139,13 +172,20 @@ in {
type = nonEmptyStr; type = nonEmptyStr;
}; };
}; };
}); }
);
}; };
}; };
}; };
config = lib.mkIf cfg.enable (let config = lib.mkIf cfg.enable (
librespeedAssets = pkgs.runCommand "librespeed-assets" (let let
mapValue = arg: if (lib.isBool arg) then librespeedAssets =
pkgs.runCommand "librespeed-assets"
(
let
mapValue =
arg:
if (lib.isBool arg) then
lib.boolToString arg lib.boolToString arg
else if ((lib.isInt arg) || (lib.isFloat arg)) then else if ((lib.isInt arg) || (lib.isFloat arg)) then
toString arg toString arg
@ -157,7 +197,8 @@ in {
(lib.attrValues) (lib.attrValues)
(lib.concatLines) (lib.concatLines)
]; ];
in { in
{
preferLocal = true; preferLocal = true;
serversList = '' serversList = ''
@ -168,7 +209,9 @@ in {
${mapSettings} ${mapSettings}
} }
''; '';
}) '' }
)
''
cp -r ${pkgs.librespeed-rust}/assets $out cp -r ${pkgs.librespeed-rust}/assets $out
chmod 666 $out/servers_list.js chmod 666 $out/servers_list.js
cat >$out/servers_list.js <<<"$serversList" cat >$out/servers_list.js <<<"$serversList"
@ -178,7 +221,8 @@ in {
--replace-fail "PUT@YOUR_EMAIL.HERE" ${lib.escapeShellArg (lib.escapeXML cfg.frontend.contactEmail)} \ --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)} --replace-fail "TO BE FILLED BY DEVELOPER" ${lib.escapeShellArg (lib.escapeXML cfg.frontend.contactEmail)}
''; '';
in { in
{
assertions = [ assertions = [
{ {
assertion = cfg.frontend.useNginx -> cfg.domain != null; assertion = cfg.frontend.useNginx -> cfg.domain != null;
@ -194,35 +238,57 @@ in {
services.nginx.virtualHosts = lib.mkIf (cfg.frontend.enable && cfg.frontend.useNginx) { services.nginx.virtualHosts = lib.mkIf (cfg.frontend.enable && cfg.frontend.useNginx) {
${cfg.domain} = { ${cfg.domain} = {
locations."/".root = librespeedAssets; locations."/".root = librespeedAssets;
locations."/backend/".extraConfig = "return 301 https://$host:${toString cfg.settings.listen_port}$request_uri;"; locations."/backend/" = {
proxyPass = "http://${cfg.settings.bind_address}:${toString cfg.settings.listen_port}/backend/";
extraConfig = ''
# add_header Cache-Control 'no-store, no-cache, max-age=0, no-transform';
# add_header Last-Modified $date_gmt;
if_modified_since off;
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; enableACME = true;
forceSSL = true; forceSSL = true;
}; };
}; };
security.acme.certs = lib.mkIf (cfg.domain != null) { security.acme.certs = lib.mkIf (cfg.domain != null) {
${cfg.domain} = { ${cfg.domain} = lib.mkIf (!cfg.frontend.useNginx) {
reloadServices = [ "librespeed.service" ]; reloadServices = [ "librespeed.service" ];
webroot = "/var/lib/acme/acme-challange"; webroot = "/var/lib/acme/acme-challenge";
}; };
}; };
services.librespeed.frontend.servers = lib.mkIf (cfg.frontend.enable && (cfg.domain != null)) [ services.librespeed.frontend.servers = lib.mkIf (cfg.frontend.enable && (cfg.domain != null)) [
{ {
name = cfg.domain; name = cfg.domain;
server = "//${cfg.domain}:${toString cfg.settings.listen_port}"; server = "//${cfg.domain}${lib.optionalString (!cfg.frontend.useNginx) ":${toString cfg.settings.listen_port}"}";
} }
]; ];
services.librespeed.frontend.settings = lib.mkIf cfg.frontend.enable {
telemetry_level = lib.mkDefault "basic";
};
services.librespeed.settings = let services.librespeed.settings =
let
inherit (lib) mkDefault mkIf; inherit (lib) mkDefault mkIf;
in { in
assets_path = if (cfg.frontend.enable && !cfg.frontend.useNginx) then librespeedAssets {
else pkgs.writeTextDir "index.html" ""; assets_path =
if (cfg.frontend.enable && !cfg.frontend.useNginx) then
librespeedAssets
else
pkgs.writeTextDir "index.html" "";
bind_address = mkDefault "::"; bind_address = mkDefault "127.0.0.1";
listen_port = mkDefault 8989; listen_port = mkDefault 8989;
base_url = mkDefault "backend"; base_url = mkDefault "backend";
worker_threads = mkDefault "auto"; worker_threads = mkDefault "auto";
@ -233,47 +299,68 @@ in {
#librespeed-rust will fail to start if the following config parameters are omitted. #librespeed-rust will fail to start if the following config parameters are omitted.
ipinfo_api_key = mkIf (!cfg.secrets ? "ipinfo_api_key") ""; ipinfo_api_key = mkIf (!cfg.secrets ? "ipinfo_api_key") "";
stats_password = mkIf (!cfg.secrets ? "stats_password") ""; 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_cert_file =
tls_key_file = if (cfg.domain != null) then (mkDefault "/run/credentials/librespeed.service/key.pem") else (mkDefault ""); 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); enable_tls = mkDefault (cfg.domain != null && !cfg.frontend.useNginx);
}; };
systemd.services = let systemd.services =
configFile = let let
mapValue = arg: if (lib.isBool arg) then configFile =
let
mapValue =
arg:
if (lib.isBool arg) then
lib.boolToString arg lib.boolToString arg
else if (lib.isInt arg) then else if (lib.isInt arg) then
toString arg toString arg
else "\"${lib.escape [ "\"" ] (toString arg)}\""; else
"\"${lib.escape [ "\"" ] (toString arg)}\"";
in in
with lib; pipe cfg.settings [ with lib;
pipe cfg.settings [
(filterAttrs (_: val: val != null)) (filterAttrs (_: val: val != null))
(mapAttrs (name: val: "${name}=${mapValue val}")) (mapAttrs (name: val: "${name}=${mapValue val}"))
(attrValues) (attrValues)
(concatLines) (concatLines)
(pkgs.writeText "${cfg.package.name}-config.toml") (pkgs.writeText "${cfg.package.name}-config.toml")
]; ];
in { in
{
librespeed-secrets = lib.mkIf (cfg.secrets != { }) { librespeed-secrets = lib.mkIf (cfg.secrets != { }) {
description = "LibreSpeed secret helper"; description = "LibreSpeed secret helper";
ExecStart = let ExecStart =
let
script = pkgs.writeShellApplication { script = pkgs.writeShellApplication {
name = "librespeed-secrets"; name = "librespeed-secrets";
runtimeInputs = [ pkgs.coreutils ]; runtimeInputs = [ pkgs.coreutils ];
text = '' text =
''
cp ${configFile} ''${RUNTIME_DIRECTORY%%:*}/config.toml cp ${configFile} ''${RUNTIME_DIRECTORY%%:*}/config.toml
'' + lib.pipe cfg.secrets [ ''
(lib.mapAttrs (name: file: '' + lib.pipe cfg.secrets [
(lib.mapAttrs (
name: file: ''
cat >>''${RUNTIME_DIRECTORY%%:*}/config.toml <<EOF cat >>''${RUNTIME_DIRECTORY%%:*}/config.toml <<EOF
${name}="$(<${lib.escapeShellArg file})" ${name}="$(<${lib.escapeShellArg file})"
EOF EOF
'')) ''
))
(lib.concatLines lib.attrValues) (lib.concatLines lib.attrValues)
]; ];
}; };
in lib.getExe script; in
lib.getExe script;
serviceConfig = { serviceConfig = {
Type = "oneshot"; Type = "oneshot";
@ -294,13 +381,15 @@ in {
DynamicUser = true; DynamicUser = true;
LoadCredential = lib.mkIf (cfg.domain != null) [ LoadCredential = lib.mkIf (cfg.domain != null && !cfg.frontend.useNginx) [
"cert.pem:${config.security.acme.certs.${cfg.domain}.directory}/cert.pem" "cert.pem:${config.security.acme.certs.${cfg.domain}.directory}/cert.pem"
"key.pem:${config.security.acme.certs.${cfg.domain}.directory}/key.pem" "key.pem:${config.security.acme.certs.${cfg.domain}.directory}/key.pem"
]; ];
ExecStartPre = lib.mkIf cfg.downloadIPDB "${lib.getExe cfg.package} --update-ipdb"; 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"}"; ExecStart = "${lib.getExe cfg.package} -c ${
if (cfg.secrets == { }) then configFile else "\${RUNTIME_DIRECTORY%%:*}/config.toml"
}";
WorkingDirectory = "/var/cache/librespeed"; WorkingDirectory = "/var/cache/librespeed";
RuntimeDirectory = "librespeed"; RuntimeDirectory = "librespeed";
RuntimeDirectoryPreserve = true; RuntimeDirectoryPreserve = true;
@ -331,7 +420,8 @@ in {
}; };
}; };
}; };
}); }
);
meta.maintainers = with lib.maintainers; [ snaki ]; meta.maintainers = with lib.maintainers; [ snaki ];
} }

View file

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