From e286b91ebca6f7de81cefb87492440582a565990 Mon Sep 17 00:00:00 2001 From: Guanran Wang Date: Tue, 1 Oct 2024 17:39:13 +0800 Subject: [PATCH 1/7] {nixos,nixosTests}/redlib: format with nixfmt --- nixos/modules/services/misc/redlib.nix | 110 ++++++++++++++++--------- nixos/tests/redlib.nix | 37 +++++---- 2 files changed, 90 insertions(+), 57 deletions(-) diff --git a/nixos/modules/services/misc/redlib.nix b/nixos/modules/services/misc/redlib.nix index 0da85df46bf7..d115248ba1df 100644 --- a/nixos/modules/services/misc/redlib.nix +++ b/nixos/modules/services/misc/redlib.nix @@ -1,8 +1,21 @@ -{ config, lib, pkgs, ... }: - -with lib; +{ + config, + lib, + pkgs, + ... +}: let + inherit (lib) + concatStringsSep + mkEnableOption + mkIf + mkOption + mkPackageOption + mkRenamedOptionModule + types + ; + cfg = config.services.redlib; args = concatStringsSep " " ([ @@ -12,7 +25,16 @@ let in { imports = [ - (mkRenamedOptionModule [ "services" "libreddit" ] [ "services" "redlib" ]) + (mkRenamedOptionModule + [ + "services" + "libreddit" + ] + [ + "services" + "redlib" + ] + ) ]; options = { @@ -24,7 +46,7 @@ in address = mkOption { default = "0.0.0.0"; example = "127.0.0.1"; - type = types.str; + type = types.str; description = "The address to listen on"; }; @@ -46,41 +68,49 @@ in config = mkIf cfg.enable { systemd.services.redlib = { - description = "Private front-end for Reddit"; - wantedBy = [ "multi-user.target" ]; - after = [ "network.target" ]; - serviceConfig = { - DynamicUser = true; - ExecStart = "${lib.getExe cfg.package} ${args}"; - AmbientCapabilities = lib.mkIf (cfg.port < 1024) [ "CAP_NET_BIND_SERVICE" ]; - Restart = "on-failure"; - RestartSec = "2s"; - # Hardening - CapabilityBoundingSet = if (cfg.port < 1024) then [ "CAP_NET_BIND_SERVICE" ] else [ "" ]; - DeviceAllow = [ "" ]; - LockPersonality = true; - MemoryDenyWriteExecute = true; - PrivateDevices = true; - # A private user cannot have process capabilities on the host's user - # namespace and thus CAP_NET_BIND_SERVICE has no effect. - PrivateUsers = (cfg.port >= 1024); - ProcSubset = "pid"; - ProtectClock = true; - ProtectControlGroups = true; - ProtectHome = true; - ProtectHostname = true; - ProtectKernelLogs = true; - ProtectKernelModules = true; - ProtectKernelTunables = true; - ProtectProc = "invisible"; - RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ]; - RestrictNamespaces = true; - RestrictRealtime = true; - RestrictSUIDSGID = true; - SystemCallArchitectures = "native"; - SystemCallFilter = [ "@system-service" "~@privileged" "~@resources" ]; - UMask = "0077"; - }; + description = "Private front-end for Reddit"; + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; + serviceConfig = { + DynamicUser = true; + ExecStart = "${lib.getExe cfg.package} ${args}"; + AmbientCapabilities = lib.mkIf (cfg.port < 1024) [ "CAP_NET_BIND_SERVICE" ]; + Restart = "on-failure"; + RestartSec = "2s"; + + # Hardening + CapabilityBoundingSet = if (cfg.port < 1024) then [ "CAP_NET_BIND_SERVICE" ] else [ "" ]; + DeviceAllow = [ "" ]; + LockPersonality = true; + MemoryDenyWriteExecute = true; + PrivateDevices = true; + # A private user cannot have process capabilities on the host's user + # namespace and thus CAP_NET_BIND_SERVICE has no effect. + PrivateUsers = (cfg.port >= 1024); + ProcSubset = "pid"; + ProtectClock = true; + ProtectControlGroups = true; + ProtectHome = true; + ProtectHostname = true; + ProtectKernelLogs = true; + ProtectKernelModules = true; + ProtectKernelTunables = true; + ProtectProc = "invisible"; + RestrictAddressFamilies = [ + "AF_INET" + "AF_INET6" + ]; + RestrictNamespaces = true; + RestrictRealtime = true; + RestrictSUIDSGID = true; + SystemCallArchitectures = "native"; + SystemCallFilter = [ + "@system-service" + "~@privileged" + "~@resources" + ]; + UMask = "0077"; + }; }; networking.firewall = mkIf cfg.openFirewall { diff --git a/nixos/tests/redlib.nix b/nixos/tests/redlib.nix index 808f857aed19..a12a7401f57c 100644 --- a/nixos/tests/redlib.nix +++ b/nixos/tests/redlib.nix @@ -1,20 +1,23 @@ -import ./make-test-python.nix ({ lib, pkgs, ... }: { - name = "redlib"; - meta.maintainers = with lib.maintainers; [ soispha ]; +import ./make-test-python.nix ( + { lib, pkgs, ... }: + { + name = "redlib"; + meta.maintainers = with lib.maintainers; [ soispha ]; - nodes.machine = { - services.redlib = { - package = pkgs.redlib; - enable = true; - # Test CAP_NET_BIND_SERVICE - port = 80; + nodes.machine = { + services.redlib = { + package = pkgs.redlib; + enable = true; + # Test CAP_NET_BIND_SERVICE + port = 80; + }; }; - }; - testScript = '' - machine.wait_for_unit("redlib.service") - machine.wait_for_open_port(80) - # Query a page that does not require Internet access - machine.succeed("curl --fail http://localhost:80/settings") - ''; -}) + testScript = '' + machine.wait_for_unit("redlib.service") + machine.wait_for_open_port(80) + # Query a page that does not require Internet access + machine.succeed("curl --fail http://localhost:80/settings") + ''; + } +) From a2a4c87cab75c0043b2241887ca1897634fc68eb Mon Sep 17 00:00:00 2001 From: Guanran Wang Date: Tue, 1 Oct 2024 17:59:05 +0800 Subject: [PATCH 2/7] {,nixos/,nixosTests/}redlib: add Guanran928 as maintainer --- nixos/modules/services/misc/redlib.nix | 4 ++++ nixos/tests/redlib.nix | 5 ++++- pkgs/by-name/re/redlib/package.nix | 5 ++++- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/nixos/modules/services/misc/redlib.nix b/nixos/modules/services/misc/redlib.nix index d115248ba1df..9c23e556584f 100644 --- a/nixos/modules/services/misc/redlib.nix +++ b/nixos/modules/services/misc/redlib.nix @@ -117,4 +117,8 @@ in allowedTCPPorts = [ cfg.port ]; }; }; + + meta = { + maintainers = with lib.maintainers; [ Guanran928 ]; + }; } diff --git a/nixos/tests/redlib.nix b/nixos/tests/redlib.nix index a12a7401f57c..f6806ea8ec85 100644 --- a/nixos/tests/redlib.nix +++ b/nixos/tests/redlib.nix @@ -2,7 +2,10 @@ import ./make-test-python.nix ( { lib, pkgs, ... }: { name = "redlib"; - meta.maintainers = with lib.maintainers; [ soispha ]; + meta.maintainers = with lib.maintainers; [ + soispha + Guanran928 + ]; nodes.machine = { services.redlib = { diff --git a/pkgs/by-name/re/redlib/package.nix b/pkgs/by-name/re/redlib/package.nix index 51c80078e372..33d1a786b4ea 100644 --- a/pkgs/by-name/re/redlib/package.nix +++ b/pkgs/by-name/re/redlib/package.nix @@ -64,6 +64,9 @@ rustPlatform.buildRustPackage rec { homepage = "https://github.com/redlib-org/redlib"; license = lib.licenses.agpl3Only; mainProgram = "redlib"; - maintainers = with lib.maintainers; [ soispha ]; + maintainers = with lib.maintainers; [ + soispha + Guanran928 + ]; }; } From 672d7efbd5ce0ab864d570b4f737d075850d4843 Mon Sep 17 00:00:00 2001 From: Guanran Wang Date: Tue, 1 Oct 2024 17:56:23 +0800 Subject: [PATCH 3/7] nixos/redlib: add cfg.settings --- nixos/modules/services/misc/redlib.nix | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/nixos/modules/services/misc/redlib.nix b/nixos/modules/services/misc/redlib.nix index 9c23e556584f..efdea9128aba 100644 --- a/nixos/modules/services/misc/redlib.nix +++ b/nixos/modules/services/misc/redlib.nix @@ -8,6 +8,8 @@ let inherit (lib) concatStringsSep + isBool + mapAttrs mkEnableOption mkIf mkOption @@ -22,6 +24,8 @@ let "--port ${toString cfg.port}" "--address ${cfg.address}" ]); + + boolToString' = b: if b then "on" else "off"; in { imports = [ @@ -63,6 +67,24 @@ in description = "Open ports in the firewall for the redlib web interface"; }; + settings = lib.mkOption { + type = lib.types.submodule { + freeformType = + with types; + attrsOf ( + nullOr (oneOf [ + bool + int + str + ]) + ); + options = { }; + }; + default = { }; + description = '' + See [GitHub](https://github.com/redlib-org/redlib/tree/main?tab=readme-ov-file#configuration) for available settings. + ''; + }; }; }; @@ -71,6 +93,7 @@ in description = "Private front-end for Reddit"; wantedBy = [ "multi-user.target" ]; after = [ "network.target" ]; + environment = mapAttrs (_: v: if isBool v then boolToString' v else toString v) cfg.settings; serviceConfig = { DynamicUser = true; ExecStart = "${lib.getExe cfg.package} ${args}"; From 4e6df6f865bf4b1b6fd94bfdcdb3e0b1a828d5a2 Mon Sep 17 00:00:00 2001 From: Guanran Wang Date: Tue, 1 Oct 2024 17:46:22 +0800 Subject: [PATCH 4/7] nixos/redlib: use upstream systemd service file --- nixos/modules/services/misc/redlib.nix | 42 ++++---------------------- pkgs/by-name/re/redlib/package.nix | 6 ++++ 2 files changed, 12 insertions(+), 36 deletions(-) diff --git a/nixos/modules/services/misc/redlib.nix b/nixos/modules/services/misc/redlib.nix index efdea9128aba..177214b9ec05 100644 --- a/nixos/modules/services/misc/redlib.nix +++ b/nixos/modules/services/misc/redlib.nix @@ -89,50 +89,20 @@ in }; config = mkIf cfg.enable { + systemd.packages = [ cfg.package ]; systemd.services.redlib = { - description = "Private front-end for Reddit"; - wantedBy = [ "multi-user.target" ]; - after = [ "network.target" ]; + wantedBy = [ "default.target" ]; environment = mapAttrs (_: v: if isBool v then boolToString' v else toString v) cfg.settings; serviceConfig = { - DynamicUser = true; - ExecStart = "${lib.getExe cfg.package} ${args}"; + ExecStart = [ + "" + "${lib.getExe cfg.package} ${args}" + ]; AmbientCapabilities = lib.mkIf (cfg.port < 1024) [ "CAP_NET_BIND_SERVICE" ]; - Restart = "on-failure"; - RestartSec = "2s"; - - # Hardening CapabilityBoundingSet = if (cfg.port < 1024) then [ "CAP_NET_BIND_SERVICE" ] else [ "" ]; - DeviceAllow = [ "" ]; - LockPersonality = true; - MemoryDenyWriteExecute = true; - PrivateDevices = true; # A private user cannot have process capabilities on the host's user # namespace and thus CAP_NET_BIND_SERVICE has no effect. PrivateUsers = (cfg.port >= 1024); - ProcSubset = "pid"; - ProtectClock = true; - ProtectControlGroups = true; - ProtectHome = true; - ProtectHostname = true; - ProtectKernelLogs = true; - ProtectKernelModules = true; - ProtectKernelTunables = true; - ProtectProc = "invisible"; - RestrictAddressFamilies = [ - "AF_INET" - "AF_INET6" - ]; - RestrictNamespaces = true; - RestrictRealtime = true; - RestrictSUIDSGID = true; - SystemCallArchitectures = "native"; - SystemCallFilter = [ - "@system-service" - "~@privileged" - "~@resources" - ]; - UMask = "0077"; }; }; diff --git a/pkgs/by-name/re/redlib/package.nix b/pkgs/by-name/re/redlib/package.nix index 33d1a786b4ea..4eb49d21d966 100644 --- a/pkgs/by-name/re/redlib/package.nix +++ b/pkgs/by-name/re/redlib/package.nix @@ -24,6 +24,12 @@ rustPlatform.buildRustPackage rec { darwin.apple_sdk.frameworks.Security ]; + postInstall = '' + install -Dm644 contrib/redlib.service $out/lib/systemd/system/redlib.service + sed -i "s#/usr/bin/redlib#$out/bin/redlib#" $out/lib/systemd/system/redlib.service + sed -i "/EnvironmentFile/d" $out/lib/systemd/system/redlib.service + ''; + checkFlags = [ # All these test try to connect to Reddit. # utils.rs From 743d0ff90b27b632e30c1ac53ea702d98a0d15f9 Mon Sep 17 00:00:00 2001 From: Guanran Wang Date: Sun, 6 Oct 2024 16:10:40 +0800 Subject: [PATCH 5/7] fixup! nixos/redlib: use upstream systemd service file --- pkgs/by-name/re/redlib/package.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/by-name/re/redlib/package.nix b/pkgs/by-name/re/redlib/package.nix index 4eb49d21d966..594a8f2c1b04 100644 --- a/pkgs/by-name/re/redlib/package.nix +++ b/pkgs/by-name/re/redlib/package.nix @@ -26,8 +26,8 @@ rustPlatform.buildRustPackage rec { postInstall = '' install -Dm644 contrib/redlib.service $out/lib/systemd/system/redlib.service - sed -i "s#/usr/bin/redlib#$out/bin/redlib#" $out/lib/systemd/system/redlib.service - sed -i "/EnvironmentFile/d" $out/lib/systemd/system/redlib.service + substituteInPlace $out/lib/systemd/system/redlib.service \ + --replace-fail "/usr/bin/redlib" "$out/bin/redlib" ''; checkFlags = [ From 4a0893c1866afd461a0c02ca9901e9a43572e20d Mon Sep 17 00:00:00 2001 From: Guanran Wang Date: Fri, 22 Nov 2024 15:24:46 +0800 Subject: [PATCH 6/7] fixup! nixos/redlib: use upstream systemd service file --- nixos/modules/services/misc/redlib.nix | 31 +++++++++++++++++--------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/nixos/modules/services/misc/redlib.nix b/nixos/modules/services/misc/redlib.nix index 177214b9ec05..3e3cd31a814c 100644 --- a/nixos/modules/services/misc/redlib.nix +++ b/nixos/modules/services/misc/redlib.nix @@ -93,17 +93,26 @@ in systemd.services.redlib = { wantedBy = [ "default.target" ]; environment = mapAttrs (_: v: if isBool v then boolToString' v else toString v) cfg.settings; - serviceConfig = { - ExecStart = [ - "" - "${lib.getExe cfg.package} ${args}" - ]; - AmbientCapabilities = lib.mkIf (cfg.port < 1024) [ "CAP_NET_BIND_SERVICE" ]; - CapabilityBoundingSet = if (cfg.port < 1024) then [ "CAP_NET_BIND_SERVICE" ] else [ "" ]; - # A private user cannot have process capabilities on the host's user - # namespace and thus CAP_NET_BIND_SERVICE has no effect. - PrivateUsers = (cfg.port >= 1024); - }; + serviceConfig = + { + ExecStart = [ + "" + "${lib.getExe cfg.package} ${args}" + ]; + } + // ( + if (cfg.port < 1024) then + { + AmbientCapabilities = [ "CAP_NET_BIND_SERVICE" ]; + CapabilityBoundingSet = [ "CAP_NET_BIND_SERVICE" ]; + } + else + { + # A private user cannot have process capabilities on the host's user + # namespace and thus CAP_NET_BIND_SERVICE has no effect. + PrivateUsers = true; + } + ); }; networking.firewall = mkIf cfg.openFirewall { From 0f77709e0f82f88e5735a2d81b86740742fce3ef Mon Sep 17 00:00:00 2001 From: Guanran Wang Date: Fri, 22 Nov 2024 15:42:09 +0800 Subject: [PATCH 7/7] nixosTests.redlib: test settings mechanic --- nixos/tests/redlib.nix | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/nixos/tests/redlib.nix b/nixos/tests/redlib.nix index f6806ea8ec85..c3a948c43795 100644 --- a/nixos/tests/redlib.nix +++ b/nixos/tests/redlib.nix @@ -13,6 +13,10 @@ import ./make-test-python.nix ( enable = true; # Test CAP_NET_BIND_SERVICE port = 80; + + settings = { + REDLIB_DEFAULT_USE_HLS = true; + }; }; }; @@ -21,6 +25,7 @@ import ./make-test-python.nix ( machine.wait_for_open_port(80) # Query a page that does not require Internet access machine.succeed("curl --fail http://localhost:80/settings") + machine.succeed("curl --fail http://localhost:80/info | grep 'Use HLSon'") ''; } )