1{ pkgs, ... }:
2{
3 name = "systemd-journal-upload";
4 meta = with pkgs.lib.maintainers; {
5 maintainers = [
6 minijackson
7 raitobezarius
8 ];
9 };
10
11 nodes.server =
12 { nodes, ... }:
13 {
14 services.journald.remote = {
15 enable = true;
16 listen = "http";
17 settings.Remote = {
18 ServerCertificateFile = "/run/secrets/sever.cert.pem";
19 ServerKeyFile = "/run/secrets/sever.key.pem";
20 TrustedCertificateFile = "/run/secrets/ca.cert.pem";
21 Seal = true;
22 };
23 };
24
25 networking.firewall.allowedTCPPorts = [ nodes.server.services.journald.remote.port ];
26 };
27
28 nodes.client =
29 { lib, nodes, ... }:
30 {
31 services.journald.upload = {
32 enable = true;
33 settings.Upload = {
34 URL = "http://server:${toString nodes.server.services.journald.remote.port}";
35 ServerCertificateFile = "/run/secrets/client.cert.pem";
36 ServerKeyFile = "/run/secrets/client.key.pem";
37 TrustedCertificateFile = "/run/secrets/ca.cert.pem";
38 };
39 };
40
41 # Wait for the PEMs to arrive
42 systemd.services.systemd-journal-upload.wantedBy = lib.mkForce [ ];
43 systemd.paths.systemd-journal-upload = {
44 wantedBy = [ "default.target" ];
45 # This file must be copied last
46 pathConfig.PathExists = [ "/run/secrets/ca.cert.pem" ];
47 };
48 };
49
50 testScript = ''
51 import subprocess
52 import tempfile
53
54 tmpdir_o = tempfile.TemporaryDirectory()
55 tmpdir = tmpdir_o.name
56
57 def generate_pems(domain: str):
58 subprocess.run(
59 [
60 "${pkgs.minica}/bin/minica",
61 "--ca-key=ca.key.pem",
62 "--ca-cert=ca.cert.pem",
63 f"--domains={domain}",
64 ],
65 cwd=str(tmpdir),
66 )
67
68 with subtest("Creating keys and certificates"):
69 generate_pems("server")
70 generate_pems("client")
71
72 server.wait_for_unit("multi-user.target")
73 client.wait_for_unit("multi-user.target")
74
75 def copy_pems(machine: Machine, domain: str):
76 machine.succeed("mkdir /run/secrets")
77 machine.copy_from_host(
78 source=f"{tmpdir}/{domain}/cert.pem",
79 target=f"/run/secrets/{domain}.cert.pem",
80 )
81 machine.copy_from_host(
82 source=f"{tmpdir}/{domain}/key.pem",
83 target=f"/run/secrets/{domain}.key.pem",
84 )
85 # Should be last
86 machine.copy_from_host(
87 source=f"{tmpdir}/ca.cert.pem",
88 target="/run/secrets/ca.cert.pem",
89 )
90
91 with subtest("Copying keys and certificates"):
92 copy_pems(server, "server")
93 copy_pems(client, "client")
94
95 client.wait_for_unit("systemd-journal-upload.service")
96 # The journal upload should have started the remote service, triggered by
97 # the .socket unit
98 server.wait_for_unit("systemd-journal-remote.service")
99
100 identifier = "nixos-test"
101 message = "Hello from NixOS test infrastructure"
102
103 client.succeed(f"systemd-cat --identifier={identifier} <<< '{message}'")
104 server.wait_until_succeeds(
105 f"journalctl --file /var/log/journal/remote/remote-*.journal --identifier={identifier} | grep -F '{message}'"
106 )
107 '';
108}