Skip to content

Commit

Permalink
nixos/haven: init
Browse files Browse the repository at this point in the history
  • Loading branch information
felixzieger committed Feb 21, 2025
1 parent 488b08f commit 0609c19
Show file tree
Hide file tree
Showing 3 changed files with 246 additions and 0 deletions.
2 changes: 2 additions & 0 deletions nixos/doc/manual/release-notes/rl-2505.section.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,8 @@

- [victorialogs][https://docs.victoriametrics.com/victorialogs/], log database from VictoriaMetrics. Available as [services.victorialogs](#opt-services.victorialogs.enable)

- [haven](https://github.com/bitvora/haven), is a high availability vault for events on nostr. Available as [services.haven](options.html#opt-services.haven.enable).

- [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).

- [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).
Expand Down
1 change: 1 addition & 0 deletions nixos/modules/module-list.nix
Original file line number Diff line number Diff line change
Expand Up @@ -1504,6 +1504,7 @@
./services/web-apps/guacamole-client.nix
./services/web-apps/guacamole-server.nix
./services/web-apps/hatsu.nix
./services/web-apps/haven.nix
./services/web-apps/healthchecks.nix
./services/web-apps/hedgedoc.nix
./services/web-apps/hledger-web.nix
Expand Down
243 changes: 243 additions & 0 deletions nixos/modules/services/web-apps/haven.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,243 @@
{
config,
pkgs,
lib,
...
}:
let
cfg = config.services.haven;
in
{
options.services.haven = {
enable = lib.mkEnableOption "haven";

package = lib.mkPackageOption pkgs "haven" { };

port = lib.mkOption {
default = 3355;
type = lib.types.port;
description = "Listen on this port.";
};

relayUrl = lib.mkOption {
type = lib.types.str;
description = "The URL of the relay.";
};

ownerNpub = lib.mkOption {
type = lib.types.str;
description = "The NPUB of the owner.";
};

ownerName = lib.mkOption {
type = lib.types.str;
description = "The name of the owner. Used for relay names and descriptions.";
default = "a nostrich";
};

blastrRelays = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
description = "List of relay configurations for blastr";
example = lib.literalExpression ''
[
"relay.example.com"
]
'';
};

importRelays = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
description = "List of relay configurations for importing historical events";
example = lib.literalExpression ''
[
"relay.example.com"
]
'';
};

settings = lib.mkOption {
type = lib.types.attrsOf lib.types.str;
default = { };
description = "Additional environment variables to set for the Haven service. See https://github.com/bitvora/haven for documentation.";
example = lib.literalExpression ''
{
PRIVATE_RELAY_NAME = "My Custom Relay Name";
BACKUP_PROVIDER = "s3";
}
'';
};

environmentFile = lib.mkOption {
type = lib.types.nullOr lib.types.path;
default = null;
description = ''
Path to a file containing sensitive environment variables. See https://github.com/bitvora/haven for documentation.
The file should contain environment-variable assignments like:
S3_SECRET_KEY=mysecretkey
S3_ACCESS_KEY_ID=myaccesskey
'';
example = "/var/lib/haven/secrets.env";
};
};

config = lib.mkIf cfg.enable {
users.users.haven = {
description = "Haven daemon user";
group = "haven";
isSystemUser = true;
};

users.groups.haven = { };

systemd.services.haven = {
description = "haven";
wants = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
environment = {
OWNER_NPUB = cfg.ownerNpub;
RELAY_URL = cfg.relayUrl;
RELAY_PORT = toString cfg.port;
RELAY_BIND_ADDRESS = "0.0.0.0"; # Can be set to a specific IP4 or IP6 address ("" for all interfaces)
DB_ENGINE = "badger"; # badger, lmdb (lmdb works best with an nvme, otherwise you might have stability issues)
LMDB_MAPSIZE = toString 0; # 0 for default (currently ~273GB), or set to a different size in bytes, e.g. 10737418240 for 10GB
BLOSSOM_PATH = "blossom/";

## Private Relay Settings
PRIVATE_RELAY_NAME = " ${cfg.ownerName}'s private relay";
PRIVATE_RELAY_NPUB = cfg.ownerNpub;
PRIVATE_RELAY_DESCRIPTION = "A safe place to store my drafts and ecash";
PRIVATE_RELAY_ICON = "https://i.nostr.build/6G6wW.gif";

## Private Relay Rate Limiters
PRIVATE_RELAY_EVENT_IP_LIMITER_TOKENS_PER_INTERVAL = toString 50;
PRIVATE_RELAY_EVENT_IP_LIMITER_INTERVAL = toString 1;
PRIVATE_RELAY_EVENT_IP_LIMITER_MAX_TOKENS = toString 100;
PRIVATE_RELAY_ALLOW_EMPTY_FILTERS = "true";
PRIVATE_RELAY_ALLOW_COMPLEX_FILTERS = "true";
PRIVATE_RELAY_CONNECTION_RATE_LIMITER_TOKENS_PER_INTERVAL = toString 3;
PRIVATE_RELAY_CONNECTION_RATE_LIMITER_INTERVAL = toString 5;
PRIVATE_RELAY_CONNECTION_RATE_LIMITER_MAX_TOKENS = toString 9;

## Chat Relay Settings
CHAT_RELAY_NAME = " ${cfg.ownerName}'s chat relay";
CHAT_RELAY_NPUB = cfg.ownerNpub;
CHAT_RELAY_DESCRIPTION = "a relay for private chats";
CHAT_RELAY_ICON = "https://i.nostr.build/6G6wW.gif";
CHAT_RELAY_WOT_DEPTH = toString 3;
CHAT_RELAY_WOT_REFRESH_INTERVAL_HOURS = toString 24;
CHAT_RELAY_MINIMUM_FOLLOWERS = toString 3;

## Chat Relay Rate Limiters
CHAT_RELAY_EVENT_IP_LIMITER_TOKENS_PER_INTERVAL = toString 50;
CHAT_RELAY_EVENT_IP_LIMITER_INTERVAL = toString 1;
CHAT_RELAY_EVENT_IP_LIMITER_MAX_TOKENS = toString 100;
CHAT_RELAY_ALLOW_EMPTY_FILTERS = "false";
CHAT_RELAY_ALLOW_COMPLEX_FILTERS = "false";
CHAT_RELAY_CONNECTION_RATE_LIMITER_TOKENS_PER_INTERVAL = toString 3;
CHAT_RELAY_CONNECTION_RATE_LIMITER_INTERVAL = toString 3;
CHAT_RELAY_CONNECTION_RATE_LIMITER_MAX_TOKENS = toString 9;

## Outbox Relay Settings
OUTBOX_RELAY_NAME = " ${cfg.ownerName}'s outbox relay";
OUTBOX_RELAY_NPUB = cfg.ownerNpub;
OUTBOX_RELAY_DESCRIPTION = "a relay and Blossom server for public messages and media";
OUTBOX_RELAY_ICON = "https://i.nostr.build/6G6wW.gif";

## Outbox Relay Rate Limiters
OUTBOX_RELAY_EVENT_IP_LIMITER_TOKENS_PER_INTERVAL = toString 10;
OUTBOX_RELAY_EVENT_IP_LIMITER_INTERVAL = toString 60;
OUTBOX_RELAY_EVENT_IP_LIMITER_MAX_TOKENS = toString 100;
OUTBOX_RELAY_ALLOW_EMPTY_FILTERS = "false";
OUTBOX_RELAY_ALLOW_COMPLEX_FILTERS = "false";
OUTBOX_RELAY_CONNECTION_RATE_LIMITER_TOKENS_PER_INTERVAL = toString 3;
OUTBOX_RELAY_CONNECTION_RATE_LIMITER_INTERVAL = toString 1;
OUTBOX_RELAY_CONNECTION_RATE_LIMITER_MAX_TOKENS = toString 9;

## Inbox Relay Settings
INBOX_RELAY_NAME = " ${cfg.ownerName}'s inbox relay";
INBOX_RELAY_NPUB = cfg.ownerNpub;
INBOX_RELAY_DESCRIPTION = "send your interactions with my notes here";
INBOX_RELAY_ICON = "https://i.nostr.build/6G6wW.gif";
INBOX_PULL_INTERVAL_SECONDS = toString 600;

## Inbox Relay Rate Limiters
INBOX_RELAY_EVENT_IP_LIMITER_TOKENS_PER_INTERVAL = toString 10;
INBOX_RELAY_EVENT_IP_LIMITER_INTERVAL = toString 1;
INBOX_RELAY_EVENT_IP_LIMITER_MAX_TOKENS = toString 20;
INBOX_RELAY_ALLOW_EMPTY_FILTERS = "false";
INBOX_RELAY_ALLOW_COMPLEX_FILTERS = "false";
INBOX_RELAY_CONNECTION_RATE_LIMITER_TOKENS_PER_INTERVAL = toString 3;
INBOX_RELAY_CONNECTION_RATE_LIMITER_INTERVAL = toString 1;
INBOX_RELAY_CONNECTION_RATE_LIMITER_MAX_TOKENS = toString 9;

## Import Settings
IMPORT_START_DATE = "2025-01-01";
IMPORT_QUERY_INTERVAL_SECONDS = toString 600;
IMPORT_SEED_RELAYS_FILE = "${pkgs.writeText "relays_import.json" (
builtins.toJSON cfg.importRelays
)}";

## Backup Settings
BACKUP_PROVIDER = "none"; # s3, none (or leave blank to disable)
BACKUP_INTERVAL_HOURS = toString 1;

## Generic S3 Bucket Backup Settings - REQUIRED IF BACKUP_PROVIDER="s3"
S3_ACCESS_KEY_ID = "access";
S3_SECRET_KEY = "secret";
S3_ENDPOINT = "nyc3.digitaloceanspaces.com";
S3_REGION = "nyc3";
S3_BUCKET_NAME = "backups";

## Blastr Settings
BLASTR_RELAYS_FILE = "${pkgs.writeText "relays_blastr.json" (builtins.toJSON cfg.blastrRelays)}";
} // cfg.settings;

serviceConfig = {
ExecStart = "${cfg.package}/bin/haven";
EnvironmentFile = lib.mkIf (cfg.environmentFile != null) cfg.environmentFile;
User = "haven";
Group = "haven";
Restart = "on-failure";
Type = "simple";

RuntimeDirectory = "haven";
StateDirectory = "haven";
WorkingDirectory = "/var/lib/haven";

# Create symlink to templates in the working directory
ExecStartPre = "+${pkgs.coreutils}/bin/ln -sfT ${cfg.package}/share/haven/templates /var/lib/haven/templates";

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.maintainers = with lib.maintainers; [
felixzieger
];
}

0 comments on commit 0609c19

Please sign in to comment.