1# end‐to‐end test for Akkoma
2{
3 lib,
4 pkgs,
5 confined ? false,
6 ...
7}:
8let
9 inherit ((pkgs.formats.elixirConf { }).lib) mkRaw;
10
11 package = pkgs.akkoma;
12
13 tlsCert =
14 names:
15 pkgs.runCommand "certificates-${lib.head names}"
16 {
17 nativeBuildInputs = with pkgs; [ openssl ];
18 }
19 ''
20 mkdir -p $out
21 openssl req -x509 \
22 -subj '/CN=${lib.head names}/' -days 49710 \
23 -addext 'subjectAltName = ${lib.concatStringsSep ", " (map (name: "DNS:${name}") names)}' \
24 -keyout "$out/key.pem" -newkey ed25519 \
25 -out "$out/cert.pem" -noenc
26 '';
27
28 tlsCertA = tlsCert [
29 "akkoma-a.nixos.test"
30 "media.akkoma-a.nixos.test"
31 ];
32
33 tlsCertB = tlsCert [
34 "akkoma-b.nixos.test"
35 "media.akkoma-b.nixos.test"
36 ];
37
38 testMedia = pkgs.runCommand "blank.png" { nativeBuildInputs = with pkgs; [ imagemagick ]; } ''
39 magick -size 640x480 canvas:transparent "PNG8:$out"
40 '';
41
42 checkFe = pkgs.writeShellApplication {
43 name = "checkFe";
44 runtimeInputs = with pkgs; [ curl ];
45 text = ''
46 paths=( / /static/{config,styles}.json /pleroma/admin/ )
47
48 for path in "''${paths[@]}"; do
49 diff \
50 <(curl -f -S -s -o /dev/null -w '%{response_code}' "https://$1$path") \
51 <(echo -n 200)
52 done
53 '';
54 };
55
56 commonConfig =
57 { nodes, ... }:
58 {
59 security.pki.certificateFiles = [
60 "${tlsCertA}/cert.pem"
61 "${tlsCertB}/cert.pem"
62 ];
63
64 networking.extraHosts = ''
65 ${nodes.akkoma-a.networking.primaryIPAddress} akkoma-a.nixos.test media.akkoma-a.nixos.test
66 ${nodes.akkoma-b.networking.primaryIPAddress} akkoma-b.nixos.test media.akkoma-b.nixos.test
67 ${nodes.client-a.networking.primaryIPAddress} client-a.nixos.test
68 ${nodes.client-b.networking.primaryIPAddress} client-b.nixos.test
69 '';
70 };
71
72 clientConfig =
73 { pkgs, ... }:
74 {
75 environment = {
76 sessionVariables = {
77 REQUESTS_CA_BUNDLE = "/etc/ssl/certs/ca-certificates.crt";
78 };
79 systemPackages = with pkgs; [ toot ];
80 };
81 };
82
83 serverConfig =
84 { config, pkgs, ... }:
85 {
86 networking = {
87 domain = "nixos.test";
88 firewall.allowedTCPPorts = [ 443 ];
89 };
90
91 systemd.services.akkoma.confinement.enable = confined;
92
93 services.akkoma = {
94 enable = true;
95 inherit package;
96 config = {
97 ":pleroma" = {
98 ":instance" = {
99 name = "NixOS test Akkoma server";
100 description = "NixOS test Akkoma server";
101 email = "akkoma@nixos.test";
102 notify_email = "akkoma@nixos.test";
103 registration_open = true;
104 };
105
106 ":media_proxy" = {
107 enabled = false;
108 };
109
110 "Pleroma.Web.Endpoint" = {
111 url.host = config.networking.fqdn;
112 };
113
114 "Pleroma.Upload" = {
115 base_url = "https://media.${config.networking.fqdn}/media/";
116 };
117
118 # disable certificate verification until we figure out how to
119 # supply our own certificates
120 ":http".adapter.pools = mkRaw "%{default: [conn_opts: [transport_opts: [verify: :verify_none]]]}";
121 };
122 };
123
124 nginx.addSSL = true;
125 };
126
127 services.nginx.enable = true;
128 services.postgresql.enable = true;
129 };
130in
131{
132 name = "akkoma";
133 nodes = {
134 client-a =
135 { ... }:
136 {
137 imports = [
138 clientConfig
139 commonConfig
140 ];
141 };
142
143 client-b =
144 { ... }:
145 {
146 imports = [
147 clientConfig
148 commonConfig
149 ];
150 };
151
152 akkoma-a =
153 { ... }:
154 {
155 imports = [
156 commonConfig
157 serverConfig
158 ];
159
160 services.akkoma.nginx = {
161 sslCertificate = "${tlsCertA}/cert.pem";
162 sslCertificateKey = "${tlsCertA}/key.pem";
163 };
164 };
165
166 akkoma-b =
167 { ... }:
168 {
169 imports = [
170 commonConfig
171 serverConfig
172 ];
173
174 services.akkoma.nginx = {
175 sslCertificate = "${tlsCertB}/cert.pem";
176 sslCertificateKey = "${tlsCertB}/key.pem";
177 };
178 };
179 };
180
181 testScript = ''
182 import json
183 import random
184 import string
185 from shlex import quote
186
187 def randomString(len):
188 return "".join(random.choice(string.ascii_letters + string.digits) for _ in range(len))
189
190 def registerUser(user, password):
191 return 'pleroma_ctl user new {0} {0}@nixos.test --password {1} -y'.format(
192 quote(user), quote(password))
193
194 def loginUser(instance, user, password):
195 return 'toot login_cli -i {}.nixos.test -e {}@nixos.test -p {}'.format(
196 quote(instance), quote(user), quote(password))
197
198 userAName = randomString(11)
199 userBName = randomString(11)
200 userAPassword = randomString(22)
201 userBPassword = randomString(22)
202
203 testMessage = randomString(22)
204 testMedia = '${testMedia}'
205
206 start_all()
207 akkoma_a.wait_for_unit('akkoma-initdb.service')
208 akkoma_b.wait_for_unit('akkoma-initdb.service')
209
210 # test repeated initialisation
211 akkoma_a.systemctl('restart akkoma-initdb.service')
212
213 akkoma_a.wait_for_unit('akkoma.service')
214 akkoma_b.wait_for_unit('akkoma.service')
215 akkoma_a.wait_for_file('/run/akkoma/socket');
216 akkoma_b.wait_for_file('/run/akkoma/socket');
217
218 akkoma_a.succeed(registerUser(userAName, userAPassword))
219 akkoma_b.succeed(registerUser(userBName, userBPassword))
220
221 akkoma_a.wait_for_unit('nginx.service')
222 akkoma_b.wait_for_unit('nginx.service')
223
224 client_a.succeed(loginUser('akkoma-a', userAName, userAPassword))
225 client_b.succeed(loginUser('akkoma-b', userBName, userBPassword))
226
227 client_b.succeed('toot follow {}@akkoma-a.nixos.test'.format(userAName))
228 client_a.wait_until_succeeds('toot followers | grep -F -q {}'.format(quote(userBName)))
229
230 client_a.succeed('toot post {} --media {} --description "nothing to see here"'.format(
231 quote(testMessage), quote(testMedia)))
232
233 # verify test message
234 status = json.loads(client_b.wait_until_succeeds(
235 'toot status --json "$(toot timeline -1 | grep -E -o \'^ID [^ ]+\' | cut -d \' \' -f 2)"'))
236 assert status['content'] == testMessage
237
238 # compare attachment to original
239 client_b.succeed('cmp {} <(curl -f -S -s {})'.format(quote(testMedia),
240 quote(status['media_attachments'][0]['url'])))
241
242 client_a.succeed('${lib.getExe checkFe} akkoma-a.nixos.test')
243 client_b.succeed('${lib.getExe checkFe} akkoma-b.nixos.test')
244 '';
245}