1{
2 config,
3 lib,
4 pkgs,
5 ...
6}:
7
8let
9 cfg = config.services.journald.remote;
10 format = pkgs.formats.systemd;
11
12 cliArgs = lib.cli.toGNUCommandLineShell { } {
13 inherit (cfg) output;
14 # "-3" specifies the file descriptor from the .socket unit.
15 "listen-${cfg.listen}" = "-3";
16 };
17in
18{
19 meta.maintainers = [ lib.maintainers.raitobezarius ];
20 options.services.journald.remote = {
21 enable = lib.mkEnableOption "receiving systemd journals from the network";
22
23 listen = lib.mkOption {
24 default = "https";
25 type = lib.types.enum [
26 "https"
27 "http"
28 ];
29 description = ''
30 Which protocol to listen to.
31 '';
32 };
33
34 output = lib.mkOption {
35 default = "/var/log/journal/remote/";
36 type = lib.types.str;
37 description = ''
38 The location of the output journal.
39
40 In case the output file is not specified, journal files will be created
41 underneath the selected directory. Files will be called
42 {file}`remote-hostname.journal`, where the `hostname` part is the
43 escaped hostname of the source endpoint of the connection, or the
44 numerical address if the hostname cannot be determined.
45 '';
46 };
47
48 port = lib.mkOption {
49 default = 19532;
50 type = lib.types.port;
51 description = ''
52 The port to listen to.
53
54 Note that this option is used only if
55 {option}`services.journald.upload.listen` is configured to be either
56 "https" or "http".
57 '';
58 };
59
60 settings = lib.mkOption {
61 default = { };
62
63 description = ''
64 Configuration in the journal-remote configuration file. See
65 {manpage}`journal-remote.conf(5)` for available options.
66 '';
67
68 type = lib.types.submodule {
69 freeformType = format.type;
70
71 options.Remote = {
72 Seal = lib.mkOption {
73 default = false;
74 example = true;
75 type = lib.types.bool;
76 description = ''
77 Periodically sign the data in the journal using Forward Secure
78 Sealing.
79 '';
80 };
81
82 SplitMode = lib.mkOption {
83 default = "host";
84 example = "none";
85 type = lib.types.enum [
86 "host"
87 "none"
88 ];
89 description = ''
90 With "host", a separate output file is used, based on the
91 hostname of the other endpoint of a connection. With "none", only
92 one output journal file is used.
93 '';
94 };
95
96 ServerKeyFile = lib.mkOption {
97 default = "/etc/ssl/private/journal-remote.pem";
98 type = lib.types.str;
99 description = ''
100 A path to a SSL secret key file in PEM format.
101
102 Note that due to security reasons, `systemd-journal-remote` will
103 refuse files from the world-readable `/nix/store`. This file
104 should be readable by the "" user.
105
106 This option can be used with `listen = "https"`. If the path
107 refers to an `AF_UNIX` stream socket in the file system a
108 connection is made to it and the key read from it.
109 '';
110 };
111
112 ServerCertificateFile = lib.mkOption {
113 default = "/etc/ssl/certs/journal-remote.pem";
114 type = lib.types.str;
115 description = ''
116 A path to a SSL certificate file in PEM format.
117
118 This option can be used with `listen = "https"`. If the path
119 refers to an `AF_UNIX` stream socket in the file system a
120 connection is made to it and the certificate read from it.
121 '';
122 };
123
124 TrustedCertificateFile = lib.mkOption {
125 default = "/etc/ssl/ca/trusted.pem";
126 type = lib.types.str;
127 description = ''
128 A path to a SSL CA certificate file in PEM format, or `all`.
129
130 If `all` is set, then client certificate checking will be
131 disabled.
132
133 This option can be used with `listen = "https"`. If the path
134 refers to an `AF_UNIX` stream socket in the file system a
135 connection is made to it and the certificate read from it.
136 '';
137 };
138 };
139 };
140 };
141 };
142
143 config = lib.mkIf cfg.enable {
144 systemd.additionalUpstreamSystemUnits = [
145 "systemd-journal-remote.service"
146 "systemd-journal-remote.socket"
147 ];
148
149 systemd.services.systemd-journal-remote.serviceConfig.ExecStart = [
150 # Clear the default command line
151 ""
152 "${pkgs.systemd}/lib/systemd/systemd-journal-remote ${cliArgs}"
153 ];
154
155 systemd.sockets.systemd-journal-remote = {
156 wantedBy = [ "sockets.target" ];
157 listenStreams = [
158 # Clear the default port
159 ""
160 (toString cfg.port)
161 ];
162 };
163
164 # User and group used by systemd-journal-remote.service
165 users.groups.systemd-journal-remote = { };
166 users.users.systemd-journal-remote = {
167 isSystemUser = true;
168 group = "systemd-journal-remote";
169 };
170
171 environment.etc."systemd/journal-remote.conf".source =
172 format.generate "journal-remote.conf" cfg.settings;
173 };
174}