From 5b9c6bcccf3937d7d5a2e3fa58b6a55facda7c9c Mon Sep 17 00:00:00 2001 From: Otto Sabart Date: Mon, 13 May 2024 21:00:00 +0200 Subject: [PATCH 1/4] joinmarket: add jmwalletd script --- pkgs/joinmarket/default.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/pkgs/joinmarket/default.nix b/pkgs/joinmarket/default.nix index 5c9a0e51c..2a5ded02f 100644 --- a/pkgs/joinmarket/default.nix +++ b/pkgs/joinmarket/default.nix @@ -44,6 +44,7 @@ stdenv.mkDerivation { cpBin yg-privacyenhanced.py cpBin genwallet.py cpBin bond-calculator.py + cpBin jmwalletd.py chmod +x -R "$out/bin" patchShebangs "$out/bin" From e6e3a961299b54c2d207d5753b7f8107be268df5 Mon Sep 17 00:00:00 2001 From: Otto Sabart Date: Mon, 13 May 2024 21:00:00 +0200 Subject: [PATCH 2/4] joinmarket: init the jmwalletd service --- modules/joinmarket-jmwalletd.nix | 163 +++++++++++++++++++++++++++++++ modules/modules.nix | 1 + modules/netns-isolation.nix | 10 +- modules/nodeinfo.nix | 1 + test/tests.nix | 5 +- test/tests.py | 11 +++ 6 files changed, 188 insertions(+), 3 deletions(-) create mode 100644 modules/joinmarket-jmwalletd.nix diff --git a/modules/joinmarket-jmwalletd.nix b/modules/joinmarket-jmwalletd.nix new file mode 100644 index 000000000..09267a3a1 --- /dev/null +++ b/modules/joinmarket-jmwalletd.nix @@ -0,0 +1,163 @@ +{ config, lib, pkgs, ... }: + +with lib; +let + options.services.joinmarket-jmwalletd = { + enable = mkEnableOption "JoinMarket jmwalletd"; + + # Unfortunately it's not possible to set the listening address for + # jmwalletd. It's used only internally. + address = mkOption { + type = types.str; + readOnly = true; + internal = true; + default = "127.0.0.1"; + description = mdDoc '' + The address where the jmwalletd listens to. + ''; + }; + port = mkOption { + type = types.port; + default = 28183; + description = mdDoc "The port over which to serve RPC."; + }; + wssPort = mkOption { + type = types.port; + default = 28283; + description = mdDoc "The port over which to serve websocket subscriptions."; + }; + extraArgs = mkOption { + type = types.separatedString " "; + default = ""; + description = mdDoc "Extra coomand line arguments passed to jmwalletd."; + }; + user = mkOption { + type = types.str; + default = "joinmarket-jmwalletd"; + description = mdDoc "The user as which to run JoinMarket jmwalletd."; + }; + group = mkOption { + type = types.str; + default = cfg.user; + description = mdDoc "The group as which to run JoinMarket jmwalletd."; + }; + dataDir = mkOption { + readOnly = true; + type = types.path; + default = config.services.joinmarket.dataDir; + description = mdDoc "The JoinMarket data directory."; + }; + sslDir = mkOption { + readOnly = true; + type = types.path; + default = "${cfg.dataDir}/ssl"; + description = mdDoc "The SSL directory for jmwalled."; + }; + certPath = mkOption { + readOnly = true; + default = "${secretsDir}/joinmarket-jmwalletd"; + description = mdDoc "JoinMarket jmwalletd TLS certificate path."; + }; + recoverSync = mkOption { + type = types.bool; + default = false; + description = mdDoc '' + Choose to do detailed wallet sync, used for recovering on new Core + instance. + ''; + }; + certificate = { + extraIPs = mkOption { + type = with types; listOf str; + default = []; + example = [ "60.100.0.1" ]; + description = mdDoc '' + Extra `subjectAltName` IPs added to the certificate. + ''; + }; + extraDomains = mkOption { + type = with types; listOf str; + default = []; + example = [ "example.com" ]; + description = mdDoc '' + Extra `subjectAltName` domain names added to the certificate. + ''; + }; + }; + }; + + cfg = config.services.joinmarket-jmwalletd; + nbLib = config.nix-bitcoin.lib; + nbPkgs = config.nix-bitcoin.pkgs; + secretsDir = config.nix-bitcoin.secretsDir; +in { + inherit options; + + config = mkIf cfg.enable (mkMerge [{ + services.joinmarket.enable = true; + + users = { + users.${cfg.user} = { + isSystemUser = true; + group = cfg.group; + home = cfg.dataDir; + # Allow access to the joinmarket dataDir. + extraGroups = [ config.services.joinmarket.group ]; + }; + groups.${cfg.group} = {}; + }; + + nix-bitcoin = { + secrets.joinmarket-jmwalletd-password.user = cfg.user; + generateSecretsCmds.joinmarket-jmwalletd-password = '' + makePasswordSecret joinmarket-jmwalletd-password + ''; + }; + } + + (mkIf cfg.enable { + nix-bitcoin = { + secrets = { + joinmarket-jmwalletd-cert.user = cfg.user; + joinmarket-jmwalletd-key.user = cfg.user; + }; + generateSecretsCmds.joinmarket-jmwalletd = '' + makeCert joinmarket-jmwalletd '${nbLib.mkCertExtraAltNames cfg.certificate}' + ''; + }; + + systemd.tmpfiles.rules = [ + "d '${cfg.sslDir}' 0770 ${cfg.user} ${cfg.group} - -" + ]; + + systemd.services.joinmarket-jmwalletd = { + wantedBy = [ "joinmarket.service" ]; + requires = [ "joinmarket.service" ]; + after = [ "joinmarket.service" "nix-bitcoin-secrets.target" ]; + preStart = '' + # Copy the certificates into a data directory under the `ssl` dir + mkdir -p '${cfg.sslDir}' + install -m600 '${cfg.certPath}-cert' '${cfg.sslDir}/cert.pem' + install -m600 '${cfg.certPath}-key' '${cfg.sslDir}/key.pem' + ''; + serviceConfig = nbLib.defaultHardening // { + WorkingDirectory = cfg.dataDir; + User = cfg.user; + ExecStart = '' + ${config.nix-bitcoin.pkgs.joinmarket}/bin/jm-jmwalletd \ + --port='${toString cfg.port}' \ + --wss-port='${toString cfg.wssPort}' \ + --datadir='${cfg.dataDir}' \ + ${optionalString (cfg.recoverSync) "--recoversync \\"} + ${cfg.extraArgs} + ''; + SyslogIdentifier = "joinmarket-jmwalletd"; + ReadWritePaths = [ cfg.dataDir ]; + Restart = "on-failure"; + RestartSec = "10s"; + MemoryDenyWriteExecute = false; + } // nbLib.allowTor; + }; + }) + ]); +} diff --git a/modules/modules.nix b/modules/modules.nix index 1b3c204d1..6c409e589 100644 --- a/modules/modules.nix +++ b/modules/modules.nix @@ -27,6 +27,7 @@ ./btcpayserver.nix ./joinmarket.nix ./joinmarket-ob-watcher.nix + ./joinmarket-jmwalletd.nix ./hardware-wallets.nix # Support features diff --git a/modules/netns-isolation.nix b/modules/netns-isolation.nix index 47b59dd62..d68b56048 100644 --- a/modules/netns-isolation.nix +++ b/modules/netns-isolation.nix @@ -345,8 +345,14 @@ in { messagingAddress = netns.joinmarket.address; cliExec = mkCliExec "joinmarket"; }; - systemd.services.joinmarket-yieldgenerator = mkIf config.services.joinmarket.yieldgenerator.enable { - serviceConfig.NetworkNamespacePath = "/var/run/netns/nb-joinmarket"; + systemd.services = { + joinmarket-yieldgenerator = mkIf config.services.joinmarket.yieldgenerator.enable { + serviceConfig.NetworkNamespacePath = "/var/run/netns/nb-joinmarket"; + }; + + joinmarket-jmwalletd = mkIf config.services.joinmarket-jmwalletd.enable { + serviceConfig.NetworkNamespacePath = "/var/run/netns/nb-joinmarket"; + }; }; services.joinmarket-ob-watcher.address = netns.joinmarket-ob-watcher.address; diff --git a/modules/nodeinfo.nix b/modules/nodeinfo.nix index bce9ff01d..a74e72e13 100644 --- a/modules/nodeinfo.nix +++ b/modules/nodeinfo.nix @@ -148,6 +148,7 @@ in { btcpayserver = mkInfo ""; liquidd = mkInfo ""; joinmarket-ob-watcher = mkInfo ""; + joinmarket-jmwalletd = mkInfo ""; rtl = mkInfo ""; mempool = mkInfo ""; mempool-frontend = name: cfg: mkInfoLong { diff --git a/test/tests.nix b/test/tests.nix index 6310cced8..f01117baf 100644 --- a/test/tests.nix +++ b/test/tests.nix @@ -128,6 +128,8 @@ let tests.joinmarket = cfg.joinmarket.enable; tests.joinmarket-yieldgenerator = cfg.joinmarket.yieldgenerator.enable; + tests.joinmarket-jmwalletd = cfg.joinmarket-jmwalletd.enable; + tests.joinmarket-ob-watcher = cfg.joinmarket-ob-watcher.enable; services.joinmarket.yieldgenerator = { enable = config.services.joinmarket.enable; @@ -138,7 +140,6 @@ let }; tests.nodeinfo = config.nix-bitcoin.nodeinfo.enable; - tests.backups = cfg.backups.enable; # To test that unused secrets are made inaccessible by 'setup-secrets' @@ -210,6 +211,7 @@ let services.btcpayserver.enable = true; services.joinmarket.enable = true; services.joinmarket-ob-watcher.enable = true; + services.joinmarket-jmwalletd.enable = true; services.backups.enable = true; nix-bitcoin.nodeinfo.enable = true; @@ -257,6 +259,7 @@ let services.fulcrum.enable = true; services.btcpayserver.enable = true; services.joinmarket.enable = true; + services.joinmarket-jmwalletd.enable = true; }; # netns and regtest, without secure-node.nix diff --git a/test/tests.py b/test/tests.py index 67cdce4fa..bbf6b23a6 100644 --- a/test/tests.py +++ b/test/tests.py @@ -281,6 +281,17 @@ def _(): assert_running("joinmarket-ob-watcher") machine.wait_until_succeeds(log_has_string("joinmarket-ob-watcher", "Starting ob-watcher")) +@test("joinmarket-jmwalletd") +def _(): + assert_running("joinmarket-jmwalletd") + machine.wait_until_succeeds(log_has_string("joinmarket-jmwalletd", "Started joinmarket-jmwalletd.service.")) + machine.wait_until_succeeds(log_has_string("joinmarket-jmwalletd", "Starting jmwalletd on port: 28183")) + wait_for_open_port(ip("joinmarket"), 28183) # RPC port + wait_for_open_port(ip("joinmarket"), 28283) # Websocket SSL port + + # Test web server response + assert_full_match(f"curl -fsSL --insecure https://{ip('joinmarket')}:28183/api/v1/getinfo | jq -jr keys[0]", "version") + @test("nodeinfo") def _(): status, _ = machine.execute("systemctl is-enabled --quiet onion-addresses 2> /dev/null") From eb964e7823c85a090960cf85283270c447e7b4f4 Mon Sep 17 00:00:00 2001 From: Otto Sabart Date: Tue, 7 May 2024 21:00:00 +0200 Subject: [PATCH 3/4] joinmarket-jam: init 0.2.0 --- pkgs/default.nix | 1 + pkgs/joinmarket-jam/default.nix | 48 +++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 pkgs/joinmarket-jam/default.nix diff --git a/pkgs/default.nix b/pkgs/default.nix index 66b92ad07..ae01913e9 100644 --- a/pkgs/default.nix +++ b/pkgs/default.nix @@ -21,6 +21,7 @@ let self = { mempool-frontend mempool-nginx-conf; trustedcoin = pkgs.callPackage ./trustedcoin { }; + joinmarket-jam = pkgs.callPackage ./joinmarket-jam { }; pyPkgs = import ./python-packages self pkgs.python3; inherit (self.pyPkgs) diff --git a/pkgs/joinmarket-jam/default.nix b/pkgs/joinmarket-jam/default.nix new file mode 100644 index 000000000..81470bef7 --- /dev/null +++ b/pkgs/joinmarket-jam/default.nix @@ -0,0 +1,48 @@ +{ lib +, buildNpmPackage +, fetchFromGitHub +, makeWrapper +}: + +buildNpmPackage rec { + pname = "jam"; + version = "0.2.0"; + + src = fetchFromGitHub { + owner = "joinmarket-webui"; + repo = pname; + rev = "v${version}"; + hash = "sha256-H5g29UJv3+B92m5Fcpa46+81992jKw1Tno2NkGQ7NRM="; + }; + + npmDepsHash = "sha256-/yBcnG6/x3aXlNOSEa/vIU970YoANYDcHWCRJJPCb+U="; + nativeBuildInputs = [ makeWrapper ]; + + buildPhase = '' + runHook preBuild + + patchShebangs node_modules + export PATH=$PWD/node_modules/.bin:$PATH + ./node_modules/.bin/react-scripts build + mkdir -p $out + + runHook postBuild + ''; + + installPhase = '' + runHook preInstall + + cp -r build/* $out + + runHook postInstall + ''; + + meta = with lib; { + description = "A web interface for JoinMarket focusing on user-friendliness and ease-of-use."; + homepage = "https://github.com/joinmarket-webui/jam"; + license = licenses.mit; + mainProgram = "jam"; + maintainers = with maintainers; [ seberm ]; + platforms = platforms.unix; + }; +} From 458b61fcc896f3c2d54bfaaf500afe4948713728 Mon Sep 17 00:00:00 2001 From: Otto Sabart Date: Wed, 8 May 2024 21:00:00 +0200 Subject: [PATCH 4/4] joinmarket-jam: init module --- README.md | 1 + docs/services.md | 10 ++ examples/configuration.nix | 7 ++ modules/joinmarket-jam.nix | 180 ++++++++++++++++++++++++++++++++++++ modules/modules.nix | 1 + modules/netns-isolation.nix | 1 + modules/nodeinfo.nix | 5 + modules/onion-services.nix | 3 + test/tests.nix | 3 + test/tests.py | 6 ++ 10 files changed, 217 insertions(+) create mode 100644 modules/joinmarket-jam.nix diff --git a/README.md b/README.md index 0d58630d3..278fc414a 100644 --- a/README.md +++ b/README.md @@ -94,6 +94,7 @@ NixOS modules ([src](modules/modules.nix)) * [liquid](https://github.com/elementsproject/elements): federated sidechain * [JoinMarket](https://github.com/joinmarket-org/joinmarket-clientserver) * [JoinMarket Orderbook Watcher](https://github.com/JoinMarket-Org/joinmarket-clientserver/blob/master/docs/orderbook.md) + * [Jam](https://github.com/joinmarket-webui/jam): simplified user-friendly JoinMarket web interface * [bitcoin-core-hwi](https://github.com/bitcoin-core/HWI) * Helper * [netns-isolation](modules/netns-isolation.nix): isolates applications on the network-level via network namespaces diff --git a/docs/services.md b/docs/services.md index f4a408dd8..96de6c31f 100644 --- a/docs/services.md +++ b/docs/services.md @@ -557,6 +557,16 @@ See [here](https://github.com/JoinMarket-Org/joinmarket-clientserver/blob/master 3. Profit +## Run the Jam, the JoinMarket web interface + +The [Jam](https://github.com/joinmarket-webui/jam) is a static web interface +which is served by nginx. It connects to the jmwalled daemon which gets started +in the background. + +TODO +- How to access the web interface using e.g. ssh proxy: `ssh -L 61851:localhost:61851 root@` +- how to access interface over onion? + # clightning ## Plugins diff --git a/examples/configuration.nix b/examples/configuration.nix index 2e45f3a59..58dd81eb2 100644 --- a/examples/configuration.nix +++ b/examples/configuration.nix @@ -249,6 +249,13 @@ # # Set this to enable the JoinMarket order book watcher. # services.joinmarket-ob-watcher.enable = true; + # + # Set this to enable Jam, the JoinMarket web interface. + # services.joinmarket-jam.enable = true; + # + # Set this to create an onion service to make the Jam web interface + # available via Tor: + # nix-bitcoin.onionServices.joinmarket-jam.enable = true; ### Nodeinfo # Set this to add command `nodeinfo` to the system environment. diff --git a/modules/joinmarket-jam.nix b/modules/joinmarket-jam.nix new file mode 100644 index 000000000..7218465a3 --- /dev/null +++ b/modules/joinmarket-jam.nix @@ -0,0 +1,180 @@ +{ config, lib, pkgs, ... }: + +with lib; +let + options.services.joinmarket-jam = { + enable = mkEnableOption "Enable the JoinMarket Jam web interface."; + address = mkOption { + type = types.str; + default = "127.0.0.1"; + description = mdDoc "HTTP server address."; + }; + port = mkOption { + type = types.port; + default = 61851; + description = mdDoc "HTTP server port."; + }; + staticContentRoot = mkOption { + type = types.path; + default = nbPkgs.joinmarket-jam; + defaultText = "config.nix-bitcoin.pkgs.joinmarket-jam"; + description = mdDoc "Path of the static content root."; + }; + nginxConfig = mkOption { + readOnly = true; + default = nginxConfig; + defaultText = "(See source)"; + description = mdDoc '' + An attrset of nginx config snippets for assembling a custom + joinmarket's jam nginx config. + ''; + }; + package = mkOption { + type = types.package; + default = nbPkgs.joinmarket-jam; + defaultText = "config.nix-bitcoin.pkgs.joinmarket-jam"; + description = mdDoc "The package providing joinmarket's jam files."; + }; + user = mkOption { + type = types.str; + default = "joinmarket-jam"; + description = mdDoc "The user as which to run Jam."; + }; + group = mkOption { + type = types.str; + default = cfg.user; + description = mdDoc "The group as which to run Jam."; + }; + tor.enforce = nbLib.tor.enforce; + + #settings = mkOption { + #}; + }; + + cfg = config.services.joinmarket-jam; + nbLib = config.nix-bitcoin.lib; + nbPkgs = config.nix-bitcoin.pkgs; + + inherit (config.services) joinmarket-ob-watcher joinmarket-jmwalletd; + + # Nginx configuration is highgly inspired by official jam-docker ui-only container. + # https://github.com/joinmarket-webui/jam-docker/tree/master/ui-only/nginx + nginxConfig = { + staticContent = '' + index index.html; + + add_header Cache-Control "public, no-transform"; + add_header Vary Accept-Language; + add_header Vary Cookie; + ''; + + proxyApi = let + jmwalletd_api_backend = "https://${nbLib.addressWithPort joinmarket-jmwalletd.address joinmarket-jmwalletd.port}"; + jmwalletd_wss_backend = "https://${nbLib.addressWithPort joinmarket-jmwalletd.address joinmarket-jmwalletd.wssPort}/"; + ob_watcher_backend = "http://${nbLib.addressWithPort joinmarket-ob-watcher.address joinmarket-ob-watcher.port}"; + in '' + location / { + #include /etc/nginx/snippets/proxy-params.conf; + + try_files $uri $uri/ /index.html; + add_header Cache-Control no-cache; + } + location /api/ { + proxy_pass ${jmwalletd_api_backend}; + + #include /etc/nginx/snippets/proxy-params.conf; + + proxy_http_version 1.1; + proxy_set_header Connection ""; + proxy_set_header Authorization $http_x_jm_authorization; + proxy_set_header x-jm-authorization ""; + proxy_read_timeout 300s; + proxy_connect_timeout 300s; + } + location = /jmws { + proxy_pass ${jmwalletd_wss_backend}; + + #include /etc/nginx/snippets/proxy-params.conf; + + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "Upgrade"; + proxy_set_header Authorization ""; + + # allow 10m without socket activity (default is 60 sec) + proxy_read_timeout 600s; + proxy_send_timeout 600s; + } + location /obwatch/ { + proxy_pass ${ob_watcher_backend}; + + #include /etc/nginx/snippets/proxy-params.conf; + + proxy_http_version 1.1; + proxy_set_header Connection ""; + proxy_read_timeout 300s; + proxy_connect_timeout 300s; + } + location = /jam/internal/auth { + internal; + proxy_pass http://$server_addr:$server_port/api/v1/session; + + #if ($jm_auth_present != 1) { + # return 401; + #} + + #include /etc/nginx/snippets/proxy-params.conf; + + proxy_http_version 1.1; + proxy_set_header Connection ""; + proxy_pass_request_body off; + proxy_set_header Content-Length ""; + } + location = /jam/api/v0/features { + auth_request /jam/internal/auth; + default_type application/json; + return 200 '{ "features": { "logs": false } }'; + } + location /jam/api/v0/log/ { + auth_request /jam/internal/auth; + return 501; # Not Implemented + } + ''; + }; + +in { + inherit options; + + config = mkIf cfg.enable { + services = { + joinmarket-ob-watcher.enable = true; + joinmarket-jmwalletd.enable = true; + + nginx = { + enable = true; + enableReload = true; + recommendedBrotliSettings = true; + recommendedGzipSettings = true; + recommendedOptimisation = true; + recommendedProxySettings = true; + recommendedTlsSettings = true; + # TODO: Use this to define "map"? See: https://github.com/joinmarket-webui/jam-docker/blob/master/ui-only/nginx/templates/default.conf.template#L20 + #commonHttpConfig = nginxConfig.httpConfig; + virtualHosts."joinmarket-jam" = { + serverName = "_"; + listen = [ { addr = cfg.address; port = cfg.port; } ]; + root = cfg.staticContentRoot; + extraConfig = nginxConfig.staticContent + nginxConfig.proxyApi; + }; + }; + }; + + users = { + users.${cfg.user} = { + isSystemUser = true; + group = cfg.group; + }; + groups.${cfg.group} = {}; + }; + }; +} diff --git a/modules/modules.nix b/modules/modules.nix index 6c409e589..95b6cb9f6 100644 --- a/modules/modules.nix +++ b/modules/modules.nix @@ -28,6 +28,7 @@ ./joinmarket.nix ./joinmarket-ob-watcher.nix ./joinmarket-jmwalletd.nix + ./joinmarket-jam.nix ./hardware-wallets.nix # Support features diff --git a/modules/netns-isolation.nix b/modules/netns-isolation.nix index d68b56048..d532a8635 100644 --- a/modules/netns-isolation.nix +++ b/modules/netns-isolation.nix @@ -356,6 +356,7 @@ in { }; services.joinmarket-ob-watcher.address = netns.joinmarket-ob-watcher.address; + services.joinmarket-jam.address = netns.nginx.address; services.lightning-pool.rpcAddress = netns.lightning-pool.address; diff --git a/modules/nodeinfo.nix b/modules/nodeinfo.nix index a74e72e13..d86d89cb8 100644 --- a/modules/nodeinfo.nix +++ b/modules/nodeinfo.nix @@ -149,6 +149,11 @@ in { liquidd = mkInfo ""; joinmarket-ob-watcher = mkInfo ""; joinmarket-jmwalletd = mkInfo ""; + joinmarket-jam = name: cfg: mkInfoLong { + inherit name cfg; + systemdServiceName = "nginx"; + extraCode = ""; + }; rtl = mkInfo ""; mempool = mkInfo ""; mempool-frontend = name: cfg: mkInfoLong { diff --git a/modules/onion-services.nix b/modules/onion-services.nix index 716ebb519..f4d2c376f 100644 --- a/modules/onion-services.nix +++ b/modules/onion-services.nix @@ -110,6 +110,9 @@ in { joinmarket-ob-watcher = { externalPort = 80; }; + joinmarket-jam = { + externalPort = 80; + }; rtl = { externalPort = 80; }; diff --git a/test/tests.nix b/test/tests.nix index f01117baf..ee411b359 100644 --- a/test/tests.nix +++ b/test/tests.nix @@ -138,6 +138,7 @@ let cjfee_a = 300; cjfee_r = 0.00003; }; + tests.joinmarket-jam = cfg.joinmarket-jam.enable; tests.nodeinfo = config.nix-bitcoin.nodeinfo.enable; tests.backups = cfg.backups.enable; @@ -212,6 +213,7 @@ let services.joinmarket.enable = true; services.joinmarket-ob-watcher.enable = true; services.joinmarket-jmwalletd.enable = true; + services.joinmarket-jam.enable = true; services.backups.enable = true; nix-bitcoin.nodeinfo.enable = true; @@ -260,6 +262,7 @@ let services.btcpayserver.enable = true; services.joinmarket.enable = true; services.joinmarket-jmwalletd.enable = true; + services.joinmarket-jam.enable = true; }; # netns and regtest, without secure-node.nix diff --git a/test/tests.py b/test/tests.py index bbf6b23a6..2cf2b8a97 100644 --- a/test/tests.py +++ b/test/tests.py @@ -292,6 +292,12 @@ def _(): # Test web server response assert_full_match(f"curl -fsSL --insecure https://{ip('joinmarket')}:28183/api/v1/getinfo | jq -jr keys[0]", "version") +@test("joinmarket-jam") +def _(): + assert_running("nginx") + wait_for_open_port(ip("nginx"), 61851) + assert_matches(f"curl -L {ip('nginx')}:61851", "Jam for JoinMarket") + @test("nodeinfo") def _(): status, _ = machine.execute("systemctl is-enabled --quiet onion-addresses 2> /dev/null")