Commit dfd82bf3 authored by Felix Zieger's avatar Felix Zieger
Browse files

nixos/strfry: init

parent e6b51c91
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -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"
  ],
+2 −0
Original line number Diff line number Diff line
@@ -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).
+1 −0
Original line number Diff line number Diff line
@@ -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
+43 −0
Original line number Diff line number Diff line
# 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;
}
```
+167 −0
Original line number Diff line number Diff line
{
  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
    ];
  };
}