nix-bitcoin/test/clightning-replication.nix
Jonas Nick b26cea03b3
update nixpkgs
bitcoin: 27.0 -> 27.1
bitcoind: 27.0 -> 27.1
clightning: 24.02.2 -> 24.05
fulcrum: 1.10.0 -> 1.11.0
lnd: 0.17.5-beta -> 0.18.0-beta

Co-authored-by: Erik Arvstedt <erik.arvstedt@gmail.com>
2024-07-03 06:12:24 +00:00

161 lines
5.5 KiB
Nix

# You can run this test via `run-tests.sh -s clightning-replication`
makeTestVM: pkgs:
with pkgs.lib;
let
keyDir = pkgs.path + "/nixos/tests/initrd-network-ssh";
keys = {
server = keyDir + "/ssh_host_ed25519_key";
client = keyDir + "/id_ed25519";
serverPub = readFile (keys.server + ".pub");
clientPub = readFile (keys.client + ".pub");
};
clientBaseConfig = {
imports = [ ../modules/modules.nix ];
nixpkgs.pkgs = pkgs;
nix-bitcoin.generateSecrets = true;
services.clightning = {
enable = true;
replication.enable = true;
# TODO-EXTERNAL:
# When WAN is disabled, DNS bootstrapping slows down service startup by ~15 s.
# TODO-EXTERNAL:
# When bitcoind is not fully synced, the offers plugin in clightning 24.05
# crashes (see https://github.com/ElementsProject/lightning/issues/7378).
extraConfig = ''
disable-dns
disable-plugin=offers
'';
};
};
in
makeTestVM {
name = "clightning-replication";
nodes = let nodes = {
replicationLocal = {
imports = [ clientBaseConfig ];
services.clightning.replication.local.directory = "/var/backup/clightning";
};
replicationLocalEncrypted = {
imports = [ nodes.replicationLocal ];
services.clightning.replication.encrypt = true;
};
replicationRemote = {
imports = [ clientBaseConfig ];
nix-bitcoin.generateSecretsCmds.clightning-replication-ssh-key = mkForce ''
install -m 600 ${keys.client} clightning-replication-ssh-key
'';
programs.ssh.knownHosts."server".publicKey = keys.serverPub;
services.clightning.replication.sshfs.destination = "nb-replication@server:writable";
};
replicationRemoteEncrypted = {
imports = [ nodes.replicationRemote ];
services.clightning.replication.encrypt = true;
};
server = {
nixpkgs.pkgs = pkgs;
environment.etc."ssh-host-key" = {
source = keys.server;
mode = "400";
};
services.openssh = {
enable = true;
extraConfig = ''
Match user nb-replication
ChrootDirectory /var/backup/nb-replication
AllowTcpForwarding no
AllowAgentForwarding no
ForceCommand internal-sftp
PasswordAuthentication no
X11Forwarding no
'';
hostKeys = mkForce [
{
path = "/etc/ssh-host-key";
type = "ed25519";
}
];
};
users.users.nb-replication = {
isSystemUser = true;
group = "nb-replication";
shell = "${pkgs.coreutils}/bin/false";
openssh.authorizedKeys.keys = [ keys.clientPub ];
};
users.groups.nb-replication = {};
systemd.tmpfiles.rules = [
# Because this directory is chrooted by sshd, it must only be writable by user/group root
"d /var/backup/nb-replication 0755 root root - -"
"d /var/backup/nb-replication/writable 0700 nb-replication - - -"
];
};
}; in nodes;
testScript = { nodes, ... }: let
systems = builtins.concatStringsSep ", "
(mapAttrsToList (name: node: ''"${name}": "${node.system.build.toplevel}"'') nodes);
in ''
systems = { ${systems} }
def switch_to_system(system):
cmd = f"{systems[system]}/bin/switch-to-configuration test >&2"
client.succeed(cmd)
client = replicationLocal
if not "is_interactive" in vars():
client.start()
server.start()
with subtest("local replication"):
client.wait_for_unit("clightning.service")
client.wait_until_succeeds("runuser -u clightning -- ls /var/backup/clightning/lightningd.sqlite3")
# No other user should be able to read the backup directory
client.fail("runuser -u bitcoin -- ls /var/backup/clightning")
# If `switch_to_system` succeeds then all services, including clightning,
# have started successfully
switch_to_system("replicationLocalEncrypted")
with subtest("local replication encrypted"):
replica_db = "/var/cache/clightning-replication/plaintext/lightningd.sqlite3"
client.wait_until_succeeds(f"runuser -u clightning -- ls {replica_db}")
# No other user should be able to read the unencrypted files
client.fail(f"runuser -u bitcoin -- ls {replica_db}")
# A gocryptfs has been created
client.succeed("ls /var/backup/clightning/lightningd-db/gocryptfs.conf")
switch_to_system("replicationRemote")
server.wait_for_unit("sshd.service")
with subtest("remote replication"):
replica_db = "/var/cache/clightning-replication/sshfs/lightningd.sqlite3"
client.wait_until_succeeds(f"runuser -u clightning -- ls {replica_db}")
# No other user should be able to read the unencrypted files
client.fail(f"runuser -u bitcoin -- ls {replica_db}")
# A clighting db exists on the server
server.succeed("ls /var/backup/nb-replication/writable/lightningd.sqlite3")
switch_to_system("replicationRemoteEncrypted")
with subtest("remote replication encrypted"):
replica_db = "/var/cache/clightning-replication/plaintext/lightningd.sqlite3"
client.wait_until_succeeds(f"runuser -u clightning -- ls {replica_db}")
# No other user should be able to read the unencrypted files
client.fail(f"runuser -u bitcoin -- ls {replica_db}")
# A gocryptfs has been created on the server
server.succeed("ls /var/backup/nb-replication/writable/lightningd-db/gocryptfs.conf")
'';
}