diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 5335ba3abd18..79c72fc14224 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -609,6 +609,7 @@ ./services/networking/iodine.nix ./services/networking/iperf3.nix ./services/networking/ircd-hybrid/default.nix + ./services/networking/jormungandr.nix ./services/networking/iwd.nix ./services/networking/keepalived/default.nix ./services/networking/keybase.nix diff --git a/nixos/modules/services/networking/jormungandr.nix b/nixos/modules/services/networking/jormungandr.nix new file mode 100644 index 000000000000..c1a16a316b7a --- /dev/null +++ b/nixos/modules/services/networking/jormungandr.nix @@ -0,0 +1,97 @@ +{ config, lib, pkgs, ... }: + +let + cfg = config.services.jormungandr; + + inherit (lib) mkEnableOption mkIf mkOption; + inherit (lib) optionalString types; + + dataDir = "/var/lib/jormungandr"; + + # Default settings so far, as the service matures we will + # move these out as separate settings + configSettings = { + storage = dataDir; + p2p = { + public_address = "/ip4/127.0.0.1/tcp/8606"; + messages = "high"; + blocks = "high"; + }; + rest = { + listen = "127.0.0.1:8607"; + }; + }; + + configFile = if cfg.configFile == null then + pkgs.writeText "jormungandr.yaml" (builtins.toJSON configSettings) + else cfg.configFile; + +in { + + options = { + + services.jormungandr = { + enable = mkEnableOption "jormungandr service"; + + configFile = mkOption { + type = types.nullOr types.path; + default = null; + example = "/var/lib/jormungandr/node.yaml"; + description = '' + The path of the jormungandr blockchain configuration file in YAML format. + If no file is specified, a file is generated using the other options. + ''; + }; + + secretFile = mkOption { + type = types.nullOr types.path; + default = null; + example = "/etc/secret/jormungandr.yaml"; + description = '' + The path of the jormungandr blockchain secret node configuration file in + YAML format. Do not store this in nix store! + ''; + }; + + genesisBlockHash = mkOption { + type = types.nullOr types.string; + default = null; + example = "d70495af81ae8600aca3e642b2427327cb6001ec4d7a0037e96a00dabed163f9"; + description = '' + Set the genesis block hash (the hash of the block0) so we can retrieve + the genesis block (and the blockchain configuration) from the existing + storage or from the network. + ''; + }; + + genesisBlockFile = mkOption { + type = types.nullOr types.path; + default = null; + example = "/var/lib/jormungandr/block-0.bin"; + description = '' + The path of the genesis block file if we are hosting it locally. + ''; + }; + + }; + }; + + config = mkIf cfg.enable { + + systemd.services.jormungandr = { + description = "jormungandr server"; + wantedBy = [ "multi-user.target" ]; + after = [ "network-online.target" ]; + serviceConfig = { + DynamicUser = true; + StateDirectory = baseNameOf dataDir; + ExecStart = '' + ${pkgs.jormungandr}/bin/jormungandr --config ${configFile} \ + ${optionalString (cfg.secretFile != null) " --secret ${cfg.secretFile}"} \ + ${optionalString (cfg.genesisBlockHash != null) " --genesis-block-hash ${cfg.genesisBlockHash}"} \ + ${optionalString (cfg.genesisBlockFile != null) " --genesis-block ${cfg.genesisBlockFile}"} + ''; + }; + }; + }; +} diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index b6930cc3a706..7564fc9eafba 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -127,6 +127,7 @@ in jackett = handleTest ./jackett.nix {}; jellyfin = handleTest ./jellyfin.nix {}; jenkins = handleTest ./jenkins.nix {}; + jormungandr = handleTest ./jormungandr.nix {}; kafka = handleTest ./kafka.nix {}; kerberos = handleTest ./kerberos/default.nix {}; kernel-latest = handleTest ./kernel-latest.nix {}; diff --git a/nixos/tests/jormungandr.nix b/nixos/tests/jormungandr.nix new file mode 100644 index 000000000000..ab4edf0506aa --- /dev/null +++ b/nixos/tests/jormungandr.nix @@ -0,0 +1,49 @@ +import ./make-test.nix ({ pkgs, ... }: { + name = "jormungandr"; + meta = with pkgs.stdenv.lib.maintainers; { + maintainers = [ mmahut ]; + }; + + nodes = { + bft = { ... }: { + environment.systemPackages = [ pkgs.jormungandr ]; + + services.jormungandr.enable = true; + services.jormungandr.genesisBlockFile = "/var/lib/jormungandr/block-0.bin"; + services.jormungandr.secretFile = "/etc/secrets/jormungandr.yaml"; + }; + }; + + testScript = '' + startAll; + + # Let's wait for the StateDirectory + $bft->waitForFile("/var/lib/jormungandr/"); + + # First, we generate the genesis file for our new blockchain + $bft->succeed("jcli genesis init > /root/genesis.yaml"); + + # We need to generate our secret key + $bft->succeed("jcli key generate --type=Ed25519 > /root/key.prv"); + + # We include the secret key into our services.jormungandr.secretFile + $bft->succeed("mkdir -p /etc/secrets"); + $bft->succeed("echo -e \"bft:\\n signing_key:\" \$(cat /root/key.prv) > /etc/secrets/jormungandr.yaml"); + + # After that, we generate our public key from it + $bft->succeed("cat /root/key.prv | jcli key to-public > /root/key.pub"); + + # We add our public key as a consensus leader in the genesis configration file + $bft->succeed("sed -ie \"s/ed25519_pk1vvwp2s0n5jl5f4xcjurp2e92sj2awehkrydrlas4vgqr7xzt33jsadha32/\$(cat /root/key.pub)/\" /root/genesis.yaml"); + + # Now we can generate the genesis block from it + $bft->succeed("jcli genesis encode --input /root/genesis.yaml --output /var/lib/jormungandr/block-0.bin"); + + # We should have everything to start the service now + $bft->succeed("systemctl restart jormungandr"); + $bft->waitForUnit("jormungandr.service"); + + # Now we can test if we are able to reach the REST API + $bft->waitUntilSucceeds("curl -L http://localhost:8607/api/v0/node/stats | grep uptime"); + ''; +})