1 import ./make-test-python.nix ({ pkgs, lib, ... }:
4 domain = "${orga}.localdomain";
6 tls-cert = pkgs.runCommand "selfSignedCert" { buildInputs = [ pkgs.openssl ]; } ''
7 openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -nodes -days 36500 \
8 -subj '/CN=machine.${domain}'
9 install -D -t $out key.pem cert.pem
13 name = "public-inbox";
15 meta.maintainers = with pkgs.lib.maintainers; [ julm ];
17 nodes.machine = { config, pkgs, nodes, ... }: let
18 inherit (config.services) gitolite public-inbox;
19 # Git repositories paths in Gitolite.
20 # Only their baseNameOf is used for configuring public-inbox.
27 virtualisation.diskSize = 1 * 1024;
28 virtualisation.memorySize = 1 * 1024;
29 networking.domain = domain;
31 security.pki.certificateFiles = [ "${tls-cert}/cert.pem" ];
32 # If using security.acme:
33 #security.acme.certs."${domain}".postRun = ''
34 # systemctl try-restart public-inbox-nntpd public-inbox-imapd
37 services.public-inbox = {
39 postfix.enable = true;
41 settings.publicinbox = {
42 css = [ "href=https://machine.${domain}/style/light.css" ];
43 nntpserver = [ "nntps://machine.${domain}" ];
44 wwwlisting = "match=domain";
48 args = [ "--no-precheck" ]; # Allow Bcc:
52 port = "/run/public-inbox-http.sock";
56 "https://machine.${domain}/inbox"
63 cert = "${tls-cert}/cert.pem";
64 key = "${tls-cert}/key.pem";
70 cert = "${tls-cert}/cert.pem";
71 key = "${tls-cert}/key.pem";
73 inboxes = lib.recursiveUpdate (lib.genAttrs (map baseNameOf repositories) (repo: {
75 # Routed to the "public-inbox:" transport in services.postfix.transport
80 discussions about ${repo}.
82 url = "https://machine.${domain}/inbox/${repo}";
83 newsgroup = "inbox.comp.${orga}.${repo}";
89 "imap" # FIXME: doesn't work for IMAP as of public-inbox 1.6.1
95 settings.coderepo = lib.listToAttrs (map (path: lib.nameValuePair (baseNameOf path) {
96 dir = "/var/lib/gitolite/repositories/${path}.git";
97 cgitUrl = "https://git.${domain}/${path}.git";
101 # Use gitolite to store Git repositories listed in coderepo entries
102 services.gitolite = {
104 adminPubkey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJmoTOQnGqX+//us5oye8UuE+tQBx9QEM7PN13jrwgqY root@localhost";
106 systemd.services.public-inbox-httpd = {
107 serviceConfig.SupplementaryGroups = [ gitolite.group ];
110 # Use nginx as a reverse proxy for public-inbox-httpd
113 recommendedGzipSettings = true;
114 recommendedOptimisation = true;
115 recommendedTlsSettings = true;
116 recommendedProxySettings = true;
117 virtualHosts."machine.${domain}" = {
119 sslCertificate = "${tls-cert}/cert.pem";
120 sslCertificateKey = "${tls-cert}/key.pem";
121 locations."/".return = "302 /inbox";
122 locations."= /inbox".return = "302 /inbox/";
123 locations."/inbox".proxyPass = "http://unix:${public-inbox.http.port}:/inbox";
124 # If using TCP instead of a Unix socket:
125 #locations."/inbox".proxyPass = "http://127.0.0.1:${toString public-inbox.http.port}/inbox";
126 # Referred to by settings.publicinbox.css
127 # See http://public-inbox.org/meta/_/text/color/
128 locations."= /style/light.css".alias = pkgs.writeText "light.css" ''
129 * { background:#fff; color:#000 }
131 a { color:#00f; text-decoration:none }
132 a:visited { color:#808 }
138 *.head { color:#000 }
139 *.hunk { color:#960 }
141 .hl.num { color:#f30 } /* number */
142 .hl.esc { color:#f0f } /* escape character */
143 .hl.str { color:#f30 } /* string */
144 .hl.ppc { color:#c3c } /* preprocessor */
145 .hl.pps { color:#f30 } /* preprocessor string */
146 .hl.slc { color:#099 } /* single-line comment */
147 .hl.com { color:#099 } /* multi-line comment */
148 /* .hl.opt { color:#ccc } */ /* operator */
149 /* .hl.ipl { color:#ccc } */ /* interpolation */
151 /* keyword groups kw[a-z] */
152 .hl.kwa { color:#f90 }
153 .hl.kwb { color:#060 }
154 .hl.kwc { color:#f90 }
155 /* .hl.kwd { color:#ccc } */
163 #sslCert = "${tls-cert}/cert.pem";
164 #sslKey = "${tls-cert}/key.pem";
165 recipientDelimiter = "+";
168 environment.systemPackages = [
177 machine.wait_for_unit("multi-user.target")
178 machine.wait_for_unit("public-inbox-init.service")
180 # Very basic check that Gitolite can work;
181 # Gitolite is not needed for the rest of this testScript
182 machine.wait_for_unit("gitolite-init.service")
184 # List inboxes through public-inbox-httpd
185 machine.wait_for_unit("nginx.service")
186 machine.succeed("curl -L https://machine.${domain} | grep repo1@${domain}")
187 # The repo2 inbox is hidden
188 machine.fail("curl -L https://machine.${domain} | grep repo2@${domain}")
189 machine.wait_for_unit("public-inbox-httpd.service")
191 # Send a mail and read it through public-inbox-httpd
192 # Must work too when using a recipientDelimiter.
193 machine.wait_for_unit("postfix.service")
194 machine.succeed("mail -t <${pkgs.writeText "mail" ''
195 Subject: Testing mail
197 To: repo1+extension@${domain}
198 Message-ID: <repo1@root-1>
199 Content-Type: text/plain; charset=utf-8
200 Content-Disposition: inline
202 This is a testing mail.
205 machine.succeed("curl -L 'https://machine.${domain}/inbox/repo1/repo1@root-1/T/#u' | grep 'This is a testing mail.'")
207 # Read a mail through public-inbox-imapd
208 machine.wait_for_open_port(993)
209 machine.wait_for_unit("public-inbox-imapd.service")
210 machine.succeed("openssl s_client -ign_eof -crlf -connect machine.${domain}:993 <${pkgs.writeText "imap-commands" ''
211 tag login anonymous@${domain} anonymous
212 tag SELECT INBOX.comp.${orga}.repo1.0
213 tag FETCH 1 (BODY[HEADER])
215 ''} | grep '^Message-ID: <repo1@root-1>'")
217 # TODO: Read a mail through public-inbox-nntpd
218 #machine.wait_for_open_port(563)
219 #machine.wait_for_unit("public-inbox-nntpd.service")
222 # Note that the use of an extension not listed in the addresses
223 # require to use --all
224 machine.succeed("curl -L https://machine.${domain}/inbox/repo1/repo1@root-1/raw | sudo -u public-inbox public-inbox-learn rm --all")
225 machine.fail("curl -L https://machine.${domain}/inbox/repo1/repo1@root-1/T/#u | grep 'This is a testing mail.'")
227 # Compact the database
228 machine.succeed("sudo -u public-inbox public-inbox-compact --all")