From 655bab40f5464f7e255166aa8c67c38c635be165 Mon Sep 17 00:00:00 2001 From: Leah Amelia Chen Date: Mon, 4 Nov 2024 10:27:13 +0100 Subject: [PATCH 1/3] fusion: init at 0.8.9 --- .../fu/fusion/frontend-pin-version.patch | 15 +++++ pkgs/by-name/fu/fusion/package.nix | 67 +++++++++++++++++++ 2 files changed, 82 insertions(+) create mode 100644 pkgs/by-name/fu/fusion/frontend-pin-version.patch create mode 100644 pkgs/by-name/fu/fusion/package.nix diff --git a/pkgs/by-name/fu/fusion/frontend-pin-version.patch b/pkgs/by-name/fu/fusion/frontend-pin-version.patch new file mode 100644 index 0000000000000..692e3996f3e09 --- /dev/null +++ b/pkgs/by-name/fu/fusion/frontend-pin-version.patch @@ -0,0 +1,15 @@ +diff --git a/vite.config.ts b/vite.config.ts +index 880b306..01f7a92 100644 +--- a/vite.config.ts ++++ b/vite.config.ts +@@ -6,9 +6,7 @@ export default defineConfig({ + plugins: [sveltekit()], + define: { + 'import.meta.env.FUSION': JSON.stringify({ +- version: +- execSync('git describe --tags --abbrev=0').toString().trimEnd() || +- execSync('git rev-parse --short HEAD').toString().trimEnd() ++ version: process.env.version + }) + }, + server: { diff --git a/pkgs/by-name/fu/fusion/package.nix b/pkgs/by-name/fu/fusion/package.nix new file mode 100644 index 0000000000000..57db6b10c5d2e --- /dev/null +++ b/pkgs/by-name/fu/fusion/package.nix @@ -0,0 +1,67 @@ +{ + lib, + fetchFromGitHub, + buildNpmPackage, + buildGoModule, + mockgen, + nix-update-script, +}: +buildGoModule rec { + pname = "fusion"; + version = "0.8.9"; + + src = fetchFromGitHub { + owner = "0x2E"; + repo = "fusion"; + rev = "v${version}"; + hash = "sha256-nI587lshHlwZMnGGtzkLSaWc8OvY8QfPsdmAR2j+slI="; + }; + + frontend = buildNpmPackage { + pname = "fusion-frontend"; + inherit version; + src = "${src}/frontend"; + + patches = [ ./frontend-pin-version.patch ]; + + npmDepsHash = "sha256-sOdviGGVB41IjO2tpw655dSxuqxufQGo2CqmsjNCDn0="; + + installPhase = '' + runHook preInstall + + cp -r build $out + + runHook postInstall + ''; + }; + + vendorHash = "sha256-isSoDDJLWIxmihu9txcPMDBJ+l323yrfXqyhqtEAoUI="; + + subPackages = [ "cmd/server" ]; + + overrideModAttrs = prev: { + nativeBuildInputs = prev.nativeBuildInputs ++ [ mockgen ]; + + preBuild = '' + go generate ./... + ''; + }; + + preBuild = '' + cp -r ${frontend} frontend/build + ''; + + postInstall = '' + mv $out/bin/server $out/bin/fusion + ''; + + passthru.updateScript = nix-update-script { }; + + meta = { + description = "Lightweight, self-hosted friendly RSS aggregator and reader"; + homepage = "https://github.com/0x2E/fusion"; + license = with lib.licenses; [ mit ]; + maintainers = with lib.maintainers; [ pluiedev ]; + mainProgram = "fusion"; + }; +} From ac7ebadd11a35a44611026f829106c6a8fe7c171 Mon Sep 17 00:00:00 2001 From: Leah Amelia Chen Date: Mon, 4 Nov 2024 17:34:05 +0100 Subject: [PATCH 2/3] nixos/fusion: init module --- nixos/modules/module-list.nix | 1 + nixos/modules/services/web-apps/fusion.nix | 144 +++++++++++++++++++++ 2 files changed, 145 insertions(+) create mode 100644 nixos/modules/services/web-apps/fusion.nix diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 7b753937e8082..75ea0896fea47 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -1422,6 +1422,7 @@ ./services/web-apps/flarum.nix ./services/web-apps/fluidd.nix ./services/web-apps/freshrss.nix + ./services/web-apps/fusion.nix ./services/web-apps/galene.nix ./services/web-apps/gancio.nix ./services/web-apps/gerrit.nix diff --git a/nixos/modules/services/web-apps/fusion.nix b/nixos/modules/services/web-apps/fusion.nix new file mode 100644 index 0000000000000..d4eaf07a3bb5d --- /dev/null +++ b/nixos/modules/services/web-apps/fusion.nix @@ -0,0 +1,144 @@ +{ + config, + lib, + pkgs, + ... +}: +let + cfg = config.services.fusion; +in +{ + options.services.fusion = { + enable = lib.mkEnableOption "Fusion, a lightweight, self-hosted friendly RSS aggregator and reader"; + + host = lib.mkOption { + type = lib.types.str; + default = "0.0.0.0"; + example = "[::1]"; + description = "The address that Fusion should listen on."; + }; + + port = lib.mkOption { + type = lib.types.port; + default = 8080; + description = "The port that Fusion should listen on."; + }; + + passwordFile = lib.mkOption { + type = lib.types.path; + example = "/run/keys/fusion-password"; + description = '' + A file containing the password for the Fusion web interface. + + This should be a path pointing to a file within a secure directory and NEVER + in the Nix store (which is world-readable)! + ''; + }; + + tls = lib.mkOption { + type = lib.types.nullOr ( + lib.types.submodule { + options = { + cert = lib.mkOption { + type = lib.types.path; + description = "Path to TLS certificate"; + }; + key = lib.mkOption { + type = lib.types.path; + description = "Path to TLS key"; + }; + }; + } + ); + default = null; + description = '' + The paths to the TLS certificate and key files for Fusion. + + If these options are set, then Fusion can only be accessed through a secure + TLS connection. If you are using a reverse proxy like Nginx to handle HTTPS, + please leave these unset. + ''; + }; + }; + + config = lib.mkIf cfg.enable { + systemd.services.fusion = { + description = "Fusion, a lightweight, self-hosted friendly RSS aggregator and reader"; + + wantedBy = [ "multi-user.target" ]; + wants = [ "network-online.target" ]; + after = [ "network-online.target" ]; + + environment = { + HOST = cfg.host; + PORT = toString cfg.port; + DB = "/var/lib/fusion/sqlite.db"; + + TLS_CERT = lib.mkIf (cfg.tls != null) cfg.tls.cert; + TLS_KEY = lib.mkIf (cfg.tls != null) cfg.tls.key; + }; + + script = '' + export PASSWORD=$(cat $CREDENTIALS_DIRECTORY/fusion) + ${lib.getExe pkgs.fusion} + ''; + + serviceConfig = { + DynamicUser = true; + User = "fusion"; + LoadCredential = "fusion:${cfg.passwordFile}"; + Restart = "on-failure"; + TimeoutStopSec = 300; + + # Hardening + WorkingDirectory = "/var/lib/fusion"; + StateDirectory = "fusion"; + RuntimeDirectory = "fusion"; + RootDirectory = "/run/fusion"; + RootDirectoryStartOnly = true; + + BindReadOnlyPaths = + [ builtins.storeDir ] + ++ lib.optionals (cfg.tls != null) [ + cfg.tls.cert + cfg.tls.key + ]; + + ProtectClock = true; + ProtectKernelLogs = true; + ProtectControlGroups = true; + ProtectKernelModules = true; + ProtectHostname = true; + ProtectKernelTunables = true; + ProtectProc = "invisible"; + ProtectHome = true; + ProcSubset = "pid"; + + PrivateTmp = true; + PrivateNetwork = false; + PrivateUsers = cfg.port >= 1024; + PrivateDevices = true; + + RestrictRealtime = true; + RestrictNamespaces = true; + RestrictAddressFamilies = [ + "AF_INET" + "AF_INET6" + ]; + + MemoryDenyWriteExecute = true; + LockPersonality = true; + AmbientCapabilities = lib.optional (cfg.port < 1024) "CAP_NET_BIND_SERVICE"; + CapabilityBoundingSet = ""; + SystemCallArchitectures = "native"; + SystemCallFilter = [ + "@system-service" + "~@resources" + "~@privileged" + "setrlimit" + ]; + UMask = "0066"; + }; + }; + }; +} From 03138ec3a9603495c55fb42feccaf1bb51417227 Mon Sep 17 00:00:00 2001 From: Leah Amelia Chen Date: Mon, 4 Nov 2024 17:34:32 +0100 Subject: [PATCH 3/3] nixos/fusion: add tests --- nixos/tests/all-tests.nix | 1 + nixos/tests/fusion.nix | 33 ++++++++++++++++++++++++++++++ pkgs/by-name/fu/fusion/package.nix | 10 ++++++++- 3 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 nixos/tests/fusion.nix diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index cea2865718d80..0adbb2734437d 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -366,6 +366,7 @@ in { fsck = handleTest ./fsck.nix {}; fsck-systemd-stage-1 = handleTest ./fsck.nix { systemdStage1 = true; }; ft2-clone = handleTest ./ft2-clone.nix {}; + fusion = handleTest ./fusion.nix {}; legit = handleTest ./legit.nix {}; mimir = handleTest ./mimir.nix {}; gancio = handleTest ./gancio.nix {}; diff --git a/nixos/tests/fusion.nix b/nixos/tests/fusion.nix new file mode 100644 index 0000000000000..5ddd807f216ef --- /dev/null +++ b/nixos/tests/fusion.nix @@ -0,0 +1,33 @@ +import ./make-test-python.nix ( + let + password = "much-secure-so-password"; + in + { lib, ... }: + { + name = "fusion"; + meta.maintainers = with lib.maintainers; [ pluiedev ]; + + nodes.machine = + { pkgs, ... }: + { + networking.firewall.enable = false; + networking.useDHCP = false; + + services.fusion = { + enable = true; + + # WARNING: Never EVER do this in production. + passwordFile = pkgs.writeText "fusion-test-password" password; + }; + }; + + testScript = '' + machine.wait_for_unit("network-online.target") + machine.wait_for_open_port(8080) + + # Try logging in + machine.succeed('curl -X POST -H "Content-Type: application/json" --data \'{"password":"${password}"}\' 127.0.0.1:8080/api/sessions') + machine.wait_for_console_text('"status":201') + ''; + } +) diff --git a/pkgs/by-name/fu/fusion/package.nix b/pkgs/by-name/fu/fusion/package.nix index 57db6b10c5d2e..e003e8e2bc502 100644 --- a/pkgs/by-name/fu/fusion/package.nix +++ b/pkgs/by-name/fu/fusion/package.nix @@ -1,9 +1,11 @@ { lib, + stdenv, fetchFromGitHub, buildNpmPackage, buildGoModule, mockgen, + nixosTests, nix-update-script, }: buildGoModule rec { @@ -55,7 +57,13 @@ buildGoModule rec { mv $out/bin/server $out/bin/fusion ''; - passthru.updateScript = nix-update-script { }; + passthru = { + tests = lib.optionalAttrs stdenv.hostPlatform.isLinux { + inherit (nixosTests) fusion; + }; + + updateScript = nix-update-script { }; + }; meta = { description = "Lightweight, self-hosted friendly RSS aggregator and reader";