diff --git a/nixos/doc/manual/redirects.json b/nixos/doc/manual/redirects.json index e8eb5a3058f7..88add2f84bc5 100644 --- a/nixos/doc/manual/redirects.json +++ b/nixos/doc/manual/redirects.json @@ -41,6 +41,15 @@ "module-services-crab-hole-upstream-options": [ "index.html#module-services-crab-hole-upstream-options" ], + "module-services-strfry": [ + "index.html#module-services-strfry" + ], + "module-services-strfry-basic-usage": [ + "index.html#module-services-strfry-basic-usage" + ], + "module-services-strfry-reverse-proxy": [ + "index.html#module-services-strfry-reverse-proxy" + ], "preface": [ "index.html#preface" ], diff --git a/nixos/doc/manual/release-notes/rl-2505.section.md b/nixos/doc/manual/release-notes/rl-2505.section.md index 94e9b434d8a9..6aec88700516 100644 --- a/nixos/doc/manual/release-notes/rl-2505.section.md +++ b/nixos/doc/manual/release-notes/rl-2505.section.md @@ -131,6 +131,8 @@ - [nostr-rs-relay](https://git.sr.ht/~gheartsfield/nostr-rs-relay/), This is a nostr relay, written in Rust. Available as [services.nostr-rs-relay](options.html#opt-services.nostr-rs-relay.enable). +- [strfry](https://github.com/hoytech/strfry), a relay for the nostr protocol. Available as [services.strfry](options.html#opt-services.strfry.enable). + - [Prometheus Node Cert Exporter](https://github.com/amimof/node-cert-exporter), a prometheus exporter to check for SSL cert expiry. Available under [services.prometheus.exporters.node-cert](#opt-services.prometheus.exporters.node-cert.enable). - [Actual Budget](https://actualbudget.org/), a local-first personal finance app. Available as [services.actual](#opt-services.actual.enable). diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 9dcd3e88bfe8..82b0ef713c07 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -1582,6 +1582,7 @@ ./services/web-apps/rutorrent.nix ./services/web-apps/screego.nix ./services/web-apps/sftpgo.nix + ./services/web-apps/strfry.nix ./services/web-apps/suwayomi-server.nix ./services/web-apps/readeck.nix ./services/web-apps/rss-bridge.nix diff --git a/nixos/modules/services/web-apps/strfry.md b/nixos/modules/services/web-apps/strfry.md new file mode 100644 index 000000000000..31a751f2d8c7 --- /dev/null +++ b/nixos/modules/services/web-apps/strfry.md @@ -0,0 +1,43 @@ +# strfry {#module-services-strfry} + +strfry is a relay for the [nostr protocol](https://github.com/nostr-protocol/nostr). + +## Basic usage {#module-services-strfry-basic-usage} + +By default, the module will execute strfry: + +```nix +{ ... }: + +{ + services.strfry.enable = true; +} +``` +It runs in the systemd service named `strfry`. + +## Reverse Proxy {#module-services-strfry-reverse-proxy} + +You can configure nginx as a reverse proxy with: + +```nix +{ ... }: + +{ + security.acme = { + acceptTerms = true; + defaults.email = "foo@bar.com"; + }; + + services.nginx.enable = true; + services.nginx.virtualHosts."strfry.example.com" = { + addSSL = true; + enableACME = true; + locations."/" = { + proxyPass = "http://127.0.0.1:${toString config.services.strfry.settings.relay.port}"; + proxyWebsockets = true; # nostr uses websockets + }; + }; + + services.strfry.enable = true; +} +``` diff --git a/nixos/modules/services/web-apps/strfry.nix b/nixos/modules/services/web-apps/strfry.nix new file mode 100644 index 000000000000..84f7d5604bd4 --- /dev/null +++ b/nixos/modules/services/web-apps/strfry.nix @@ -0,0 +1,167 @@ +{ + config, + pkgs, + lib, + ... +}: +let + defaultSettings = { + db = "/var/lib/strfry"; + + dbParams = { + maxreaders = 256; + mapsize = 10995116277760; + noReadAhead = false; + }; + + events = { + maxEventSize = 65536; + rejectEventsNewerThanSeconds = 900; + rejectEventsOlderThanSeconds = 94608000; + rejectEphemeralEventsOlderThanSeconds = 60; + ephemeralEventsLifetimeSeconds = 300; + maxNumTags = 2000; + maxTagValSize = 1024; + }; + + relay = { + bind = "127.0.0.1"; + port = 7777; + nofiles = 1000000; + realIpHeader = ""; + + info = { + name = "strfry default"; + description = "This is a strfry instance."; + pubkey = ""; + contact = ""; + icon = ""; + nips = ""; + }; + + maxWebsocketPayloadSize = 131072; + maxReqFilterSize = 200; + autoPingSeconds = 55; + enableTcpKeepalive = false; + queryTimesliceBudgetMicroseconds = 10000; + maxFilterLimit = 500; + maxSubsPerConnection = 20; + + writePolicy = { + plugin = ""; + }; + + compression = { + enabled = true; + slidingWindow = true; + }; + + logging = { + dumpInAll = false; + dumpInEvents = false; + dumpInReqs = false; + dbScanPerf = false; + invalidEvents = true; + }; + + numThreads = { + ingester = 3; + reqWorker = 3; + reqMonitor = 3; + negentropy = 2; + }; + + negentropy = { + enabled = true; + maxSyncEvents = 1000000; + }; + }; + }; + + cfg = config.services.strfry; + settingsFormat = pkgs.formats.json { }; + configFile = settingsFormat.generate "config.json" cfg.settings; +in +{ + options.services.strfry = { + enable = lib.mkEnableOption "strfry"; + + package = lib.mkPackageOption pkgs "strfry" { }; + + settings = lib.mkOption { + type = settingsFormat.type; + default = defaultSettings; + apply = lib.recursiveUpdate defaultSettings; + description = "Configuration options to set for the Strfry service. See https://github.com/hoytech/strfry for documentation."; + example = lib.literalExpression '' + dbParams = { + maxreaders = 256; + mapsize = 10995116277760; + noReadAhead = false; + }; + ''; + }; + + }; + + config = lib.mkIf cfg.enable { + users.users.strfry = { + description = "Strfry daemon user"; + group = "strfry"; + isSystemUser = true; + }; + + users.groups.strfry = { }; + + systemd.services.strfry = { + description = "strfry"; + wants = [ "network.target" ]; + wantedBy = [ "multi-user.target" ]; + + serviceConfig = { + ExecStart = "${lib.getExe cfg.package} --config=${configFile} relay"; + User = "strfry"; + Group = "strfry"; + Restart = "on-failure"; + + StateDirectory = "strfry"; + WorkingDirectory = cfg.settings.db; + ReadWritePaths = [ cfg.settings.db ]; + + LimitNOFILE = cfg.settings.relay.nofiles; + + PrivateTmp = true; + PrivateUsers = true; + PrivateDevices = true; + ProtectSystem = "strict"; + ProtectHome = true; + NoNewPrivileges = true; + MemoryDenyWriteExecute = true; + ProtectKernelTunables = true; + ProtectKernelModules = true; + ProtectKernelLogs = true; + ProtectClock = true; + ProtectProc = "invisible"; + ProcSubset = "pid"; + ProtectControlGroups = true; + LockPersonality = true; + RestrictSUIDSGID = true; + RemoveIPC = true; + RestrictRealtime = true; + ProtectHostname = true; + CapabilityBoundingSet = ""; + SystemCallFilter = [ + "@system-service" + ]; + SystemCallArchitectures = "native"; + }; + }; + }; + + meta = { + doc = ./strfry.md; + maintainers = with lib.maintainers; [ + felixzieger + ]; + }; +}