fedimint: 0.5.1 -> 0.7.1

0.7 release of Fedimint includes deployment changes. Notably:

* Experimental Iroh p2p connectivity support (uses UDP)
* built-in admin UI
This commit is contained in:
Dawid Ciężarkiewicz 2025-04-11 08:43:15 -07:00
parent 7f8424d862
commit c0f52c28cd
3 changed files with 103 additions and 33 deletions

View File

@ -49,36 +49,36 @@ let
openFirewall = mkOption { openFirewall = mkOption {
type = types.bool; type = types.bool;
default = true; default = true;
description = "Opens port in firewall for fedimintd's p2p port"; description = "Opens port in firewall for fedimintd's p2p port (both TCP and UDP)";
}; };
port = mkOption { port = mkOption {
type = types.port; type = types.port;
default = 8173; default = 8173;
description = "Port to bind on for p2p connections from peers"; description = "Port to bind on for p2p connections from peers (both TCP and UDP)";
}; };
bind = mkOption { bind = mkOption {
type = types.str; type = types.str;
default = "0.0.0.0"; default = "0.0.0.0";
description = "Address to bind on for p2p connections from peers"; description = "Address to bind on for p2p connections from peers (both TCP and UDP)";
}; };
url = mkOption { url = mkOption {
type = types.str; type = types.nullOr types.str;
example = "fedimint://p2p.myfedimint.com:8173"; example = "fedimint://p2p.myfedimint.com:8173";
description = '' description = ''
Public address for p2p connections from peers Public address for p2p connections from peers (if TCP is used)
''; '';
}; };
}; };
api = { api_ws = {
openFirewall = mkOption { openFirewall = mkOption {
type = types.bool; type = types.bool;
default = false; default = false;
description = "Opens port in firewall for fedimintd's api port"; description = "Opens TCP port in firewall for fedimintd's Websocket API";
}; };
port = mkOption { port = mkOption {
type = types.port; type = types.port;
default = 8174; default = 8174;
description = "Port to bind on for API connections relied by the reverse proxy/tls terminator."; description = "TCP Port to bind on for API connections relayed by the reverse proxy/tls terminator.";
}; };
bind = mkOption { bind = mkOption {
type = types.str; type = types.str;
@ -86,12 +86,46 @@ let
description = "Address to bind on for API connections relied by the reverse proxy/tls terminator."; description = "Address to bind on for API connections relied by the reverse proxy/tls terminator.";
}; };
url = mkOption { url = mkOption {
type = types.str; type = types.nullOr types.str;
description = '' description = ''
Public URL of the API address of the reverse proxy/tls terminator. Usually starting with `wss://`. Public URL of the API address of the reverse proxy/tls terminator. Usually starting with `wss://`.
''; '';
}; };
}; };
api_iroh = {
openFirewall = mkOption {
type = types.bool;
default = true;
description = "Opens UDP port in firewall for fedimintd's API Iroh endpoint";
};
port = mkOption {
type = types.port;
default = 8174;
description = "UDP Port to bind Iroh endpoint for API connections";
};
bind = mkOption {
type = types.str;
default = "0.0.0.0";
description = "Address to bind on for Iroh endpoint for API connections";
};
};
ui = {
openFirewall = mkOption {
type = types.bool;
default = false;
description = "Opens TCP port in firewall for built-in UI";
};
port = mkOption {
type = types.port;
default = 8175;
description = "TCP Port to bind on for UI connections";
};
bind = mkOption {
type = types.str;
default = "127.0.0.1";
description = "Address to bind on for UI connections";
};
};
bitcoin = { bitcoin = {
network = mkOption { network = mkOption {
type = types.str; type = types.str;
@ -159,7 +193,13 @@ let
example = "api.myfedimint.com"; example = "api.myfedimint.com";
description = "Public domain of the API address of the reverse proxy/tls terminator."; description = "Public domain of the API address of the reverse proxy/tls terminator.";
}; };
path = mkOption { path_ui = mkOption {
type = types.str;
example = "/";
default = "/";
description = "Path to host the built-in UI on and forward to the daemon's api port";
};
path_ws = mkOption {
type = types.str; type = types.str;
example = "/"; example = "/";
default = "/ws/"; default = "/ws/";
@ -197,7 +237,21 @@ in
networking.firewall.allowedTCPPorts = concatLists ( networking.firewall.allowedTCPPorts = concatLists (
mapAttrsToList ( mapAttrsToList (
fedimintdName: cfg: fedimintdName: cfg:
(lib.optional cfg.api.openFirewall cfg.api.port ++ lib.optional cfg.p2p.openFirewall cfg.p2p.port) (
lib.optional cfg.api_ws.openFirewall cfg.api_ws.port
++ lib.optional cfg.p2p.openFirewall cfg.p2p.port
++ lib.optional cfg.ui.openFirewall cfg.ui.port
)
) eachFedimintd
);
networking.firewall.allowedUDPPorts = concatLists (
mapAttrsToList (
fedimintdName: cfg:
(
lib.optional cfg.api_iroh.openFirewall cfg.api_iroh.port
++ lib.optional cfg.p2p.openFirewall cfg.p2p.port
)
) eachFedimintd ) eachFedimintd
); );
@ -205,14 +259,13 @@ in
fedimintdName: cfg: fedimintdName: cfg:
(nameValuePair "fedimintd-${fedimintdName}" ( (nameValuePair "fedimintd-${fedimintdName}" (
let let
startScript = pkgs.writeShellScript "fedimintd-start" ( startScript = pkgs.writeShellScriptBin "fedimintd" (
( (
if cfg.bitcoin.rpc.secretFile != null then if cfg.bitcoin.rpc.secretFile != null then
'' ''
secret=$(${pkgs.coreutils}/bin/head -n 1 "${cfg.bitcoin.rpc.secretFile}") >&2 echo "Setting FM_FORCE_BITCOIN_RPC_URL using password from ${cfg.bitcoin.rpc.secretFile}"
prefix="''${FM_BITCOIN_RPC_URL%*@*}" # Everything before the last '@' secret=$(${pkgs.coreutils}/bin/head -n 1 "${cfg.bitcoin.rpc.secretFile}" || exit 1)
suffix="''${FM_BITCOIN_RPC_URL##*@}" # Everything after the last '@' export FM_FORCE_BITCOIN_RPC_URL=$(echo "$FM_BITCOIN_RPC_URL" | sed "s|^\(\w\+://[^@]\+\)\(@.*\)|\1:''${secret}\2|")
FM_BITCOIN_RPC_URL="''${prefix}:''${secret}@''${suffix}"
'' ''
else else
"" ""
@ -229,14 +282,23 @@ in
environment = lib.mkMerge [ environment = lib.mkMerge [
{ {
FM_BIND_P2P = "${cfg.p2p.bind}:${toString cfg.p2p.port}"; FM_BIND_P2P = "${cfg.p2p.bind}:${toString cfg.p2p.port}";
FM_BIND_API = "${cfg.api.bind}:${toString cfg.api.port}"; FM_BIND_API_WS = "${cfg.api_ws.bind}:${toString cfg.api_ws.port}";
FM_P2P_URL = cfg.p2p.url; FM_BIND_API_IROH = "${cfg.api_iroh.bind}:${toString cfg.api_iroh.port}";
FM_API_URL = cfg.api.url; FM_BIND_UI = "${cfg.ui.bind}:${toString cfg.ui.port}";
FM_DATA_DIR = cfg.dataDir; FM_DATA_DIR = cfg.dataDir;
FM_BITCOIN_NETWORK = cfg.bitcoin.network; FM_BITCOIN_NETWORK = cfg.bitcoin.network;
FM_BITCOIN_RPC_URL = cfg.bitcoin.rpc.url; FM_BITCOIN_RPC_URL = cfg.bitcoin.rpc.url;
FM_BITCOIN_RPC_KIND = cfg.bitcoin.rpc.kind; FM_BITCOIN_RPC_KIND = cfg.bitcoin.rpc.kind;
} }
(lib.optionalAttrs (cfg.p2p.url != null) {
FM_P2P_URL = cfg.p2p.url;
})
(lib.optionalAttrs (cfg.api_ws.url != null) {
FM_API_URL = cfg.api_ws.url;
})
cfg.environment cfg.environment
]; ];
serviceConfig = { serviceConfig = {
@ -244,7 +306,7 @@ in
StateDirectory = "fedimintd-${fedimintdName}"; StateDirectory = "fedimintd-${fedimintdName}";
StateDirectoryMode = "0700"; StateDirectoryMode = "0700";
ExecStart = startScript; ExecStart = "${startScript}/bin/fedimintd";
Restart = "always"; Restart = "always";
RestartSec = 10; RestartSec = 10;
@ -268,9 +330,11 @@ in
RestrictAddressFamilies = [ RestrictAddressFamilies = [
"AF_INET" "AF_INET"
"AF_INET6" "AF_INET6"
"AF_NETLINK"
]; ];
RestrictNamespaces = true; RestrictNamespaces = true;
RestrictRealtime = true; RestrictRealtime = true;
SocketBindAllow = "udp:${builtins.toString cfg.api_iroh.port}";
SystemCallArchitectures = "native"; SystemCallArchitectures = "native";
SystemCallFilter = [ SystemCallFilter = [
"@system-service" "@system-service"
@ -289,16 +353,22 @@ in
{ {
# Note: we want by default to enable OpenSSL, but it seems anything 100 and above is # Note: we want by default to enable OpenSSL, but it seems anything 100 and above is
# overriden by default value from vhost-options.nix # overridden by default value from vhost-options.nix
enableACME = mkOverride 99 true; enableACME = mkOverride 99 true;
forceSSL = mkOverride 99 true; forceSSL = mkOverride 99 true;
locations.${cfg.nginx.path} = { locations.${cfg.nginx.path_ws} = {
proxyPass = "http://127.0.0.1:${toString cfg.api.port}/"; proxyPass = "http://127.0.0.1:${builtins.toString cfg.api_ws.port}/";
proxyWebsockets = true; proxyWebsockets = true;
extraConfig = '' extraConfig = ''
proxy_pass_header Authorization; proxy_pass_header Authorization;
''; '';
}; };
locations.${cfg.nginx.path_ui} = {
proxyPass = "http://127.0.0.1:${builtins.toString cfg.ui.port}/";
extraConfig = ''
proxy_pass_header Authorization;
'';
};
} }
] ]
)) ))

View File

@ -17,12 +17,10 @@
p2p = { p2p = {
url = "fedimint://example.com"; url = "fedimint://example.com";
}; };
api = { api_ws = {
url = "wss://example.com"; url = "wss://example.com";
}; };
environment = { environment = { };
"FM_REL_NOTES_ACK" = "0_4_xyz";
};
}; };
}; };
@ -32,6 +30,6 @@
start_all() start_all()
machine.wait_for_unit("fedimintd-mainnet.service") machine.wait_for_unit("fedimintd-mainnet.service")
machine.wait_for_open_port(${toString nodes.machine.services.fedimintd.mainnet.api.port}) machine.wait_for_open_port(${toString nodes.machine.services.fedimintd.mainnet.api_ws.port})
''; '';
} }

View File

@ -6,21 +6,24 @@
pkg-config, pkg-config,
protobuf, protobuf,
rustPlatform, rustPlatform,
version ? "0.7.1",
hash ? "sha256-7meBYUN7sG1OAtMEm6I66+ptf4EfsbA+dm5/4P3IRV4=",
cargoHash ? "sha256-4cFuasH2hvrnzTBTFifHEMtXZKsBv7OVpuwPlV19GGw=",
}: }:
rustPlatform.buildRustPackage rec { rustPlatform.buildRustPackage rec {
pname = "fedimint"; pname = "fedimint";
version = "0.5.1"; inherit version;
src = fetchFromGitHub { src = fetchFromGitHub {
owner = "fedimint"; owner = "fedimint";
repo = "fedimint"; repo = "fedimint";
rev = "v${version}"; rev = "v${version}";
hash = "sha256-dhZYOfXepOnt1lQEgrM/y++5V58weiiTMAyMKl2t37Q="; inherit hash;
}; };
useFetchCargoVendor = true; useFetchCargoVendor = true;
cargoHash = "sha256-WElH4AdLlF/BuxRrURUv6xNGUVBZ6hhSFg1p+T3jG54="; inherit cargoHash;
nativeBuildInputs = [ nativeBuildInputs = [
protobuf protobuf
@ -45,7 +48,7 @@ rustPlatform.buildRustPackage rec {
mkdir -p $fedimint/bin $fedimintCli/bin $gateway/bin $gatewayCli/bin $devimint/bin mkdir -p $fedimint/bin $fedimintCli/bin $gateway/bin $gatewayCli/bin $devimint/bin
# delete fuzzing targets and other binaries no one cares about # delete fuzzing targets and other binaries no one cares about
binsToKeep=(fedimint-cli fedimint-dbtool recoverytool fedimintd gatewayd gateway-cli gateway-cln-extension devimint) binsToKeep=(fedimint-cli fedimint-dbtool recoverytool fedimintd gatewayd gateway-cli devimint)
keepPattern=$(printf "|%s" "''${binsToKeep[@]}") keepPattern=$(printf "|%s" "''${binsToKeep[@]}")
keepPattern=''${keepPattern:1} keepPattern=''${keepPattern:1}
find "$out/bin" -maxdepth 1 -type f | grep -Ev "(''${keepPattern})" | xargs rm -f find "$out/bin" -maxdepth 1 -type f | grep -Ev "(''${keepPattern})" | xargs rm -f
@ -59,7 +62,6 @@ rustPlatform.buildRustPackage rec {
cp -a $releaseDir/gateway-cli $gatewayCli/bin/ cp -a $releaseDir/gateway-cli $gatewayCli/bin/
cp -a $releaseDir/gatewayd $gateway/bin/ cp -a $releaseDir/gatewayd $gateway/bin/
cp -a $releaseDir/gateway-cln-extension $gateway/bin/
cp -a $releaseDir/devimint $devimint/bin/ cp -a $releaseDir/devimint $devimint/bin/
''; '';