mirror of
https://forgejo.ellis.link/continuwuation/continuwuity/
synced 2026-08-07 02:49:45 +00:00
Compare commits
718
Commits
v1.1.0-rc1
..
v1.5.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5110b9e47b | ||
|
|
707dc74127 | ||
|
|
024c08f795 | ||
|
|
fafdb5d7ea | ||
|
|
0b864801f5 | ||
|
|
7e426e5fc8 | ||
|
|
c27fb45dc8 | ||
|
|
a2e5d61745 | ||
|
|
cdf188a776 | ||
|
|
0aa9160af7 | ||
|
|
6e87758cf6 | ||
|
|
b94f5b5963 | ||
|
|
0474753333 | ||
|
|
1fc69efffe | ||
|
|
2fb032fabb | ||
|
|
f2a15fda34 | ||
|
|
dbc208d5d9 | ||
|
|
5aea9d139b | ||
|
|
3398d1730e | ||
|
|
895387e8c2 | ||
|
|
fbeaed1c15 | ||
|
|
13ad2c7966 | ||
|
|
522f9181a5 | ||
|
|
9920f8bab0 | ||
|
|
32e3d38866 | ||
|
|
876c291c91 | ||
|
|
712c0c9487 | ||
|
|
010c519677 | ||
|
|
cc9e99f31d | ||
|
|
73eee626df | ||
|
|
c76a66be28 | ||
|
|
90d4bda70b | ||
|
|
ae35e5a5b2 | ||
|
|
10060cef69 | ||
|
|
136c0f2682 | ||
|
|
7bc25ad1b1 | ||
|
|
5112c55bf0 | ||
|
|
9411996813 | ||
|
|
8e29fbb3a4 | ||
|
|
23b532d0aa | ||
|
|
afbf854cfd | ||
|
|
ae3f08eb9a | ||
|
|
cb3dfbc437 | ||
|
|
0b82fe27b5 | ||
|
|
a1960553e9 | ||
|
|
daa869fced | ||
|
|
23a3e87e93 | ||
|
|
56f3f5ea15 | ||
|
|
0dbe79df8e | ||
|
|
3caab50e0d | ||
|
|
bb26b749ae | ||
|
|
8000fcce9e | ||
|
|
0c9a3abb71 | ||
|
|
fbedd713ca | ||
|
|
6db87a4027 | ||
|
|
a3294fe1cf | ||
|
|
885e402e38 | ||
|
|
f048f87dac | ||
|
|
7ff51a8eca | ||
|
|
be542da6e4 | ||
|
|
f03321d33d | ||
|
|
9d8525e7f7 | ||
|
|
c6c85374fa | ||
|
|
948e1681c2 | ||
|
|
48aa6035f6 | ||
|
|
afcb2315ee | ||
|
|
7b22e7930a | ||
|
|
944f165202 | ||
|
|
a0b98fa575 | ||
|
|
b7fe61b423 | ||
|
|
b849bcac19 | ||
|
|
dca100ff16 | ||
|
|
7ec9d7f5aa | ||
|
|
8510ca32c8 | ||
|
|
16acc3e1d0 | ||
|
|
0f547115af | ||
|
|
a91b01f9a2 | ||
|
|
5bc2863721 | ||
|
|
aadc9ade3e | ||
|
|
22a7f6cb33 | ||
|
|
a73b4eba8b | ||
|
|
50e8fcc403 | ||
|
|
2b32769649 | ||
|
|
3e1246984c | ||
|
|
04dc0fda60 | ||
|
|
106bba761e | ||
|
|
6619171e13 | ||
|
|
3a9446bb9c | ||
|
|
2f4d3c2851 | ||
|
|
1b68588b84 | ||
|
|
f4ba3d4a29 | ||
|
|
04e66a03d3 | ||
|
|
fb102f0e0a | ||
|
|
99c84039da | ||
|
|
2f2fc5c5f9 | ||
|
|
b3f8118f0e | ||
|
|
6579df299a | ||
|
|
3a613963f9 | ||
|
|
5cb6d2058f | ||
|
|
64149f0cc4 | ||
|
|
98f5ea203b | ||
|
|
85ac256786 | ||
|
|
f9f00d83fc | ||
|
|
e78bf21085 | ||
|
|
95121ad905 | ||
|
|
62ec58b1ed | ||
|
|
c0aaeefaf2 | ||
|
|
38ae93fe42 | ||
|
|
2880facc4c | ||
|
|
4b9d4794fb | ||
|
|
8a95390f1c | ||
|
|
9346e69b87 | ||
|
|
d0b2181817 | ||
|
|
febd4d1a23 | ||
|
|
8be0a579db | ||
|
|
1b5e11e943 | ||
|
|
dfb65d771f | ||
|
|
86fc42bba0 | ||
|
|
53d4495e21 | ||
|
|
fa7838ffb1 | ||
|
|
ae8f266385 | ||
|
|
3426b824a0 | ||
|
|
d095a4fd3b | ||
|
|
fd519ff7f1 | ||
|
|
76c09851ea | ||
|
|
5e532593fa | ||
|
|
fd8ee422dd | ||
|
|
cf8b57b751 | ||
|
|
05898034e5 | ||
|
|
257168946e | ||
|
|
fc104d02a4 | ||
|
|
bd0a0acf4a | ||
|
|
11038b0ec7 | ||
|
|
2a7455b5c9 | ||
|
|
fbf66f565a | ||
|
|
6303ae28e9 | ||
|
|
a434c4d452 | ||
|
|
121aa9e39d | ||
|
|
6b4a09fc81 | ||
|
|
5a92a00939 | ||
|
|
b412aafaf8 | ||
|
|
63bdeb79c9 | ||
|
|
0bbe96f761 | ||
|
|
b33e73672b | ||
|
|
59481ad28d | ||
|
|
977f9e2e2e | ||
|
|
432e6a2663 | ||
|
|
f4ee8bc433 | ||
|
|
8aeaaea271 | ||
|
|
5847d8135d | ||
|
|
14e7a001b9 | ||
|
|
d56ee58a73 | ||
|
|
806ecaec7e | ||
|
|
11309062a2 | ||
|
|
d665a34f30 | ||
|
|
e019ed77d0 | ||
|
|
568a28220c | ||
|
|
4229a1d630 | ||
|
|
0cbdcf3b3d | ||
|
|
fe57ea3354 | ||
|
|
422802a9cf | ||
|
|
e79b888367 | ||
|
|
f91b3b6a6c | ||
|
|
4150b917d8 | ||
|
|
5b0dfaeef6 | ||
|
|
7a4d07fd3b | ||
|
|
eadc9e782d | ||
|
|
af570c481e | ||
|
|
dc9314de1f | ||
|
|
cf005ee537 | ||
|
|
6455ef72cd | ||
|
|
7115fb2796 | ||
|
|
959c559bd8 | ||
|
|
a1bf188504 | ||
|
|
87770fefeb | ||
|
|
0c7ba1dd5a | ||
|
|
7b2079f714 | ||
|
|
c5508bba58 | ||
|
|
88a6b72f0f | ||
|
|
22c5f0207d | ||
|
|
3af78ac851 | ||
|
|
b5f50c3fda | ||
|
|
c9a26a0280 | ||
|
|
417e9ba052 | ||
|
|
085cdb30f4 | ||
|
|
77474479b5 | ||
|
|
d244e8027c | ||
|
|
4fea0abac4 | ||
|
|
cab0b3fd9f | ||
|
|
f311332bad | ||
|
|
fb0c2a2832 | ||
|
|
3403943880 | ||
|
|
7e69e9b051 | ||
|
|
27ed9b88f1 | ||
|
|
10edc3bd5e | ||
|
|
6553ba829f | ||
|
|
1ce3d2b01f | ||
|
|
50bfb0fe5e | ||
|
|
74f8cd3708 | ||
|
|
bcc2be7661 | ||
|
|
4f9b1d6dbd | ||
|
|
c9362b8605 | ||
|
|
e84d6666c0 | ||
|
|
7666bb63d8 | ||
|
|
3125b7e291 | ||
|
|
aebe2d72de | ||
|
|
8f54d9dc09 | ||
|
|
52b156e034 | ||
|
|
d2d6a98180 | ||
|
|
0bbc228f7a | ||
|
|
0d782095ad | ||
|
|
f6b95ff1c4 | ||
|
|
347298d7d6 | ||
|
|
442a5aafeb | ||
|
|
8bb0d02619 | ||
|
|
71f3ccf140 | ||
|
|
98affbdeaf | ||
|
|
e5073165f0 | ||
|
|
6705efc760 | ||
|
|
61085f4707 | ||
|
|
deb5c65885 | ||
|
|
11c4cbf54e | ||
|
|
a748edd621 | ||
|
|
9e539d0a22 | ||
|
|
5260912c3b | ||
|
|
b924412efb | ||
|
|
120ab1d068 | ||
|
|
e60e86e9ed | ||
|
|
5147b541b5 | ||
|
|
f4eeaaf167 | ||
|
|
54fe4bdf56 | ||
|
|
fe12daead9 | ||
|
|
6f29a34ffb | ||
|
|
dafbe59d00 | ||
|
|
0746f4b1ad | ||
|
|
90228e4865 | ||
|
|
53b5eb4ba6 | ||
|
|
20f080fc49 | ||
|
|
424ed3d7ad | ||
|
|
728085bd1b | ||
|
|
64a029ee09 | ||
|
|
a3f6971579 | ||
|
|
51681aec1b | ||
|
|
39c84fabb4 | ||
|
|
f77bd41837 | ||
|
|
6f34b8e9ca | ||
|
|
5051da493a | ||
|
|
ff0e007c45 | ||
|
|
b85fb5ea6f | ||
|
|
e905538269 | ||
|
|
6f672b7304 | ||
|
|
4363ed6ec3 | ||
|
|
dd50a4cb0b | ||
|
|
e0a997c227 | ||
|
|
e1f89b69ea | ||
|
|
888f72d8d0 | ||
|
|
06618eadab | ||
|
|
05390d6097 | ||
|
|
1f803fe3a9 | ||
|
|
1492d68e25 | ||
|
|
c1aa94fb91 | ||
|
|
7320d0a40b | ||
|
|
abded2d442 | ||
|
|
4afd6f347b | ||
|
|
6b8d6956a3 | ||
|
|
f59d62c01c | ||
|
|
a14556da97 | ||
|
|
8b1de3d8db | ||
|
|
240b498489 | ||
|
|
d680a6ba53 | ||
|
|
aa3f14cd57 | ||
|
|
15627bc8d0 | ||
|
|
084facf474 | ||
|
|
d24986edf1 | ||
|
|
ce1ac277a6 | ||
|
|
7aeed0a95a | ||
|
|
9265748a57 | ||
|
|
e85cfdf48a | ||
|
|
48923b3657 | ||
|
|
aedaf3f0c1 | ||
|
|
b24b59dc38 | ||
|
|
738b5e3fa5 | ||
|
|
1f0cfec5ca | ||
|
|
9c5caa3a5f | ||
|
|
1cf4a26ae9 | ||
|
|
3694ffbab3 | ||
|
|
af0e01e016 | ||
|
|
5e89f0acae | ||
|
|
563873af77 | ||
|
|
d2072080c9 | ||
|
|
e191730950 | ||
|
|
f660e00bb5 | ||
|
|
f613d0c2ad | ||
|
|
7596ad2019 | ||
|
|
384add9784 | ||
|
|
a234f019b1 | ||
|
|
e8a87bdfa3 | ||
|
|
6a4aff424f | ||
|
|
8959d9e2c1 | ||
|
|
a30c043386 | ||
|
|
a39ef994d2 | ||
|
|
b714f24029 | ||
|
|
2263f2e874 | ||
|
|
9abe9becd6 | ||
|
|
4b74c01895 | ||
|
|
1223763e2b | ||
|
|
9b64c1f105 | ||
|
|
212a8434a8 | ||
|
|
bfaac8b5a2 | ||
|
|
9af15ecbba | ||
|
|
f66a83763e | ||
|
|
718c3adcb2 | ||
|
|
af80482c04 | ||
|
|
a20ddcd586 | ||
|
|
b483306367 | ||
|
|
f5e98467be | ||
|
|
d44db45f83 | ||
|
|
0397bb8237 | ||
|
|
4010fc62bc | ||
|
|
0d823a2822 | ||
|
|
9cd175b125 | ||
|
|
050a1a350a | ||
|
|
ec0f872f8f | ||
|
|
024e8eae62 | ||
|
|
4fd60b2605 | ||
|
|
e53968d9eb | ||
|
|
7cbc2ee385 | ||
|
|
0df5e5e7ac | ||
|
|
312eb69450 | ||
|
|
5b620a2c37 | ||
|
|
3b4fbb8c1a | ||
|
|
158d44e1a9 | ||
|
|
d2aab468cf | ||
|
|
aa4486dfdf | ||
|
|
2a662445b6 | ||
|
|
5b3f0fde23 | ||
|
|
9640afebff | ||
|
|
dd5c5c7a4a | ||
|
|
fc0f04defa | ||
|
|
7d8f7cbe5d | ||
|
|
4e0249cd2f | ||
|
|
d5b39aa995 | ||
|
|
46c940b863 | ||
|
|
ab8536d5c3 | ||
|
|
4918868632 | ||
|
|
9e00f70197 | ||
|
|
d3aaf9e4a9 | ||
|
|
96dc56ad07 | ||
|
|
e12b0262da | ||
|
|
e5bf005eaf | ||
|
|
02ccb1dceb | ||
|
|
a450eb96eb | ||
|
|
155af0fda3 | ||
|
|
5c61b4d4a3 | ||
|
|
97e709492c | ||
|
|
51fc2342a4 | ||
|
|
4ca68deef8 | ||
|
|
4d8d64f5c7 | ||
|
|
dff30e5924 | ||
|
|
7fee459b1a | ||
|
|
a6127fcd1a | ||
|
|
6c724bbc2f | ||
|
|
b1ea7b101d | ||
|
|
4baa25f66f | ||
|
|
227b77e58e | ||
|
|
54057da84e | ||
|
|
732825a390 | ||
|
|
6b74425f76 | ||
|
|
74a576caf7 | ||
|
|
2b7cf7d5d5 | ||
|
|
443248965d | ||
|
|
ee777bc287 | ||
|
|
aef38b1178 | ||
|
|
4743a8d968 | ||
|
|
53ab6742c8 | ||
|
|
46193de7e8 | ||
|
|
9253f46c80 | ||
|
|
5c127b5abd | ||
|
|
17f6f1a5a6 | ||
|
|
75509d50ca | ||
|
|
1d14426018 | ||
|
|
2b9563be67 | ||
|
|
68c4f60bb3 | ||
|
|
d95c3f126f | ||
|
|
f1c2548807 | ||
|
|
eda45e445c | ||
|
|
049defe977 | ||
|
|
3c073110b8 | ||
|
|
8d6bfde5a0 | ||
|
|
43f0882d83 | ||
|
|
fed52d24e4 | ||
|
|
e6c85c97c6 | ||
|
|
368ead20a6 | ||
|
|
a803b84b27 | ||
|
|
1058fbe9a7 | ||
|
|
ae4aad3641 | ||
|
|
95435ffe98 | ||
|
|
63e2cfa21b | ||
|
|
9383922d09 | ||
|
|
ae52676e33 | ||
|
|
292b601755 | ||
|
|
1313eb0b64 | ||
|
|
ba12773a5a | ||
|
|
83afe81f60 | ||
|
|
f2740822e2 | ||
|
|
2417764771 | ||
|
|
41ff81f843 | ||
|
|
fbcf4ba4f3 | ||
|
|
af3cdf9263 | ||
|
|
9d9ace1452 | ||
|
|
83d64e0879 | ||
|
|
4cae17e83d | ||
|
|
1c6992ccd4 | ||
|
|
89be6dc097 | ||
|
|
a47f8f8a82 | ||
|
|
aac5006bf5 | ||
|
|
6d3ed09a2b | ||
|
|
377b7166f0 | ||
|
|
85b3de055d | ||
|
|
b9c790326a | ||
|
|
4e5910471b | ||
|
|
c3bc8c14f7 | ||
|
|
ac3ceb1b95 | ||
|
|
aa37e32471 | ||
|
|
887a22dabd | ||
|
|
6dca02860c | ||
|
|
86103183b3 | ||
|
|
8f4cc87051 | ||
|
|
14721c90c9 | ||
|
|
6d3b2d864f | ||
|
|
7cf246eb73 | ||
|
|
bffb7f89c8 | ||
|
|
5467c9e486 | ||
|
|
89a67af607 | ||
|
|
6bb101ac51 | ||
|
|
1c0b4e94ac | ||
|
|
9c4d376bec | ||
|
|
d6e95c51c0 | ||
|
|
d5ce4b316f | ||
|
|
8f07a6c60f | ||
|
|
b882e7efdb | ||
|
|
e0169e3dca | ||
|
|
fe46755418 | ||
|
|
bbac80d2e6 | ||
|
|
a31c9b0c62 | ||
|
|
cf4e65c607 | ||
|
|
f32b6ae17d | ||
|
|
27222f23d2 | ||
|
|
ed324d5972 | ||
|
|
69075b166f | ||
|
|
e3a711482a | ||
|
|
6759187b37 | ||
|
|
83ed29eb65 | ||
|
|
6a685b7ee9 | ||
|
|
fb4dfafe2d | ||
|
|
8dbea51968 | ||
|
|
7b5905bbca | ||
|
|
42d143c013 | ||
|
|
10fb1cd192 | ||
|
|
1322ba1b00 | ||
|
|
d73b4332bf | ||
|
|
11eeca7e01 | ||
|
|
19dc5fafd4 | ||
|
|
54b347b855 | ||
|
|
8ed61aecb0 | ||
|
|
bf8aa57d03 | ||
|
|
a9f1926654 | ||
|
|
248d778290 | ||
|
|
2e13e87e43 | ||
|
|
ba19d407d0 | ||
|
|
de7c5dcbc8 | ||
|
|
adadafa88f | ||
|
|
deda746222 | ||
|
|
29c2c8a333 | ||
|
|
296018f0cc | ||
|
|
6295ca135a | ||
|
|
b5a9884194 | ||
|
|
1be7fd9247 | ||
|
|
be1264965a | ||
|
|
f6d2ce2f22 | ||
|
|
3cbe1e25cd | ||
|
|
897322964c | ||
|
|
996a5488be | ||
|
|
0ed4bd1e07 | ||
|
|
da79de5381 | ||
|
|
1bcf3ae19a | ||
|
|
91e500efe3 | ||
|
|
35b1ebaf3b | ||
|
|
ea5deb7e85 | ||
|
|
542cc51047 | ||
|
|
3225db0ddd | ||
|
|
a164da8b58 | ||
|
|
7221d466ce | ||
|
|
f6c88e3a16 | ||
|
|
3deebeab78 | ||
|
|
1d2818de58 | ||
|
|
86781522b6 | ||
|
|
4b49aaad53 | ||
|
|
3a78ba2b16 | ||
|
|
685946faed | ||
|
|
13c9385ef7 | ||
|
|
6a583a359e | ||
|
|
eec6e45358 | ||
|
|
804257eb52 | ||
|
|
a1677f05d3 | ||
|
|
1f77200299 | ||
|
|
888b93df91 | ||
|
|
a127724eaa | ||
|
|
00102c4276 | ||
|
|
b59af0530c | ||
|
|
44af849ed0 | ||
|
|
26e7a8e962 | ||
|
|
aa413ae601 | ||
|
|
7c19d1e1ff | ||
|
|
616f20f273 | ||
|
|
91efcf8a8e | ||
|
|
8708e98478 | ||
|
|
4bdc260015 | ||
|
|
7bc47e58d0 | ||
|
|
6172b9c8ec | ||
|
|
9dc16eeab7 | ||
|
|
402f7a2157 | ||
|
|
9c6e0e3350 | ||
|
|
12bdfe3b66 | ||
|
|
54ce221e88 | ||
|
|
33a16f4831 | ||
|
|
d8e6d95f4b | ||
|
|
9c290bc513 | ||
|
|
a4520424bd | ||
|
|
280d7733fc | ||
|
|
79e3c898ac | ||
|
|
757d38e891 | ||
|
|
4b66911886 | ||
|
|
9db3e35f41 | ||
|
|
7977512d5d | ||
|
|
e354be6830 | ||
|
|
f58081838e | ||
|
|
526a138021 | ||
|
|
7fa6894334 | ||
|
|
33d0ad1be2 | ||
|
|
fbc3892904 | ||
|
|
ce6212b161 | ||
|
|
0aea56f02a | ||
|
|
d05d3f710f | ||
|
|
7a3496869b | ||
|
|
146b72265d | ||
|
|
120a43cceb | ||
|
|
c40671bfb0 | ||
|
|
8e9c6661b2 | ||
|
|
6810604629 | ||
|
|
3dd984eff9 | ||
|
|
bcd4f80149 | ||
|
|
f51a7b12b5 | ||
|
|
3a1649bcaf | ||
|
|
d4421422b2 | ||
|
|
4884c55be7 | ||
|
|
a4f589f475 | ||
|
|
b5890b9664 | ||
|
|
26b3a84b88 | ||
|
|
3430d4ac86 | ||
|
|
3e2f2fbffa | ||
|
|
74deb14ca0 | ||
|
|
acd930b9ca | ||
|
|
e2db2029c5 | ||
|
|
4bb83a1972 | ||
|
|
751aa27859 | ||
|
|
628597c318 | ||
|
|
2c6dd78502 | ||
|
|
cdb0e31b21 | ||
|
|
6a6f77a100 | ||
|
|
a3666fe672 | ||
|
|
0c8df52d18 | ||
|
|
d7e5c0ccf3 | ||
|
|
e106e50ed0 | ||
|
|
00f11a9e8f | ||
|
|
bf48c7b1b4 | ||
|
|
8a8a5d598e | ||
|
|
fa84a7e6c2 | ||
|
|
2bdeca0ed3 | ||
|
|
c337ea1864 | ||
|
|
b00361d274 | ||
|
|
fb17aa19bf | ||
|
|
fc28e8e1dd | ||
|
|
cea25c6580 | ||
|
|
a0dc37e024 | ||
|
|
003257693b | ||
|
|
bc898efcce | ||
|
|
fa8ad1d629 | ||
|
|
44b60050b3 | ||
|
|
4b84e7c31a | ||
|
|
4237f21903 | ||
|
|
4ac61fd87b | ||
|
|
d217927000 | ||
|
|
4b9b85f671 | ||
|
|
fa3b72947a | ||
|
|
5d963abda6 | ||
|
|
a91380ac17 | ||
|
|
1664a2c225 | ||
|
|
0d7eeb7766 | ||
|
|
16447f7383 | ||
|
|
3612b04890 | ||
|
|
e6f1b98d6a | ||
|
|
6742e1d206 | ||
|
|
dc0976a2e5 | ||
|
|
f3f23ee7ee | ||
|
|
0b15ab2006 | ||
|
|
bd0c3e33e2 | ||
|
|
1bb16c8b73 | ||
|
|
59b62b1453 | ||
|
|
2e0b156de0 | ||
|
|
3593b8ebf7 | ||
|
|
80015a6a30 | ||
|
|
95e49d3cb8 | ||
|
|
25164e030d | ||
|
|
f04924d6be | ||
|
|
df7cd58618 | ||
|
|
bf12e05dae | ||
|
|
e53366a492 | ||
|
|
ce25d79e66 | ||
|
|
71ef093edc | ||
|
|
066097a83d | ||
|
|
1c24ed09fa | ||
|
|
d3dbe09380 | ||
|
|
e9d0baa32e | ||
|
|
7dd10ebc6c | ||
|
|
29ac62ec27 | ||
|
|
8c8985e8f2 | ||
|
|
730920b571 | ||
|
|
66334bdd53 | ||
|
|
6b7bf80de5 | ||
|
|
4c35bfbda4 | ||
|
|
ba51748ad3 | ||
|
|
63dfe8f7e3 | ||
|
|
c6836e51b2 | ||
|
|
33a9fce828 | ||
|
|
267fd4de5b | ||
|
|
ce30f83052 | ||
|
|
e09a2c0e0f | ||
|
|
992abfab8f | ||
|
|
51931de94c | ||
|
|
85a84f93c7 | ||
|
|
e58ef326d4 | ||
|
|
0d439188e8 | ||
|
|
22ef704ac6 | ||
|
|
7bdd4065c8 | ||
|
|
0fcb072239 | ||
|
|
05bb1f4ac7 | ||
|
|
89e3a8c182 | ||
|
|
f0576f8d7d | ||
|
|
11f77defc7 | ||
|
|
23c75855ba | ||
|
|
5253a8d36a | ||
|
|
c9adee86f5 | ||
|
|
3c47516c85 | ||
|
|
299d3230a1 | ||
|
|
9ea8fbc482 | ||
|
|
f7877d122b | ||
|
|
17119670c0 | ||
|
|
535fcab4b5 | ||
|
|
cbe34affa3 | ||
|
|
ed0b3c764e | ||
|
|
190269f616 | ||
|
|
3ea8c82ef0 | ||
|
|
2a627baa96 | ||
|
|
50de6277b8 | ||
|
|
4429323e11 | ||
|
|
18f8d6c65c | ||
|
|
aac49b09c7 | ||
|
|
c8d35cca57 | ||
|
|
cca0f20148 | ||
|
|
23d188f612 | ||
|
|
ae707ab465 | ||
|
|
8244d78cb2 | ||
|
|
b0315da3d7 | ||
|
|
eca01cfb3f | ||
|
|
cf13f5afc1 | ||
|
|
c944f1124a | ||
|
|
70fc95e800 | ||
|
|
507bd1edc7 | ||
|
|
ee0e594aef | ||
|
|
fd080914c2 | ||
|
|
9dd2b28605 | ||
|
|
34abe1cce4 | ||
|
|
a340e6786d | ||
|
|
c37ee97351 | ||
|
|
7d2d42542c | ||
|
|
fd0082fd2c | ||
|
|
ca8f3ae057 | ||
|
|
8a748e02df | ||
|
|
79ee7838e7 | ||
|
|
e9a441fb6e | ||
|
|
93f5557232 | ||
|
|
3d88767977 | ||
|
|
b68cff3b2f | ||
|
|
36c3845ff6 | ||
|
|
7f1c7b964e | ||
|
|
1cbcd3fc88 | ||
|
|
ad9ddd91cd | ||
|
|
a2b4c07cf7 | ||
|
|
2ead282bec | ||
|
|
9496d05cd2 | ||
|
|
c8ab1713c3 | ||
|
|
84acdccb93 | ||
|
|
6164f62395 | ||
|
|
b36ad9cfef | ||
|
|
d557f0f456 | ||
|
|
d858c5c1f4 | ||
|
|
972201da60 | ||
|
|
56d9c9a8b5 | ||
|
|
84ce3e0d0e | ||
|
|
578cf9d2d7 | ||
|
|
ca69af97c1 | ||
|
|
ac26193ffe | ||
|
|
a84e559640 | ||
|
|
2e559a0d3e | ||
|
|
2634fed2d4 | ||
|
|
31a3676cd8 | ||
|
|
aa1609d611 |
+1
-1
@@ -1,5 +1,5 @@
|
||||
[advisories]
|
||||
ignore = ["RUSTSEC-2024-0436", "RUSTSEC-2025-0014"] # advisory IDs to ignore e.g. ["RUSTSEC-2019-0001", ...]
|
||||
ignore = ["RUSTSEC-2024-0436", "RUSTSEC-2025-0014", "RUSTSEC-2025-0134"] # advisory IDs to ignore e.g. ["RUSTSEC-2019-0001", ...]
|
||||
informational_warnings = [] # warn for categories of informational advisories
|
||||
severity_threshold = "none" # CVSS severity ("none", "low", "medium", "high", "critical")
|
||||
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
[env]
|
||||
RUMA_UNSTABLE_EXHAUSTIVE_TYPES = "true"
|
||||
@@ -0,0 +1,27 @@
|
||||
name: Update .rpm SPEC files
|
||||
on:
|
||||
# Allows for manually running an update from the actions tab
|
||||
workflow_dispatch:
|
||||
|
||||
schedule:
|
||||
# Runs every day at ~12am UTC - see https://crontab.guru/
|
||||
- cron: '0 0 * * *'
|
||||
|
||||
# Revoke all default permissions
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
update:
|
||||
name: update
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
# needed to push commits to this repo
|
||||
# see `check` mode if you don't want to give this permission
|
||||
contents: write
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- uses: aidandenlinger/autocopr@v1 # Or a specific release tag, or commit
|
||||
with:
|
||||
mode: "push"
|
||||
@@ -42,6 +42,10 @@ on:
|
||||
type: string
|
||||
default: '[]'
|
||||
description: Matrix inclusions
|
||||
checkout:
|
||||
type: string
|
||||
default: 'HEAD'
|
||||
description: Specific commit to checkout
|
||||
max-parallel:
|
||||
type: number
|
||||
default: 128
|
||||
@@ -111,6 +115,8 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
fetch-depth: 0
|
||||
fetch-tags: true
|
||||
|
||||
# Call docker
|
||||
- name: Bake ${{matrix.bake_target}}
|
||||
@@ -129,6 +135,7 @@ jobs:
|
||||
CI_VERBOSE_ENV: ${{inputs.verbose_env}}
|
||||
CI_SILENT_BAKE: ${{inputs.silent_bake}}
|
||||
CI_PRINT_BAKE: ${{inputs.print_bake}}
|
||||
git_checkout: ${{inputs.checkout}}
|
||||
|
||||
run: |
|
||||
docker/bake.sh "${{matrix.bake_target}}"
|
||||
|
||||
+24
-15
@@ -35,6 +35,9 @@ on:
|
||||
type: string
|
||||
default: '[]'
|
||||
description: Matrix inclusions
|
||||
checkout:
|
||||
type: string
|
||||
default: 'HEAD'
|
||||
|
||||
jobs:
|
||||
fmt:
|
||||
@@ -43,7 +46,7 @@ jobs:
|
||||
&& contains(fromJSON(inputs.cargo_profiles), fromJSON('["test"]')[0])
|
||||
&& contains(fromJSON(inputs.feat_sets), fromJSON('["all"]')[0])
|
||||
&& contains(fromJSON(inputs.rust_toolchains), fromJSON('["nightly"]')[0])
|
||||
&& contains(fromJSON(inputs.machines), fromJSON('["X64"]')[0])
|
||||
&& contains(fromJSON(inputs.sys_targets), fromJSON('["x86_64-v1-linux-gnu"]')[0])
|
||||
|
||||
name: Format
|
||||
uses: ./.github/workflows/bake.yml
|
||||
@@ -54,11 +57,12 @@ jobs:
|
||||
rust_toolchains: '["nightly"]'
|
||||
rust_targets: ${{inputs.rust_targets}}
|
||||
sys_names: ${{inputs.sys_names}}
|
||||
sys_targets: ${{inputs.sys_targets}}
|
||||
sys_versions: ${{inputs.sys_versions}}
|
||||
machines: '["X64"]'
|
||||
sys_targets: '["x86_64-v1-linux-gnu"]'
|
||||
machines: ${{inputs.machines}}
|
||||
excludes: ${{inputs.excludes}}
|
||||
includes: ${{inputs.includes}}
|
||||
checkout: ${{inputs.checkout}}
|
||||
|
||||
typos:
|
||||
if: >
|
||||
@@ -66,7 +70,7 @@ jobs:
|
||||
&& contains(fromJSON(inputs.cargo_profiles), fromJSON('["test"]')[0])
|
||||
&& contains(fromJSON(inputs.feat_sets), fromJSON('["all"]')[0])
|
||||
&& contains(fromJSON(inputs.rust_toolchains), fromJSON('["nightly"]')[0])
|
||||
&& contains(fromJSON(inputs.machines), fromJSON('["X64"]')[0])
|
||||
&& contains(fromJSON(inputs.sys_targets), fromJSON('["x86_64-v1-linux-gnu"]')[0])
|
||||
|
||||
name: Typos
|
||||
uses: ./.github/workflows/bake.yml
|
||||
@@ -78,10 +82,11 @@ jobs:
|
||||
sys_names: ${{inputs.sys_names}}
|
||||
sys_versions: ${{inputs.sys_versions}}
|
||||
rust_targets: ${{inputs.rust_targets}}
|
||||
sys_targets: ${{inputs.sys_targets}}
|
||||
machines: '["X64"]'
|
||||
sys_targets: '["x86_64-v1-linux-gnu"]'
|
||||
machines: ${{inputs.machines}}
|
||||
excludes: ${{inputs.excludes}}
|
||||
includes: ${{inputs.includes}}
|
||||
checkout: ${{inputs.checkout}}
|
||||
|
||||
audit:
|
||||
if: >
|
||||
@@ -89,7 +94,7 @@ jobs:
|
||||
&& contains(fromJSON(inputs.cargo_profiles), fromJSON('["test"]')[0])
|
||||
&& contains(fromJSON(inputs.feat_sets), fromJSON('["all"]')[0])
|
||||
&& contains(fromJSON(inputs.rust_toolchains), fromJSON('["nightly"]')[0])
|
||||
&& contains(fromJSON(inputs.machines), fromJSON('["X64"]')[0])
|
||||
&& contains(fromJSON(inputs.sys_targets), fromJSON('["x86_64-v1-linux-gnu"]')[0])
|
||||
|
||||
name: Audit
|
||||
uses: ./.github/workflows/bake.yml
|
||||
@@ -101,10 +106,11 @@ jobs:
|
||||
sys_names: ${{inputs.sys_names}}
|
||||
sys_versions: ${{inputs.sys_versions}}
|
||||
rust_targets: ${{inputs.rust_targets}}
|
||||
sys_targets: ${{inputs.sys_targets}}
|
||||
machines: '["X64"]'
|
||||
sys_targets: '["x86_64-v1-linux-gnu"]'
|
||||
machines: ${{inputs.machines}}
|
||||
excludes: ${{inputs.excludes}}
|
||||
includes: ${{inputs.includes}}
|
||||
checkout: ${{inputs.checkout}}
|
||||
|
||||
lychee:
|
||||
if: >
|
||||
@@ -112,7 +118,7 @@ jobs:
|
||||
&& contains(fromJSON(inputs.cargo_profiles), fromJSON('["test"]')[0])
|
||||
&& contains(fromJSON(inputs.feat_sets), fromJSON('["all"]')[0])
|
||||
&& contains(fromJSON(inputs.rust_toolchains), fromJSON('["nightly"]')[0])
|
||||
&& contains(fromJSON(inputs.machines), fromJSON('["X64"]')[0])
|
||||
&& contains(fromJSON(inputs.sys_targets), fromJSON('["x86_64-v1-linux-gnu"]')[0])
|
||||
|
||||
name: Lychee
|
||||
uses: ./.github/workflows/bake.yml
|
||||
@@ -124,10 +130,11 @@ jobs:
|
||||
sys_names: ${{inputs.sys_names}}
|
||||
sys_versions: ${{inputs.sys_versions}}
|
||||
rust_targets: ${{inputs.rust_targets}}
|
||||
sys_targets: ${{inputs.sys_targets}}
|
||||
machines: '["X64"]'
|
||||
sys_targets: '["x86_64-v1-linux-gnu"]'
|
||||
machines: ${{inputs.machines}}
|
||||
excludes: ${{inputs.excludes}}
|
||||
includes: ${{inputs.includes}}
|
||||
checkout: ${{inputs.checkout}}
|
||||
|
||||
check:
|
||||
if: >
|
||||
@@ -135,7 +142,7 @@ jobs:
|
||||
&& contains(fromJSON(inputs.cargo_profiles), fromJSON('["test"]')[0])
|
||||
&& contains(fromJSON(inputs.feat_sets), fromJSON('["all"]')[0])
|
||||
&& contains(fromJSON(inputs.rust_toolchains), fromJSON('["nightly"]')[0])
|
||||
&& contains(fromJSON(inputs.machines), fromJSON('["X64"]')[0])
|
||||
&& contains(fromJSON(inputs.sys_targets), fromJSON('["x86_64-v1-linux-gnu"]')[0])
|
||||
|
||||
name: Check
|
||||
uses: ./.github/workflows/bake.yml
|
||||
@@ -147,10 +154,11 @@ jobs:
|
||||
sys_names: ${{inputs.sys_names}}
|
||||
sys_versions: ${{inputs.sys_versions}}
|
||||
rust_targets: ${{inputs.rust_targets}}
|
||||
sys_targets: ${{inputs.sys_targets}}
|
||||
machines: '["X64"]'
|
||||
sys_targets: '["x86_64-v1-linux-gnu"]'
|
||||
machines: ${{inputs.machines}}
|
||||
excludes: ${{inputs.excludes}}
|
||||
includes: ${{inputs.includes}}
|
||||
checkout: ${{inputs.checkout}}
|
||||
|
||||
clippy:
|
||||
if: >
|
||||
@@ -171,3 +179,4 @@ jobs:
|
||||
machines: ${{inputs.machines}}
|
||||
excludes: ${{inputs.excludes}}
|
||||
includes: ${{inputs.includes}}
|
||||
checkout: ${{inputs.checkout}}
|
||||
|
||||
+249
-48
@@ -10,6 +10,73 @@ on:
|
||||
branches:
|
||||
- "**"
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
pipeline:
|
||||
type: string
|
||||
description: "Directives e.g. '[ci only it]'"
|
||||
checkout:
|
||||
type: string
|
||||
description: "Checkout commit instead of HEAD"
|
||||
cargo_profiles:
|
||||
type: string
|
||||
default: '["test", "bench", "release", "release-debuginfo", "release-native"]'
|
||||
description: "Matrix Selector: Cargo profiles"
|
||||
feat_sets:
|
||||
type: string
|
||||
default: '["none", "default", "logging", "all"]'
|
||||
description: "Matrix Selector: Cargo feature sets"
|
||||
rust_toolchains:
|
||||
type: string
|
||||
default: '["nightly", "stable"]'
|
||||
description: "Matrix Selector: Rust toolchains"
|
||||
rust_targets:
|
||||
type: string
|
||||
default: '["x86_64-unknown-linux-gnu", "aarch64-unknown-linux-gnu"]'
|
||||
description: "Matrix Selector: Rust targets"
|
||||
sys_names:
|
||||
type: string
|
||||
default: '["debian"]'
|
||||
description: "Matrix Selector: System names"
|
||||
sys_targets:
|
||||
type: string
|
||||
default: '["x86_64-v1-linux-gnu", "x86_64-v2-linux-gnu", "x86_64-v3-linux-gnu", "aarch64-v8-linux-gnu"]'
|
||||
description: "Matrix Selector: System targets"
|
||||
sys_versions:
|
||||
type: string
|
||||
default: '["testing-slim"]'
|
||||
description: "Matrix Selector: System versions"
|
||||
machines:
|
||||
type: string
|
||||
default: '["X64", "ARM64"]'
|
||||
description: "Matrix Selector: Machine architectures"
|
||||
runners:
|
||||
type: string
|
||||
default: '["het", "aws"]'
|
||||
description: "Matrix Selector: Runner labels"
|
||||
package_containers:
|
||||
type: string
|
||||
default: '["docker", "oci"]'
|
||||
description: "Bake Selector: Container packages"
|
||||
package_distros:
|
||||
type: string
|
||||
default: '["deb", "rpm", "nix"]'
|
||||
description: "Bake Selector: Distro packages"
|
||||
enable_lint:
|
||||
type: boolean
|
||||
default: true
|
||||
description: Enable linting stage
|
||||
enable_test:
|
||||
type: boolean
|
||||
default: true
|
||||
description: Enable testing stage
|
||||
enable_package:
|
||||
type: boolean
|
||||
default: false
|
||||
description: Enable packaging stage
|
||||
enable_publish:
|
||||
type: boolean
|
||||
default: false
|
||||
description: Enable publication stage
|
||||
|
||||
concurrency:
|
||||
group: ${{github.workflow}}-${{github.ref}}
|
||||
@@ -20,39 +87,81 @@ jobs:
|
||||
name: Init
|
||||
runs-on: ${{matrix.runner}}
|
||||
env:
|
||||
default_cargo_profiles: '["test", "release"]'
|
||||
default_cargo_profiles: '["test", "bench", "release"]'
|
||||
default_feat_sets: '["none", "default", "all"]'
|
||||
default_rust_toolchains: '["nightly", "stable"]'
|
||||
default_sys_names: '["debian"]'
|
||||
default_sys_versions: '["testing-slim"]'
|
||||
default_rust_targets: '["x86_64-unknown-linux-gnu"]'
|
||||
default_sys_targets: '["x86_64-linux-gnu"]'
|
||||
default_sys_targets: '["x86_64-v1-linux-gnu", "x86_64-v3-linux-gnu"]'
|
||||
default_machines: '["X64"]'
|
||||
default_package_containers: '["docker", "oci"]'
|
||||
default_package_distros: '["deb", "rpm", "nix"]'
|
||||
is_release: ${{contains(github.ref, 'tags/v')}}
|
||||
is_branch: ${{contains(github.ref, 'refs/heads')}}
|
||||
is_pull: ${{contains(github.ref, 'refs/pull')}}
|
||||
is_main: ${{github.ref == 'refs/heads/main'}}
|
||||
is_test: ${{github.ref == 'refs/heads/test'}}
|
||||
is_dev: ${{contains(github.ref, 'refs/heads') && github.ref != 'refs/heads/main' && github.ref != 'refs/heads/test'}}
|
||||
is_fat: ${{contains(github.ref, 'tags/v') || github.ref == 'refs/heads/main' || github.ref == 'refs/heads/test'}}
|
||||
|
||||
outputs:
|
||||
cargo_profiles: ${{vars.CARGO_PROFILES || env.default_cargo_profiles}}
|
||||
feat_sets: ${{vars.FEAT_SETS || env.default_feat_sets}}
|
||||
rust_toolchains: ${{vars.RUST_TOOLCHAINS || env.default_rust_toolchains}}
|
||||
rust_targets: ${{vars.RUST_TARGETS || env.default_rust_targets}}
|
||||
sys_names: ${{vars.SYS_NAMES || env.default_sys_names}}
|
||||
sys_targets: ${{vars.SYS_TARGETS || env.default_sys_targets}}
|
||||
sys_versions: ${{vars.SYS_VERSIONS || env.default_sys_versions}}
|
||||
machines: ${{vars.MACHINES || env.default_machines}}
|
||||
cargo_profiles: ${{inputs.cargo_profiles || vars.CARGO_PROFILES || env.default_cargo_profiles}}
|
||||
feat_sets: ${{inputs.feat_sets || vars.FEAT_SETS || env.default_feat_sets}}
|
||||
rust_toolchains: ${{inputs.rust_toolchains || vars.RUST_TOOLCHAINS || env.default_rust_toolchains}}
|
||||
rust_targets: ${{inputs.rust_targets || vars.RUST_TARGETS || env.default_rust_targets}}
|
||||
sys_names: ${{inputs.sys_names || vars.SYS_NAMES || env.default_sys_names}}
|
||||
sys_targets: ${{inputs.sys_targets || vars.SYS_TARGETS || env.default_sys_targets}}
|
||||
sys_versions: ${{inputs.sys_versions || vars.SYS_VERSIONS || env.default_sys_versions}}
|
||||
machines: ${{inputs.machines || (fromJSON(env.is_fat) && vars.MACHINES) || env.default_machines}}
|
||||
pipeline: ${{inputs.pipeline || github.event.head_commit.message || github.event.workflow_run.head_commit.message}}
|
||||
checkout: ${{inputs.checkout || github.sha}}
|
||||
enable_lint: ${{fromJSON(inputs.enable_lint || 'true')}}
|
||||
enable_test: ${{fromJSON(inputs.enable_test || 'true')}}
|
||||
enable_test_unit: ${{fromJSON(inputs.enable_test_unit || 'true')}}
|
||||
enable_test_docs: ${{fromJSON(inputs.enable_test_docs || 'true')}}
|
||||
enable_test_bench: ${{fromJSON(inputs.enable_test_bench || 'true')}}
|
||||
enable_test_memcheck: ${{fromJSON(inputs.enable_test_memcheck || 'true')}}
|
||||
enable_test_smoke: ${{fromJSON(inputs.enable_test_smoke || 'true')}}
|
||||
enable_test_nix: ${{fromJSON(inputs.enable_test_nix || 'true')}}
|
||||
enable_test_rustsdk: ${{fromJSON(inputs.enable_test_rustsdk || 'true')}}
|
||||
enable_test_complement: ${{fromJSON(inputs.enable_test_complement || 'true')}}
|
||||
complement_verbose: ${{fromJSON(inputs.complement_verbose || 'false')}}
|
||||
complement_runner: 'het'
|
||||
enable_package: ${{fromJSON(inputs.enable_package || 'true')}}
|
||||
enable_package_book: ${{fromJSON(inputs.enable_package_book || 'true')}}
|
||||
enable_package_binary: ${{fromJSON(inputs.enable_package_binary || 'true')}}
|
||||
enable_package_container: ${{fromJSON(inputs.enable_package_container || env.is_fat || 'true')}}
|
||||
package_containers: ${{inputs.package_containers || env.default_package_containers}}
|
||||
enable_package_distro: ${{fromJSON(inputs.enable_package_distro || env.is_fat || 'false')}}
|
||||
package_distros: ${{inputs.package_distros || env.default_package_distros}}
|
||||
enable_package_checks: ${{fromJSON(inputs.enable_package_checks || env.is_test || 'false')}}
|
||||
enable_publish: ${{fromJSON(inputs.enable_publish || 'true')}}
|
||||
is_release: ${{fromJSON(env.is_release || 'false')}}
|
||||
is_main: ${{fromJSON(env.is_main || 'false')}}
|
||||
is_test: ${{fromJSON(env.is_test || 'false')}}
|
||||
is_pull: ${{fromJSON(env.is_pull || 'false')}}
|
||||
is_fat: ${{fromJSON(env.is_fat || 'false')}}
|
||||
is_dev: ${{fromJSON(env.is_dev || 'true')}}
|
||||
pages_url: 'https://matrix-construct.github.io/tuwunel/'
|
||||
release_url: ${{steps.release.outputs.upload_url}}
|
||||
docker_repo: ${{vars.DOCKER_REPO}}
|
||||
docker_acct: ${{vars.DOCKER_ACCT}}
|
||||
|
||||
strategy:
|
||||
fail-fast: true
|
||||
matrix:
|
||||
runner: ${{fromJSON(vars.RUNNERS)}}
|
||||
machine: ${{fromJSON(vars.MACHINES)}}
|
||||
exclude: ${{fromJSON(vars.RUNNERS_EXCLUDES)}}
|
||||
runner: ${{fromJSON(inputs.runners || vars.RUNNERS || '["het"]')}}
|
||||
machine: ${{fromJSON(inputs.machines || vars.MACHINES || '["X64"]')}}
|
||||
exclude: ${{fromJSON(vars.RUNNERS_EXCLUDES || '[]')}}
|
||||
|
||||
steps:
|
||||
- name: Initialize Builder
|
||||
env:
|
||||
runner: ${{matrix.runner}}
|
||||
reserved_space: '{"het": "256GB", "aws": "48GB", "gcp": "160GB"}'
|
||||
max_used_space: '{"het": "448GB", "aws": "64GB", "gcp": "192GB"}'
|
||||
reserved_space: '{"het": "192GB", "aws": "48GB", "gcp": "160GB"}'
|
||||
max_used_space: '{"het": "384GB", "aws": "64GB", "gcp": "192GB"}'
|
||||
min_free_space: '{"het": "512GB", "aws": "16GB", "gcp": "16GB"}'
|
||||
run: |
|
||||
set +e
|
||||
docker buildx inspect "${GITHUB_ACTOR}"
|
||||
@@ -63,6 +172,7 @@ jobs:
|
||||
set -eux
|
||||
reserved_space=$(echo -n "$reserved_space" | jq -r ".$runner")
|
||||
max_used_space=$(echo -n "$max_used_space" | jq -r ".$runner")
|
||||
min_free_space=$(echo -n "$min_free_space" | jq -r ".$runner")
|
||||
cat <<EOF > ./buildkitd.toml
|
||||
[system]
|
||||
platformsCacheMaxAge = "504h"
|
||||
@@ -72,11 +182,16 @@ jobs:
|
||||
gc = true
|
||||
reservedSpace = "${reserved_space}"
|
||||
maxUsedSpace = "${max_used_space}"
|
||||
minFreeSpace = "${min_free_space}"
|
||||
[[worker.oci.gcpolicy]]
|
||||
reservedSpace = "${reserved_space}"
|
||||
maxUsedSpace = "${max_used_space}"
|
||||
minFreeSpace = "${min_free_space}"
|
||||
filters = ["label!=cache==pin"]
|
||||
all = true
|
||||
[[worker.oci.gcpolicy]]
|
||||
minFreeSpace = "${min_free_space}"
|
||||
all = true
|
||||
EOF
|
||||
|
||||
docker buildx create \
|
||||
@@ -106,12 +221,16 @@ jobs:
|
||||
lint:
|
||||
if: >
|
||||
!failure() && !cancelled()
|
||||
&& !contains(github.ref, 'refs/tags/v')
|
||||
&& fromJSON(needs.init.outputs.enable_lint)
|
||||
&& !fromJSON(needs.init.outputs.is_release)
|
||||
&& !contains(needs.init.outputs.pipeline, '[ci no lint]')
|
||||
&& !contains(needs.init.outputs.pipeline, '[ci only it]')
|
||||
|
||||
name: Lint
|
||||
needs: [init] #needs: [init, deps]
|
||||
uses: ./.github/workflows/lint.yml
|
||||
with:
|
||||
checkout: ${{needs.init.outputs.checkout}}
|
||||
cargo_profiles: ${{needs.init.outputs.cargo_profiles}}
|
||||
feat_sets: ${{needs.init.outputs.feat_sets}}
|
||||
rust_toolchains: ${{needs.init.outputs.rust_toolchains}}
|
||||
@@ -122,34 +241,58 @@ jobs:
|
||||
machines: ${{needs.init.outputs.machines}}
|
||||
excludes: >
|
||||
[
|
||||
{"cargo_profile": "test", "feat_set": "logging"},
|
||||
{"cargo_profile": "test", "rust_toolchain": "stable", "feat_set": "none"},
|
||||
{"cargo_profile": "test", "rust_target": "aarch64-unknown-linux-gnu"},
|
||||
{"cargo_profile": "bench"},
|
||||
{"cargo_profile": "release", "rust_toolchain": "nightly", "feat_set": "none"},
|
||||
{"cargo_profile": "release", "rust_toolchain": "nightly", "feat_set": "default"},
|
||||
{"cargo_profile": "release", "rust_toolchain": "nightly", "feat_set": "logging"},
|
||||
{"cargo_profile": "release-debuginfo"},
|
||||
{"cargo_profile": "release-native", "rust_toolchain": "stable"},
|
||||
{"cargo_profile": "release-native", "feat_set": "none"},
|
||||
{"cargo_profile": "release-native", "feat_set": "default"},
|
||||
{"cargo_profile": "release-native", "feat_set": "logging"},
|
||||
{"cargo_profile": "release-native", "rust_toolchain": "stable"},
|
||||
{"cargo_profile": "release-native", "rust_target": "aarch64-unknown-linux-gnu"},
|
||||
{"rust_target": "aarch64-unknown-linux-gnu", "feat_set": "none"},
|
||||
{"rust_target": "aarch64-unknown-linux-gnu", "feat_set": "default"},
|
||||
{"rust_target": "aarch64-unknown-linux-gnu", "feat_set": "logging"},
|
||||
{"rust_target": "aarch64-unknown-linux-gnu", "rust_toolchain": "nightly"},
|
||||
{"rust_target": "aarch64-unknown-linux-gnu", "sys_target": "x86_64-linux-gnu"},
|
||||
{"rust_target": "x86_64-unknown-linux-gnu", "sys_target": "aarch64-linux-gnu"},
|
||||
{"sys_target": "x86_64-linux-gnu", "machine": "ARM64"},
|
||||
{"sys_target": "aarch64-linux-gnu", "machine": "X64"},
|
||||
{"rust_target": "aarch64-unknown-linux-gnu", "sys_target": "x86_64-v1-linux-gnu"},
|
||||
{"rust_target": "aarch64-unknown-linux-gnu", "sys_target": "x86_64-v2-linux-gnu"},
|
||||
{"rust_target": "aarch64-unknown-linux-gnu", "sys_target": "x86_64-v3-linux-gnu"},
|
||||
{"rust_target": "aarch64-unknown-linux-gnu", "sys_target": "x86_64-v4-linux-gnu"},
|
||||
{"rust_target": "x86_64-unknown-linux-gnu", "sys_target": "aarch64-v8-linux-gnu"},
|
||||
{"sys_target": "aarch64-v8-linux-gnu", "machine": "X64"},
|
||||
{"sys_target": "x86_64-v1-linux-gnu", "machine": "ARM64"},
|
||||
{"sys_target": "x86_64-v2-linux-gnu"},
|
||||
{"sys_target": "x86_64-v3-linux-gnu"},
|
||||
{"sys_target": "x86_64-v4-linux-gnu"},
|
||||
]
|
||||
|
||||
test:
|
||||
if: >
|
||||
!failure() && !cancelled()
|
||||
&& !contains(github.ref, 'refs/tags/v')
|
||||
&& fromJSON(needs.init.outputs.enable_test)
|
||||
&& !fromJSON(needs.init.outputs.is_release)
|
||||
&& !contains(needs.init.outputs.pipeline, '[ci no test]')
|
||||
|
||||
name: Test
|
||||
needs: [init, lint]
|
||||
uses: ./.github/workflows/test.yml
|
||||
with:
|
||||
complement: ${{fromJSON(vars.COMPLEMENT || 'true')}}
|
||||
pipeline: ${{needs.init.outputs.pipeline}}
|
||||
checkout: ${{needs.init.outputs.checkout}}
|
||||
enable_docs: ${{needs.init.outputs.enable_test_docs}}
|
||||
enable_unit: ${{needs.init.outputs.enable_test_unit}}
|
||||
enable_bench: ${{needs.init.outputs.enable_test_bench}}
|
||||
enable_memcheck: ${{needs.init.outputs.enable_test_memcheck}}
|
||||
enable_smoke: ${{needs.init.outputs.enable_test_smoke}}
|
||||
enable_nix: ${{needs.init.outputs.enable_test_nix}}
|
||||
enable_rustsdk: ${{needs.init.outputs.enable_test_rustsdk}}
|
||||
enable_complement: ${{needs.init.outputs.enable_test_complement}}
|
||||
complement_runner: ${{needs.init.outputs.complement_runner}}
|
||||
complement_verbose: ${{needs.init.outputs.complement_verbose}}
|
||||
cargo_profiles: ${{needs.init.outputs.cargo_profiles}}
|
||||
feat_sets: ${{needs.init.outputs.feat_sets}}
|
||||
rust_toolchains: ${{needs.init.outputs.rust_toolchains}}
|
||||
@@ -158,33 +301,57 @@ jobs:
|
||||
sys_targets: ${{needs.init.outputs.sys_targets}}
|
||||
sys_versions: ${{needs.init.outputs.sys_versions}}
|
||||
machines: ${{needs.init.outputs.machines}}
|
||||
complement_runner: 'het'
|
||||
excludes: >
|
||||
[
|
||||
{"cargo_profile": "test", "rust_toolchain": "stable", "feat_set": "none"},
|
||||
{"cargo_profile": "test", "rust_target": "aarch64-unknown-linux-gnu"},
|
||||
{"cargo_profile": "release-debuginfo"},
|
||||
{"cargo_profile": "release-native", "rust_toolchain": "stable"},
|
||||
{"cargo_profile": "release-native", "feat_set": "default"},
|
||||
{"cargo_profile": "release-native", "feat_set": "none"},
|
||||
{"cargo_profile": "release-native", "feat_set": "default"},
|
||||
{"cargo_profile": "release-native", "rust_toolchain": "stable"},
|
||||
{"cargo_profile": "release-native", "rust_target": "aarch64-unknown-linux-gnu"},
|
||||
{"rust_target": "aarch64-unknown-linux-gnu", "feat_set": "none"},
|
||||
{"rust_target": "aarch64-unknown-linux-gnu", "feat_set": "default"},
|
||||
{"rust_target": "aarch64-unknown-linux-gnu", "feat_set": "logging"},
|
||||
{"rust_target": "aarch64-unknown-linux-gnu", "rust_toolchain": "nightly"},
|
||||
{"rust_target": "aarch64-unknown-linux-gnu", "sys_target": "x86_64-linux-gnu"},
|
||||
{"rust_target": "x86_64-unknown-linux-gnu", "sys_target": "aarch64-linux-gnu"},
|
||||
{"sys_target": "x86_64-linux-gnu", "machine": "ARM64"},
|
||||
{"sys_target": "aarch64-linux-gnu", "machine": "X64"},
|
||||
{"rust_target": "aarch64-unknown-linux-gnu", "sys_target": "x86_64-v1-linux-gnu"},
|
||||
{"rust_target": "aarch64-unknown-linux-gnu", "sys_target": "x86_64-v2-linux-gnu"},
|
||||
{"rust_target": "aarch64-unknown-linux-gnu", "sys_target": "x86_64-v3-linux-gnu"},
|
||||
{"rust_target": "aarch64-unknown-linux-gnu", "sys_target": "x86_64-v4-linux-gnu"},
|
||||
{"rust_target": "x86_64-unknown-linux-gnu", "sys_target": "aarch64-v8-linux-gnu"},
|
||||
{"sys_target": "aarch64-v8-linux-gnu", "machine": "X64"},
|
||||
{"sys_target": "x86_64-v1-linux-gnu", "machine": "ARM64"},
|
||||
{"sys_target": "x86_64-v2-linux-gnu", "machine": "ARM64"},
|
||||
{"sys_target": "x86_64-v2-linux-gnu", "feat_set": "none"},
|
||||
{"sys_target": "x86_64-v2-linux-gnu", "feat_set": "default"},
|
||||
{"sys_target": "x86_64-v3-linux-gnu", "machine": "ARM64"},
|
||||
{"sys_target": "x86_64-v3-linux-gnu", "feat_set": "none"},
|
||||
{"sys_target": "x86_64-v3-linux-gnu", "feat_set": "default"},
|
||||
{"sys_target": "x86_64-v4-linux-gnu", "machine": "ARM64"},
|
||||
{"sys_target": "x86_64-v4-linux-gnu", "feat_set": "none"},
|
||||
{"sys_target": "x86_64-v4-linux-gnu", "feat_set": "default"},
|
||||
]
|
||||
|
||||
package:
|
||||
if: >
|
||||
!failure() && !cancelled()
|
||||
&& fromJSON(needs.init.outputs.enable_package)
|
||||
&& !contains(needs.init.outputs.pipeline, '[ci only it]')
|
||||
&& !contains(needs.init.outputs.pipeline, '[ci no build]')
|
||||
&& !contains(needs.init.outputs.pipeline, '[ci no package]')
|
||||
|
||||
name: Package
|
||||
needs: [init, lint]
|
||||
needs: [init, test]
|
||||
uses: ./.github/workflows/package.yml
|
||||
with:
|
||||
enable_book: ${{needs.init.outputs.enable_package_book}}
|
||||
enable_binary: ${{needs.init.outputs.enable_package_binary}}
|
||||
enable_container: ${{needs.init.outputs.enable_package_container}}
|
||||
enable_distro: ${{needs.init.outputs.enable_package_distro}}
|
||||
enable_checks: ${{needs.init.outputs.enable_package_checks}}
|
||||
distros: ${{needs.init.outputs.package_distros}}
|
||||
containers: ${{needs.init.outputs.package_containers}}
|
||||
checkout: ${{needs.init.outputs.checkout}}
|
||||
release_url: ${{needs.init.outputs.release_url}}
|
||||
cargo_profiles: ${{needs.init.outputs.cargo_profiles}}
|
||||
feat_sets: ${{needs.init.outputs.feat_sets}}
|
||||
@@ -198,34 +365,58 @@ jobs:
|
||||
[
|
||||
{"feat_set": "none"},
|
||||
{"cargo_profile": "test"},
|
||||
{"cargo_profile": "bench"},
|
||||
{"cargo_profile": "release-native"},
|
||||
{"cargo_profile": "release-debuginfo", "feat_set": "default"},
|
||||
{"cargo_profile": "release-debuginfo", "feat_set": "logging"},
|
||||
{"cargo_profile": "release-debuginfo", "rust_toolchain": "nightly"},
|
||||
{"cargo_profile": "release-debuginfo", "bake_target": "oci"},
|
||||
{"cargo_profile": "release-debuginfo", "rust_target": "aarch64-unknown-linux-gnu"},
|
||||
{"cargo_profile": "release-native", "feat_set": "default"},
|
||||
{"cargo_profile": "release-native", "rust_toolchain": "stable"},
|
||||
{"cargo_profile": "release-native", "feat_set": "default"},
|
||||
{"cargo_profile": "release-native", "bake_target": "docker"},
|
||||
{"cargo_profile": "release-native", "bake_target": "oci"},
|
||||
{"cargo_profile": "release-native", "rust_target": "aarch64-unknown-linux-gnu"},
|
||||
{"cargo_profile": "release-debuginfo", "sys_target": "x86_64-v2-linux-gnu"},
|
||||
{"cargo_profile": "release-debuginfo", "sys_target": "x86_64-v3-linux-gnu"},
|
||||
{"cargo_profile": "release-debuginfo", "sys_target": "x86_64-v4-linux-gnu"},
|
||||
{"cargo_profile": "release", "rust_toolchain": "nightly"},
|
||||
{"rust_target": "aarch64-unknown-linux-gnu", "feat_set": "default"},
|
||||
{"rust_target": "aarch64-unknown-linux-gnu", "sys_target": "x86_64-linux-gnu"},
|
||||
{"rust_target": "x86_64-unknown-linux-gnu", "sys_target": "aarch64-linux-gnu"},
|
||||
{"sys_target": "x86_64-linux-gnu", "machine": "ARM64"},
|
||||
{"sys_target": "aarch64-linux-gnu", "machine": "X64"},
|
||||
{"rust_target": "aarch64-unknown-linux-gnu", "bake_target": "nix"},
|
||||
{"rust_target": "aarch64-unknown-linux-gnu", "sys_target": "x86_64-v1-linux-gnu"},
|
||||
{"rust_target": "aarch64-unknown-linux-gnu", "sys_target": "x86_64-v2-linux-gnu"},
|
||||
{"rust_target": "aarch64-unknown-linux-gnu", "sys_target": "x86_64-v3-linux-gnu"},
|
||||
{"rust_target": "aarch64-unknown-linux-gnu", "sys_target": "x86_64-v4-linux-gnu"},
|
||||
{"rust_target": "x86_64-unknown-linux-gnu", "sys_target": "aarch64-v8-linux-gnu"},
|
||||
{"sys_target": "aarch64-v8-linux-gnu", "machine": "X64"},
|
||||
{"sys_target": "x86_64-v1-linux-gnu", "machine": "ARM64"},
|
||||
{"sys_target": "x86_64-v2-linux-gnu", "machine": "ARM64"},
|
||||
{"sys_target": "x86_64-v2-linux-gnu", "feat_set": "default"},
|
||||
{"sys_target": "x86_64-v2-linux-gnu", "feat_set": "logging"},
|
||||
{"sys_target": "x86_64-v2-linux-gnu", "bake_target": "nix"},
|
||||
{"sys_target": "x86_64-v3-linux-gnu", "machine": "ARM64"},
|
||||
{"sys_target": "x86_64-v3-linux-gnu", "feat_set": "default"},
|
||||
{"sys_target": "x86_64-v3-linux-gnu", "feat_set": "logging"},
|
||||
{"sys_target": "x86_64-v3-linux-gnu", "bake_target": "nix"},
|
||||
{"sys_target": "x86_64-v4-linux-gnu", "machine": "ARM64"},
|
||||
{"sys_target": "x86_64-v4-linux-gnu", "feat_set": "default"},
|
||||
{"sys_target": "x86_64-v4-linux-gnu", "feat_set": "logging"},
|
||||
{"sys_target": "x86_64-v4-linux-gnu", "bake_target": "nix"},
|
||||
]
|
||||
|
||||
publish:
|
||||
if: >
|
||||
!failure() && !cancelled()
|
||||
&& fromJSON(needs.init.outputs.enable_publish)
|
||||
&& !contains(needs.init.outputs.pipeline, '[ci only it]')
|
||||
&& !contains(needs.init.outputs.pipeline, '[ci no build]')
|
||||
&& !contains(needs.init.outputs.pipeline, '[ci no package]')
|
||||
&& !contains(needs.init.outputs.pipeline, '[ci no publish]')
|
||||
|
||||
name: Publish
|
||||
needs: [init, test, package]
|
||||
uses: ./.github/workflows/publish.yml
|
||||
with:
|
||||
docker_repo: ${{vars.DOCKER_REPO}}
|
||||
checkout: ${{needs.init.outputs.checkout}}
|
||||
docker_repo: ${{needs.init.outputs.docker_repo}}
|
||||
docker_acct: ${{needs.init.outputs.docker_acct}}
|
||||
release_url: ${{needs.init.outputs.release_url}}
|
||||
pages_url: ${{needs.init.outputs.pages_url}}
|
||||
cargo_profiles: ${{needs.init.outputs.cargo_profiles}}
|
||||
feat_sets: ${{needs.init.outputs.feat_sets}}
|
||||
rust_toolchains: ${{needs.init.outputs.rust_toolchains}}
|
||||
@@ -237,15 +428,25 @@ jobs:
|
||||
excludes: >
|
||||
[
|
||||
{"feat_set": "none"},
|
||||
{"feat_set": "default"},
|
||||
{"cargo_profile": "test"},
|
||||
{"cargo_profile": "bench"},
|
||||
{"cargo_profile": "release-debuginfo"},
|
||||
{"cargo_profile": "release-native"},
|
||||
{"cargo_profile": "release", "rust_toolchain": "nightly"},
|
||||
{"rust_target": "aarch64-unknown-linux-gnu", "feat_set": "default"},
|
||||
{"rust_target": "aarch64-unknown-linux-gnu", "sys_target": "x86_64-linux-gnu"},
|
||||
{"rust_target": "x86_64-unknown-linux-gnu", "sys_target": "aarch64-linux-gnu"},
|
||||
{"sys_target": "x86_64-linux-gnu", "machine": "ARM64"},
|
||||
{"sys_target": "aarch64-linux-gnu", "machine": "X64"},
|
||||
{"rust_toolchain": "nightly"},
|
||||
{"rust_target": "aarch64-unknown-linux-gnu", "sys_target": "x86_64-v1-linux-gnu"},
|
||||
{"rust_target": "aarch64-unknown-linux-gnu", "sys_target": "x86_64-v2-linux-gnu"},
|
||||
{"rust_target": "aarch64-unknown-linux-gnu", "sys_target": "x86_64-v3-linux-gnu"},
|
||||
{"rust_target": "aarch64-unknown-linux-gnu", "sys_target": "x86_64-v4-linux-gnu"},
|
||||
{"rust_target": "x86_64-unknown-linux-gnu", "sys_target": "aarch64-v8-linux-gnu"},
|
||||
{"sys_target": "aarch64-v8-linux-gnu", "machine": "X64"},
|
||||
{"sys_target": "x86_64-v1-linux-gnu", "machine": "ARM64"},
|
||||
{"sys_target": "x86_64-v2-linux-gnu", "machine": "ARM64"},
|
||||
{"sys_target": "x86_64-v2-linux-gnu", "feat_set": "logging"},
|
||||
{"sys_target": "x86_64-v3-linux-gnu", "machine": "ARM64"},
|
||||
{"sys_target": "x86_64-v3-linux-gnu", "feat_set": "logging"},
|
||||
{"sys_target": "x86_64-v4-linux-gnu", "machine": "ARM64"},
|
||||
{"sys_target": "x86_64-v4-linux-gnu", "feat_set": "logging"},
|
||||
]
|
||||
|
||||
secrets:
|
||||
|
||||
@@ -38,15 +38,40 @@ on:
|
||||
release_url:
|
||||
type: string
|
||||
description: For release assets
|
||||
checkout:
|
||||
type: string
|
||||
default: 'HEAD'
|
||||
enable_book:
|
||||
type: string
|
||||
default: 'true'
|
||||
enable_binary:
|
||||
type: string
|
||||
default: 'true'
|
||||
enable_container:
|
||||
type: string
|
||||
default: 'true'
|
||||
enable_distro:
|
||||
type: string
|
||||
default: 'true'
|
||||
enable_checks:
|
||||
type: string
|
||||
default: 'true'
|
||||
containers:
|
||||
type: string
|
||||
default: '["docker", "oci"]'
|
||||
distros:
|
||||
type: string
|
||||
default: '["deb", "rpm", "nix"]'
|
||||
|
||||
jobs:
|
||||
book:
|
||||
if: >
|
||||
!failure() && !cancelled()
|
||||
&& fromJSON(inputs.enable_book)
|
||||
&& contains(fromJSON(inputs.cargo_profiles), fromJSON('["release"]')[0])
|
||||
&& contains(fromJSON(inputs.feat_sets), fromJSON('["default"]')[0])
|
||||
&& contains(fromJSON(inputs.rust_toolchains), fromJSON('["stable"]')[0])
|
||||
&& contains(fromJSON(inputs.machines), fromJSON('["X64"]')[0])
|
||||
&& contains(fromJSON(inputs.sys_targets), fromJSON('["x86_64-v1-linux-gnu"]')[0])
|
||||
|
||||
name: Book
|
||||
uses: ./.github/workflows/bake.yml
|
||||
@@ -57,13 +82,14 @@ jobs:
|
||||
rust_toolchains: '["stable"]'
|
||||
rust_targets: ${{inputs.rust_targets}}
|
||||
sys_names: ${{inputs.sys_names}}
|
||||
sys_targets: ${{inputs.sys_targets}}
|
||||
sys_versions: ${{inputs.sys_versions}}
|
||||
machines: '["X64"]'
|
||||
sys_targets: '["x86_64-v1-linux-gnu"]'
|
||||
machines: ${{inputs.machines}}
|
||||
runner: 'het'
|
||||
excludes: ${{inputs.excludes}}
|
||||
includes: ${{inputs.includes}}
|
||||
release_url: ${{inputs.release_url}}
|
||||
checkout: ${{inputs.checkout}}
|
||||
artifact: >
|
||||
{
|
||||
"book": {
|
||||
@@ -76,6 +102,7 @@ jobs:
|
||||
binary:
|
||||
if: >
|
||||
!failure() && !cancelled()
|
||||
&& fromJSON(inputs.enable_binary)
|
||||
|
||||
name: Binaries
|
||||
uses: ./.github/workflows/bake.yml
|
||||
@@ -92,6 +119,7 @@ jobs:
|
||||
excludes: ${{inputs.excludes}}
|
||||
includes: ${{inputs.includes}}
|
||||
release_url: ${{inputs.release_url}}
|
||||
checkout: ${{inputs.checkout}}
|
||||
artifact: >
|
||||
{
|
||||
"static": {
|
||||
@@ -106,11 +134,12 @@ jobs:
|
||||
container:
|
||||
if: >
|
||||
!failure() && !cancelled()
|
||||
&& fromJSON(inputs.enable_container)
|
||||
|
||||
name: Containers
|
||||
uses: ./.github/workflows/bake.yml
|
||||
with:
|
||||
bake_targets: '["docker", "oci"]'
|
||||
bake_targets: ${{inputs.containers}}
|
||||
cargo_profiles: ${{inputs.cargo_profiles}}
|
||||
feat_sets: ${{inputs.feat_sets}}
|
||||
rust_toolchains: ${{inputs.rust_toolchains}}
|
||||
@@ -122,6 +151,7 @@ jobs:
|
||||
excludes: ${{inputs.excludes}}
|
||||
includes: ${{inputs.includes}}
|
||||
release_url: ${{inputs.release_url}}
|
||||
checkout: ${{inputs.checkout}}
|
||||
artifact: >
|
||||
{
|
||||
"docker": {
|
||||
@@ -138,18 +168,18 @@ jobs:
|
||||
}
|
||||
}
|
||||
|
||||
pkgs:
|
||||
distro:
|
||||
if: >
|
||||
!failure() && !cancelled()
|
||||
&& fromJSON(inputs.enable_distro)
|
||||
&& contains(fromJSON(inputs.feat_sets), fromJSON('["all"]')[0])
|
||||
&& contains(fromJSON(inputs.cargo_profiles), fromJSON('["release"]')[0])
|
||||
&& contains(fromJSON(inputs.rust_toolchains), fromJSON('["stable"]')[0])
|
||||
&& (github.ref == 'refs/heads/main' || contains(github.ref, 'refs/tags/v'))
|
||||
|
||||
name: Distro Packages
|
||||
uses: ./.github/workflows/bake.yml
|
||||
with:
|
||||
bake_targets: '["deb", "rpm"]'
|
||||
bake_targets: ${{inputs.distros}}
|
||||
cargo_profiles: '["release"]'
|
||||
feat_sets: '["all"]'
|
||||
rust_toolchains: '["stable"]'
|
||||
@@ -161,6 +191,7 @@ jobs:
|
||||
excludes: ${{inputs.excludes}}
|
||||
includes: ${{inputs.includes}}
|
||||
release_url: ${{inputs.release_url}}
|
||||
checkout: ${{inputs.checkout}}
|
||||
artifact: >
|
||||
{
|
||||
"deb": {
|
||||
@@ -170,19 +201,25 @@ jobs:
|
||||
"rpm": {
|
||||
"dst": "tuwunel.rpm",
|
||||
"mime": "application/x-rpm"
|
||||
},
|
||||
"nix": {
|
||||
"dst": "tuwunel.nix.tar.zst",
|
||||
"src": "/opt/tuwunel.nix.tar",
|
||||
"mime": "application/zstd",
|
||||
"zstd": 11
|
||||
}
|
||||
}
|
||||
|
||||
check_pkgs:
|
||||
checks:
|
||||
if: >
|
||||
!failure() && !cancelled()
|
||||
&& fromJSON(inputs.enable_checks)
|
||||
&& contains(fromJSON(inputs.feat_sets), fromJSON('["all"]')[0])
|
||||
&& contains(fromJSON(inputs.cargo_profiles), fromJSON('["release"]')[0])
|
||||
&& contains(fromJSON(inputs.rust_toolchains), fromJSON('["stable"]')[0])
|
||||
&& github.ref == 'refs/heads/main'
|
||||
|
||||
name: Check Packages
|
||||
needs: [pkgs]
|
||||
needs: [distro]
|
||||
uses: ./.github/workflows/bake.yml
|
||||
with:
|
||||
bake_targets: '["deb-install", "rpm-install"]'
|
||||
@@ -196,3 +233,4 @@ jobs:
|
||||
machines: ${{inputs.machines}}
|
||||
excludes: ${{inputs.excludes}}
|
||||
includes: ${{inputs.includes}}
|
||||
checkout: ${{inputs.checkout}}
|
||||
|
||||
+230
-20
@@ -38,26 +38,39 @@ on:
|
||||
type: string
|
||||
default: '[]'
|
||||
description: Matrix inclusions
|
||||
checkout:
|
||||
type: string
|
||||
default: 'HEAD'
|
||||
docker_repo:
|
||||
type: string
|
||||
description: DockerHub Repository
|
||||
docker_acct:
|
||||
type: string
|
||||
description: DockerHub account name
|
||||
release_url:
|
||||
type: string
|
||||
description: For release assets
|
||||
pages_url:
|
||||
type: string
|
||||
description: For pages deployment
|
||||
|
||||
jobs:
|
||||
documents:
|
||||
if: >
|
||||
!failure() && !cancelled()
|
||||
&& contains(fromJSON(inputs.machines), fromJSON('["X64"]')[0])
|
||||
&& (github.ref == 'refs/heads/main' || contains(github.ref, 'refs/tags/v'))
|
||||
&& !contains(github.ref, '-draft')
|
||||
|
||||
name: Documents
|
||||
runs-on: ['X64', 'het']
|
||||
permissions:
|
||||
pages: write
|
||||
contents: read
|
||||
id-token: write
|
||||
pages: write
|
||||
|
||||
environment:
|
||||
name: github-pages
|
||||
url: ${{inputs.pages_url}}
|
||||
|
||||
steps:
|
||||
- id: book
|
||||
@@ -70,16 +83,14 @@ jobs:
|
||||
&& inputs.machines
|
||||
&& inputs.docker_repo != ''
|
||||
&& (github.ref == 'refs/heads/main' || contains(github.ref, 'refs/tags/v'))
|
||||
&& !contains(github.ref, '-draft')
|
||||
|
||||
name: Containers
|
||||
runs-on: ${{matrix.machine}}
|
||||
permissions: write-all
|
||||
continue-on-error: false
|
||||
strategy:
|
||||
fail-fast: true
|
||||
matrix:
|
||||
bake_target: ${{fromJSON('["github", "dockerhub"]')}}
|
||||
bake_target: ${{fromJSON('["docker_io", "ghcr_io"]')}}
|
||||
cargo_profile: ${{fromJSON(inputs.cargo_profiles)}}
|
||||
rust_toolchain: ${{fromJSON(inputs.rust_toolchains)}}
|
||||
feat_set: ${{fromJSON(inputs.feat_sets)}}
|
||||
@@ -91,6 +102,75 @@ jobs:
|
||||
exclude: ${{fromJSON(inputs.excludes)}}
|
||||
include: ${{fromJSON(inputs.includes)}}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
fetch-depth: 0
|
||||
fetch-tags: true
|
||||
|
||||
- name: GitHub Login
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.ghcr_token }}
|
||||
|
||||
- name: DockerHub Login
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: docker.io
|
||||
username: ${{ inputs.docker_acct }}
|
||||
password: ${{ secrets.dockerhub_token }}
|
||||
|
||||
- name: Bake
|
||||
env:
|
||||
bake_target: ${{matrix.bake_target}}
|
||||
cargo_profile: ${{matrix.cargo_profile}}
|
||||
rust_toolchain: ${{matrix.rust_toolchain}}
|
||||
rust_target: ${{matrix.rust_target}}
|
||||
feat_set: ${{matrix.feat_set}}
|
||||
sys_name: ${{matrix.sys_name}}
|
||||
sys_version: ${{matrix.sys_version}}
|
||||
sys_target: ${{matrix.sys_target}}
|
||||
machine: ${{matrix.machine}}
|
||||
git_checkout: ${{inputs.checkout}}
|
||||
acct: ${{github.actor}}
|
||||
repo: ${{github.repository}}
|
||||
docker_repo: ${{inputs.docker_repo}}
|
||||
|
||||
run: |
|
||||
docker/bake.sh "${{matrix.bake_target}}"
|
||||
|
||||
bundles:
|
||||
if: >
|
||||
!failure() && !cancelled()
|
||||
&& inputs.machines
|
||||
&& inputs.docker_repo != ''
|
||||
&& contains(fromJSON(inputs.cargo_profiles), fromJSON('["release"]')[0])
|
||||
&& contains(fromJSON(inputs.feat_sets), fromJSON('["all"]')[0])
|
||||
&& contains(fromJSON(inputs.rust_toolchains), fromJSON('["stable"]')[0])
|
||||
&& (github.ref == 'refs/heads/main' || contains(github.ref, 'refs/tags/v'))
|
||||
|
||||
name: Bundles
|
||||
needs: [containers]
|
||||
runs-on: 'het'
|
||||
permissions: write-all
|
||||
strategy:
|
||||
fail-fast: true
|
||||
matrix:
|
||||
bake_target: ${{fromJSON('["docker_io", "ghcr_io"]')}}
|
||||
cargo_profile: ${{fromJSON('["release"]')}}
|
||||
feat_set: ${{fromJSON('["all"]')}}
|
||||
rust_toolchain: ${{fromJSON('["stable"]')}}
|
||||
sys_name: ${{fromJSON(inputs.sys_names)}}
|
||||
sys_version: ${{fromJSON(inputs.sys_versions)}}
|
||||
rust_target: ${{fromJSON(inputs.rust_targets)}}
|
||||
sys_target: ${{fromJSON(inputs.sys_targets)}}
|
||||
machine: ${{fromJSON(inputs.machines)}}
|
||||
exclude: ${{fromJSON(inputs.excludes)}}
|
||||
include: ${{fromJSON(inputs.includes)}}
|
||||
|
||||
steps:
|
||||
- name: GitHub Login
|
||||
uses: docker/login-action@v3
|
||||
@@ -103,25 +183,155 @@ jobs:
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: docker.io
|
||||
username: ${{ github.actor }}
|
||||
username: ${{ inputs.docker_acct }}
|
||||
password: ${{ secrets.dockerhub_token }}
|
||||
|
||||
- name: Bake
|
||||
- name: Release Branch
|
||||
if: >
|
||||
!failure() && !cancelled()
|
||||
&& (github.ref == 'refs/heads/main' || contains(github.ref, 'refs/tags/v'))
|
||||
|
||||
env:
|
||||
bake_target: ${{matrix.bake_target}}
|
||||
cargo_profile: ${{matrix.cargo_profile}}
|
||||
rust_toolchain: ${{matrix.rust_toolchain}}
|
||||
rust_target: ${{matrix.rust_target}}
|
||||
feat_set: ${{matrix.feat_set}}
|
||||
sys_name: ${{matrix.sys_name}}
|
||||
sys_version: ${{matrix.sys_version}}
|
||||
sys_target: ${{matrix.sys_target}}
|
||||
machine: ${{matrix.machine}}
|
||||
acct: ${{github.actor}}
|
||||
repo: ${{github.repository}}
|
||||
ghcr_repo: ${{github.repository}}
|
||||
docker_repo: ${{inputs.docker_repo}}
|
||||
docker_tag_preview: ${{ matrix.cargo_profile == 'release' && matrix.feat_set == 'all' && matrix.sys_target == 'x86_64-linux-gnu' && contains(github.ref, 'refs/tags/v') }}
|
||||
docker_tag_latest: ${{ matrix.cargo_profile == 'release' && matrix.feat_set == 'all' && matrix.sys_target == 'x86_64-linux-gnu' && contains(github.ref, 'refs/tags/v') && !contains(github.ref, '-rc') }}
|
||||
registry: ${{matrix.bake_target}}
|
||||
cargo_profile: ${{matrix.cargo_profile}}
|
||||
feat_set: ${{matrix.feat_set}}
|
||||
sys_target: ${{matrix.sys_target}}
|
||||
ref_name: ${{github.ref_name}}
|
||||
|
||||
run: |
|
||||
docker/bake.sh "${{matrix.bake_target}}"
|
||||
registry="$(echo -n $registry | sed s/_/./)"
|
||||
if test "$registry" = "ghcr.io"; then
|
||||
repo="$ghcr_repo"
|
||||
else
|
||||
repo="$docker_repo"
|
||||
fi
|
||||
|
||||
docker manifest create "${registry}/${repo}:${ref_name}" \
|
||||
--amend "${registry}/${repo}:${ref_name}-${cargo_profile}-${feat_set}-${sys_target}"
|
||||
|
||||
- name: Release Preview
|
||||
if: >
|
||||
!failure() && !cancelled()
|
||||
&& contains(github.ref, 'refs/tags/v')
|
||||
&& !contains(github.ref, '-draft')
|
||||
|
||||
env:
|
||||
acct: ${{github.actor}}
|
||||
ghcr_repo: ${{github.repository}}
|
||||
docker_repo: ${{inputs.docker_repo}}
|
||||
registry: ${{matrix.bake_target}}
|
||||
cargo_profile: ${{matrix.cargo_profile}}
|
||||
feat_set: ${{matrix.feat_set}}
|
||||
sys_target: ${{matrix.sys_target}}
|
||||
ref_name: ${{github.ref_name}}
|
||||
|
||||
run: |
|
||||
registry="$(echo -n $registry | sed s/_/./)"
|
||||
if test "$registry" = "ghcr.io"; then
|
||||
repo="$ghcr_repo"
|
||||
else
|
||||
repo="$docker_repo"
|
||||
fi
|
||||
|
||||
docker manifest create "${registry}/${repo}:preview" \
|
||||
--amend "${registry}/${repo}:${ref_name}-${cargo_profile}-${feat_set}-${sys_target}"
|
||||
|
||||
- name: Release Latest
|
||||
if: >
|
||||
!failure() && !cancelled()
|
||||
&& contains(github.ref, 'refs/tags/v')
|
||||
&& !contains(github.ref, '-draft')
|
||||
&& !contains(github.ref, '-rc')
|
||||
|
||||
env:
|
||||
acct: ${{github.actor}}
|
||||
ghcr_repo: ${{github.repository}}
|
||||
docker_repo: ${{inputs.docker_repo}}
|
||||
registry: ${{matrix.bake_target}}
|
||||
cargo_profile: ${{matrix.cargo_profile}}
|
||||
feat_set: ${{matrix.feat_set}}
|
||||
sys_target: ${{matrix.sys_target}}
|
||||
ref_name: ${{github.ref_name}}
|
||||
|
||||
run: |
|
||||
registry="$(echo -n $registry | sed s/_/./)"
|
||||
if test "$registry" = "ghcr.io"; then
|
||||
repo="$ghcr_repo"
|
||||
else
|
||||
repo="$docker_repo"
|
||||
fi
|
||||
|
||||
docker manifest create "${registry}/${repo}:latest" \
|
||||
--amend "${registry}/${repo}:${ref_name}-${cargo_profile}-${feat_set}-${sys_target}"
|
||||
|
||||
delivery:
|
||||
if: >
|
||||
!failure() && !cancelled()
|
||||
&& inputs.machines
|
||||
&& inputs.docker_repo != ''
|
||||
&& (github.ref == 'refs/heads/main' || contains(github.ref, 'refs/tags/v'))
|
||||
|
||||
name: Delivery
|
||||
needs: [bundles, documents]
|
||||
runs-on: 'het'
|
||||
permissions: write-all
|
||||
steps:
|
||||
- name: GitHub Login
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.ghcr_token }}
|
||||
|
||||
- name: DockerHub Login
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: docker.io
|
||||
username: ${{ inputs.docker_acct }}
|
||||
password: ${{ secrets.dockerhub_token }}
|
||||
|
||||
- name: Push Branch
|
||||
if: >
|
||||
!failure() && !cancelled()
|
||||
&& (github.ref == 'refs/heads/main' || contains(github.ref, 'refs/tags/v'))
|
||||
|
||||
env:
|
||||
ref_name: ${{github.ref_name}}
|
||||
ghcr_repo: ${{github.repository}}
|
||||
docker_repo: ${{inputs.docker_repo}}
|
||||
|
||||
run: |
|
||||
docker manifest push -p "ghcr.io/${ghcr_repo}:${ref_name}"
|
||||
docker manifest push -p "docker.io/${docker_repo}:${ref_name}"
|
||||
|
||||
- name: Push Preview
|
||||
if: >
|
||||
!failure() && !cancelled()
|
||||
&& contains(github.ref, 'refs/tags/v')
|
||||
&& !contains(github.ref, '-draft')
|
||||
|
||||
env:
|
||||
ghcr_repo: ${{github.repository}}
|
||||
docker_repo: ${{inputs.docker_repo}}
|
||||
|
||||
run: |
|
||||
docker manifest push -p "ghcr.io/${ghcr_repo}:preview"
|
||||
docker manifest push -p "docker.io/${docker_repo}:preview"
|
||||
|
||||
- name: Push Latest
|
||||
if: >
|
||||
!failure() && !cancelled()
|
||||
&& contains(github.ref, 'refs/tags/v')
|
||||
&& !contains(github.ref, '-draft')
|
||||
&& !contains(github.ref, '-rc')
|
||||
|
||||
env:
|
||||
ghcr_repo: ${{github.repository}}
|
||||
docker_repo: ${{inputs.docker_repo}}
|
||||
|
||||
run: |
|
||||
docker manifest push -p "ghcr.io/${ghcr_repo}:latest"
|
||||
docker manifest push -p "docker.io/${docker_repo}:latest"
|
||||
|
||||
+271
-39
@@ -35,41 +35,151 @@ on:
|
||||
type: string
|
||||
default: '[]'
|
||||
description: Matrix inclusions
|
||||
complement:
|
||||
type: boolean
|
||||
default: true
|
||||
complement_feat_sets:
|
||||
pipeline:
|
||||
type: string
|
||||
default: '["all"]'
|
||||
default: ${{github.event.inputs.pipeline || github.event.workflow_run.head_commit.message}}
|
||||
checkout:
|
||||
type: string
|
||||
default: 'HEAD'
|
||||
enable_docs:
|
||||
type: string
|
||||
default: 'true'
|
||||
enable_unit:
|
||||
type: string
|
||||
default: 'true'
|
||||
enable_bench:
|
||||
type: string
|
||||
default: 'true'
|
||||
enable_memcheck:
|
||||
type: string
|
||||
default: 'true'
|
||||
enable_smoke:
|
||||
type: string
|
||||
default: 'true'
|
||||
enable_nix:
|
||||
type: string
|
||||
default: 'true'
|
||||
enable_rustsdk:
|
||||
type: string
|
||||
default: 'true'
|
||||
enable_complement:
|
||||
type: string
|
||||
default: 'true'
|
||||
complement_runner:
|
||||
type: string
|
||||
default: 'het'
|
||||
complement_verbose:
|
||||
type: string
|
||||
default: 'false'
|
||||
|
||||
jobs:
|
||||
unit:
|
||||
docs:
|
||||
if: >
|
||||
contains(fromJSON(inputs.cargo_profiles), fromJSON('["test"]')[0])
|
||||
fromJSON(inputs.enable_docs)
|
||||
&& !contains(inputs.pipeline, '[ci only it]')
|
||||
&& contains(fromJSON(inputs.cargo_profiles), fromJSON('["test"]')[0])
|
||||
&& contains(fromJSON(inputs.feat_sets), fromJSON('["all"]')[0])
|
||||
&& contains(fromJSON(inputs.rust_toolchains), fromJSON('["nightly"]')[0])
|
||||
&& contains(fromJSON(inputs.machines), fromJSON('["X64"]')[0])
|
||||
&& contains(fromJSON(inputs.sys_targets), fromJSON('["x86_64-v1-linux-gnu"]')[0])
|
||||
|
||||
name: Unit
|
||||
name: Docs
|
||||
uses: ./.github/workflows/bake.yml
|
||||
with:
|
||||
bake_targets: '["unit"]'
|
||||
bake_targets: '["docs"]'
|
||||
cargo_profiles: '["test"]'
|
||||
feat_sets: '["all"]'
|
||||
rust_toolchains: '["nightly"]'
|
||||
sys_names: ${{inputs.sys_names}}
|
||||
sys_versions: ${{inputs.sys_versions}}
|
||||
rust_targets: ${{inputs.rust_targets}}
|
||||
sys_targets: '["x86_64-v1-linux-gnu"]'
|
||||
machines: ${{inputs.machines}}
|
||||
excludes: ${{inputs.excludes}}
|
||||
includes: ${{inputs.includes}}
|
||||
checkout: ${{inputs.checkout}}
|
||||
|
||||
unit:
|
||||
if: >
|
||||
fromJSON(inputs.enable_unit)
|
||||
&& !contains(inputs.pipeline, '[ci only it]')
|
||||
&& contains(fromJSON(inputs.cargo_profiles), fromJSON('["test"]')[0])
|
||||
&& contains(fromJSON(inputs.feat_sets), fromJSON('["all"]')[0])
|
||||
&& contains(fromJSON(inputs.rust_toolchains), fromJSON('["nightly"]')[0])
|
||||
&& contains(fromJSON(inputs.sys_targets), fromJSON('["x86_64-v1-linux-gnu"]')[0])
|
||||
|
||||
name: Module
|
||||
uses: ./.github/workflows/bake.yml
|
||||
with:
|
||||
bake_targets: '["unit", "integ"]'
|
||||
cargo_profiles: '["test"]'
|
||||
feat_sets: '["all"]'
|
||||
rust_toolchains: ${{inputs.rust_toolchains}}
|
||||
sys_names: ${{inputs.sys_names}}
|
||||
sys_versions: ${{inputs.sys_versions}}
|
||||
rust_targets: ${{inputs.rust_targets}}
|
||||
sys_targets: ${{inputs.sys_targets}}
|
||||
machines: '["X64"]'
|
||||
sys_targets: '["x86_64-v1-linux-gnu"]'
|
||||
machines: ${{inputs.machines}}
|
||||
excludes: ${{inputs.excludes}}
|
||||
includes: ${{inputs.includes}}
|
||||
checkout: ${{inputs.checkout}}
|
||||
|
||||
bench:
|
||||
if: >
|
||||
fromJSON(inputs.enable_bench)
|
||||
&& !contains(inputs.pipeline, '[ci only it]')
|
||||
&& contains(fromJSON(inputs.cargo_profiles), fromJSON('["bench"]')[0])
|
||||
&& contains(fromJSON(inputs.feat_sets), fromJSON('["all"]')[0])
|
||||
&& contains(fromJSON(inputs.rust_toolchains), fromJSON('["nightly"]')[0])
|
||||
&& contains(fromJSON(inputs.sys_targets), fromJSON('["x86_64-v3-linux-gnu"]')[0])
|
||||
|
||||
name: Bench
|
||||
uses: ./.github/workflows/bake.yml
|
||||
with:
|
||||
bake_targets: '["unit", "integ"]'
|
||||
cargo_profiles: '["bench"]'
|
||||
feat_sets: '["all"]'
|
||||
rust_toolchains: '["nightly"]'
|
||||
sys_names: ${{inputs.sys_names}}
|
||||
sys_versions: ${{inputs.sys_versions}}
|
||||
rust_targets: ${{inputs.rust_targets}}
|
||||
sys_targets: '["x86_64-v3-linux-gnu"]'
|
||||
machines: ${{inputs.machines}}
|
||||
excludes: ${{inputs.excludes}}
|
||||
includes: ${{inputs.includes}}
|
||||
checkout: ${{inputs.checkout}}
|
||||
|
||||
memcheck:
|
||||
if: >
|
||||
fromJSON(inputs.enable_memcheck)
|
||||
&& !contains(inputs.pipeline, '[ci only it]')
|
||||
&& contains(fromJSON(inputs.cargo_profiles), fromJSON('["bench"]')[0])
|
||||
&& contains(fromJSON(inputs.feat_sets), fromJSON('["all"]')[0])
|
||||
&& contains(fromJSON(inputs.rust_toolchains), fromJSON('["nightly"]')[0])
|
||||
&& contains(fromJSON(inputs.sys_targets), fromJSON('["x86_64-v3-linux-gnu"]')[0])
|
||||
|
||||
name: Memcheck
|
||||
uses: ./.github/workflows/bake.yml
|
||||
with:
|
||||
#bake_targets: '["unit-valgrind", "integ-valgrind"]'
|
||||
bake_targets: '["integ-valgrind"]'
|
||||
cargo_profiles: '["bench"]' # use bench not release for debug syms
|
||||
feat_sets: '["all"]'
|
||||
rust_toolchains: '["nightly"]'
|
||||
sys_names: ${{inputs.sys_names}}
|
||||
sys_versions: ${{inputs.sys_versions}}
|
||||
rust_targets: ${{inputs.rust_targets}}
|
||||
sys_targets: '["x86_64-v3-linux-gnu"]'
|
||||
machines: ${{inputs.machines}}
|
||||
includes: ${{inputs.includes}}
|
||||
excludes: ${{inputs.excludes}}
|
||||
checkout: ${{inputs.checkout}}
|
||||
|
||||
smoke:
|
||||
if: >
|
||||
!failure() && !cancelled()
|
||||
&& fromJSON(inputs.enable_smoke)
|
||||
&& !contains(inputs.pipeline, '[ci only it]')
|
||||
&& !contains(inputs.pipeline, '[ci no build]')
|
||||
&& inputs.cargo_profiles
|
||||
&& inputs.machines
|
||||
|
||||
@@ -86,15 +196,22 @@ jobs:
|
||||
sys_targets: ${{inputs.sys_targets}}
|
||||
machines: ${{inputs.machines}}
|
||||
includes: ${{inputs.includes}}
|
||||
checkout: ${{inputs.checkout}}
|
||||
excludes: >
|
||||
[
|
||||
{"cargo_profile": "test", "feat_set": "default"},
|
||||
{"cargo_profile": "test", "feat_set": "logging"},
|
||||
{"cargo_profile": "test", "feat_set": "none", "bake_target": "smoke-valgrind"},
|
||||
{"cargo_profile": "test", "rust_toolchain": "stable"},
|
||||
{"cargo_profile": "test", "rust_target": "aarch64-unknown-linux-gnu"},
|
||||
{"cargo_profile": "test", "sys_target": "x86_64-v2-linux-gnu"},
|
||||
{"cargo_profile": "test", "sys_target": "x86_64-v3-linux-gnu"},
|
||||
{"cargo_profile": "test", "bake_target": "smoke-valgrind"},
|
||||
{"cargo_profile": "bench"},
|
||||
{"cargo_profile": "release", "rust_toolchain": "nightly"},
|
||||
{"cargo_profile": "release", "rust_toolchain": "stable", "feat_set": "none"},
|
||||
{"cargo_profile": "release", "bake_target": "smoke-valgrind"},
|
||||
{"cargo_profile": "release-debuginfo", "feat_set": "logging"},
|
||||
{"cargo_profile": "release-debuginfo", "rust_toolchain": "nightly"},
|
||||
{"cargo_profile": "release-debuginfo", "rust_toolchain": "stable", "feat_set": "none"},
|
||||
{"cargo_profile": "release-debuginfo", "bake_target": "smoke"},
|
||||
@@ -102,53 +219,156 @@ jobs:
|
||||
{"cargo_profile": "release-native", "rust_toolchain": "stable"},
|
||||
{"cargo_profile": "release-native", "feat_set": "none"},
|
||||
{"cargo_profile": "release-native", "feat_set": "default"},
|
||||
{"cargo_profile": "release-native", "feat_set": "logging"},
|
||||
{"cargo_profile": "release-native", "bake_target": "smoke-valgrind"},
|
||||
{"cargo_profile": "release-native", "rust_target": "aarch64-unknown-linux-gnu"},
|
||||
{"cargo_profile": "release-native", "sys_target": "x86_64-v2-linux-gnu"},
|
||||
{"cargo_profile": "release-native", "sys_target": "x86_64-v3-linux-gnu"},
|
||||
{"cargo_profile": "release-native", "sys_target": "x86_64-v4-linux-gnu"},
|
||||
{"rust_target": "aarch64-unknown-linux-gnu", "feat_set": "none"},
|
||||
{"rust_target": "aarch64-unknown-linux-gnu", "feat_set": "default"},
|
||||
{"rust_target": "aarch64-unknown-linux-gnu", "sys_target": "x86_64-linux-gnu"},
|
||||
{"rust_target": "x86_64-unknown-linux-gnu", "sys_target": "aarch64-linux-gnu"},
|
||||
{"sys_target": "x86_64-linux-gnu", "machine": "ARM64"},
|
||||
{"sys_target": "aarch64-linux-gnu", "machine": "X64"},
|
||||
{"rust_target": "aarch64-unknown-linux-gnu", "sys_target": "x86_64-v1-linux-gnu"},
|
||||
{"rust_target": "aarch64-unknown-linux-gnu", "sys_target": "x86_64-v2-linux-gnu"},
|
||||
{"rust_target": "aarch64-unknown-linux-gnu", "sys_target": "x86_64-v3-linux-gnu"},
|
||||
{"rust_target": "aarch64-unknown-linux-gnu", "sys_target": "x86_64-v4-linux-gnu"},
|
||||
{"rust_target": "x86_64-unknown-linux-gnu", "sys_target": "aarch64-v8-linux-gnu"},
|
||||
{"sys_target": "aarch64-v8-linux-gnu", "machine": "X64"},
|
||||
{"sys_target": "x86_64-v1-linux-gnu", "machine": "ARM64"},
|
||||
{"sys_target": "x86_64-v2-linux-gnu", "machine": "ARM64"},
|
||||
{"sys_target": "x86_64-v2-linux-gnu", "feat_set": "none"},
|
||||
{"sys_target": "x86_64-v2-linux-gnu", "feat_set": "default"},
|
||||
{"sys_target": "x86_64-v2-linux-gnu", "feat_set": "logging"},
|
||||
{"sys_target": "x86_64-v3-linux-gnu", "machine": "ARM64"},
|
||||
{"sys_target": "x86_64-v3-linux-gnu", "feat_set": "none"},
|
||||
{"sys_target": "x86_64-v3-linux-gnu", "feat_set": "default"},
|
||||
{"sys_target": "x86_64-v3-linux-gnu", "feat_set": "logging"},
|
||||
{"sys_target": "x86_64-v3-linux-gnu", "bake_target": "smoke-valgrind"},
|
||||
{"sys_target": "x86_64-v4-linux-gnu", "machine": "ARM64"},
|
||||
{"sys_target": "x86_64-v4-linux-gnu", "feat_set": "none"},
|
||||
{"sys_target": "x86_64-v4-linux-gnu", "feat_set": "default"},
|
||||
{"sys_target": "x86_64-v4-linux-gnu", "feat_set": "logging"},
|
||||
{"sys_target": "x86_64-v4-linux-gnu", "bake_target": "smoke-valgrind"},
|
||||
]
|
||||
|
||||
nix:
|
||||
if: >
|
||||
!failure() && !cancelled()
|
||||
&& fromJSON(inputs.enable_nix)
|
||||
&& !contains(inputs.pipeline, '[ci only it]')
|
||||
&& !contains(inputs.pipeline, '[ci no build]')
|
||||
&& !contains(github.ref, 'refs/pull')
|
||||
&& contains(fromJSON(inputs.cargo_profiles), fromJSON('["release"]')[0])
|
||||
&& contains(fromJSON(inputs.feat_sets), fromJSON('["all"]')[0])
|
||||
&& contains(fromJSON(inputs.rust_toolchains), fromJSON('["stable"]')[0])
|
||||
&& contains(fromJSON(inputs.sys_targets), fromJSON('["x86_64-v1-linux-gnu"]')[0])
|
||||
|
||||
name: Smoke NixOS
|
||||
uses: ./.github/workflows/bake.yml
|
||||
with:
|
||||
bake_targets: '["smoke-nix"]'
|
||||
cargo_profiles: '["release"]'
|
||||
feat_sets: '["all"]'
|
||||
rust_toolchains: '["stable"]'
|
||||
sys_names: ${{inputs.sys_names}}
|
||||
sys_versions: ${{inputs.sys_versions}}
|
||||
rust_targets: ${{inputs.rust_targets}}
|
||||
sys_targets: '["x86_64-v1-linux-gnu"]'
|
||||
machines: ${{inputs.machines}}
|
||||
excludes: ${{inputs.excludes}}
|
||||
includes: ${{inputs.includes}}
|
||||
checkout: ${{inputs.checkout}}
|
||||
|
||||
rust-sdk-integ:
|
||||
if: >
|
||||
!failure() && !cancelled()
|
||||
&& fromJSON(inputs.enable_rustsdk)
|
||||
&& !contains(inputs.pipeline, '[ci no build]')
|
||||
&& contains(fromJSON(inputs.feat_sets), fromJSON('["all"]')[0])
|
||||
&& contains(fromJSON(inputs.rust_toolchains), fromJSON('["nightly"]')[0])
|
||||
&& contains(fromJSON(inputs.rust_targets), fromJSON('["x86_64-unknown-linux-gnu"]')[0])
|
||||
|
||||
name: Matrix SDK Integration
|
||||
needs: [smoke]
|
||||
uses: ./.github/workflows/bake.yml
|
||||
with:
|
||||
#bake_targets: '["rust-sdk-integ", "rust-sdk-valgrind"]'
|
||||
bake_targets: '["rust-sdk-integ"]'
|
||||
cargo_profiles: ${{inputs.cargo_profiles}}
|
||||
feat_sets: '["all"]'
|
||||
rust_toolchains: '["nightly"]'
|
||||
sys_names: ${{inputs.sys_names}}
|
||||
sys_versions: ${{inputs.sys_versions}}
|
||||
rust_targets: '["x86_64-unknown-linux-gnu"]'
|
||||
sys_targets: ${{inputs.sys_targets}}
|
||||
machines: '["X64"]'
|
||||
runner: ${{inputs.complement_runner}}
|
||||
checkout: ${{inputs.checkout}}
|
||||
includes: ${{inputs.includes}}
|
||||
artifact: >
|
||||
{
|
||||
"rust-sdk-integ": {
|
||||
"src": "/var/log/tuwunel.log",
|
||||
"dst": "rust-sdk-integ.tuwunel.log",
|
||||
},
|
||||
"rust-sdk-valgrind": {
|
||||
"src": "/var/log/tuwunel.log",
|
||||
"dst": "rust-sdk-valgrind.tuwunel.log",
|
||||
}
|
||||
}
|
||||
excludes: >
|
||||
[
|
||||
{"bake_target": "rust-sdk-valgrind", "cargo_profile": "test"},
|
||||
{"feat_set": "none"},
|
||||
{"feat_set": "logging"},
|
||||
{"cargo_profile": "release"},
|
||||
{"cargo_profile": "release-debuginfo"},
|
||||
{"cargo_profile": "release-native"},
|
||||
{"cargo_profile": "test", "sys_target": "x86_64-v2-linux-gnu"},
|
||||
{"cargo_profile": "test", "sys_target": "x86_64-v3-linux-gnu"},
|
||||
{"cargo_profile": "bench", "sys_target": "x86_64-v1-linux-gnu"},
|
||||
{"cargo_profile": "bench", "sys_target": "x86_64-v2-linux-gnu"},
|
||||
{"rust_target": "aarch64-unknown-linux-gnu"},
|
||||
{"sys_target": "aarch64-v8-linux-gnu"},
|
||||
]
|
||||
|
||||
complement:
|
||||
if: >
|
||||
!failure() && !cancelled()
|
||||
&& inputs.complement
|
||||
&& contains(fromJSON(inputs.cargo_profiles), fromJSON('["test"]')[0])
|
||||
&& contains(fromJSON(inputs.complement_feat_sets), fromJSON('["all"]')[0])
|
||||
&& fromJSON(inputs.enable_complement)
|
||||
&& !contains(inputs.pipeline, '[ci no build]')
|
||||
&& contains(fromJSON(inputs.cargo_profiles), fromJSON('["bench"]')[0])
|
||||
&& contains(fromJSON(inputs.rust_toolchains), fromJSON('["nightly"]')[0])
|
||||
&& contains(fromJSON(inputs.machines), fromJSON('["X64"]')[0])
|
||||
&& contains(fromJSON(inputs.sys_targets), fromJSON('["x86_64-v3-linux-gnu"]')[0])
|
||||
|
||||
name: Complement
|
||||
uses: ./.github/workflows/bake.yml
|
||||
with:
|
||||
bake_targets: '["complement-tester", "complement-testee"]'
|
||||
cargo_profiles: '["test"]'
|
||||
feat_sets: ${{inputs.complement_feat_sets}}
|
||||
cargo_profiles: '["bench"]'
|
||||
feat_sets: '["logging"]'
|
||||
rust_toolchains: '["nightly"]'
|
||||
sys_names: ${{inputs.sys_names}}
|
||||
sys_versions: ${{inputs.sys_versions}}
|
||||
rust_targets: ${{inputs.rust_targets}}
|
||||
sys_targets: ${{inputs.sys_targets}}
|
||||
machines: '["X64"]'
|
||||
sys_targets: '["x86_64-v3-linux-gnu"]'
|
||||
machines: ${{inputs.machines}}
|
||||
runner: ${{inputs.complement_runner}}
|
||||
excludes: ${{inputs.excludes}}
|
||||
includes: ${{inputs.includes}}
|
||||
checkout: ${{inputs.checkout}}
|
||||
|
||||
compliance:
|
||||
if: >
|
||||
!failure() && !cancelled()
|
||||
&& inputs.complement
|
||||
&& fromJSON(inputs.enable_complement)
|
||||
&& !contains(inputs.pipeline, '[ci no build]')
|
||||
&& inputs.machines
|
||||
&& contains(fromJSON(inputs.cargo_profiles), fromJSON('["test"]')[0])
|
||||
&& contains(fromJSON(inputs.feat_sets), fromJSON('["all"]')[0])
|
||||
&& contains(fromJSON(inputs.cargo_profiles), fromJSON('["bench"]')[0])
|
||||
&& contains(fromJSON(inputs.rust_toolchains), fromJSON('["nightly"]')[0])
|
||||
&& contains(fromJSON(inputs.machines), fromJSON('["X64"]')[0])
|
||||
&& contains(fromJSON(inputs.sys_targets), fromJSON('["x86_64-v3-linux-gnu"]')[0])
|
||||
|
||||
name: Matrix Compliance
|
||||
needs: [complement]
|
||||
needs: [complement, smoke]
|
||||
runs-on: ["${{matrix.machine}}", "${{inputs.complement_runner}}"]
|
||||
concurrency:
|
||||
group: complement-cant-walk-and-chew-bubblegum
|
||||
@@ -157,14 +377,14 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
cargo_profile: ${{fromJSON('["test"]')}}
|
||||
feat_set: ${{fromJSON(inputs.complement_feat_sets)}}
|
||||
cargo_profile: ${{fromJSON('["bench"]')}}
|
||||
feat_set: ${{fromJSON('["logging"]')}}
|
||||
rust_toolchain: ${{fromJSON('["nightly"]')}}
|
||||
sys_name: ${{fromJSON(inputs.sys_names)}}
|
||||
sys_version: ${{fromJSON(inputs.sys_versions)}}
|
||||
rust_target: ${{fromJSON(inputs.rust_targets)}}
|
||||
sys_target: ${{fromJSON(inputs.sys_targets)}}
|
||||
machine: ${{fromJSON('["X64"]')}}
|
||||
sys_target: ${{fromJSON('["x86_64-v3-linux-gnu"]')}}
|
||||
machine: ${{fromJSON(inputs.machines)}}
|
||||
exclude: ${{fromJSON(inputs.excludes)}}
|
||||
include: ${{fromJSON(inputs.includes)}}
|
||||
|
||||
@@ -173,6 +393,7 @@ jobs:
|
||||
- name: Execute
|
||||
id: execute
|
||||
env:
|
||||
complement_verbose: ${{inputs.complement_verbose && 1 || 0}}
|
||||
cargo_profile: ${{matrix.cargo_profile}}
|
||||
rust_toolchain: ${{matrix.rust_toolchain}}
|
||||
rust_target: ${{matrix.rust_target}}
|
||||
@@ -185,7 +406,8 @@ jobs:
|
||||
run: |
|
||||
docker/complement.sh
|
||||
|
||||
- name: Extract
|
||||
- if: success() || failure() && steps.execute.outcome == 'failure'
|
||||
name: Extract
|
||||
id: extract
|
||||
env:
|
||||
name: complement_tester__${{matrix.sys_name}}__${{matrix.sys_version}}__${{matrix.sys_target}}
|
||||
@@ -193,14 +415,24 @@ jobs:
|
||||
|
||||
run: |
|
||||
cid=$(cat "$name")
|
||||
docker cp "$cid:/usr/src/complement/new_results.jsonl" tests/test_results/complement/test_results.jsonl
|
||||
docker cp "$cid:/usr/src/complement/new_results.jsonl" tests/complement/results.jsonl
|
||||
|
||||
- name: Upload
|
||||
id: upload
|
||||
- if: success() || failure() && steps.execute.outcome == 'failure'
|
||||
name: Upload New Results
|
||||
id: upload-result
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: test_results-${{matrix.feat_set}}-${{matrix.sys_name}}-${{matrix.sys_target}}.jsonl
|
||||
path: ./tests/test_results/complement/test_results.jsonl
|
||||
name: complement_results-${{matrix.feat_set}}-${{matrix.sys_name}}-${{matrix.sys_target}}.jsonl
|
||||
path: ./tests/complement/results.jsonl
|
||||
|
||||
- if: success() || (failure() && steps.execute.outcome == 'failure')
|
||||
name: Upload Log Output
|
||||
id: upload-output
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: complement_output-${{matrix.feat_set}}-${{matrix.sys_name}}-${{matrix.sys_target}}.jsonl
|
||||
path: ./tests/complement/logs.jsonl
|
||||
if-no-files-found: ignore
|
||||
|
||||
- name: Accept
|
||||
id: accept
|
||||
|
||||
+8
-1
@@ -94,4 +94,11 @@ public/
|
||||
rustc-ice-*
|
||||
|
||||
# complement test logs are huge
|
||||
tests/test_results/complement/test_logs.jsonl
|
||||
tests/complement/logs.jsonl
|
||||
|
||||
# cargo profiles from -Z self-profile
|
||||
*.mm_profdata
|
||||
|
||||
# Editor crashfiles
|
||||
*.save
|
||||
*.swp
|
||||
|
||||
Generated
+1440
-1199
File diff suppressed because it is too large
Load Diff
+163
-156
@@ -28,8 +28,8 @@ keywords = [
|
||||
license = "Apache-2.0"
|
||||
readme = "README.md"
|
||||
repository = "https://github.com/matrix-construct/tuwunel"
|
||||
rust-version = "1.86.0"
|
||||
version = "1.1.0"
|
||||
rust-version = "1.91.1"
|
||||
version = "1.5.0"
|
||||
|
||||
[workspace.metadata.crane]
|
||||
name = "tuwunel"
|
||||
@@ -39,7 +39,7 @@ name = "tuwunel"
|
||||
#
|
||||
|
||||
[workspace.dependencies.argon2]
|
||||
version = "0.5.3"
|
||||
version = "0.5"
|
||||
default-features = false
|
||||
features = [
|
||||
"alloc",
|
||||
@@ -47,17 +47,17 @@ features = [
|
||||
]
|
||||
|
||||
[workspace.dependencies.arrayvec]
|
||||
version = "0.7.6"
|
||||
version = "0.7"
|
||||
features = ["serde"]
|
||||
|
||||
[workspace.dependencies.async-channel]
|
||||
version = "2.3.1"
|
||||
|
||||
[workspace.dependencies.async-trait]
|
||||
version = "0.1.88"
|
||||
version = "0.1"
|
||||
|
||||
[workspace.dependencies.axum]
|
||||
version = "0.8.4"
|
||||
version = "0.8"
|
||||
default-features = false
|
||||
features = [
|
||||
"form",
|
||||
@@ -73,15 +73,16 @@ features = [
|
||||
version = "0.7"
|
||||
|
||||
[workspace.dependencies.axum-extra]
|
||||
version = "0.10.1"
|
||||
version = "0.10"
|
||||
default-features = false
|
||||
features = [
|
||||
"cookie",
|
||||
"typed-header",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[workspace.dependencies.axum-server]
|
||||
version = "0.7.2"
|
||||
version = "0.7"
|
||||
default-features = false
|
||||
|
||||
[workspace.dependencies.axum-server-dual-protocol]
|
||||
@@ -89,11 +90,11 @@ version = "0.7"
|
||||
default-features = false
|
||||
|
||||
[workspace.dependencies.base64]
|
||||
version = "0.22.1"
|
||||
version = "0.22"
|
||||
default-features = false
|
||||
|
||||
[workspace.dependencies.blurhash]
|
||||
version = "0.2.3"
|
||||
version = "0.2"
|
||||
default-features = false
|
||||
features = [
|
||||
"fast-linear-to-srgb",
|
||||
@@ -101,13 +102,13 @@ features = [
|
||||
]
|
||||
|
||||
[workspace.dependencies.bytes]
|
||||
version = "1.10.1"
|
||||
version = "1.10"
|
||||
|
||||
[workspace.dependencies.bytesize]
|
||||
version = "2.0.1"
|
||||
version = "2.1"
|
||||
|
||||
[workspace.dependencies.cargo_toml]
|
||||
version = "0.22.1"
|
||||
version = "0.22"
|
||||
default-features = false
|
||||
features = ["features"]
|
||||
|
||||
@@ -115,12 +116,12 @@ features = ["features"]
|
||||
version = "0.1"
|
||||
|
||||
[workspace.dependencies.chrono]
|
||||
version = "0.4.41"
|
||||
version = "0.4"
|
||||
features = ["alloc", "std"]
|
||||
default-features = false
|
||||
|
||||
[workspace.dependencies.clap]
|
||||
version = "4.5.39"
|
||||
version = "4.5"
|
||||
default-features = false
|
||||
features = [
|
||||
"derive",
|
||||
@@ -140,40 +141,40 @@ features = [
|
||||
version = "0.8.3"
|
||||
|
||||
[workspace.dependencies.const-str]
|
||||
version = "0.6.2"
|
||||
version = "0.7"
|
||||
|
||||
[workspace.dependencies.criterion]
|
||||
version = "0.7"
|
||||
default-features = false
|
||||
features = [
|
||||
"cargo_bench_support",
|
||||
"async_futures",
|
||||
"async_tokio",
|
||||
]
|
||||
|
||||
[workspace.dependencies.ctor]
|
||||
version = "0.4.2"
|
||||
version = "0.5"
|
||||
|
||||
[workspace.dependencies.cyborgtime]
|
||||
version = "2.1.1"
|
||||
version = "2.1"
|
||||
|
||||
[workspace.dependencies.either]
|
||||
version = "1.15.0"
|
||||
version = "1.15"
|
||||
default-features = false
|
||||
features = ["serde"]
|
||||
|
||||
[workspace.dependencies.figment]
|
||||
version = "0.10.19"
|
||||
version = "0.10"
|
||||
default-features = false
|
||||
features = ["env", "toml"]
|
||||
|
||||
[workspace.dependencies.futures]
|
||||
version = "0.3.31"
|
||||
version = "0.3"
|
||||
default-features = false
|
||||
features = ["std", "async-await"]
|
||||
|
||||
[workspace.dependencies.hardened_malloc-rs]
|
||||
version = "0.1.2"
|
||||
default-features = false
|
||||
features = [
|
||||
"static",
|
||||
"gcc",
|
||||
"light",
|
||||
]
|
||||
|
||||
[workspace.dependencies.hickory-resolver]
|
||||
version = "0.25.2"
|
||||
version = "0.25"
|
||||
default-features = false
|
||||
features = [
|
||||
"serde",
|
||||
@@ -182,17 +183,17 @@ features = [
|
||||
]
|
||||
|
||||
[workspace.dependencies.hmac]
|
||||
version = "0.12.1"
|
||||
version = "0.12"
|
||||
default-features = false
|
||||
|
||||
[workspace.dependencies.http]
|
||||
version = "1.3.1"
|
||||
version = "1.3"
|
||||
|
||||
[workspace.dependencies.http-body-util]
|
||||
version = "0.1.3"
|
||||
version = "0.1"
|
||||
|
||||
[workspace.dependencies.hyper]
|
||||
version = "1.6.0"
|
||||
version = "1.7"
|
||||
default-features = false
|
||||
features = [
|
||||
"server",
|
||||
@@ -210,7 +211,7 @@ features = [
|
||||
]
|
||||
|
||||
[workspace.dependencies.image]
|
||||
version = "0.25.6"
|
||||
version = "0.25"
|
||||
default-features = false
|
||||
features = [
|
||||
"jpeg",
|
||||
@@ -219,60 +220,73 @@ features = [
|
||||
"webp",
|
||||
]
|
||||
|
||||
[workspace.dependencies.insta]
|
||||
version = "1.43"
|
||||
features = [
|
||||
"json",
|
||||
]
|
||||
|
||||
[workspace.dependencies.ipaddress]
|
||||
version = "0.1.3"
|
||||
version = "0.1"
|
||||
|
||||
[workspace.dependencies.itertools]
|
||||
version = "0.14.0"
|
||||
version = "0.14"
|
||||
|
||||
[workspace.dependencies.jevmalloc]
|
||||
git = "https://github.com/matrix-construct/jevmalloc"
|
||||
rev = "93795449913f65ab533b7fa482333eef63fc3ae0"
|
||||
|
||||
[workspace.dependencies.jsonwebtoken]
|
||||
version = "9.3.1"
|
||||
version = "9.3"
|
||||
default-features = false
|
||||
features = ["use_pem"]
|
||||
|
||||
[workspace.dependencies.ldap3]
|
||||
git = "https://github.com/matrix-construct/ldap3"
|
||||
rev = "7d423314b9dbc66347284e38fc2b78c3d8f3d494"
|
||||
rev = "fdfbba2bf916b53e5f73cdb1a495ebb649978079"
|
||||
default-features = false
|
||||
features = ["sync", "tls-rustls"]
|
||||
|
||||
[workspace.dependencies.libc]
|
||||
version = "0.2.172"
|
||||
version = "0.2"
|
||||
|
||||
[workspace.dependencies.libloading]
|
||||
version = "0.8.8"
|
||||
version = "0.8"
|
||||
|
||||
[workspace.dependencies.log]
|
||||
version = "0.4.27"
|
||||
version = "0.4"
|
||||
default-features = false
|
||||
|
||||
[workspace.dependencies.loole]
|
||||
version = "0.4.1"
|
||||
version = "0.4"
|
||||
|
||||
[workspace.dependencies.lru-cache]
|
||||
version = "0.1.2"
|
||||
version = "0.1"
|
||||
|
||||
[workspace.dependencies.maplit]
|
||||
version = "1.0.2"
|
||||
version = "1.0"
|
||||
|
||||
[workspace.dependencies.minicbor]
|
||||
version = "1.0.0"
|
||||
version = "2.1"
|
||||
features = ["std"]
|
||||
|
||||
[workspace.dependencies.minicbor-serde]
|
||||
version = "0.5.0"
|
||||
version = "0.6"
|
||||
features = ["std"]
|
||||
|
||||
[workspace.dependencies.nix]
|
||||
version = "0.30.1"
|
||||
version = "0.30"
|
||||
default-features = false
|
||||
features = ["resource"]
|
||||
features = [
|
||||
"resource",
|
||||
"user",
|
||||
]
|
||||
|
||||
[workspace.dependencies.num-traits]
|
||||
version = "0.2.19"
|
||||
version = "0.2"
|
||||
|
||||
[workspace.dependencies.opentelemetry]
|
||||
version = "0.30.0"
|
||||
version = "0.31"
|
||||
|
||||
# Disabled until they move to opentelemetry 0.30
|
||||
#[workspace.dependencies.opentelemetry-jaeger]
|
||||
@@ -280,78 +294,81 @@ version = "0.30.0"
|
||||
#features = ["rt-tokio"]
|
||||
|
||||
[workspace.dependencies.opentelemetry_sdk]
|
||||
version = "0.30.0"
|
||||
version = "0.31"
|
||||
features = ["rt-tokio"]
|
||||
|
||||
[workspace.dependencies.proc-macro2]
|
||||
version = "1.0.95"
|
||||
version = "1.0"
|
||||
|
||||
[workspace.dependencies.quote]
|
||||
version = "1.0.40"
|
||||
version = "1.0"
|
||||
|
||||
[workspace.dependencies.rand]
|
||||
version = "0.8.5"
|
||||
version = "0.8"
|
||||
|
||||
[workspace.dependencies.regex]
|
||||
version = "1.11.1"
|
||||
version = "1.12"
|
||||
|
||||
[workspace.dependencies.reqwest]
|
||||
version = "0.12.19"
|
||||
version = "0.12"
|
||||
default-features = false
|
||||
features = [
|
||||
"rustls-tls-native-roots",
|
||||
"socks",
|
||||
"charset",
|
||||
"hickory-dns",
|
||||
"http2",
|
||||
"json",
|
||||
"rustls-tls-native-roots",
|
||||
"socks",
|
||||
]
|
||||
|
||||
[workspace.dependencies.ring]
|
||||
version = "0.17.14"
|
||||
version = "0.17"
|
||||
default-features = false
|
||||
|
||||
[workspace.dependencies.ruma]
|
||||
git = "https://github.com/matrix-construct/ruma"
|
||||
rev = "0155c2b33233bec9dece79d5134a9574b347f4c1"
|
||||
rev = "069b3f6ee7499cdac84175946aeb9443d2578363"
|
||||
features = [
|
||||
"compat",
|
||||
"rand",
|
||||
"__compat",
|
||||
"appservice-api-c",
|
||||
"client-api",
|
||||
"client-api-s",
|
||||
"compat-upload-signatures",
|
||||
"federation-api",
|
||||
"identifiers-validation",
|
||||
"markdown",
|
||||
"push-gateway-api-c",
|
||||
"unstable-exhaustive-types",
|
||||
"rand",
|
||||
"ring-compat",
|
||||
"compat-upload-signatures",
|
||||
"identifiers-validation",
|
||||
"unstable-unspecified",
|
||||
"unstable-msc2448",
|
||||
"unstable-msc2666",
|
||||
"unstable-msc2815",
|
||||
"unstable-msc2867",
|
||||
"unstable-msc2870",
|
||||
"unstable-msc3026",
|
||||
"unstable-msc3061",
|
||||
"unstable-msc3814",
|
||||
"unstable-msc3245",
|
||||
"unstable-msc3266",
|
||||
"unstable-msc3381", # polls
|
||||
"unstable-msc3489", # beacon / live location
|
||||
"unstable-msc3575",
|
||||
"unstable-msc3930", # polls push rules
|
||||
"unstable-msc4075",
|
||||
"unstable-msc4095",
|
||||
"unstable-msc4121",
|
||||
"unstable-msc4125",
|
||||
"unstable-msc4133",
|
||||
"unstable-msc4143",
|
||||
"unstable-msc4186",
|
||||
"unstable-msc4203", # sending to-device events to appservices
|
||||
"unstable-msc4210", # remove legacy mentions
|
||||
"unstable-msc4310",
|
||||
"unstable-msc4311",
|
||||
"unstable-extensible-events",
|
||||
"unstable-pdu",
|
||||
]
|
||||
|
||||
[workspace.dependencies.rustls]
|
||||
version = "0.23.27"
|
||||
version = "0.23"
|
||||
default-features = false
|
||||
features = ["aws_lc_rs"]
|
||||
features = ["aws_lc_rs", "logging", "tls12", "prefer-post-quantum"]
|
||||
|
||||
[workspace.dependencies.rustyline-async]
|
||||
version = "0.4.6"
|
||||
@@ -359,25 +376,27 @@ default-features = false
|
||||
|
||||
[workspace.dependencies.rust-rocksdb]
|
||||
git = "https://github.com/matrix-construct/rust-rocksdb"
|
||||
rev = "225a42519276e502205bdc845cebdb22d70ee245"
|
||||
rev = "c11395350bc1f2090a0152f2d15c8c5847821eba"
|
||||
default-features = false
|
||||
features = [
|
||||
"multi-threaded-cf",
|
||||
"mt_static",
|
||||
"lz4",
|
||||
"zstd",
|
||||
"bzip2",
|
||||
"lto",
|
||||
"lz4",
|
||||
"multi-threaded-cf",
|
||||
"serde1",
|
||||
"zstd",
|
||||
"zstd-static-linking-only",
|
||||
]
|
||||
|
||||
[workspace.dependencies.sanitize-filename]
|
||||
version = "0.6.0"
|
||||
version = "0.6"
|
||||
|
||||
[workspace.dependencies.sd-notify]
|
||||
version = "0.4.5"
|
||||
version = "0.4"
|
||||
default-features = false
|
||||
|
||||
[workspace.dependencies.sentry]
|
||||
version = "0.38.1"
|
||||
version = "0.45"
|
||||
default-features = false
|
||||
features = [
|
||||
"backtrace",
|
||||
@@ -393,48 +412,56 @@ features = [
|
||||
]
|
||||
|
||||
[workspace.dependencies.sentry-tower]
|
||||
version = "0.38.1"
|
||||
version = "0.45"
|
||||
|
||||
[workspace.dependencies.sentry-tracing]
|
||||
version = "0.38.1"
|
||||
version = "0.45"
|
||||
|
||||
[workspace.dependencies.serde]
|
||||
version = "1.0.219"
|
||||
version = "1.0"
|
||||
default-features = false
|
||||
features = ["rc"]
|
||||
|
||||
[workspace.dependencies.serde_core]
|
||||
version = "1.0"
|
||||
default-features = false
|
||||
|
||||
[workspace.dependencies.serde_html_form]
|
||||
version = "0.2.6"
|
||||
version = "0.2"
|
||||
|
||||
[workspace.dependencies.serde_json]
|
||||
version = "1.0.140"
|
||||
version = "1.0"
|
||||
default-features = false
|
||||
features = ["raw_value"]
|
||||
|
||||
[workspace.dependencies.serde_regex]
|
||||
version = "1.1.0"
|
||||
version = "1.1"
|
||||
|
||||
[workspace.dependencies.serde_yaml]
|
||||
version = "0.9.34"
|
||||
version = "0.9"
|
||||
|
||||
[workspace.dependencies.sha1]
|
||||
version = "0.10.6"
|
||||
version = "0.10"
|
||||
default-features = false
|
||||
|
||||
[workspace.dependencies.sha2]
|
||||
version = "0.10.9"
|
||||
version = "0.10"
|
||||
default-features = false
|
||||
|
||||
[workspace.dependencies.similar]
|
||||
version = "2.7"
|
||||
|
||||
[workspace.dependencies.smallstr]
|
||||
version = "0.3"
|
||||
features = [
|
||||
"ffi",
|
||||
"serde",
|
||||
"std",
|
||||
"union",
|
||||
]
|
||||
|
||||
[workspace.dependencies.smallvec]
|
||||
version = "1.15.1"
|
||||
version = "1.15"
|
||||
features = [
|
||||
"const_generics",
|
||||
"const_new",
|
||||
@@ -444,7 +471,7 @@ features = [
|
||||
]
|
||||
|
||||
[workspace.dependencies.syn]
|
||||
version = "2.0.101"
|
||||
version = "2.0"
|
||||
default-features = false
|
||||
features = [
|
||||
"extra-traits",
|
||||
@@ -455,39 +482,15 @@ features = [
|
||||
]
|
||||
|
||||
[workspace.dependencies.termimad]
|
||||
version = "0.33.0"
|
||||
version = "0.34"
|
||||
default-features = false
|
||||
|
||||
[workspace.dependencies.thiserror]
|
||||
version = "2.0.12"
|
||||
version = "2.0"
|
||||
default-features = false
|
||||
|
||||
[workspace.dependencies.tikv-jemallocator]
|
||||
git = "https://github.com/matrix-construct/jemallocator"
|
||||
rev = "03bed96afbbc898bef4d4f7d335c0519e3d1afad"
|
||||
default-features = false
|
||||
features = [
|
||||
"background_threads_runtime_support",
|
||||
"unprefixed_malloc_on_supported_platforms",
|
||||
]
|
||||
|
||||
[workspace.dependencies.tikv-jemalloc-ctl]
|
||||
git = "https://github.com/matrix-construct/jemallocator"
|
||||
rev = "03bed96afbbc898bef4d4f7d335c0519e3d1afad"
|
||||
default-features = false
|
||||
features = ["use_std"]
|
||||
|
||||
[workspace.dependencies.tikv-jemalloc-sys]
|
||||
git = "https://github.com/matrix-construct/jemallocator"
|
||||
rev = "03bed96afbbc898bef4d4f7d335c0519e3d1afad"
|
||||
default-features = false
|
||||
features = [
|
||||
"background_threads_runtime_support",
|
||||
"unprefixed_malloc_on_supported_platforms",
|
||||
]
|
||||
|
||||
[workspace.dependencies.tokio]
|
||||
version = "1.45.1"
|
||||
version = "1.48"
|
||||
default-features = false
|
||||
features = [
|
||||
"fs",
|
||||
@@ -502,20 +505,20 @@ features = [
|
||||
]
|
||||
|
||||
[workspace.dependencies.tokio-metrics]
|
||||
version = "0.4.2"
|
||||
version = "0.4"
|
||||
|
||||
[workspace.dependencies.toml]
|
||||
version = "0.8.23"
|
||||
version = "0.9"
|
||||
default-features = false
|
||||
features = ["parse"]
|
||||
|
||||
[workspace.dependencies.tower]
|
||||
version = "0.5.2"
|
||||
version = "0.5"
|
||||
default-features = false
|
||||
features = ["util"]
|
||||
|
||||
[workspace.dependencies.tower-http]
|
||||
version = "0.6.6"
|
||||
version = "0.6"
|
||||
default-features = false
|
||||
features = [
|
||||
"add-extension",
|
||||
@@ -529,21 +532,21 @@ features = [
|
||||
]
|
||||
|
||||
[workspace.dependencies.tracing]
|
||||
version = "0.1.41"
|
||||
version = "=0.1.43"
|
||||
default-features = false
|
||||
|
||||
[workspace.dependencies.tracing-core]
|
||||
version = "0.1.33"
|
||||
version = "0.1"
|
||||
default-features = false
|
||||
|
||||
[workspace.dependencies.tracing-flame]
|
||||
version = "0.2.0"
|
||||
version = "0.2"
|
||||
|
||||
[workspace.dependencies.tracing-opentelemetry]
|
||||
version = "0.31.0"
|
||||
version = "0.32"
|
||||
|
||||
[workspace.dependencies.tracing-subscriber]
|
||||
version = "0.3.19"
|
||||
version = "0.3"
|
||||
default-features = false
|
||||
features = [
|
||||
"ansi",
|
||||
@@ -555,35 +558,18 @@ features = [
|
||||
]
|
||||
|
||||
[workspace.dependencies.url]
|
||||
version = "2.5.4"
|
||||
version = "2.5"
|
||||
default-features = false
|
||||
features = ["serde"]
|
||||
|
||||
[workspace.dependencies.webpage]
|
||||
version = "2.0.1"
|
||||
version = "2.0"
|
||||
default-features = false
|
||||
|
||||
#
|
||||
# Patches
|
||||
#
|
||||
|
||||
# backport of [https://github.com/tokio-rs/tracing/pull/2956] to the 0.1.x
|
||||
# branch of tracing. we can switch back to upstream if #2956 is merged and
|
||||
# backported in the upstream repo.
|
||||
# https://github.com/girlbossceo/tracing/commit/b348dca742af641c47bc390261f60711c2af573c
|
||||
[patch.crates-io.tracing-subscriber]
|
||||
git = "https://github.com/matrix-construct/tracing"
|
||||
rev = "1e64095a8051a1adf0d1faa307f9f030889ec2aa"
|
||||
[patch.crates-io.tracing]
|
||||
git = "https://github.com/matrix-construct/tracing"
|
||||
rev = "1e64095a8051a1adf0d1faa307f9f030889ec2aa"
|
||||
[patch.crates-io.tracing-core]
|
||||
git = "https://github.com/matrix-construct/tracing"
|
||||
rev = "1e64095a8051a1adf0d1faa307f9f030889ec2aa"
|
||||
[patch.crates-io.tracing-log]
|
||||
git = "https://github.com/matrix-construct/tracing"
|
||||
rev = "1e64095a8051a1adf0d1faa307f9f030889ec2aa"
|
||||
|
||||
# adds a tab completion callback:
|
||||
# https://github.com/girlbossceo/rustyline-async/commit/de26100b0db03e419a3d8e1dd26895d170d1fe50
|
||||
# adds event for CTRL+\:
|
||||
@@ -709,7 +695,7 @@ inherits = "release-native.build-override"
|
||||
|
||||
[profile.bench]
|
||||
debug = "limited"
|
||||
strip = false
|
||||
strip = "none"
|
||||
#rustflags = [
|
||||
# "-Cremark=all",
|
||||
# '-Ztime-passes',
|
||||
@@ -729,7 +715,7 @@ strip = false
|
||||
# and can be raised if build times are tolerable.
|
||||
|
||||
[profile.dev]
|
||||
debug = "full"
|
||||
debug = 0
|
||||
#rustflags = [
|
||||
# '--cfg', 'tuwunel_mods',
|
||||
# '-Ztime-passes',
|
||||
@@ -789,7 +775,7 @@ inherits = "dev"
|
||||
|
||||
[profile.dev.package.'*']
|
||||
inherits = "dev"
|
||||
debug = "limited"
|
||||
debug = 0
|
||||
incremental = false
|
||||
codegen-units = 1
|
||||
opt-level = 'z'
|
||||
@@ -806,6 +792,11 @@ opt-level = 'z'
|
||||
# '-Clink-arg=-Wl,-z,nodelete',
|
||||
#]
|
||||
|
||||
# same as dev but slower.
|
||||
[profile.dbg]
|
||||
inherits = "dev"
|
||||
debug = "full"
|
||||
|
||||
# primarily used for CI
|
||||
[profile.test]
|
||||
debug = "limited"
|
||||
@@ -829,6 +820,7 @@ elided-lifetimes-in-paths = "warn"
|
||||
explicit-outlives-requirements = "warn"
|
||||
ffi-unwind-calls = "warn"
|
||||
keyword-idents = "warn"
|
||||
macro-extended-temporary-scopes = "warn"
|
||||
macro-use-extern-crate = "warn"
|
||||
meta-variable-misuse = "warn"
|
||||
missing-abi = "warn"
|
||||
@@ -839,6 +831,7 @@ rust-2021-incompatible-closure-captures = "warn"
|
||||
rust-2021-incompatible-or-patterns = "warn"
|
||||
rust-2021-prefixes-incompatible-syntax = "warn"
|
||||
rust-2021-prelude-collisions = "warn"
|
||||
semicolon-in-expressions-from-macros = "warn"
|
||||
single-use-lifetimes = "warn"
|
||||
trivial-casts = "warn"
|
||||
trivial-numeric-casts = "warn"
|
||||
@@ -851,11 +844,13 @@ unused-extern-crates = "warn"
|
||||
unused-import-braces = "warn"
|
||||
unused-lifetimes = "warn"
|
||||
unused-macro-rules = "warn"
|
||||
unused-must-use = "warn"
|
||||
unused-qualifications = "warn"
|
||||
#unused-results = "warn" # TODO
|
||||
|
||||
## some sadness
|
||||
elided_named_lifetimes = "allow" # TODO!
|
||||
mismatched_lifetime_syntaxes = "allow" # TODO!
|
||||
let_underscore_drop = "allow"
|
||||
missing_docs = "allow"
|
||||
# cfgs cannot be limited to expected cfgs or their de facto non-transitive/opt-in use-case e.g.
|
||||
@@ -871,6 +866,15 @@ variant_size_differences = "allow"
|
||||
# we check nightly clippy lints
|
||||
unknown_lints = "allow"
|
||||
|
||||
# rust claims elided_named_lifetimes has been replaced by
|
||||
# mismatched_lifetime_syntaxes but it actually has not.
|
||||
renamed_and_removed_lints = "allow"
|
||||
|
||||
# nightly has a new lint that conflicts with our BoolExt trait at
|
||||
# src/core/utils/bool.rs:68:48
|
||||
# <https://github.com/rust-lang/rust/issues/142748>
|
||||
unstable_name_collisions = "allow" # TODO
|
||||
|
||||
#######################################
|
||||
#
|
||||
# Clippy lints
|
||||
@@ -887,6 +891,9 @@ multiple_crate_versions = { level = "allow", priority = 1 }
|
||||
###################
|
||||
complexity = { level = "warn", priority = -1 }
|
||||
|
||||
# promotes forward-compat for literal ..default() construction
|
||||
needless_update = { level = "allow", priority = 1 }
|
||||
|
||||
###################
|
||||
correctness = { level = "warn", priority = -1 }
|
||||
|
||||
@@ -899,17 +906,20 @@ option_if_let_else = { level = "allow", priority = 1 } # TODO
|
||||
redundant_pub_crate = { level = "allow", priority = 1 } # TODO
|
||||
significant_drop_in_scrutinee = { level = "allow", priority = 1 } # TODO
|
||||
significant_drop_tightening = { level = "allow", priority = 1 } # TODO
|
||||
tuple_array_conversions = { level = "allow", priority = 1 }
|
||||
|
||||
###################
|
||||
pedantic = { level = "warn", priority = -1 }
|
||||
|
||||
## some sadness
|
||||
too_long_first_doc_paragraph = { level = "allow", priority = 1 }
|
||||
default_trait_access = { level = "allow", priority = 1 }
|
||||
doc_markdown = { level = "allow", priority = 1 }
|
||||
enum_glob_use = { level = "allow", priority = 1 }
|
||||
if_not_else = { level = "allow", priority = 1 }
|
||||
if_then_some_else_none = { level = "allow", priority = 1 }
|
||||
inline_always = { level = "allow", priority = 1 }
|
||||
map_unwrap_or = { level = "allow", priority = 1 }
|
||||
match_bool = { level = "allow", priority = 1 }
|
||||
missing_docs_in_private_items = { level = "allow", priority = 1 }
|
||||
missing_errors_doc = { level = "allow", priority = 1 }
|
||||
@@ -922,7 +932,6 @@ single_match_else = { level = "allow", priority = 1 }
|
||||
struct_excessive_bools = { level = "allow", priority = 1 }
|
||||
struct_field_names = { level = "allow", priority = 1 }
|
||||
unnecessary_wraps = { level = "allow", priority = 1 }
|
||||
unused_async = { level = "allow", priority = 1 }
|
||||
|
||||
###################
|
||||
perf = { level = "warn", priority = -1 }
|
||||
@@ -930,7 +939,6 @@ perf = { level = "warn", priority = -1 }
|
||||
###################
|
||||
#restriction = "warn"
|
||||
|
||||
#allow_attributes = "warn" # UNSTABLE
|
||||
arithmetic_side_effects = "warn"
|
||||
as_conversions = "warn"
|
||||
as_underscore = "warn"
|
||||
@@ -956,12 +964,11 @@ pub_without_shorthand = "warn"
|
||||
rc_buffer = "warn"
|
||||
rc_mutex = "warn"
|
||||
redundant_type_annotations = "warn"
|
||||
rest_pat_in_fully_bound_structs = "warn"
|
||||
semicolon_outside_block = "warn"
|
||||
str_to_string = "warn"
|
||||
string_lit_chars_any = "warn"
|
||||
string_slice = "warn"
|
||||
string_to_string = "warn"
|
||||
implicit_clone = "warn"
|
||||
suspicious_xor_used_as_pow = "warn"
|
||||
tests_outside_test_module = "warn"
|
||||
try_err = "warn"
|
||||
@@ -982,7 +989,7 @@ style = { level = "warn", priority = -1 }
|
||||
assertions_on_constants = { level = "allow", priority = 1 }
|
||||
module_inception = { level = "allow", priority = 1 }
|
||||
obfuscated_if_else = { level = "allow", priority = 1 }
|
||||
collapsible_if = { level = "allow", priority = 1 } # TODO stable v. nightly 05-21-25
|
||||
toplevel-ref-arg = { level = "allow", priority = 1 }
|
||||
|
||||
###################
|
||||
suspicious = { level = "warn", priority = -1 }
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
# Tuwunel <sup>🎔</sup>
|
||||
# Tuwunel<sup>💕</sup>
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
[](https://github.com/matrix-construct/tuwunel/actions/workflows/main.yml)
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
[](https://github.com/matrix-construct/tuwunel/actions/workflows/main.yml)
|
||||
|
||||
<!-- ANCHOR: catchphrase -->
|
||||
|
||||
@@ -15,19 +15,21 @@ ## High Performance Matrix Homeserver in Rust!
|
||||
|
||||
<!-- ANCHOR: body -->
|
||||
|
||||
[](https://matrix-construct.github.io/tuwunel/)
|
||||
[](https://try.tuwunel.chat)
|
||||
[](https://matrix.to/#/#tuwunel:grin.hu)
|
||||
|
||||
Tuwunel is a featureful [Matrix](https://matrix.org/) homeserver you can use instead of Synapse
|
||||
with your favorite [client](https://matrix.org/ecosystem/clients/),
|
||||
[bridge](https://matrix.org/ecosystem/bridges/) or
|
||||
[bot](https://matrix.org/ecosystem/integrations/). It is written entirely in Rust to be a scalable,
|
||||
lightweight, low-cost, community-driven alternative covering all but the most niche uses.
|
||||
low-cost, enterprise-ready, community-driven alternative, fully implementing the
|
||||
[Matrix Specification](https://spec.matrix.org/latest/) for all but the most niche uses.
|
||||
|
||||
This project is the official successor to [conduwuit](https://github.com/girlbossceo/conduwuit), which
|
||||
was a featureful and high-performance fork of [Conduit](https://gitlab.com/famedly/conduit), all
|
||||
community-lead homeservers implementing the compatible
|
||||
[Matrix Specification](https://spec.matrix.org/latest/).
|
||||
|
||||
Tuwunel is operated by enterprise users with a vested interest in sponsoring its continued
|
||||
development. It is now maintained by full-time staff.
|
||||
This project is the official successor to [conduwuit](https://github.com/x86pup/conduwuit) after it
|
||||
reached stability. Tuwunel is now used by many companies with a vested interest in its continued
|
||||
development by full-time staff. It is primarily sponsored by the government of
|
||||
Switzerland 🇨🇭 where it is currently deployed for citizens.
|
||||
|
||||
### Getting Started
|
||||
|
||||
@@ -38,7 +40,8 @@ ### Getting Started
|
||||
- Static binaries available as [releases](https://github.com/matrix-construct/tuwunel/releases) or [build artifacts](https://github.com/matrix-construct/tuwunel/actions?query=branch%3Amain).
|
||||
- Deb and RPM packages available as [releases](https://github.com/matrix-construct/tuwunel/releases) or [build artifacts](https://github.com/matrix-construct/tuwunel/actions?query=branch%3Amain).
|
||||
- Arch package available as [tuwunel](https://aur.archlinux.org/packages/tuwunel) or [tuwunel-git](https://aur.archlinux.org/packages/tuwunel-git).
|
||||
- Nix package still [needs some love](https://github.com/NixOS/nixpkgs/issues/415469).
|
||||
- Nix package available as [`matrix-tuwunel`](https://search.nixos.org/packages?query=matrix-tuwunel) and NixOS module available as [`services.matrix-tuwunel`](https://search.nixos.org/options?query=services.matrix-tuwunel).
|
||||
- Alpine package available as [tuwunel](https://pkgs.alpinelinux.org/package/edge/testing/x86_64/tuwunel).
|
||||
|
||||
**1.** [Configure](https://matrix-construct.github.io/tuwunel/configuration.html) by
|
||||
copying and editing the `tuwunel-example.toml`. The `server_name` and `database_path` must be
|
||||
@@ -47,7 +50,7 @@ ### Getting Started
|
||||
This is just a summary for the impatient. See the full
|
||||
[documentation](https://matrix-construct.github.io/tuwunel/).
|
||||
|
||||
> [!WARNING]
|
||||
> [!TIP]
|
||||
> Avoid using a sub-domain for your `server_name`. You can always delegate later with a [`.well-known`](https://github.com/spantaleev/matrix-docker-ansible-deploy/blob/master/docs/configuring-well-known.md)
|
||||
> file, but you can never change your `server_name`.
|
||||
|
||||
@@ -57,12 +60,12 @@ ### Getting Started
|
||||
`/etc/caddy/Caddyfile` configuration with [Element](https://github.com/element-hq/element-web/releases)
|
||||
unzipped to `/var/www/element`:
|
||||
```
|
||||
https://tuwunel.me:8448 {
|
||||
reverse_proxy http://127.0.0.1:8008
|
||||
tuwunel.me, tuwunel.me:8448 {
|
||||
reverse_proxy localhost:8008
|
||||
}
|
||||
https://tuwunel.me:443 {
|
||||
root * /var/www/element/
|
||||
file_server
|
||||
web.tuwunel.me {
|
||||
root * /var/www/element/
|
||||
file_server
|
||||
}
|
||||
```
|
||||
`caddy reload --config /etc/caddy/Caddyfile`
|
||||
@@ -75,7 +78,7 @@ ### Getting Started
|
||||
|
||||
🤗 Did you find this and other documentation helpful? We would love to hear feedback about setting
|
||||
up Tuwunel.
|
||||
|
||||
|
||||
|
||||
### Migrating to Tuwunel
|
||||
|
||||
@@ -110,22 +113,11 @@ ### Upgrading & Downgrading Tuwunel
|
||||
safe but often prevented by a guard. An error will indicate the downgrade is not possible and a
|
||||
newer version which does not error must be sought.
|
||||
|
||||
#### Versioning
|
||||
|
||||
Tuwunel uses a semantic version tag in the format of `v<major>.<minor>.<patch>`. The `patch` value will
|
||||
always correspond to the number of commits from the last `minor` change with significance to developers.
|
||||
The `minor` version is changed for fixes or features significant to users. The `major` value corresponds
|
||||
to significant feature evolutions, and does not indicate any "breaking change" nor connote stability.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> **Users should attempt to keep up to date with the latest minor version.**
|
||||
|
||||
#### Branches
|
||||
|
||||
The main branch is always _reasonably safe_ to run. We understand the propensity for users to simply clone
|
||||
the main branch to get up and running, and we're obliged to ensure it's always viable. Nevertheless, only
|
||||
tagged releases are true releases. If you don't care to update often, find the latest `minor` version
|
||||
change rather than `patch`. We don't recommend simply following `major` version changes at this time.
|
||||
tagged releases are true releases.
|
||||
|
||||
#### Container Tracking
|
||||
|
||||
@@ -140,31 +132,26 @@ #### Container Tracking
|
||||
|
||||
### Getting Help & Support
|
||||
|
||||
The official community will be found at [#tuwunel:tuwunel.chat](https://matrix.to/#/#tuwunel:tuwunel.chat).
|
||||
If this is currently inaccessible please be patient as it's still coming online at the time of
|
||||
the first release; we will have updates to this section. This is a fully moderated space to protect
|
||||
the wellbeing of our users and create a non-toxic work environment for staff. If you require assistance
|
||||
with anything that is not remedied by the documentation, don't hesitate to open an issue on github.
|
||||
|
||||
If you are opposed to using github, or if private discussion is required such as for security
|
||||
disclosures, or for any other reason, I would be happy to receive your DM at
|
||||
[@jason:tuwunel.me](https://matrix.to/#/@jason:tuwunel.me). This will not be bothering me as it would
|
||||
be my pleasure to help you anytime. As an emergency contact you can send an email to jasonzemos@gmail.com.
|
||||
be my pleasure to help you when possible. As an emergency contact you can send an email to
|
||||
jasonzemos@gmail.com.
|
||||
|
||||
##### Tuwunel Fanclub
|
||||
|
||||
We also have an unofficial community-run chat which is publicly accessible at
|
||||
[#tuwunel:grin.hu](https://matrix.to/#/#tuwunel:grin.hu). The members, content, or moderation
|
||||
We have an unofficial community-run chat which is publicly accessible at
|
||||
[#tuwunel:matrix.org](https://matrix.to/#/#tuwunel:matrix.org). The members, content, or moderation
|
||||
decisions of this room are not in any way related or endorsed by this project or its sponsors,
|
||||
and not all project staff will be present there. There will be at least some presence by staff to
|
||||
offer assistance so long as the room remains in minimally good standing.
|
||||
|
||||
|
||||
## Tuwunel <sup>🎔</sup>
|
||||
## Tuwunel<sup>💕</sup>
|
||||
|
||||
Tuwunel's theme is **empathy** in communication defined by the works of
|
||||
[Edith Stein](https://plato.stanford.edu/entries/stein/). Empathy is the basis for how we approach
|
||||
every message, and a reminder for how we should all conduct ourselves in every conversation.
|
||||
every message and our responsibility to the other in every conversation.
|
||||
|
||||
<!-- ANCHOR_END: body -->
|
||||
|
||||
|
||||
+76
-26
@@ -1,37 +1,87 @@
|
||||
# Tuwunel 1.1.0
|
||||
# Tuwunel 1.5.0
|
||||
|
||||
June 19, 2025
|
||||
January 31, 2025
|
||||
|
||||
All dependencies have been fully upgraded for the first time since the
|
||||
conduwuit transition. RocksDB is now synchronized to 10.2.1-tuwunel for all
|
||||
builders. The Nix build itself has now been fully migrated from conduwuit;
|
||||
special thanks to @wkordalski for making this happen. Thanks to @Askhalion
|
||||
for opening a NixOS package request which you can [vote for here](https://github.com/NixOS/nixpkgs/issues/415469).
|
||||
An [Arch package](https://aur.archlinux.org/packages/tuwunel) has also been
|
||||
created in the AUR courtesy of @drrossum in addition to the transitional
|
||||
package setup by @Kimiblock which we failed to acknowledge during the first
|
||||
release. The RPM package now has systemd and proper installation added thanks
|
||||
to a report by @alythemonk.
|
||||
### New Features & Enhancements
|
||||
|
||||
ARMv8 builds are now supported and bundled with this release. Thanks to
|
||||
@zaninime and @clement-escolano for reminding us.
|
||||
- SSO/OIDC support. This feature allows users to register and login via authorizations from OIDC Identity Providers. For example, you can now use your GitHub account to register on the server. Tuwunel implements the OIDC client protocol directly. This is referred to as "legacy SSO" in the Matrix specification; Matrix client support is widespread. Credit to @samip5 for opening the feature-issue (#7), the most 👍 feature of the project.
|
||||
|
||||
JSON Web Token logins are now supported. This feature was commissioned and
|
||||
made public by an enterprise sponsor. The type `org.matrix.login.jwt` is now
|
||||
recognized.
|
||||
- [MSC2815](https://github.com/matrix-org/matrix-spec-proposals/pull/2815) has been implemented, allowing configurable redacted event retention and retrieval by room admins. The content of redacted events is persisted for sixty days by default. Redacted events can be viewed using Gomuks.
|
||||
|
||||
### New Features
|
||||
- Secure limited-use registration token support was implemented by @dasha-uwu building off earlier work by @gingershaped in (56f3f5ea154). Use this feature with the new `!admin token` set of commands.
|
||||
|
||||
- JWT login support.
|
||||
- An outstanding major rework of the presence system by @lhjt in (#264) coordinates conflicting updates from multiple devices and further builds on push suppression features first introduced by @tototomate123.
|
||||
|
||||
### Follow-up Features
|
||||
- [MSC3706](https://github.com/matrix-org/matrix-spec-proposals/pull/3706) has been implemented, improving the performance and reliability of joining rooms over federation (b33e73672b).
|
||||
|
||||
- aarch64 build and packages.
|
||||
- NixOS build support. (thanks @wkordalski and @coolGi69)
|
||||
- Dependency upgrades, including Axum 0.8. (thanks @dasha_uwu)
|
||||
- RPM package systemd and proper installation scripts.
|
||||
- @VlaDexa implemented reading the `client_secret` configuration for an SSO Identity Provider from a separate file; a recommended secure practice (#256).
|
||||
|
||||
- Special thanks to @winyadepla for adding highly sought Matrix RTC (Element Call) documentation for Tuwunel in (#265) and for having a kind heart to follow up with maintenance in (#270).
|
||||
|
||||
- Thank you @Xerusion for documenting Traefik for deploying Tuwunel in (#259). This will save a lot of time and headache for many new users!
|
||||
|
||||
- At the request of @ChronosXYZ in (#260), @dasha-uwu implemented a configurable feature to include all local users in search results, rather than limiting to those in public or shared rooms (95121ad905fb).
|
||||
|
||||
- Thanks to a collaboration by @x86pup and @VlaDexa working through Nix maintenance we can now upgrade the MSRV to 1.91.1 (#275).
|
||||
|
||||
- Thank you @scvalex for updating the README indicating Tuwunel is in stable NixOS (#233).
|
||||
|
||||
- Thank you @divideableZero for updating the README with great news about an [Alpine Package](https://pkgs.alpinelinux.org/package/edge/testing/x86_64/tuwunel) (#248).
|
||||
|
||||
- Storage hardware characteristics for mdraid devices on Linux are now detected. On these systems we can now shape database requests to increase performance above generic defaults.
|
||||
|
||||
- EdDSA is now a supported algorithm for JWT logins. Thank you @vnhdx for the excellent report in (#258).
|
||||
|
||||
- Optimizations were made to maximize concurrency and cache performance when gathering the `auth_chain`.
|
||||
|
||||
- An admin command to manually remove a pusher is available (note: not intended for normal use).
|
||||
|
||||
- An admin command to list local users by recent activity was added.
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- Changing passwords for pre-migration users was precluded by an error.
|
||||
Special thanks to @teidesu for making a superb report about this.
|
||||
- LDAP users are now auto-joined to configured rooms upon creation. Thank you @yefimg for (#234), we especially appreciate help from domain-experts on these features.
|
||||
|
||||
- A surgical fix by @kuhnchris in (#254) addressed a pesky bug where LDAP logins would result in admin privileges being removed for the user. Thank you @foxing-quietly for reporting in (#236).
|
||||
|
||||
- @OptimoSupreme fixed issues with unread notification counting, including eliminating one of the last remaining non-async database calls in the codebase in (#253).
|
||||
|
||||
- @x86pup fixed linker issues for platforms without static builds of `io_uring`. Thanks @darix for reporting in (#238).
|
||||
|
||||
- @x86pup fixed compatibility for our optimized jemalloc build on macOS (#239).
|
||||
|
||||
- @dasha-uwu made Livekit operate properly even when federation is disabled (b5f50c3fda3). Thank you @apodavalov for reporting in (#240).
|
||||
|
||||
- Thank you @VlaDexa for updating the `Cache-Control` header to cache media as `private` which is more appropriate now in the Authenticated Media era.
|
||||
|
||||
- Appservices now receive events properly matching on the sender MXID's localpart thanks to @dasha-uwu (c5508bba58d0).
|
||||
|
||||
- Additional PDU format and compliance checks were added by @dasha-uwu (7b2079f71499).
|
||||
|
||||
- Codepaths in sync systems which assumed `device_id` from appservices were fixed by @dasha-uwu.
|
||||
|
||||
- Auto-joining version 12 rooms was inhibited from a bug fixed by @dasha-uwu in (7115fb2796f).
|
||||
|
||||
- Thank you @x86pup for updating our ldap3 dependency with SSL/TLS enhancements in (#243) and fixing errors reported by @fruzitent in (#108).
|
||||
|
||||
- Thanks to @x86pup `join_rule` is now properly defaulted in `/publicRooms` responses in (#244); additional compliance tests now pass!
|
||||
|
||||
- Thank you @bdfd9 for reporting a regression where tracing spans around registrations did not filter out passwords from the list of fields.
|
||||
|
||||
- The timezone and extended profile features were not correctly stabilized last summer and the `m.tz` field was incorrectly labeled `tz`. Thank you @bunnyblack:matrix.org for reporting in #tuwunel:matrix.org.
|
||||
|
||||
- @dasha-uwu fixed git tags not being pulled and applied to CI builds (eadc9e782d8).
|
||||
|
||||
- @dasha-uwu fixed a bug in sliding-sync which may result in lost invites (fd519ff7f174).
|
||||
|
||||
- `since` tokens in legacy sync are now clamped to a maximum when the client sends a value greater than expected, preventing a possibility of missing events during the request.
|
||||
|
||||
- Media deletion commands which are time-based suffered a bug from incorrect creation timestamps on some filesystems. This was resolved by exclusively using the `mtime` attribute, which is acceptable because Matrix media is immutable.
|
||||
|
||||
- Queries for the deprecated `_matrix._tcp` SRV record have been reactivated due to an ineffective and unenforced sunset by the specification and other implementations.
|
||||
|
||||
- Thank you @x86pup and @dasha-uwu for various maintenance and linting efforts for the latest rustc versions and in general.
|
||||
|
||||
### Honorable Mentions
|
||||
|
||||
- Please take a moment to recognize how lucky we are to have @scvalex as our NixOS package maintainer. From having the wherewithal to rise above the noise and lend this project trust from the very first days, time and again this gentleman has gone above and beyond on our behalf. Thank you @symphorien at NixOS as well for the patch applied surgically in https://github.com/NixOS/nixpkgs/pull/462394.
|
||||
|
||||
@@ -4,7 +4,6 @@ Wants=network-online.target
|
||||
After=network-online.target
|
||||
Documentation=https://tuwunel.chat/
|
||||
RequiresMountsFor=/var/lib/private/tuwunel
|
||||
Alias=matrix-tuwunel.service
|
||||
|
||||
[Service]
|
||||
DynamicUser=yes
|
||||
@@ -77,3 +76,4 @@ StartLimitBurst=5
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
Alias=matrix-tuwunel.service
|
||||
|
||||
@@ -5,7 +5,6 @@ authors = [
|
||||
]
|
||||
description = "Tuwunel, a high performance successor to Conduit and Conduwuit"
|
||||
language = "en"
|
||||
multilingual = false
|
||||
src = "docs"
|
||||
title = "Tuwunel One"
|
||||
text-direction = "ltr"
|
||||
@@ -15,7 +14,9 @@ build-dir = "public"
|
||||
create-missing = true
|
||||
extra-watch-dirs = [
|
||||
"debian",
|
||||
"docker",
|
||||
"docs",
|
||||
"rpm",
|
||||
]
|
||||
|
||||
[rust]
|
||||
@@ -24,7 +25,7 @@ edition = "2024"
|
||||
[output.html]
|
||||
git-repository-url = "https://github.com/matrix-construct/tuwunel"
|
||||
edit-url-template = "https://github.com/matrix-construct/tuwunel/edit/main/{path}"
|
||||
git-repository-icon = "fa-github-square"
|
||||
git-repository-icon = "fab-github"
|
||||
|
||||
[output.html.search]
|
||||
limit-results = 15
|
||||
|
||||
+6
-6
@@ -1,11 +1,11 @@
|
||||
stack-size-threshold = 393216
|
||||
future-size-threshold = 24576
|
||||
array-size-threshold = 4096
|
||||
cognitive-complexity-threshold = 100 # TODO reduce me ALARA
|
||||
excessive-nesting-threshold = 11 # TODO reduce me to 4 or 5
|
||||
future-size-threshold = 7745 # TODO reduce me ALARA
|
||||
stack-size-threshold = 196608 # TODO reduce me ALARA
|
||||
too-many-lines-threshold = 780 # TODO reduce me to <= 100
|
||||
type-complexity-threshold = 250 # reduce me to ~200
|
||||
large-error-threshold = 256 # TODO reduce me ALARA
|
||||
too-many-lines-threshold = 780 # TODO reduce me to <= 100
|
||||
excessive-nesting-threshold = 8
|
||||
type-complexity-threshold = 250 # reduce me to ~200
|
||||
cognitive-complexity-threshold = 100 # TODO reduce me ALARA
|
||||
|
||||
#disallowed-macros = [
|
||||
# { path = "log::error", reason = "use tuwunel_core::error" },
|
||||
|
||||
Vendored
+1
-2
@@ -2,11 +2,9 @@
|
||||
Description=Tuwunel Matrix homeserver
|
||||
Wants=network-online.target
|
||||
After=network-online.target
|
||||
Alias=matrix-tuwunel.service
|
||||
Documentation=https://tuwunel.chat/
|
||||
|
||||
[Service]
|
||||
DynamicUser=yes
|
||||
User=tuwunel
|
||||
Group=tuwunel
|
||||
Type=notify
|
||||
@@ -64,3 +62,4 @@ StartLimitBurst=5
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
Alias=matrix-tuwunel.service
|
||||
|
||||
+11
-10
@@ -1,10 +1,11 @@
|
||||
(import
|
||||
(
|
||||
let lock = builtins.fromJSON (builtins.readFile ./flake.lock); in
|
||||
fetchTarball {
|
||||
url = lock.nodes.flake-compat.locked.url or "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz";
|
||||
sha256 = lock.nodes.flake-compat.locked.narHash;
|
||||
}
|
||||
)
|
||||
{ src = ./.; }
|
||||
).defaultNix
|
||||
(import (
|
||||
let
|
||||
lock = builtins.fromJSON (builtins.readFile ./flake.lock);
|
||||
in
|
||||
fetchTarball {
|
||||
url =
|
||||
lock.nodes.flake-compat.locked.url
|
||||
or "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz";
|
||||
sha256 = lock.nodes.flake-compat.locked.narHash;
|
||||
}
|
||||
) { src = ./.; }).defaultNix
|
||||
|
||||
+21
-13
@@ -1,7 +1,7 @@
|
||||
# syntax = docker/dockerfile:1.11-labs
|
||||
|
||||
FROM input AS cargo
|
||||
ARG sys_target
|
||||
ARG sys_triple
|
||||
ARG rust_target
|
||||
ARG rust_toolchain
|
||||
ARG RUST_HOME
|
||||
@@ -12,10 +12,13 @@ ARG CARGO_TARGET_DIR
|
||||
ARG cargo_target_profile
|
||||
ARG cargo_target_artifact
|
||||
ARG cargo_target_share
|
||||
ARG cargo_share
|
||||
ARG CARGO_TERM_VERBOSE=0
|
||||
ARG RUST_BACKTRACE
|
||||
ARG JEMALLOC_OVERRIDE
|
||||
ARG ROCKSDB_LIB_DIR
|
||||
ARG VALGRINDFLAGS=""
|
||||
ARG VALGRIND_MAX_WORKERS=128
|
||||
ARG CARGO_BUILD_RUSTFLAGS
|
||||
ARG CARGO_PROFILE_TEST_DEBUG
|
||||
ARG CARGO_PROFILE_TEST_INCREMENTAL
|
||||
@@ -32,21 +35,26 @@ ARG color_args="--color always"
|
||||
ARG recipe_args=""
|
||||
ARG cargo_args=""
|
||||
ARG git_checkout
|
||||
ARG targ_dir="${CARGO_TARGET_DIR}/${cargo_target_profile}"
|
||||
ARG targ_targ_dir="${CARGO_TARGET_DIR}/${rust_target}/${cargo_target_profile}"
|
||||
|
||||
WORKDIR /
|
||||
COPY --link --from=input . .
|
||||
COPY --link --from=rust ${RUST_HOME} ${RUST_HOME}
|
||||
COPY --link --from=deps /usr/src/tuwunel /usr/src/tuwunel
|
||||
|
||||
WORKDIR /usr/lib/${sys_target}
|
||||
WORKDIR /usr/lib/${sys_triple}
|
||||
COPY --link --from=rocksdb . .
|
||||
|
||||
WORKDIR /usr/src/tuwunel
|
||||
SHELL ["/bin/bash", "-c"]
|
||||
ENV PATH="${CARGO_HOME}/bin:$PATH"
|
||||
ENV CARGO_TERM_VERBOSE="${CARGO_TERM_VERBOSE}"
|
||||
ENV RUST_BACKTRACE="${RUST_BACKTRACE}"
|
||||
ENV JEMALLOC_OVERRIDE="${JEMALLOC_OVERRIDE}"
|
||||
ENV ROCKSDB_LIB_DIR="${ROCKSDB_LIB_DIR}"
|
||||
ENV VALGRINDFLAGS="${VALGRINDFLAGS}"
|
||||
ENV TUWUNEL_DB_POOL_MAX_WORKERS="${VALGRIND_MAX_WORKERS}"
|
||||
ENV CARGO_PROFILE_TEST_DEBUG="${CARGO_PROFILE_TEST_DEBUG}"
|
||||
ENV CARGO_PROFILE_TEST_INCREMENTAL="${CARGO_PROFILE_TEST_INCREMENTAL}"
|
||||
ENV CARGO_PROFILE_BENCH_DEBUG="${CARGO_PROFILE_BENCH_DEBUG}"
|
||||
@@ -56,17 +64,15 @@ ENV CARGO_PROFILE_RELEASE_DEBUGINFO_DEBUG="${CARGO_PROFILE_RELEASE_DEBUGINFO_DEB
|
||||
ENV CARGO_PROFILE_RELEASE_DEBUGINFO_LTO="${CARGO_PROFILE_RELEASE_DEBUGINFO_LTO}"
|
||||
ENV CARGO_BUILD_RUSTFLAGS="${CARGO_BUILD_RUSTFLAGS}"
|
||||
ENV CARGO_TARGET_DIR="${CARGO_TARGET_DIR}"
|
||||
ENV targ_dir="${CARGO_TARGET_DIR}/${cargo_target_profile}"
|
||||
ENV targ_targ_dir="${CARGO_TARGET_DIR}/${rust_target}/${cargo_target_profile}"
|
||||
RUN \
|
||||
--mount=type=cache,dst=${RUSTUP_HOME}/downloads,sharing=shared,ro \
|
||||
--mount=type=cache,dst=${CARGO_HOME}/registry,sharing=shared,ro \
|
||||
--mount=type=cache,dst=${CARGO_HOME}/git,sharing=shared,ro \
|
||||
--mount=type=cache,dst=${targ_dir}/deps,id=${cargo_target_share}/deps,sharing=locked \
|
||||
--mount=type=cache,dst=${targ_dir}/build,id=${cargo_target_share}/build,sharing=locked \
|
||||
--mount=type=cache,dst=${targ_dir}/examples,id=${cargo_target_share}/examples,sharing=locked \
|
||||
--mount=type=cache,dst=${targ_dir}/incremental,id=${cargo_target_share}/incremental,sharing=locked \
|
||||
--mount=type=cache,dst=${targ_dir}/.fingerprint,id=${cargo_target_share}/fingerprint,sharing=locked \
|
||||
--mount=type=cache,dst=${RUSTUP_HOME}/downloads,sharing=shared \
|
||||
--mount=type=cache,dst=${CARGO_HOME}/registry,sharing=shared \
|
||||
--mount=type=cache,dst=${CARGO_HOME}/git,sharing=shared \
|
||||
--mount=type=cache,dst=${targ_dir}/deps,id=${cargo_share}/deps,sharing=locked \
|
||||
--mount=type=cache,dst=${targ_dir}/build,id=${cargo_share}/build,sharing=locked \
|
||||
--mount=type=cache,dst=${targ_dir}/examples,id=${cargo_share}/examples,sharing=locked \
|
||||
--mount=type=cache,dst=${targ_dir}/incremental,id=${cargo_share}/incremental,sharing=locked \
|
||||
--mount=type=cache,dst=${targ_dir}/.fingerprint,id=${cargo_share}/fingerprint,sharing=locked \
|
||||
--mount=type=cache,dst=${targ_targ_dir}/deps,id=${cargo_target_share}/deps,sharing=locked \
|
||||
--mount=type=cache,dst=${targ_targ_dir}/build,id=${cargo_target_share}/build,sharing=locked \
|
||||
--mount=type=cache,dst=${targ_targ_dir}/examples,id=${cargo_target_share}/examples,sharing=locked \
|
||||
@@ -74,7 +80,9 @@ RUN \
|
||||
--mount=type=cache,dst=${targ_targ_dir}/.fingerprint,id=${cargo_target_share}/fingerprint,sharing=locked \
|
||||
<<EOF
|
||||
set -eux
|
||||
rustup run ${rust_toolchain} \
|
||||
ulimit -n 65535
|
||||
|
||||
rustup run "${rust_toolchain}" \
|
||||
cargo ${cargo_cmd} \
|
||||
--verbose \
|
||||
--locked \
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
# syntax = docker/dockerfile:1.11-labs
|
||||
|
||||
FROM input AS audit
|
||||
ARG sys_target
|
||||
ARG rust_toolchain="nightly"
|
||||
ARG RUSTUP_HOME
|
||||
ARG CARGO_HOME
|
||||
@@ -12,9 +11,9 @@ COPY --link --from=input . .
|
||||
|
||||
WORKDIR /usr/src/tuwunel
|
||||
RUN \
|
||||
--mount=type=cache,dst=${RUSTUP_HOME}/downloads,sharing=shared,ro \
|
||||
--mount=type=cache,dst=${CARGO_HOME}/registry,sharing=shared,ro \
|
||||
--mount=type=cache,dst=${CARGO_HOME}/git,sharing=shared,ro \
|
||||
--mount=type=cache,dst=${RUSTUP_HOME}/downloads,sharing=shared \
|
||||
--mount=type=cache,dst=${CARGO_HOME}/registry,sharing=shared \
|
||||
--mount=type=cache,dst=${CARGO_HOME}/git,sharing=shared \
|
||||
<<EOF
|
||||
set -eux
|
||||
rustup run ${rust_toolchain} \
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
# syntax = docker/dockerfile:1.11-labs
|
||||
|
||||
FROM input AS build-deb
|
||||
ARG sys_target
|
||||
ARG rust_target
|
||||
ARG rust_toolchain
|
||||
ARG RUSTUP_HOME
|
||||
@@ -11,9 +10,12 @@ ARG CARGO_TARGET_DIR
|
||||
ARG cargo_target_profile
|
||||
ARG cargo_target_artifact
|
||||
ARG cargo_target_share
|
||||
ARG cargo_share
|
||||
ARG cargo_profile
|
||||
ARG cargo_features
|
||||
ARG cargo_spec_features
|
||||
ARG targ_dir="${CARGO_TARGET_DIR}/${cargo_target_profile}"
|
||||
ARG targ_targ_dir="${CARGO_TARGET_DIR}/${rust_target}/${cargo_target_profile}"
|
||||
ARG pkg_dir
|
||||
ARG deb_args=""
|
||||
|
||||
@@ -21,17 +23,15 @@ WORKDIR /
|
||||
COPY --link --from=input . .
|
||||
|
||||
WORKDIR /usr/src/tuwunel
|
||||
ENV targ_dir="${CARGO_TARGET_DIR}/${cargo_target_profile}"
|
||||
ENV targ_targ_dir="${CARGO_TARGET_DIR}/${rust_target}/${cargo_target_profile}"
|
||||
RUN \
|
||||
--mount=type=cache,dst=${RUSTUP_HOME}/downloads,sharing=shared \
|
||||
--mount=type=cache,dst=${CARGO_HOME}/registry,sharing=shared \
|
||||
--mount=type=cache,dst=${CARGO_HOME}/git,sharing=shared \
|
||||
--mount=type=cache,dst=${targ_dir}/deps,id=${cargo_target_share}/deps,sharing=locked \
|
||||
--mount=type=cache,dst=${targ_dir}/build,id=${cargo_target_share}/build,sharing=locked \
|
||||
--mount=type=cache,dst=${targ_dir}/examples,id=${cargo_target_share}/examples,sharing=locked \
|
||||
--mount=type=cache,dst=${targ_dir}/incremental,id=${cargo_target_share}/incremental,sharing=locked \
|
||||
--mount=type=cache,dst=${targ_dir}/.fingerprint,id=${cargo_target_share}/fingerprint,sharing=locked \
|
||||
--mount=type=cache,dst=${targ_dir}/deps,id=${cargo_share}/deps,sharing=locked \
|
||||
--mount=type=cache,dst=${targ_dir}/build,id=${cargo_share}/build,sharing=locked \
|
||||
--mount=type=cache,dst=${targ_dir}/examples,id=${cargo_share}/examples,sharing=locked \
|
||||
--mount=type=cache,dst=${targ_dir}/incremental,id=${cargo_share}/incremental,sharing=locked \
|
||||
--mount=type=cache,dst=${targ_dir}/.fingerprint,id=${cargo_share}/fingerprint,sharing=locked \
|
||||
--mount=type=cache,dst=${targ_targ_dir}/deps,id=${cargo_target_share}/deps,sharing=locked \
|
||||
--mount=type=cache,dst=${targ_targ_dir}/build,id=${cargo_target_share}/build,sharing=locked \
|
||||
--mount=type=cache,dst=${targ_targ_dir}/examples,id=${cargo_target_share}/examples,sharing=locked \
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
# syntax = docker/dockerfile:1.11-labs
|
||||
|
||||
FROM input AS fmt
|
||||
ARG sys_target
|
||||
ARG rust_toolchain="nightly"
|
||||
ARG RUSTUP_HOME
|
||||
ARG CARGO_HOME
|
||||
@@ -12,9 +11,9 @@ COPY --link --from=input . .
|
||||
|
||||
WORKDIR /usr/src/tuwunel
|
||||
RUN \
|
||||
--mount=type=cache,dst=${RUSTUP_HOME}/downloads,sharing=shared,ro \
|
||||
--mount=type=cache,dst=${CARGO_HOME}/registry,sharing=shared,ro \
|
||||
--mount=type=cache,dst=${CARGO_HOME}/git,sharing=shared,ro \
|
||||
--mount=type=cache,dst=${RUSTUP_HOME}/downloads,sharing=shared \
|
||||
--mount=type=cache,dst=${CARGO_HOME}/registry,sharing=shared \
|
||||
--mount=type=cache,dst=${CARGO_HOME}/git,sharing=shared \
|
||||
<<EOF
|
||||
set -eux
|
||||
rustup run ${rust_toolchain} \
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
# syntax = docker/dockerfile:1.11-labs
|
||||
|
||||
FROM input AS lychee
|
||||
ARG sys_target
|
||||
ARG rust_toolchain="nightly"
|
||||
ARG RUSTUP_HOME
|
||||
ARG CARGO_HOME
|
||||
@@ -16,9 +15,9 @@ COPY --link --from=input . .
|
||||
|
||||
WORKDIR /usr/src/
|
||||
RUN \
|
||||
--mount=type=cache,dst=${RUSTUP_HOME}/downloads,sharing=shared,ro \
|
||||
--mount=type=cache,dst=${CARGO_HOME}/registry,sharing=shared,ro \
|
||||
--mount=type=cache,dst=${CARGO_HOME}/git,sharing=shared,ro \
|
||||
--mount=type=cache,dst=${RUSTUP_HOME}/downloads,sharing=shared \
|
||||
--mount=type=cache,dst=${CARGO_HOME}/registry,sharing=shared \
|
||||
--mount=type=cache,dst=${CARGO_HOME}/git,sharing=shared \
|
||||
--mount=type=cache,dst=lychee,sharing=locked \
|
||||
<<EOF
|
||||
set -eux
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# syntax = docker/dockerfile:1.11-labs
|
||||
|
||||
FROM input AS build-rpm
|
||||
ARG sys_target
|
||||
ARG rust_target
|
||||
ARG rust_toolchain
|
||||
ARG RUSTUP_HOME
|
||||
ARG CARGO_HOME
|
||||
@@ -10,9 +10,12 @@ ARG CARGO_TARGET_DIR
|
||||
ARG cargo_target_profile
|
||||
ARG cargo_target_artifact
|
||||
ARG cargo_target_share
|
||||
ARG cargo_share
|
||||
ARG cargo_profile
|
||||
ARG cargo_features
|
||||
ARG cargo_spec_features
|
||||
ARG targ_dir="${CARGO_TARGET_DIR}/${cargo_target_profile}"
|
||||
ARG targ_targ_dir="${CARGO_TARGET_DIR}/${rust_target}/${cargo_target_profile}"
|
||||
ARG pkg_dir
|
||||
ARG gen_rpm_args=""
|
||||
|
||||
@@ -24,11 +27,11 @@ RUN \
|
||||
--mount=type=cache,dst=${RUSTUP_HOME}/downloads,sharing=shared \
|
||||
--mount=type=cache,dst=${CARGO_HOME}/registry,sharing=shared \
|
||||
--mount=type=cache,dst=${CARGO_HOME}/git,sharing=shared \
|
||||
--mount=type=cache,dst=${targ_dir}/deps,id=${cargo_target_share}/deps,sharing=locked \
|
||||
--mount=type=cache,dst=${targ_dir}/build,id=${cargo_target_share}/build,sharing=locked \
|
||||
--mount=type=cache,dst=${targ_dir}/examples,id=${cargo_target_share}/examples,sharing=locked \
|
||||
--mount=type=cache,dst=${targ_dir}/incremental,id=${cargo_target_share}/incremental,sharing=locked \
|
||||
--mount=type=cache,dst=${targ_dir}/.fingerprint,id=${cargo_target_share}/fingerprint,sharing=locked \
|
||||
--mount=type=cache,dst=${targ_dir}/deps,id=${cargo_share}/deps,sharing=locked \
|
||||
--mount=type=cache,dst=${targ_dir}/build,id=${cargo_share}/build,sharing=locked \
|
||||
--mount=type=cache,dst=${targ_dir}/examples,id=${cargo_share}/examples,sharing=locked \
|
||||
--mount=type=cache,dst=${targ_dir}/incremental,id=${cargo_share}/incremental,sharing=locked \
|
||||
--mount=type=cache,dst=${targ_dir}/.fingerprint,id=${cargo_share}/fingerprint,sharing=locked \
|
||||
--mount=type=cache,dst=${targ_targ_dir}/deps,id=${cargo_target_share}/deps,sharing=locked \
|
||||
--mount=type=cache,dst=${targ_targ_dir}/build,id=${cargo_target_share}/build,sharing=locked \
|
||||
--mount=type=cache,dst=${targ_targ_dir}/examples,id=${cargo_target_share}/examples,sharing=locked \
|
||||
|
||||
@@ -11,9 +11,9 @@ COPY --link --from=input . .
|
||||
|
||||
WORKDIR /usr/src/tuwunel
|
||||
RUN \
|
||||
--mount=type=cache,dst=${RUSTUP_HOME}/downloads,sharing=shared,ro \
|
||||
--mount=type=cache,dst=${CARGO_HOME}/registry,sharing=shared,ro \
|
||||
--mount=type=cache,dst=${CARGO_HOME}/git,sharing=shared,ro \
|
||||
--mount=type=cache,dst=${RUSTUP_HOME}/downloads,sharing=shared \
|
||||
--mount=type=cache,dst=${CARGO_HOME}/registry,sharing=shared \
|
||||
--mount=type=cache,dst=${CARGO_HOME}/git,sharing=shared \
|
||||
<<EOF
|
||||
set -eux
|
||||
rustup run ${rust_toolchain} \
|
||||
|
||||
@@ -1,22 +1,6 @@
|
||||
# syntax = docker/dockerfile:1.11-labs
|
||||
|
||||
FROM input AS key-gen-base
|
||||
ARG var_cache
|
||||
ARG var_lib_apt
|
||||
|
||||
WORKDIR /
|
||||
COPY --link --from=input . .
|
||||
|
||||
RUN \
|
||||
--mount=type=cache,dst=/var/cache,id=${var_cache},sharing=locked \
|
||||
--mount=type=cache,dst=/var/lib/apt,id=${var_lib_apt},sharing=locked \
|
||||
<<EOF
|
||||
set -eux
|
||||
apt-get -y -U install --no-install-recommends openssl gawk
|
||||
EOF
|
||||
|
||||
|
||||
FROM key-gen-base AS key-gen
|
||||
FROM input AS key-gen
|
||||
|
||||
WORKDIR /complement
|
||||
COPY <<EOF v3.ext
|
||||
@@ -62,53 +46,53 @@ RUN [ -f certificate.crt ] && [ -f private_key.pem ]
|
||||
FROM scratch AS complement-config
|
||||
WORKDIR /complement
|
||||
COPY --from=key-gen /complement/* .
|
||||
COPY --from=source /usr/src/tuwunel/tests/test_results/complement/test_results.jsonl old_results.jsonl
|
||||
COPY --from=source /usr/src/tuwunel/tests/complement/results.jsonl old_results.jsonl
|
||||
COPY <<EOF complement.toml
|
||||
[global]
|
||||
address = "0.0.0.0"
|
||||
admin_room_notices = false
|
||||
allow_device_name_federation = true
|
||||
allow_guest_registration = true
|
||||
allow_invalid_tls_certificates = true
|
||||
allow_legacy_media = true
|
||||
allow_public_room_directory_over_federation = true
|
||||
allow_public_room_directory_without_auth = true
|
||||
allow_registration = true
|
||||
create_admin_room = false
|
||||
database_path = "/database"
|
||||
log = "debug,tuwunel=trace,h2=warn,hyper=warn"
|
||||
port = [8008, 8448]
|
||||
trusted_servers = []
|
||||
only_query_trusted_key_servers = false
|
||||
query_trusted_key_servers_first = false
|
||||
query_trusted_key_servers_first_on_join = false
|
||||
yes_i_am_very_very_sure_i_want_an_open_registration_server_prone_to_abuse = true
|
||||
dns_attempts = 20
|
||||
dns_timeout = 60
|
||||
error_on_unknown_config_opts = true
|
||||
federation_idle_timeout = 300
|
||||
ip_range_denylist = []
|
||||
url_preview_domain_contains_allowlist = ["*"]
|
||||
url_preview_domain_explicit_denylist = ["*"]
|
||||
log = "debug,tuwunel=trace,h2=warn,hyper=warn"
|
||||
log_colors = false
|
||||
log_guest_registrations = false
|
||||
log_span_events = "NONE"
|
||||
log_thread_ids = true
|
||||
media_compat_file_link = false
|
||||
media_startup_check = true
|
||||
port = [8008, 8448]
|
||||
prune_missing_media = true
|
||||
log_colors = false
|
||||
admin_room_notices = false
|
||||
allow_check_for_updates = false
|
||||
intentionally_unknown_config_option_for_testing = true
|
||||
rocksdb_log_level = "debug"
|
||||
rocksdb_max_log_files = 1
|
||||
rocksdb_recovery_mode = 0
|
||||
rocksdb_paranoid_file_checks = true
|
||||
log_guest_registrations = false
|
||||
allow_legacy_media = true
|
||||
startup_netburst = true
|
||||
startup_netburst_keep = -1
|
||||
# valgrind makes things so slow
|
||||
dns_timeout = 60
|
||||
dns_attempts = 20
|
||||
query_trusted_key_servers_first = false
|
||||
query_trusted_key_servers_first_on_join = false
|
||||
request_conn_timeout = 60
|
||||
request_timeout = 120
|
||||
well_known_conn_timeout = 60
|
||||
well_known_timeout = 60
|
||||
federation_idle_timeout = 300
|
||||
sender_timeout = 300
|
||||
rocksdb_log_level = "debug"
|
||||
rocksdb_max_log_files = 1
|
||||
rocksdb_paranoid_file_checks = true
|
||||
rocksdb_recovery_mode = 0
|
||||
sender_idle_timeout = 300
|
||||
sender_retry_backoff_limit = 300
|
||||
allow_invalid_tls_certificates = true
|
||||
sender_timeout = 300
|
||||
startup_netburst = true
|
||||
startup_netburst_keep = -1
|
||||
trusted_servers = []
|
||||
url_preview_domain_contains_allowlist = ["*"]
|
||||
url_preview_domain_explicit_denylist = ["*"]
|
||||
well_known_conn_timeout = 60
|
||||
well_known_timeout = 60
|
||||
yes_i_am_very_very_sure_i_want_an_open_registration_server_prone_to_abuse = true
|
||||
|
||||
[global.tls]
|
||||
certs = "/complement/certificate.crt"
|
||||
@@ -119,9 +103,6 @@ EOF
|
||||
|
||||
FROM input AS complement-testee
|
||||
|
||||
WORKDIR /
|
||||
COPY --link --from=input . .
|
||||
|
||||
EXPOSE 8008 8448
|
||||
RUN mkdir /database
|
||||
COPY --from=complement-config * /complement/
|
||||
@@ -130,9 +111,7 @@ ENTRYPOINT tuwunel -Oserver_name=\""$SERVER_NAME\""
|
||||
|
||||
|
||||
FROM input AS complement-testee-valgrind
|
||||
|
||||
WORKDIR /
|
||||
COPY --link --from=input . .
|
||||
ARG db_pool_max_workers=128
|
||||
|
||||
EXPOSE 8008 8448
|
||||
RUN mkdir /database
|
||||
@@ -144,28 +123,20 @@ ENTRYPOINT valgrind \
|
||||
--exit-on-first-error=yes \
|
||||
--error-exitcode=1 \
|
||||
tuwunel \
|
||||
-Oserver_name=\""$SERVER_NAME\""
|
||||
-Oserver_name=\""$SERVER_NAME\"" \
|
||||
-Odb_pool_max_workers=${db_pool_max_workers}
|
||||
|
||||
|
||||
FROM input AS complement-base
|
||||
ARG var_cache
|
||||
ARG var_lib_apt
|
||||
ARG complement_tags="tuwunel_blacklist"
|
||||
ARG complement_ref="4d3130f06d0dc3f794b5d48fbdba0b466792b52b"
|
||||
ARG complement_tags="conduwuit_blacklist"
|
||||
ARG complement_tests="./tests/..."
|
||||
ARG complement_run=".*"
|
||||
|
||||
WORKDIR /
|
||||
RUN \
|
||||
--mount=type=cache,dst=/var/cache,id=${var_cache},sharing=locked \
|
||||
--mount=type=cache,dst=/var/lib/apt,id=${var_lib_apt},sharing=locked \
|
||||
--mount=type=cache,dst=/go/pkg/mod/cache,sharing=locked \
|
||||
<<EOF
|
||||
set -eux
|
||||
apt-get -y -U install --no-install-recommends golang-go jq
|
||||
EOF
|
||||
|
||||
WORKDIR /usr/src
|
||||
ADD https://github.com/matrix-construct/complement.git complement
|
||||
ADD https://github.com/matrix-construct/complement.git#${complement_ref} complement
|
||||
|
||||
WORKDIR /usr/src/complement
|
||||
ENV COMPLEMENT_BASE_IMAGE="complement-testee"
|
||||
@@ -181,8 +152,9 @@ EOF
|
||||
FROM input AS complement-tester
|
||||
ARG complement_verbose=0
|
||||
ARG complement_debug=0
|
||||
ARG complement_dirty=0
|
||||
ARG complement_count=1
|
||||
ARG complement_parallel=16
|
||||
ARG complement_parallel=1
|
||||
ARG complement_shuffle=1337
|
||||
ARG complement_timeout="1h"
|
||||
ARG complement_run=".*"
|
||||
@@ -191,9 +163,6 @@ ARG complement_tags="conduwuit_blacklist"
|
||||
ARG complement_tests="./tests/..."
|
||||
ARG complement_base_image
|
||||
|
||||
WORKDIR /
|
||||
COPY --link --from=input . .
|
||||
|
||||
WORKDIR /usr/src/complement
|
||||
ENV COMPLEMENT_DEBUG=$complement_debug
|
||||
ENV complement_parallel="$complement_parallel"
|
||||
@@ -205,12 +174,14 @@ ENV complement_tests="$complement_tests"
|
||||
ENV complement_skip="$complement_skip"
|
||||
ENV complement_run="$complement_run"
|
||||
ENV complement_tests="$complement_tests"
|
||||
ENV COMPLEMENT_ENABLE_DIRTY_RUNS="$complement_dirty"
|
||||
ENV COMPLEMENT_ALWAYS_PRINT_SERVER_LOGS="$complement_verbose"
|
||||
ENV COMPLEMENT_HOSTNAME_RUNNING_COMPLEMENT="host.docker.internal"
|
||||
ENV COMPLEMENT_HOST_MOUNTS="/var/run/docker.sock:/var/run/docker.sock"
|
||||
ENV jq_res='{Action: .Action, Test: .Test}'
|
||||
ENV jq_sel='select((.Action == \"pass\" or .Action == \"fail\" or .Action == \"skip\") and .Test != null)'
|
||||
ENV jq_tab='[.Action, .Test] | @tsv'
|
||||
ENV jq_out='select(.Test != null) | {Test: .Test, Output: .Output}'
|
||||
COPY --from=complement-config /complement/old_results.jsonl .
|
||||
COPY <<EOF uwu.sh
|
||||
env;
|
||||
@@ -219,22 +190,23 @@ COPY <<EOF uwu.sh
|
||||
COMPLEMENT_BASE_IMAGE="\${1:-$complement_base_image}"
|
||||
go test
|
||||
-json
|
||||
-shuffle="${complement_shuffle}"
|
||||
-parallel="${complement_parallel}"
|
||||
-timeout="${complement_timeout}"
|
||||
-count="${complement_count}"
|
||||
-tags="${complement_tags}"
|
||||
-skip="${complement_skip}"
|
||||
-run="${complement_run}"
|
||||
"${complement_tests}"
|
||||
| jq --unbuffered -c "${jq_sel} | ${jq_res}"
|
||||
"-shuffle=\$complement_shuffle"
|
||||
"-parallel=\$complement_parallel"
|
||||
"-timeout=\$complement_timeout"
|
||||
"-count=\$complement_count"
|
||||
"-tags=\$complement_tags"
|
||||
"-skip=\$complement_skip"
|
||||
"-run=\$complement_run"
|
||||
"\$complement_tests"
|
||||
| jq --unbuffered -c "."
|
||||
| tee output.jsonl
|
||||
| jq --unbuffered -c "$jq_sel | $jq_res"
|
||||
| tee results.jsonl
|
||||
| jq --unbuffered -r "${jq_tab}"
|
||||
| jq --unbuffered -r "$jq_tab"
|
||||
;
|
||||
|
||||
jq -s -c "sort_by(.Test)[]" < results.jsonl | uniq > new_results.jsonl;
|
||||
wc -l old_results.jsonl new_results.jsonl;
|
||||
diff -w -y -t --width=275 --suppress-common-lines old_results.jsonl new_results.jsonl;
|
||||
jq -s -c "sort_by(.Test, .Timestamp)[] | $jq_out" < output.jsonl > full_output.jsonl;
|
||||
EOF
|
||||
RUN echo $(tr -d '\n' < uwu.sh) > uwu.sh
|
||||
RUN echo $(tr -d '\n' < uwu.sh) > uwu.sh && chmod a+x uwu.sh
|
||||
ENTRYPOINT ["/bin/bash", "/usr/src/complement/uwu.sh"]
|
||||
|
||||
@@ -15,15 +15,17 @@ ENV src_path="${CARGO_TARGET_DIR}/${rust_target}/${cargo_target_profile}/tuwunel
|
||||
ENV dst_path="${install_prefix}/bin/tuwunel"
|
||||
COPY --from=bins $src_path $dst_path
|
||||
RUN <<EOF
|
||||
ret=$(ldd "${dst_path}")
|
||||
ldd -v "${dst_path}"
|
||||
ret=$?
|
||||
if [ "$ret" = "0" ] && [ "$assert_linkage" = "static" ]; then
|
||||
echo "($ret) expected a static binary"
|
||||
exit 1
|
||||
elif [ "$ret" != "0" ] && [ "$assert_linkage" = "dynamic" ]; then
|
||||
echo "($ret) expected a dynamic binary"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
set -eux
|
||||
ldd -v ${dst_path} || true
|
||||
du -h ${dst_path}
|
||||
sha1sum ${dst_path}
|
||||
du -h "${dst_path}"
|
||||
sha1sum "${dst_path}"
|
||||
EOF
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
# syntax = docker/dockerfile:1.11-labs
|
||||
|
||||
FROM input AS rust-sdk-integration
|
||||
ARG sys_name
|
||||
ARG sys_version
|
||||
ARG feat_set
|
||||
ARG rust_target
|
||||
ARG rust_toolchain
|
||||
ARG cargo_profile
|
||||
ARG RUSTUP_HOME
|
||||
ARG CARGO_HOME
|
||||
ARG CARGO_TARGET
|
||||
ARG MRSDK_TARGET_DIR="/usr/src/matrix-rust-sdk/target"
|
||||
ARG mrsdk_target_share
|
||||
#ARG mrsdk_ref="integration"
|
||||
ARG mrsdk_ref="tuwunel-changes"
|
||||
ARG mrsdk_test_args=""
|
||||
ARG mrsdk_test_opts=""
|
||||
ARG mrsdk_skip_list=""
|
||||
ARG mrsdk_parallel=2
|
||||
ARG mrsdk_startup_delay="10s"
|
||||
ARG mrsdk_testee="/usr/bin/tuwunel"
|
||||
|
||||
WORKDIR /usr/src
|
||||
ADD --link https://github.com/matrix-construct/matrix-rust-sdk.git#${mrsdk_ref} matrix-rust-sdk
|
||||
|
||||
WORKDIR /etc
|
||||
COPY <<EOF tuwunel.toml
|
||||
[global]
|
||||
admin_room_notices = false
|
||||
allow_device_name_federation = true
|
||||
allow_guest_registration = true
|
||||
allow_legacy_media = true
|
||||
allow_public_room_directory_over_federation = true
|
||||
allow_public_room_directory_without_auth = true
|
||||
allow_registration = true
|
||||
create_admin_room = false
|
||||
error_on_unknown_config_opts = true
|
||||
ip_range_denylist = []
|
||||
log = "debug,tuwunel=trace,h2=warn,hyper=warn"
|
||||
log_colors = false
|
||||
log_guest_registrations = false
|
||||
log_span_events = "NONE"
|
||||
log_thread_ids = true
|
||||
media_compat_file_link = false
|
||||
media_startup_check = true
|
||||
query_trusted_key_servers_first = false
|
||||
query_trusted_key_servers_first_on_join = false
|
||||
rocksdb_log_level = "debug"
|
||||
rocksdb_max_log_files = 1
|
||||
rocksdb_paranoid_file_checks = true
|
||||
rocksdb_recovery_mode = 0
|
||||
trusted_servers = []
|
||||
url_preview_domain_contains_allowlist = ["*"]
|
||||
url_preview_domain_explicit_denylist = ["*"]
|
||||
yes_i_am_very_very_sure_i_want_an_open_registration_server_prone_to_abuse = true
|
||||
EOF
|
||||
|
||||
WORKDIR /usr/lib
|
||||
COPY --link --from=install /usr/lib .
|
||||
|
||||
WORKDIR /usr/bin
|
||||
COPY --link --from=install /usr/bin/tuwunel .
|
||||
|
||||
WORKDIR /usr/src/matrix-rust-sdk
|
||||
SHELL ["/bin/bash", "-c"]
|
||||
ENV RUST_BACKTRACE="full"
|
||||
ENV TUWUNEL_CONFIG="/etc/tuwunel.toml"
|
||||
ENV TUWUNEL_DATABASE_PATH="/var/db/tuwunel"
|
||||
ENV TUWUNEL_SERVER_NAME="localhost"
|
||||
ENV TUWUNEL_PORT="[8448]"
|
||||
ENV HOMESERVER_URL="http://localhost:8448"
|
||||
RUN \
|
||||
--mount=type=cache,dst=${RUSTUP_HOME}/downloads,sharing=shared \
|
||||
--mount=type=cache,dst=${CARGO_HOME}/registry,sharing=shared \
|
||||
--mount=type=cache,dst=${CARGO_HOME}/git,sharing=shared \
|
||||
--mount=type=cache,dst=${MRSDK_TARGET_DIR},id=${mrsdk_target_share},sharing=locked \
|
||||
<<EOF
|
||||
set -eux
|
||||
|
||||
nohup ${mrsdk_testee[@]} 1> /var/log/tuwunel.log &
|
||||
PID=$!; trap "sleep 10s; set +e; kill -QUIT ${PID}; wait ${PID}" EXIT
|
||||
sleep "${mrsdk_startup_delay}"
|
||||
|
||||
rustup run ${rust_toolchain} \
|
||||
cargo test \
|
||||
--locked \
|
||||
--release \
|
||||
"--color=always" \
|
||||
"--features=default" \
|
||||
"--target=${rust_target}" \
|
||||
"--target-dir=${MRSDK_TARGET_DIR}" \
|
||||
"--package=matrix-sdk-integration-testing" \
|
||||
${mrsdk_test_args[@]} \
|
||||
-- \
|
||||
"--color=always" \
|
||||
"--test-threads=${mrsdk_parallel}" \
|
||||
${mrsdk_skip_list[@]} \
|
||||
${mrsdk_test_opts[@]} \
|
||||
;
|
||||
EOF
|
||||
@@ -0,0 +1,92 @@
|
||||
# syntax = docker/dockerfile:1.11-labs
|
||||
|
||||
FROM input AS nix-base
|
||||
|
||||
WORKDIR /
|
||||
COPY --link --from=input . .
|
||||
|
||||
RUN \
|
||||
--mount=type=cache,dst=/nix,sharing=shared \
|
||||
--mount=type=cache,dst=/root/.cache/nix,sharing=shared \
|
||||
--mount=type=cache,dst=/root/.local/state/nix,sharing=shared \
|
||||
<<EOF
|
||||
set -eux
|
||||
curl --proto '=https' --tlsv1.2 -L https://nixos.org/nix/install > nix-install
|
||||
sh ./nix-install --daemon
|
||||
rm nix-install
|
||||
EOF
|
||||
|
||||
|
||||
FROM nix-base AS build-nix
|
||||
|
||||
WORKDIR /usr/src/tuwunel
|
||||
COPY --link --from=source /usr/src/tuwunel .
|
||||
RUN \
|
||||
--mount=type=cache,dst=/nix,sharing=shared \
|
||||
--mount=type=cache,dst=/root/.cache/nix,sharing=shared \
|
||||
--mount=type=cache,dst=/root/.local/state/nix,sharing=shared \
|
||||
<<EOF
|
||||
set -eux
|
||||
|
||||
nix-build \
|
||||
--verbose \
|
||||
--cores 0 \
|
||||
--max-jobs $(nproc) \
|
||||
--log-format raw \
|
||||
.
|
||||
|
||||
cp -afRL --copy-contents result /opt/tuwunel
|
||||
EOF
|
||||
|
||||
|
||||
FROM input AS smoke-nix
|
||||
|
||||
WORKDIR /
|
||||
COPY --link --from=nix-base . .
|
||||
|
||||
WORKDIR /usr/src/tuwunel
|
||||
COPY --link --from=source /usr/src/tuwunel .
|
||||
ENV TUWUNEL_DATABASE_PATH="/tmp/tuwunel/smoketest.db"
|
||||
ENV TUWUNEL_LOG="info"
|
||||
RUN \
|
||||
--mount=type=cache,dst=/nix,sharing=shared \
|
||||
--mount=type=cache,dst=/root/.cache/nix,sharing=shared \
|
||||
--mount=type=cache,dst=/root/.local/state/nix,sharing=shared \
|
||||
<<EOF
|
||||
set -eux
|
||||
alias nix="nix --extra-experimental-features nix-command --extra-experimental-features flakes"
|
||||
|
||||
nix run \
|
||||
--verbose \
|
||||
--cores 0 \
|
||||
--max-jobs $(nproc) \
|
||||
--log-format raw \
|
||||
.#all-features \
|
||||
-- \
|
||||
-Otest='["smoke", "fresh"]' \
|
||||
-Oserver_name=\"localhost\" \
|
||||
-Oerror_on_unknown_config_opts=true \
|
||||
EOF
|
||||
|
||||
|
||||
FROM input AS nix-pkg
|
||||
|
||||
WORKDIR /
|
||||
COPY --link --from=nix-base . .
|
||||
|
||||
WORKDIR /usr/src/tuwunel
|
||||
COPY --link --from=source /usr/src/tuwunel .
|
||||
RUN \
|
||||
--mount=type=cache,dst=/nix,sharing=shared \
|
||||
--mount=type=cache,dst=/root/.cache/nix,sharing=shared \
|
||||
--mount=type=cache,dst=/root/.local/state/nix,sharing=shared \
|
||||
<<EOF
|
||||
set -eux
|
||||
alias nix="nix --extra-experimental-features nix-command --extra-experimental-features flakes"
|
||||
|
||||
ID=$(nix-store --realise $(nix path-info --derivation))
|
||||
|
||||
mkdir -p tuwunel
|
||||
nix-store --export $ID > tuwunel/tuwunel.drv
|
||||
tar -cvf /opt/tuwunel.nix.tar tuwunel
|
||||
EOF
|
||||
@@ -26,12 +26,14 @@ EOF
|
||||
|
||||
FROM input AS rocksdb-build
|
||||
ARG rocksdb_shared=0
|
||||
ARG rocksdb_portable=1
|
||||
ARG rocksdb_portable="1"
|
||||
ARG rocksdb_opt_level="3"
|
||||
ARG rocksdb_lto="-flto -ffat-lto-objects"
|
||||
ARG rocksdb_build_type="Release"
|
||||
ARG rocksdb_cxx_flags="-ftls-model=initial-exec -mno-outline-atomics"
|
||||
ARG rocksdb_cxx_flags="-ftls-model=initial-exec"
|
||||
ARG rocksdb_make_verbose="ON"
|
||||
ARG rocksdb_make_rule_messages="OFF"
|
||||
ARG rocksdb_numa=0
|
||||
ARG rocksdb_jemalloc=1
|
||||
ARG rocksdb_iouring=1
|
||||
ARG rocksdb_zstd=1
|
||||
@@ -59,7 +61,7 @@ RUN <<EOF
|
||||
"-DBUILD_SHARED_LIBS=${rocksdb_shared}" \
|
||||
"-DROCKSDB_BUILD_SHARED=${rocksdb_shared}" \
|
||||
"-DCMAKE_CXX_FLAGS:STRING=${rocksdb_cxx_flags}" \
|
||||
"-DCMAKE_CXX_FLAGS_RELEASE:STRING=-g0 -O${rocksdb_opt_level} -DNDEBUG" \
|
||||
"-DCMAKE_CXX_FLAGS_RELEASE:STRING=-g0 -O${rocksdb_opt_level} -DNDEBUG ${rocksdb_lto}" \
|
||||
"-DPORTABLE=${rocksdb_portable}" \
|
||||
"-DFAIL_ON_WARNINGS=0" \
|
||||
"-DUSE_RTTI=0" \
|
||||
@@ -73,6 +75,7 @@ RUN <<EOF
|
||||
"-DWITH_TOOLS=0" \
|
||||
"-DWITH_TESTS=0" \
|
||||
"-DWITH_GFLAGS=0" \
|
||||
"-DWITH_NUMA=${rocksdb_numa}" \
|
||||
"-DWITH_LIBURING=${rocksdb_iouring}" \
|
||||
"-DWITH_JEMALLOC=${rocksdb_jemalloc}" \
|
||||
"-DWITH_ZSTD=${rocksdb_zstd}" \
|
||||
|
||||
@@ -6,9 +6,6 @@ ARG rust_target
|
||||
ARG rustup_version="1.28.2"
|
||||
ARG rustup_profile="minimal"
|
||||
|
||||
WORKDIR /
|
||||
COPY --link --from=input . .
|
||||
|
||||
WORKDIR ${RUST_HOME}
|
||||
RUN <<EOF
|
||||
set -eux
|
||||
@@ -16,7 +13,7 @@ RUN <<EOF
|
||||
var="${rustup_version}/${rust_target}"
|
||||
url="https://static.rust-lang.org/rustup/archive/$var/rustup-init"
|
||||
curl -S -O -s "$url"
|
||||
chmod o+x rustup-init
|
||||
chmod a+rx rustup-init
|
||||
EOF
|
||||
|
||||
FROM input AS rust
|
||||
@@ -32,9 +29,6 @@ ARG CARGO_TERM_VERBOSE
|
||||
ARG rustup_components
|
||||
ARG cargo_installs
|
||||
|
||||
WORKDIR /
|
||||
COPY --link --from=input . .
|
||||
|
||||
WORKDIR ${RUST_HOME}
|
||||
ENV CARGO_TARGET="${rust_target}"
|
||||
ENV RUSTUP_HOME="${RUSTUP_HOME}"
|
||||
@@ -54,7 +48,7 @@ RUN \
|
||||
--no-update-default-toolchain \
|
||||
--no-modify-path
|
||||
|
||||
chmod -R go+rw $CARGO_HOME $RUSTUP_HOME
|
||||
chmod -R a+rw $CARGO_HOME $RUSTUP_HOME
|
||||
rm rustup-init
|
||||
|
||||
rustup component add \
|
||||
|
||||
@@ -19,7 +19,8 @@ RUN <<EOF
|
||||
tuwunel \
|
||||
-Otest='["smoke"]' \
|
||||
-Oserver_name=\"localhost\" \
|
||||
-Odatabase_path=\"${TUWUNEL_DATABASE_PATH}\"
|
||||
-Odatabase_path=\"${TUWUNEL_DATABASE_PATH}\" \
|
||||
-Oerror_on_unknown_config_opts=true
|
||||
|
||||
rm -rf "${TUWUNEL_DATABASE_PATH}"
|
||||
EOF
|
||||
@@ -28,6 +29,7 @@ EOF
|
||||
FROM input AS smoke-valgrind
|
||||
ARG leak_check="no"
|
||||
ARG undef_value_errors="no"
|
||||
ARG db_pool_max_workers=128
|
||||
COPY --link --from=input . .
|
||||
ENV TUWUNEL_LOG="info"
|
||||
ENV TUWUNEL_DATABASE_PATH="/tmp/smoketest.db"
|
||||
@@ -42,7 +44,9 @@ RUN <<EOF
|
||||
tuwunel \
|
||||
-Otest='["smoke"]' \
|
||||
-Oserver_name=\"localhost\" \
|
||||
-Odatabase_path=\"${TUWUNEL_DATABASE_PATH}\"
|
||||
-Odatabase_path=\"${TUWUNEL_DATABASE_PATH}\" \
|
||||
-Odb_pool_max_workers=${db_pool_max_workers} \
|
||||
-Oerror_on_unknown_config_opts=true
|
||||
|
||||
rm -rf "${TUWUNEL_DATABASE_PATH}"
|
||||
EOF
|
||||
@@ -60,7 +64,8 @@ RUN <<EOF
|
||||
tuwunel \
|
||||
-Otest='["smoke"]' \
|
||||
-Oserver_name=\"localhost\" \
|
||||
-Odatabase_path=\"${TUWUNEL_DATABASE_PATH}\"
|
||||
-Odatabase_path=\"${TUWUNEL_DATABASE_PATH}\" \
|
||||
-Oerror_on_unknown_config_opts=true
|
||||
|
||||
rm -rf "${TUWUNEL_DATABASE_PATH}"
|
||||
EOF
|
||||
|
||||
@@ -3,9 +3,6 @@
|
||||
FROM input AS source
|
||||
ARG git_checkout
|
||||
|
||||
WORKDIR /
|
||||
COPY --link --from=input . .
|
||||
|
||||
ADD --link --keep-git-dir . /usr/src/tuwunel
|
||||
WORKDIR /usr/src/tuwunel
|
||||
RUN <<EOF
|
||||
@@ -18,7 +15,6 @@ EOF
|
||||
|
||||
|
||||
FROM input AS ingredients
|
||||
ARG sys_target
|
||||
ARG rust_target
|
||||
ARG rust_toolchain
|
||||
ARG RUST_HOME
|
||||
@@ -31,7 +27,6 @@ ARG JEMALLOC_OVERRIDE
|
||||
ARG ROCKSDB_LIB_DIR
|
||||
|
||||
WORKDIR /
|
||||
COPY --link --from=input . .
|
||||
COPY --link --from=rust ${RUST_HOME} ${RUST_HOME}
|
||||
COPY --link --from=source /usr/src/tuwunel /usr/src/tuwunel
|
||||
|
||||
@@ -68,9 +63,6 @@ ARG RUSTUP_HOME
|
||||
ARG CARGO_HOME
|
||||
ARG CARGO_TARGET
|
||||
|
||||
WORKDIR /
|
||||
COPY --link --from=input . .
|
||||
|
||||
WORKDIR /usr/src/tuwunel
|
||||
RUN \
|
||||
--mount=type=cache,dst=${RUSTUP_HOME}/downloads,sharing=locked \
|
||||
|
||||
@@ -12,9 +12,6 @@ ARG var_lib_apt
|
||||
ARG packages
|
||||
ARG DEBIAN_FRONTEND
|
||||
|
||||
WORKDIR /
|
||||
COPY --link --from=input . .
|
||||
|
||||
ENV DEBIAN_FRONTEND="${DEBIAN_FRONTEND}"
|
||||
RUN \
|
||||
--mount=type=cache,dst=/var/cache,id=${var_cache},sharing=locked \
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
# Docker Builder
|
||||
|
||||
> [!NOTE]
|
||||
> This directory is for building docker images. For [deploying](https://github.com/matrix-construct/tuwunel/tree/main/docs/deploying)
|
||||
> [docker](https://github.com/matrix-construct/tuwunel/blob/main/docs/deploying/docker.md) visit
|
||||
> the appropriate documentation instead.
|
||||
|
||||
All Docker images for the project are built here. All images are
|
||||
[Docker Bake](https://docs.docker.com/build/bake/) targets. All targets are leaves and
|
||||
branches of a unified tree leading to a single root. It is a combinatorial matrix
|
||||
|
||||
+411
-81
@@ -1,4 +1,4 @@
|
||||
variable "CI" {}
|
||||
|
||||
variable "GITHUB_ACTOR" {}
|
||||
variable "GITHUB_REPOSITORY" {}
|
||||
variable "GITHUB_REF" {}
|
||||
@@ -16,12 +16,6 @@ variable "repo" {
|
||||
variable "docker_repo" {
|
||||
default = "${repo}"
|
||||
}
|
||||
variable "docker_tag_preview" {
|
||||
default = false
|
||||
}
|
||||
variable "docker_tag_latest" {
|
||||
default = false
|
||||
}
|
||||
|
||||
variable "git_ref" {
|
||||
default = "${GITHUB_REF}"
|
||||
@@ -35,8 +29,12 @@ variable "git_ref_name" {
|
||||
|
||||
cargo_feat_sets = {
|
||||
none = ""
|
||||
# Default features
|
||||
default = "brotli_compression,element_hacks,gzip_compression,io_uring,jemalloc,jemalloc_conf,media_thumbnail,release_max_log_level,systemd,url_preview,zstd_compression"
|
||||
all = "blurhashing,brotli_compression,tuwunel_mods,console,default,direct_tls,element_hacks,gzip_compression,hardened_malloc,io_uring,jemalloc,jemalloc_conf,jemalloc_prof,jemalloc_stats,ldap,media_thumbnail,perf_measurements,release_max_log_level,sentry_telemetry,systemd,tokio_console,url_preview,zstd_compression"
|
||||
# All features sans release_max_log_level
|
||||
logging = "blurhashing,brotli_compression,bzip2_compression,console,direct_tls,element_hacks,gzip_compression,io_uring,jemalloc,jemalloc_conf,jemalloc_prof,jemalloc_stats,ldap,lz4_compression,media_thumbnail,perf_measurements,sentry_telemetry,systemd,tokio_console,tuwunel_mods,url_preview,zstd_compression"
|
||||
# All features
|
||||
all = "blurhashing,brotli_compression,bzip2_compression,console,direct_tls,element_hacks,gzip_compression,io_uring,jemalloc,jemalloc_conf,jemalloc_prof,jemalloc_stats,ldap,lz4_compression,media_thumbnail,perf_measurements,release_max_log_level,sentry_telemetry,systemd,tokio_console,tuwunel_mods,url_preview,zstd_compression"
|
||||
}
|
||||
variable "cargo_features_always" {
|
||||
default = "direct_tls"
|
||||
@@ -63,19 +61,19 @@ variable "rust_targets" {
|
||||
default = "[\"x86_64-unknown-linux-gnu\"]"
|
||||
}
|
||||
|
||||
variable "sys_targets" {
|
||||
default = "[\"x86_64-linux-gnu\"]"
|
||||
variable "sys_names" {
|
||||
default = "[\"debian\"]"
|
||||
}
|
||||
variable "sys_versions" {
|
||||
default = "[\"testing-slim\"]"
|
||||
}
|
||||
variable "sys_names" {
|
||||
default = "[\"debian\"]"
|
||||
variable "sys_targets" {
|
||||
default = "[\"x86_64-v1-linux-gnu\"]"
|
||||
}
|
||||
|
||||
# RocksDB options
|
||||
variable "rocksdb_portable" {
|
||||
default = 1
|
||||
default = "1"
|
||||
}
|
||||
variable "rocksdb_opt_level" {
|
||||
default = "3"
|
||||
@@ -86,6 +84,9 @@ variable "rocksdb_build_type" {
|
||||
variable "rocksdb_make_verbose" {
|
||||
default = "ON"
|
||||
}
|
||||
variable "rocksdb_numa" {
|
||||
default = "0"
|
||||
}
|
||||
|
||||
# Complement options
|
||||
variable "complement_count" {
|
||||
@@ -186,7 +187,6 @@ dynamic_libs = [
|
||||
|
||||
nightly_rustflags = [
|
||||
"--cfg tokio_unstable",
|
||||
"--cfg tuwunel_bench",
|
||||
"--allow=unstable-features",
|
||||
"-Z crate-attr=feature(test)",
|
||||
"-Z enforce-type-length-limit",
|
||||
@@ -239,9 +239,18 @@ group "lints" {
|
||||
|
||||
group "tests" {
|
||||
targets = [
|
||||
"docs",
|
||||
"unit",
|
||||
"smoke",
|
||||
"integration",
|
||||
"matrix-compliance",
|
||||
]
|
||||
}
|
||||
|
||||
group "matrix-compliance" {
|
||||
targets = [
|
||||
"complement",
|
||||
"rust-sdk-integ",
|
||||
]
|
||||
}
|
||||
|
||||
@@ -279,28 +288,24 @@ group "publish" {
|
||||
]
|
||||
}
|
||||
|
||||
target "github" {
|
||||
target "ghcr_io" {
|
||||
name = elem("github", [cargo_profile, rust_toolchain, rust_target, feat_set, sys_name, sys_version, sys_target])
|
||||
tags = [
|
||||
"ghcr.io/${repo}:${git_ref_name}-${cargo_profile}-${feat_set}-${sys_target}",
|
||||
docker_tag_preview? "ghcr.io/${repo}:preview": "",
|
||||
docker_tag_latest? "ghcr.io/${repo}:latest": "",
|
||||
]
|
||||
output = ["type=registry,compression=zstd,mode=min,compression-level=${zstd_image_compress_level}"]
|
||||
output = ["type=registry,oci-mediatypes=true,compression=zstd,compression-level=${zstd_image_compress_level},force-compression=true,mode=min"]
|
||||
matrix = cargo_rust_feat_sys
|
||||
inherits = [
|
||||
elem("docker", [cargo_profile, rust_toolchain, rust_target, feat_set, sys_name, sys_version, sys_target]),
|
||||
]
|
||||
}
|
||||
|
||||
target "dockerhub" {
|
||||
target "docker_io" {
|
||||
name = elem("dockerhub", [cargo_profile, rust_toolchain, rust_target, feat_set, sys_name, sys_version, sys_target])
|
||||
tags = [
|
||||
"${docker_repo}:${git_ref_name}-${cargo_profile}-${feat_set}-${sys_target}",
|
||||
docker_tag_preview? "${docker_repo}:preview": "",
|
||||
docker_tag_latest? "${docker_repo}:latest": "",
|
||||
"docker.io/${docker_repo}:${git_ref_name}-${cargo_profile}-${feat_set}-${sys_target}",
|
||||
]
|
||||
output = ["type=registry,compression=zstd,mode=min,compression-level=${zstd_image_compress_level}"]
|
||||
output = ["type=registry,oci-mediatypes=true,compression=zstd,compression-level=${zstd_image_compress_level},force-compression=true,mode=min"]
|
||||
matrix = cargo_rust_feat_sys
|
||||
inherits = [
|
||||
elem("docker", [cargo_profile, rust_toolchain, rust_target, feat_set, sys_name, sys_version, sys_target]),
|
||||
@@ -413,7 +418,7 @@ target "complement-base" {
|
||||
elem("complement-config", [sys_name, sys_version, sys_target])
|
||||
]
|
||||
contexts = {
|
||||
input = elem("target:base", [sys_name, sys_version, sys_target])
|
||||
input = elem("target:builder", [sys_name, sys_version, sys_target])
|
||||
}
|
||||
args = complement_args
|
||||
}
|
||||
@@ -434,6 +439,125 @@ target "complement-config" {
|
||||
}
|
||||
}
|
||||
|
||||
#
|
||||
# Integration tests
|
||||
#
|
||||
|
||||
group "integration" {
|
||||
targets = [
|
||||
"integ",
|
||||
"rust-sdk-integ",
|
||||
]
|
||||
}
|
||||
|
||||
variable "valgrind_max_workers" {
|
||||
default = 128
|
||||
}
|
||||
|
||||
variable "valgrind_flags" {
|
||||
default = "--error-exitcode=1 --exit-on-first-error=yes --undef-value-errors=no --leak-check=no"
|
||||
}
|
||||
|
||||
variable "valgrind_testee_args" {
|
||||
default = "-Odb_pool_max_workers=${valgrind_max_workers}"
|
||||
}
|
||||
|
||||
target "rust-sdk-valgrind" {
|
||||
name = elem("rust-sdk-valgrind", [cargo_profile, rust_toolchain, rust_target, feat_set, sys_name, sys_version, sys_target])
|
||||
tags = [
|
||||
elem_tag("rust-sdk-valgrind", [cargo_profile, rust_toolchain, rust_target, feat_set, sys_name, sys_version, sys_target], "latest"),
|
||||
]
|
||||
matrix = cargo_rust_feat_sys
|
||||
inherits = [
|
||||
elem("rust-sdk-integ", [cargo_profile, rust_toolchain, rust_target, feat_set, sys_name, sys_version, sys_target])
|
||||
]
|
||||
contexts = {
|
||||
input = elem("target:rust", [rust_toolchain, rust_target, sys_name, sys_version, sys_target])
|
||||
install = elem("target:install", [cargo_profile, rust_toolchain, rust_target, feat_set, sys_name, sys_version, sys_target])
|
||||
}
|
||||
args = {
|
||||
VALGRINDFLAGS = "${valgrind_flags}"
|
||||
mrsdk_testee = "valgrind ${valgrind_flags} /usr/bin/tuwunel ${valgrind_testee_args}"
|
||||
mrsdk_test_args = ""
|
||||
mrsdk_startup_delay = "30s"
|
||||
mrsdk_skip_list =<<EOF
|
||||
--skip test_delayed_invite_response_and_sent_message_decryption
|
||||
--skip test_history_share_on_invite_pin_violation
|
||||
EOF
|
||||
}
|
||||
}
|
||||
|
||||
target "rust-sdk-integ" {
|
||||
name = elem("rust-sdk-integ", [cargo_profile, rust_toolchain, rust_target, feat_set, sys_name, sys_version, sys_target])
|
||||
tags = [
|
||||
elem_tag("rust-sdk-integ", [cargo_profile, rust_toolchain, rust_target, feat_set, sys_name, sys_version, sys_target], "latest"),
|
||||
]
|
||||
output = ["type=docker,compression=zstd,mode=max,compression-level=${zstd_image_compress_level}"]
|
||||
cache_to = ["type=local,compression=zstd,mode=max,compression-level=${cache_compress_level}"]
|
||||
target = "rust-sdk-integration"
|
||||
dockerfile = "${docker_dir}/Dockerfile.matrix-rust-sdk"
|
||||
matrix = cargo_rust_feat_sys
|
||||
inherits = [
|
||||
elem("rust", [rust_toolchain, rust_target, sys_name, sys_version, sys_target]),
|
||||
elem("integ", [cargo_profile, rust_toolchain, rust_target, feat_set, sys_name, sys_version, sys_target]),
|
||||
]
|
||||
contexts = {
|
||||
input = elem("target:rust", [rust_toolchain, rust_target, sys_name, sys_version, sys_target])
|
||||
install = elem("target:install", [cargo_profile, rust_toolchain, rust_target, feat_set, sys_name, sys_version, sys_target])
|
||||
}
|
||||
args = {
|
||||
mrsdk_target_share = "/usr/src/matrix-rust-sdk/target/${sys_name}/${sys_version}/${rust_target}/${rust_toolchain}/_shared_cache"
|
||||
|
||||
mrsdk_testee = "/usr/bin/tuwunel"
|
||||
mrsdk_test_args = "--no-fail-fast"
|
||||
|
||||
mrsdk_skip_list =<<EOF
|
||||
--skip test_delayed_invite_response_and_sent_message_decryption
|
||||
EOF
|
||||
}
|
||||
}
|
||||
|
||||
target "integ-valgrind" {
|
||||
name = elem("integ-valgrind", [cargo_profile, rust_toolchain, rust_target, feat_set, sys_name, sys_version, sys_target])
|
||||
tags = [
|
||||
elem_tag("integ-valgrind", [cargo_profile, rust_toolchain, rust_target, feat_set, sys_name, sys_version, sys_target], "latest"),
|
||||
]
|
||||
matrix = cargo_rust_feat_sys
|
||||
inherits = [
|
||||
elem("integ", [cargo_profile, rust_toolchain, rust_target, feat_set, sys_name, sys_version, sys_target]),
|
||||
]
|
||||
contexts = {
|
||||
input = elem("target:build-tests", [cargo_profile, rust_toolchain, rust_target, feat_set, sys_name, sys_version, sys_target])
|
||||
}
|
||||
args = {
|
||||
VALGRIND_MAX_WORKERS = "${valgrind_max_workers}"
|
||||
VALGRINDFLAGS = "${valgrind_flags}"
|
||||
cargo_cmd = "valgrind test"
|
||||
cargo_args = "--test=*"
|
||||
}
|
||||
}
|
||||
|
||||
target "integ" {
|
||||
name = elem("integ", [cargo_profile, rust_toolchain, rust_target, feat_set, sys_name, sys_version, sys_target])
|
||||
tags = [
|
||||
elem_tag("integ", [cargo_profile, rust_toolchain, rust_target, feat_set, sys_name, sys_version, sys_target], "latest"),
|
||||
]
|
||||
matrix = cargo_rust_feat_sys
|
||||
inherits = [
|
||||
elem("build-tests", [cargo_profile, rust_toolchain, rust_target, feat_set, sys_name, sys_version, sys_target]),
|
||||
]
|
||||
contexts = {
|
||||
input = elem("target:build-tests", [cargo_profile, rust_toolchain, rust_target, feat_set, sys_name, sys_version, sys_target])
|
||||
}
|
||||
args = {
|
||||
TUWUNEL_DATABASE_PATH = "/tmp/integration.test.db"
|
||||
cargo_cmd = (cargo_profile == "bench"? "bench": "test")
|
||||
cargo_args = (cargo_profile == "bench"?
|
||||
"--no-fail-fast --bench=*": "--no-fail-fast --test=*"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#
|
||||
# Smoke tests
|
||||
#
|
||||
@@ -442,11 +566,26 @@ group "smoke" {
|
||||
targets = [
|
||||
"smoke-version",
|
||||
"smoke-startup",
|
||||
#"smoke-nix",
|
||||
#"smoke-valgrind",
|
||||
#"smoke-perf",
|
||||
]
|
||||
}
|
||||
|
||||
target "smoke-nix" {
|
||||
name = elem("smoke-nix", [cargo_profile, rust_toolchain, rust_target, feat_set, sys_name, sys_version, sys_target])
|
||||
tags = [
|
||||
elem_tag("smoke-nix", [cargo_profile, rust_toolchain, rust_target, feat_set, sys_name, sys_version, sys_target], "latest"),
|
||||
]
|
||||
output = ["type=cacheonly,compression=zstd,mode=min,compression-level=${cache_compress_level}"]
|
||||
dockerfile = "${docker_dir}/Dockerfile.nix"
|
||||
target = "smoke-nix"
|
||||
matrix = cargo_rust_feat_sys
|
||||
inherits = [
|
||||
elem("build-nix", [cargo_profile, rust_toolchain, rust_target, feat_set, sys_name, sys_version, sys_target]),
|
||||
]
|
||||
}
|
||||
|
||||
target "smoke-valgrind" {
|
||||
name = elem("smoke-valgrind", [cargo_profile, rust_toolchain, rust_target, feat_set, sys_name, sys_version, sys_target])
|
||||
tags = [
|
||||
@@ -519,6 +658,70 @@ target "tests-smoke" {
|
||||
}
|
||||
}
|
||||
|
||||
#
|
||||
# Unit tests
|
||||
#
|
||||
|
||||
target "unit-valgrind" {
|
||||
name = elem("unit-valgrind", [cargo_profile, rust_toolchain, rust_target, feat_set, sys_name, sys_version, sys_target])
|
||||
tags = [
|
||||
elem_tag("unit-valgrind", [cargo_profile, rust_toolchain, rust_target, feat_set, sys_name, sys_version, sys_target], "latest"),
|
||||
]
|
||||
target = "cargo"
|
||||
matrix = cargo_rust_feat_sys
|
||||
inherits = [
|
||||
elem("unit", [cargo_profile, rust_toolchain, rust_target, feat_set, sys_name, sys_version, sys_target]),
|
||||
]
|
||||
contexts = {
|
||||
input = elem("target:unit", [cargo_profile, rust_toolchain, rust_target, feat_set, sys_name, sys_version, sys_target])
|
||||
}
|
||||
args = {
|
||||
VALGRINDFLAGS = "${valgrind_flags}"
|
||||
cargo_cmd = "valgrind test"
|
||||
cargo_args = "--lib --bins"
|
||||
}
|
||||
}
|
||||
|
||||
target "unit" {
|
||||
name = elem("unit", [cargo_profile, rust_toolchain, rust_target, feat_set, sys_name, sys_version, sys_target])
|
||||
tags = [
|
||||
elem_tag("unit", [cargo_profile, rust_toolchain, rust_target, feat_set, sys_name, sys_version, sys_target], "latest"),
|
||||
]
|
||||
target = "cargo"
|
||||
matrix = cargo_rust_feat_sys
|
||||
inherits = [
|
||||
elem("build-tests", [cargo_profile, rust_toolchain, rust_target, feat_set, sys_name, sys_version, sys_target]),
|
||||
]
|
||||
contexts = {
|
||||
input = elem("target:build-tests", [cargo_profile, rust_toolchain, rust_target, feat_set, sys_name, sys_version, sys_target])
|
||||
}
|
||||
args = {
|
||||
cargo_cmd = (cargo_profile == "bench"? "bench": "test")
|
||||
cargo_args = (cargo_profile == "bench"?
|
||||
"--no-fail-fast --lib": "--no-fail-fast --lib --bins"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
target "docs" {
|
||||
name = elem("docs", [cargo_profile, rust_toolchain, rust_target, feat_set, sys_name, sys_version, sys_target])
|
||||
tags = [
|
||||
elem_tag("docs", [cargo_profile, rust_toolchain, rust_target, feat_set, sys_name, sys_version, sys_target], "latest"),
|
||||
]
|
||||
target = "cargo"
|
||||
matrix = cargo_rust_feat_sys
|
||||
inherits = [
|
||||
elem("build-tests", [cargo_profile, rust_toolchain, rust_target, feat_set, sys_name, sys_version, sys_target]),
|
||||
]
|
||||
contexts = {
|
||||
input = elem("target:build-tests", [cargo_profile, rust_toolchain, rust_target, feat_set, sys_name, sys_version, sys_target])
|
||||
}
|
||||
args = {
|
||||
cargo_cmd = "test"
|
||||
cargo_args = "--doc --no-fail-fast"
|
||||
}
|
||||
}
|
||||
|
||||
#
|
||||
# Installation
|
||||
#
|
||||
@@ -534,7 +737,7 @@ group "installs" {
|
||||
|
||||
install_labels = {
|
||||
"org.opencontainers.image.authors" = "${package_authors}"
|
||||
"org.opencontainers.image.created" ="${package_last_modified}"
|
||||
"org.opencontainers.image.created" = "${package_last_modified}"
|
||||
"org.opencontainers.image.description" = "Matrix Chat Server in Rust"
|
||||
"org.opencontainers.image.documentation" = "https://github.com/matrix-construct/tuwunel/tree/main/docs/"
|
||||
"org.opencontainers.image.licenses" = "Apache-2.0"
|
||||
@@ -546,12 +749,26 @@ install_labels = {
|
||||
"org.opencontainers.image.version" = "${package_version}"
|
||||
}
|
||||
|
||||
install_annotations = [
|
||||
"org.opencontainers.image.authors=${package_authors}",
|
||||
"org.opencontainers.image.created=${package_last_modified}",
|
||||
"org.opencontainers.image.description=Matrix Chat Server in Rust",
|
||||
"org.opencontainers.image.documentation=https://github.com/matrix-construct/tuwunel/tree/main/docs/",
|
||||
"org.opencontainers.image.licenses=Apache-2.0",
|
||||
"org.opencontainers.image.revision=${package_revision}",
|
||||
"org.opencontainers.image.source=https://github.com/matrix-construct/tuwunel",
|
||||
"org.opencontainers.image.title=${package_name}",
|
||||
"org.opencontainers.image.url=https://github.com/matrix-construct/tuwunel",
|
||||
"org.opencontainers.image.vendor=matrix-construct",
|
||||
"org.opencontainers.image.version=${package_version}",
|
||||
]
|
||||
|
||||
target "oci" {
|
||||
name = elem("oci", [cargo_profile, rust_toolchain, rust_target, feat_set, sys_name, sys_version, sys_target])
|
||||
tags = [
|
||||
elem_tag("oci", [cargo_profile, rust_toolchain, rust_target, feat_set, sys_name, sys_version, sys_target], "latest"),
|
||||
]
|
||||
output = ["type=oci,dest=tuwunel-oci.tar.zst,mode=min,compression=zstd,compression-level=${zstd_image_compress_level}"]
|
||||
output = ["type=oci,dest=tuwunel-oci.tar.zst,compression=zstd,compression-level=${zstd_image_compress_level},force-compression=true,mode=min"]
|
||||
matrix = cargo_rust_feat_sys
|
||||
inherits = [
|
||||
elem("docker", [cargo_profile, rust_toolchain, rust_target, feat_set, sys_name, sys_version, sys_target]),
|
||||
@@ -563,7 +780,7 @@ target "docker" {
|
||||
tags = [
|
||||
elem_tag("docker", [cargo_profile, rust_toolchain, rust_target, feat_set, sys_name, sys_version, sys_target], "latest"),
|
||||
]
|
||||
output = ["type=docker,compression=gzip,mode=min,compression-level=${gz_image_compress_level}"]
|
||||
output = ["type=docker,compression=zstd,compression-level=${zstd_image_compress_level},force-compression=true,mode=min"]
|
||||
matrix = cargo_rust_feat_sys
|
||||
inherits = [
|
||||
elem("static", [cargo_profile, rust_toolchain, rust_target, feat_set, sys_name, sys_version, sys_target]),
|
||||
@@ -643,7 +860,8 @@ target "install" {
|
||||
elem_tag("install", [cargo_profile, rust_toolchain, rust_target, feat_set, sys_name, sys_version, sys_target], "latest"),
|
||||
]
|
||||
labels = install_labels
|
||||
output = ["type=docker,compression=zstd,mode=min,compression-level=${zstd_image_compress_level}"]
|
||||
annotations = install_annotations
|
||||
output = ["type=docker,compression=zstd,mode=max,compression-level=${zstd_image_compress_level}"]
|
||||
cache_to = ["type=local,compression=zstd,mode=max,compression-level=${cache_compress_level}"]
|
||||
dockerfile = "${docker_dir}/Dockerfile.install"
|
||||
target = "install"
|
||||
@@ -659,6 +877,12 @@ target "install" {
|
||||
}
|
||||
args = {
|
||||
install_prefix = install_prefix
|
||||
assert_linkage = (
|
||||
substr(cargo_profile, 0, 5) == "bench"? "static":
|
||||
substr(cargo_profile, 0, 7) == "release"? "static":
|
||||
substr(rust_toolchain, 0, 6) == "stable"? "static":
|
||||
""
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -668,6 +892,7 @@ target "install" {
|
||||
|
||||
group "pkg" {
|
||||
targets = [
|
||||
"nix",
|
||||
"deb",
|
||||
"rpm",
|
||||
"deb-install",
|
||||
@@ -779,28 +1004,36 @@ target "build-deb" {
|
||||
}
|
||||
}
|
||||
|
||||
#
|
||||
# Unit tests
|
||||
#
|
||||
|
||||
target "unit" {
|
||||
name = elem("unit", [cargo_profile, rust_toolchain, rust_target, feat_set, sys_name, sys_version, sys_target])
|
||||
target "nix" {
|
||||
name = elem("nix", [cargo_profile, rust_toolchain, rust_target, feat_set, sys_name, sys_version, sys_target])
|
||||
tags = [
|
||||
elem_tag("unit", [cargo_profile, rust_toolchain, rust_target, feat_set, sys_name, sys_version, sys_target], "latest"),
|
||||
elem_tag("nix", [cargo_profile, rust_toolchain, rust_target, feat_set, sys_name, sys_version, sys_target], "latest"),
|
||||
]
|
||||
target = "cargo"
|
||||
output = ["type=docker,compression=zstd,mode=min,compression-level=${zstd_image_compress_level}"]
|
||||
target = "nix-pkg"
|
||||
matrix = cargo_rust_feat_sys
|
||||
inherits = [
|
||||
elem("build-tests", [cargo_profile, rust_toolchain, rust_target, feat_set, sys_name, sys_version, sys_target]),
|
||||
elem("build-nix", [cargo_profile, rust_toolchain, rust_target, feat_set, sys_name, sys_version, sys_target]),
|
||||
]
|
||||
}
|
||||
|
||||
target "build-nix" {
|
||||
name = elem("build-nix", [cargo_profile, rust_toolchain, rust_target, feat_set, sys_name, sys_version, sys_target])
|
||||
tags = [
|
||||
elem_tag("build-nix", [cargo_profile, rust_toolchain, rust_target, feat_set, sys_name, sys_version, sys_target], "latest"),
|
||||
]
|
||||
output = ["type=cacheonly,compression=zstd,mode=min,compression-level=${cache_compress_level}"]
|
||||
cache_to = ["type=local,compression=zstd,mode=max,compression-level=${cache_compress_level}"]
|
||||
dockerfile = "${docker_dir}/Dockerfile.nix"
|
||||
target = "build-nix"
|
||||
matrix = cargo_rust_feat_sys
|
||||
inherits = [
|
||||
elem("builder", [sys_name, sys_version, sys_target]),
|
||||
elem("source", [sys_name, sys_version, sys_target]),
|
||||
]
|
||||
contexts = {
|
||||
input = elem("target:build-tests", [cargo_profile, rust_toolchain, rust_target, feat_set, sys_name, sys_version, sys_target])
|
||||
}
|
||||
args = {
|
||||
cargo_cmd = (cargo_profile == "bench"? "bench": "test")
|
||||
cargo_args = (rust_toolchain == "nightly"?
|
||||
"--no-fail-fast --all-targets": "--no-fail-fast --bins --tests"
|
||||
)
|
||||
input = elem("target:builder", [sys_name, sys_version, sys_target]),
|
||||
source = elem("target:source", [sys_name, sys_version, sys_target]),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -825,15 +1058,14 @@ target "book" {
|
||||
}
|
||||
dockerfile-inline =<<EOF
|
||||
FROM input AS book
|
||||
COPY --link --from=input . .
|
||||
RUN ["mdbook", "build", "-d", "/book", "/usr/src/tuwunel"]
|
||||
EOF
|
||||
}
|
||||
|
||||
target "docs" {
|
||||
name = elem("docs", [cargo_profile, rust_toolchain, rust_target, feat_set, sys_name, sys_version, sys_target])
|
||||
target "build-docs" {
|
||||
name = elem("build-docs", [cargo_profile, rust_toolchain, rust_target, feat_set, sys_name, sys_version, sys_target])
|
||||
tags = [
|
||||
elem_tag("docs", [cargo_profile, rust_toolchain, rust_target, feat_set, sys_name, sys_version, sys_target], "latest"),
|
||||
elem_tag("build-docs", [cargo_profile, rust_toolchain, rust_target, feat_set, sys_name, sys_version, sys_target], "latest"),
|
||||
]
|
||||
matrix = cargo_rust_feat_sys
|
||||
inherits = [
|
||||
@@ -893,7 +1125,7 @@ target "build-tests" {
|
||||
}
|
||||
args = {
|
||||
cargo_cmd = (cargo_profile == "bench"? "bench": "test")
|
||||
cargo_args = "--no-run"
|
||||
cargo_args = (cargo_profile == "bench"? "--no-run --benches": "--no-run --tests")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1030,7 +1262,7 @@ target "fmt" {
|
||||
input = elem("target:ingredients", [rust_toolchain, rust_target, feat_set, sys_name, sys_version, sys_target])
|
||||
}
|
||||
args = {
|
||||
fmt_args = "-- --color always"
|
||||
fmt_args = "-- --color=always"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1171,6 +1403,8 @@ target "deps-base" {
|
||||
# cache key for unique artifact area
|
||||
cargo_target_artifact = "${cargo_tgt_dir_base}/${sys_name}/${sys_version}/${rust_target}/${rust_toolchain}/${cargo_profile}/${feat_set}/${git_ref_sha}"
|
||||
# cache key for hashed subdirs
|
||||
cargo_share = "${cargo_tgt_dir_base}/${sys_name}/${sys_version}/${rust_toolchain}/${cargo_profile}/_shared_cache"
|
||||
# cache key for hashed subdirs
|
||||
cargo_target_share = "${cargo_tgt_dir_base}/${sys_name}/${sys_version}/${rust_target}/${rust_toolchain}/${cargo_profile}/_shared_cache"
|
||||
# cased name of profile subdir within target complex
|
||||
cargo_target_profile = (
|
||||
@@ -1181,8 +1415,8 @@ target "deps-base" {
|
||||
|
||||
CARGO_PROFILE_TEST_DEBUG = "false"
|
||||
CARGO_PROFILE_TEST_INCREMENTAL = "false"
|
||||
CARGO_PROFILE_BENCH_DEBUG = "limited"
|
||||
CARGO_PROFILE_BENCH_LTO = "false"
|
||||
CARGO_PROFILE_BENCH_DEBUG = "false"
|
||||
CARGO_PROFILE_BENCH_LTO = "thin"
|
||||
CARGO_PROFILE_RELEASE_LTO = "thin"
|
||||
CARGO_PROFILE_RELEASE_DEBUGINFO_DEBUG = "limited"
|
||||
CARGO_PROFILE_RELEASE_DEBUGINFO_LTO = "off"
|
||||
@@ -1195,65 +1429,93 @@ target "deps-base" {
|
||||
join(" ", static_rustflags),
|
||||
join(" ", static_nightly_rustflags),
|
||||
join(" ", native_rustflags),
|
||||
"-C link-arg=-L/usr/lib/gcc/${sys_target}/14", #FIXME
|
||||
"-C link-arg=-L/usr/lib/gcc/${sys_target_triple(sys_target)}/15", #FIXME
|
||||
contains(split(",", cargo_feat_sets[feat_set]), "bzip2_compression")?
|
||||
"-C link-arg=-l:libbz2.a": "",
|
||||
contains(split(",", cargo_feat_sets[feat_set]), "lz4_compression")?
|
||||
"-C link-arg=-l:liblz4.a": "",
|
||||
contains(split(",", cargo_feat_sets[feat_set]), "zstd_compression")?
|
||||
"-C link-arg=-l:libzstd.a": "",
|
||||
contains(split(",", cargo_feat_sets[feat_set]), "io_uring")?
|
||||
"-C link-arg=-l:liburing.a": "",
|
||||
join(" ", static_libs),
|
||||
sys_target == "aarch64-linux-gnu"?
|
||||
sys_target_triple(sys_target) == "aarch64-linux-gnu"?
|
||||
"-C link-arg=-l:libgcc.a": "",
|
||||
]):
|
||||
|
||||
cargo_profile == "release" && rust_toolchain == "nightly"?
|
||||
(cargo_profile == "release" || cargo_profile == "bench") && substr(rust_toolchain, 0, 7) == "nightly"?
|
||||
join(" ", [
|
||||
join(" ", rustflags),
|
||||
join(" ", nightly_rustflags),
|
||||
join(" ", static_rustflags),
|
||||
join(" ", static_nightly_rustflags),
|
||||
"-C link-arg=-L/usr/lib/gcc/${sys_target}/14", #FIXME
|
||||
sys_target_triple(sys_target) == "x86_64-linux-gnu"?
|
||||
"-C target-cpu=${sys_target_isa(sys_target)}": "",
|
||||
"-C link-arg=-L/usr/lib/gcc/${sys_target_triple(sys_target)}/15", #FIXME
|
||||
contains(split(",", cargo_feat_sets[feat_set]), "bzip2_compression")?
|
||||
"-C link-arg=-l:libbz2.a": "",
|
||||
contains(split(",", cargo_feat_sets[feat_set]), "lz4_compression")?
|
||||
"-C link-arg=-l:liblz4.a": "",
|
||||
contains(split(",", cargo_feat_sets[feat_set]), "zstd_compression")?
|
||||
"-C link-arg=-l:libzstd.a": "",
|
||||
contains(split(",", cargo_feat_sets[feat_set]), "io_uring")?
|
||||
"-C link-arg=-l:liburing.a": "",
|
||||
join(" ", static_libs),
|
||||
sys_target == "aarch64-linux-gnu"?
|
||||
sys_target_triple(sys_target) == "aarch64-linux-gnu"?
|
||||
"-C link-arg=-l:libgcc.a": "",
|
||||
]):
|
||||
|
||||
cargo_profile == "release" || cargo_profile == "release-debuginfo"?
|
||||
cargo_profile == "release" || cargo_profile == "release-debuginfo" || cargo_profile == "bench"?
|
||||
join(" ", [
|
||||
join(" ", rustflags),
|
||||
join(" ", static_rustflags),
|
||||
"-C link-arg=-L/usr/lib/gcc/${sys_target}/14", #FIXME
|
||||
sys_target_triple(sys_target) == "x86_64-linux-gnu"?
|
||||
"-C target-cpu=${sys_target_isa(sys_target)}": "",
|
||||
"-C link-arg=-L/usr/lib/gcc/${sys_target_triple(sys_target)}/15", #FIXME
|
||||
contains(split(",", cargo_feat_sets[feat_set]), "bzip2_compression")?
|
||||
"-C link-arg=-l:libbz2.a": "",
|
||||
contains(split(",", cargo_feat_sets[feat_set]), "lz4_compression")?
|
||||
"-C link-arg=-l:liblz4.a": "",
|
||||
contains(split(",", cargo_feat_sets[feat_set]), "zstd_compression")?
|
||||
"-C link-arg=-l:libzstd.a": "",
|
||||
contains(split(",", cargo_feat_sets[feat_set]), "io_uring")?
|
||||
"-C link-arg=-l:liburing.a": "",
|
||||
join(" ", static_libs),
|
||||
sys_target == "aarch64-linux-gnu"?
|
||||
sys_target_triple(sys_target) == "aarch64-linux-gnu"?
|
||||
"-C link-arg=-l:libgcc.a": "",
|
||||
]):
|
||||
|
||||
rust_toolchain == "stable"?
|
||||
substr(rust_toolchain, 0, 6) == "stable"?
|
||||
join(" ", [
|
||||
join(" ", rustflags),
|
||||
join(" ", static_rustflags),
|
||||
"-C link-arg=-L/usr/lib/gcc/${sys_target}/14", #FIXME
|
||||
sys_target_triple(sys_target) == "x86_64-linux-gnu"?
|
||||
"-C target-cpu=${sys_target_isa(sys_target)}": "",
|
||||
"-C link-arg=-L/usr/lib/gcc/${sys_target_triple(sys_target)}/15", #FIXME
|
||||
contains(split(",", cargo_feat_sets[feat_set]), "bzip2_compression")?
|
||||
"-C link-arg=-l:libbz2.a": "",
|
||||
contains(split(",", cargo_feat_sets[feat_set]), "lz4_compression")?
|
||||
"-C link-arg=-l:liblz4.a": "",
|
||||
contains(split(",", cargo_feat_sets[feat_set]), "zstd_compression")?
|
||||
"-C link-arg=-l:libzstd.a": "",
|
||||
contains(split(",", cargo_feat_sets[feat_set]), "io_uring")?
|
||||
"-C link-arg=-l:liburing.a": "",
|
||||
join(" ", static_libs),
|
||||
sys_target == "aarch64-linux-gnu"?
|
||||
sys_target_triple(sys_target) == "aarch64-linux-gnu"?
|
||||
"-C link-arg=-l:libgcc.a": "",
|
||||
]):
|
||||
|
||||
rust_toolchain == "nightly"?
|
||||
substr(rust_toolchain, 0, 7) == "nightly"?
|
||||
join(" ", [
|
||||
join(" ", rustflags),
|
||||
join(" ", nightly_rustflags),
|
||||
join(" ", dynamic_rustflags),
|
||||
sys_target_triple(sys_target) == "x86_64-linux-gnu"?
|
||||
"-C target-cpu=${sys_target_isa(sys_target)}": "",
|
||||
contains(split(",", cargo_feat_sets[feat_set]), "bzip2_compression")?
|
||||
"-C link-arg=-lbz2": "",
|
||||
contains(split(",", cargo_feat_sets[feat_set]), "lz4_compression")?
|
||||
"-C link-arg=-llz4": "",
|
||||
contains(split(",", cargo_feat_sets[feat_set]), "zstd_compression")?
|
||||
"-C link-arg=-lzstd": "",
|
||||
contains(split(",", cargo_feat_sets[feat_set]), "io_uring")?
|
||||
@@ -1303,13 +1565,33 @@ target "rocksdb-build" {
|
||||
input = elem("target:kitchen", [feat_set, sys_name, sys_version, sys_target])
|
||||
}
|
||||
args = {
|
||||
rocksdb_bz2 = contains(split(",", cargo_feat_sets[feat_set]), "bzip2_compression")? 1: 0
|
||||
rocksdb_lz4 = contains(split(",", cargo_feat_sets[feat_set]), "lz4_compression")? 1: 0
|
||||
rocksdb_zstd = contains(split(",", cargo_feat_sets[feat_set]), "zstd_compression")? 1: 0
|
||||
rocksdb_jemalloc = contains(split(",", cargo_feat_sets[feat_set]), "jemalloc")? 1: 0
|
||||
rocksdb_iouring = contains(split(",", cargo_feat_sets[feat_set]), "io_uring")? 1: 0
|
||||
rocksdb_portable = cargo_profile == "release_max_perf"? 0: rocksdb_portable
|
||||
rocksdb_build_type = rocksdb_build_type
|
||||
rocksdb_opt_level = rocksdb_opt_level
|
||||
rocksdb_numa = rocksdb_numa
|
||||
rocksdb_shared = 0
|
||||
rocksdb_opt_level = rocksdb_opt_level
|
||||
rocksdb_build_type = rocksdb_build_type
|
||||
rocksdb_cxx_flags = (
|
||||
cargo_profile == "release-native" && sys_target_triple(sys_target) == "aarch64-linux-gnu"?
|
||||
"-ftls-model=local-exec -mno-outline-atomics":
|
||||
cargo_profile == "release-native"?
|
||||
"-ftls-model=local-exec":
|
||||
sys_target_triple(sys_target) == "aarch64-linux-gnu"?
|
||||
"-ftls-model=initial-exec -mno-outline-atomics":
|
||||
sys_target_triple(sys_target) == "x86_64-linux-gnu" && sys_target != "x86_64-v1-linux-gnu"?
|
||||
"-ftls-model=initial-exec -mpclmul":
|
||||
"-ftls-model=initial-exec"
|
||||
)
|
||||
rocksdb_portable = (
|
||||
cargo_profile == "release-native"?
|
||||
"0":
|
||||
sys_target_triple(sys_target) == "x86_64-linux-gnu"?
|
||||
"${sys_target_isa(sys_target)}":
|
||||
rocksdb_portable
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1405,8 +1687,8 @@ target "ingredients" {
|
||||
"--all-features": "--no-default-features"
|
||||
)
|
||||
RUST_BACKTRACE = "full"
|
||||
ROCKSDB_LIB_DIR="/usr/lib/${sys_target}"
|
||||
JEMALLOC_OVERRIDE="/usr/lib/${sys_target}/libjemalloc.a"
|
||||
ROCKSDB_LIB_DIR="/usr/lib/${sys_target_triple(sys_target)}"
|
||||
JEMALLOC_OVERRIDE="/usr/lib/${sys_target_triple(sys_target)}/libjemalloc.a"
|
||||
ZSTD_SYS_USE_PKG_CONFIG = (
|
||||
contains(split(",", cargo_feat_sets[feat_set]), "zstd_compression")? 1: 0
|
||||
)
|
||||
@@ -1447,11 +1729,12 @@ rustup_components = [
|
||||
]
|
||||
|
||||
cargo_installs = [
|
||||
"cargo-chef",
|
||||
"cargo-audit",
|
||||
"cargo-deb",
|
||||
#"cargo-arch",
|
||||
"cargo-chef",
|
||||
"cargo-deb",
|
||||
"cargo-generate-rpm",
|
||||
"cargo-valgrind",
|
||||
"lychee",
|
||||
"mdbook",
|
||||
"typos-cli",
|
||||
@@ -1487,8 +1770,8 @@ target "rust" {
|
||||
cargo_installs = join(" ", cargo_installs)
|
||||
|
||||
CARGO_TERM_VERBOSE = CARGO_TERM_VERBOSE
|
||||
RUSTUP_HOME = "/opt/rust/rustup/${sys_name}/${sys_target}"
|
||||
CARGO_HOME = "/opt/rust/cargo/${sys_name}/${sys_target}"
|
||||
RUSTUP_HOME = "/opt/rust/rustup/${sys_name}/${sys_target_triple(sys_target)}"
|
||||
CARGO_HOME = "/opt/rust/cargo/${sys_name}/${sys_target_triple(sys_target)}"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1535,12 +1818,22 @@ kitchen_packages = [
|
||||
"clang",
|
||||
"cmake",
|
||||
"curl",
|
||||
"gawk",
|
||||
"git",
|
||||
"golang-go",
|
||||
"gzip",
|
||||
"jq",
|
||||
"libc6-dev",
|
||||
"libclang-dev",
|
||||
"libnuma-dev",
|
||||
"libssl-dev",
|
||||
"libsqlite3-dev",
|
||||
"make",
|
||||
"nix-bin",
|
||||
"openssl",
|
||||
"pkg-config",
|
||||
"pkgconf",
|
||||
"valgrind",
|
||||
"xz-utils",
|
||||
]
|
||||
|
||||
@@ -1559,10 +1852,11 @@ target "kitchen" {
|
||||
}
|
||||
args = {
|
||||
packages = join(" ", [
|
||||
contains(split(",", cargo_feat_sets[feat_set]), "bzip2_compression")? "libbz2-dev": "",
|
||||
contains(split(",", cargo_feat_sets[feat_set]), "io_uring")? "liburing-dev": "",
|
||||
contains(split(",", cargo_feat_sets[feat_set]), "zstd_compression")? "libzstd-dev": "",
|
||||
contains(split(",", cargo_feat_sets[feat_set]), "jemalloc")? "libjemalloc-dev": "",
|
||||
contains(split(",", cargo_feat_sets[feat_set]), "hardened_malloc")? "g++": "",
|
||||
contains(split(",", cargo_feat_sets[feat_set]), "lz4_compression")? "liblz4-dev": "",
|
||||
contains(split(",", cargo_feat_sets[feat_set]), "zstd_compression")? "libzstd-dev": "",
|
||||
])
|
||||
}
|
||||
}
|
||||
@@ -1662,18 +1956,18 @@ target "runtime" {
|
||||
}
|
||||
args = {
|
||||
packages = join(" ", [
|
||||
contains(split(",", cargo_feat_sets[feat_set]), "bzip2_compression")? "bzip2": "",
|
||||
contains(split(",", cargo_feat_sets[feat_set]), "io_uring")? "liburing2": "",
|
||||
contains(split(",", cargo_feat_sets[feat_set]), "zstd_compression")? "libzstd1": "",
|
||||
contains(split(",", cargo_feat_sets[feat_set]), "jemalloc")? "libjemalloc2": "",
|
||||
contains(split(",", cargo_feat_sets[feat_set]), "lz4_compression")? "liblz4-1": "",
|
||||
contains(split(",", cargo_feat_sets[feat_set]), "zstd_compression")? "libzstd1": "",
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
base_pkgs = [
|
||||
"adduser",
|
||||
"bzip2",
|
||||
"ca-certificates",
|
||||
"gzip",
|
||||
]
|
||||
|
||||
target "base" {
|
||||
@@ -1692,8 +1986,8 @@ target "base" {
|
||||
}
|
||||
args = {
|
||||
DEBIAN_FRONTEND="noninteractive"
|
||||
var_lib_apt = "/var/lib/apt/${sys_name}/${sys_version}/${sys_target}"
|
||||
var_cache = "/var/cache/${sys_name}/${sys_version}/${sys_target}"
|
||||
var_lib_apt = "/var/lib/apt/${sys_name}/${sys_version}/${sys_target_triple(sys_target)}"
|
||||
var_cache = "/var/cache/${sys_name}/${sys_version}/${sys_target_triple(sys_target)}"
|
||||
packages = join(" ", base_pkgs)
|
||||
}
|
||||
}
|
||||
@@ -1713,12 +2007,21 @@ target "system" {
|
||||
cache_to = ["type=local,compression=zstd,mode=max,compression-level=${cache_compress_level}"]
|
||||
cache_from = ["type=local"]
|
||||
dockerfile = "${docker_dir}/Dockerfile.system"
|
||||
matrix = sys
|
||||
context = "."
|
||||
matrix = sys
|
||||
platforms = (
|
||||
sys_target_triple(sys_target) == "x86_64-linux-gnu"?
|
||||
["linux/amd64/${sys_target_ver(sys_target)}"]:
|
||||
sys_target_triple(sys_target) == "aarch64-linux-gnu"?
|
||||
["linux/arm64"]:
|
||||
["local"]
|
||||
)
|
||||
args = {
|
||||
sys_name = sys_name
|
||||
sys_version = sys_version
|
||||
sys_target = sys_target
|
||||
sys_triple = sys_target_triple(sys_target)
|
||||
sys_isa = sys_target_isa(sys_target)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1727,6 +2030,33 @@ target "system" {
|
||||
# Utils
|
||||
#
|
||||
|
||||
function "sys_target_isa" {
|
||||
params = [sys_target]
|
||||
result = (
|
||||
sys_target_ver(sys_target) != "v1"?
|
||||
join("-",
|
||||
[
|
||||
replace(split("-", sys_target)[0], "_", "-"),
|
||||
sys_target_ver(sys_target)
|
||||
]):
|
||||
replace(split("-", sys_target)[0], "_", "-")
|
||||
)
|
||||
}
|
||||
|
||||
function "sys_target_triple" {
|
||||
params = [sys_target]
|
||||
result = join("-", [
|
||||
split("-", sys_target)[0],
|
||||
split("-", sys_target)[2],
|
||||
split("-", sys_target)[3],
|
||||
])
|
||||
}
|
||||
|
||||
function "sys_target_ver" {
|
||||
params = [sys_target]
|
||||
result = split("-", sys_target)[1]
|
||||
}
|
||||
|
||||
function "elem_tag" {
|
||||
params = [prefix, matrix, tag]
|
||||
result = join(":", [elem(prefix, matrix), tag])
|
||||
|
||||
+3
-12
@@ -14,8 +14,8 @@ default_feat_sets='["all"]'
|
||||
default_rust_toolchains='["nightly"]'
|
||||
default_rust_targets='["x86_64-unknown-linux-gnu"]'
|
||||
default_sys_names='["debian"]'
|
||||
default_sys_targets='["x86_64-linux-gnu"]'
|
||||
default_sys_versions='["testing-slim"]'
|
||||
default_sys_targets='["x86_64-v1-linux-gnu"]'
|
||||
|
||||
if test ! -z "$cargo_profile"; then
|
||||
env_cargo_profiles="[\"${cargo_profile}\"]"
|
||||
@@ -61,18 +61,8 @@ toolchain_toml="$docker_dir/../rust-toolchain.toml"
|
||||
rust_msrv=$(grep "channel = " "$toolchain_toml" | cut -d'=' -f2 | sed 's/\s"\|"$//g')
|
||||
rocksdb_opt_level=3
|
||||
rocksdb_portable=1
|
||||
git_checkout="HEAD"
|
||||
git_checkout="${git_checkout:-HEAD}"
|
||||
use_chef="true"
|
||||
complement_count=1
|
||||
complement_skip="TestPartialStateJoin.*"
|
||||
complement_skip="${complement_skip}|TestRoomDeleteAlias/Pa.*/Can_delete_canonical_alias"
|
||||
complement_skip="${complement_skip}|TestUnbanViaInvite.*"
|
||||
complement_skip="${complement_skip}|TestRoomDeleteAlias/Pa.*/Regular_users_can_add_and_delete_aliases_when.*"
|
||||
complement_skip="${complement_skip}|TestToDeviceMessagesOverFederation/stopped_server"
|
||||
complement_skip="${complement_skip}|TestLogin/parallel/POST_/login_as_non-existing_user_is_rejected"
|
||||
complement_skip="${complement_skip}|TestRoomState/Parallel/GET_/publicRooms_lists_newly-created_room"
|
||||
complement_skip="${complement_skip}|TestThreadReceiptsInSyncMSC4102"
|
||||
complement_run=".*"
|
||||
set +a
|
||||
|
||||
###############################################################################
|
||||
@@ -83,6 +73,7 @@ if test "$CI" = "true"; then
|
||||
fi
|
||||
|
||||
args=""
|
||||
args="$args --provenance=false"
|
||||
args="$args --builder ${builder_name}"
|
||||
#args="$args --set *.platform=${sys_platform}"
|
||||
|
||||
|
||||
+52
-11
@@ -12,9 +12,28 @@ default_feat_set="all"
|
||||
default_rust_toolchain="nightly"
|
||||
default_rust_target="x86_64-unknown-linux-gnu"
|
||||
default_sys_name="debian"
|
||||
default_sys_target="x86_64-linux-gnu"
|
||||
default_sys_target="x86_64-v1-linux-gnu"
|
||||
default_sys_version="testing-slim"
|
||||
|
||||
default_complement_verbose=0
|
||||
default_complement_dirty=0
|
||||
default_complement_count=1
|
||||
default_complement_parallel=1
|
||||
default_complement_shuffle=0
|
||||
default_complement_timeout="1h"
|
||||
default_complement_run=".*"
|
||||
|
||||
run="${1:-$default_complement_run}"
|
||||
skip=""
|
||||
skip="${skip}TestToDeviceMessagesOverFederation/stopped_server"
|
||||
skip="${skip}|TestToDeviceMessagesOverFederation/interrupted_connectivity"
|
||||
skip="${skip}|TestRoomCreate/Parallel/POST_/createRoom_makes_a_room_with_a_topic_and_writes_rich_topic_representation"
|
||||
skip="${skip}|TestRoomCreate/Parallel/POST_/createRoom_makes_a_room_with_a_topic_via_initial_state_overwritten_by_topic"
|
||||
skip="${skip}|TestLogin/parallel/POST_/"
|
||||
skip="${skip}|TestUnbanViaInvite"
|
||||
skip="${skip}|TestRoomState/Parallel/GET_/publicRooms_lists_newly-created_room"
|
||||
skip="${skip}|TestThreadReceiptsInSyncMSC4102"
|
||||
|
||||
set -a
|
||||
cargo_profile="${cargo_profile:-$default_cargo_profile}"
|
||||
feat_set="${feat_set:-$default_feat_set}"
|
||||
@@ -30,12 +49,22 @@ set +a
|
||||
|
||||
###############################################################################
|
||||
|
||||
envs=""
|
||||
envs="$envs -e complement_verbose=${complement_verbose:-$default_complement_verbose}"
|
||||
envs="$envs -e complement_count=${complement_count:-$default_complement_count}"
|
||||
envs="$envs -e complement_dirty=${complement_dirty:-$default_complement_dirty}"
|
||||
envs="$envs -e complement_parallel=${complement_parallel:-$default_complement_parallel}"
|
||||
envs="$envs -e complement_shuffle=${complement_shuffle:-$default_complement_shuffle}"
|
||||
envs="$envs -e complement_timeout=${complement_timeout:-$default_complement_timeout}"
|
||||
envs="$envs -e complement_skip=${complement_skip:-$skip}"
|
||||
envs="$envs -e complement_run=${1:-$default_complement_run}"
|
||||
|
||||
set -x
|
||||
tester_image="complement-tester--${sys_name}--${sys_version}--${sys_target}"
|
||||
testee_image="complement-testee--${cargo_profile}--${rust_toolchain}--${rust_target}--${feat_set}--${sys_name}--${sys_version}--${sys_target}"
|
||||
name="complement_tester__${sys_name}__${sys_version}__${sys_target}"
|
||||
sock="/var/run/docker.sock"
|
||||
arg="--name $name -v $sock:$sock --network=host $tester_image ${testee_image}"
|
||||
arg="--name $name -v $sock:$sock --network=host $envs $tester_image ${testee_image}"
|
||||
set +x
|
||||
|
||||
if test "$CI_VERBOSE_ENV" = "true"; then
|
||||
@@ -45,21 +74,33 @@ fi
|
||||
|
||||
docker rm -f "$name" 2>/dev/null
|
||||
|
||||
trap 'set +x; date; echo -e "\033[1;41;37mERROR\033[0m"' ERR
|
||||
arg="-d $arg"
|
||||
cid=$(docker run $arg)
|
||||
|
||||
if test "$CI" = "true"; then
|
||||
arg="-d $arg"
|
||||
cid=$(docker run $arg)
|
||||
else
|
||||
arg="--rm -a stdout -a stderr $arg"
|
||||
docker run $arg
|
||||
exit $?
|
||||
echo -n "$cid" > "$name"
|
||||
fi
|
||||
|
||||
echo -n "$cid" > "$name"
|
||||
output_src="$cid:/usr/src/complement/full_output.jsonl"
|
||||
output_dst="tests/complement/logs.jsonl"
|
||||
extract_output() {
|
||||
docker cp "$output_src" "$output_dst"
|
||||
}
|
||||
|
||||
trap 'docker container stop $cid; set +x; date; echo -e "\033[1;41;37mERROR\033[0m"' INT
|
||||
result_src="$cid:/usr/src/complement/new_results.jsonl"
|
||||
result_dst="tests/complement/results.jsonl"
|
||||
extract_results() {
|
||||
docker cp "$result_src" "$result_dst"
|
||||
}
|
||||
|
||||
trap 'extract_output; set +x; date; echo -e "\033[1;41;37mERROR\033[0m"' ERR
|
||||
trap 'docker container stop $cid; extract_output' INT
|
||||
docker logs -f "$cid"
|
||||
docker wait "$cid" 2>/dev/null
|
||||
|
||||
extract_results
|
||||
extract_output
|
||||
git diff -U0 --color --shortstat "$result_dst" | (grep "$run" || true)
|
||||
|
||||
git diff --quiet --exit-code "$result_dst"
|
||||
echo -e "\033[1;42;30mACCEPT\033[0m"
|
||||
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../CODE_OF_CONDUCT.md
|
||||
+5
-1
@@ -5,6 +5,9 @@ # Summary
|
||||
- [Examples](configuration/examples.md)
|
||||
- [Deploying](deploying.md)
|
||||
- [Generic](deploying/generic.md)
|
||||
- [Reverse Proxy - Caddy](deploying/reverse-proxy-caddy.md)
|
||||
- [Reverse Proxy - Nginx](deploying/reverse-proxy-nginx.md)
|
||||
- [Reverse Proxy - Traefik](deploying/reverse-proxy-traefik.md)
|
||||
- [NixOS](deploying/nixos.md)
|
||||
- [Docker](deploying/docker.md)
|
||||
- [Kubernetes](deploying/kubernetes.md)
|
||||
@@ -13,6 +16,7 @@ # Summary
|
||||
- [Red Hat](deploying/redhat.md)
|
||||
- [FreeBSD](deploying/freebsd.md)
|
||||
- [TURN](turn.md)
|
||||
- [Matrix RTC (Element Call)](matrix_rtc.md)
|
||||
- [Appservices](appservices.md)
|
||||
- [Maintenance](maintenance.md)
|
||||
- [Troubleshooting](troubleshooting.md)
|
||||
@@ -20,4 +24,4 @@ # Summary
|
||||
- [Contributing](contributing.md)
|
||||
- [Testing](development/testing.md)
|
||||
- [Hot Reloading ("Live" Development)](development/hot_reload.md)
|
||||
- [Tuwunel Community Code of Conduct](../CODE_OF_CONDUCT.md)
|
||||
- [Tuwunel Community Code of Conduct](CODE_OF_CONDUCT.md)
|
||||
|
||||
+26
-6
@@ -7,14 +7,20 @@ ## Basics
|
||||
Tuwunel uses a config file for the majority of the settings, but also supports
|
||||
setting individual config options via commandline.
|
||||
|
||||
Please refer to the [example config
|
||||
file](./configuration/examples.md#example-configuration) for all of those
|
||||
settings.
|
||||
Please refer to the [example config file](./configuration/examples.md#example-configuration) for all of those settings.
|
||||
|
||||
The config file to use can be specified on the commandline when running
|
||||
Tuwunel by specifying the `-c`, `--config` flag. Alternatively, you can use
|
||||
the environment variable `TUWUNEL_CONFIG` to specify the config file to used.
|
||||
Conduit's environment variables are supported for backwards compatibility.
|
||||
Tuwunel by specifying the `-c`, `--config` flag. It is also possible to specify
|
||||
more than one config file.
|
||||
|
||||
Alternatively, you can use the environment variable `TUWUNEL_CONFIG` to specify
|
||||
the config file to used. Conduit's environment variables are supported for
|
||||
backwards compatibility.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> It is bad practice to uncomment default options without changing them. Many
|
||||
> defaults are updated by developers as features evolve and can be essential
|
||||
> to expected server function.
|
||||
|
||||
## Option commandline flag
|
||||
|
||||
@@ -31,6 +37,20 @@ ## Option commandline flag
|
||||
- `--option log=\"debug\"` works ✅
|
||||
- `--option server_name='"example.com'"` works ✅
|
||||
|
||||
## Relevance of configuration settings
|
||||
|
||||
There is a specific sequence for reading and overwriting the settings. The
|
||||
latest setting takes precedence and defines the configuration.
|
||||
|
||||
1. Set in `CONDUIT_CONFIG`.
|
||||
2. Set in `CONDUWUIT_CONFIG`.
|
||||
3. Set in `TUWUNEL_CONFIG`.
|
||||
4. Set in the first config file on the command line (e.g. `-c config_file_1.toml`).
|
||||
5. Set in the second config file on the command line (e.g. `-c config_file_2.toml`).
|
||||
6. Set in any additional config file on the command line (e.g. `-c config_file_n.toml`).
|
||||
7. Set within the options (again, the latest option in the list overrides).
|
||||
|
||||
|
||||
## Execute commandline flag
|
||||
|
||||
Tuwunel supports running admin commands on startup using the commandline
|
||||
|
||||
@@ -20,7 +20,6 @@ services:
|
||||
TUWUNEL_REGISTRATION_TOKEN: 'YOUR_TOKEN' # A registration token is required when registration is allowed.
|
||||
#TUWUNEL_YES_I_AM_VERY_VERY_SURE_I_WANT_AN_OPEN_REGISTRATION_SERVER_PRONE_TO_ABUSE: 'true'
|
||||
TUWUNEL_ALLOW_FEDERATION: 'true'
|
||||
TUWUNEL_ALLOW_CHECK_FOR_UPDATES: 'true'
|
||||
TUWUNEL_TRUSTED_SERVERS: '["matrix.org"]'
|
||||
#TUWUNEL_LOG: warn,state_res=warn
|
||||
TUWUNEL_ADDRESS: 0.0.0.0
|
||||
|
||||
@@ -36,7 +36,6 @@ services:
|
||||
TUWUNEL_REGISTRATION_TOKEN: 'YOUR_TOKEN' # A registration token is required when registration is allowed.
|
||||
#TUWUNEL_YES_I_AM_VERY_VERY_SURE_I_WANT_AN_OPEN_REGISTRATION_SERVER_PRONE_TO_ABUSE: 'true'
|
||||
TUWUNEL_ALLOW_FEDERATION: 'true'
|
||||
TUWUNEL_ALLOW_CHECK_FOR_UPDATES: 'true'
|
||||
TUWUNEL_TRUSTED_SERVERS: '["matrix.org"]'
|
||||
#TUWUNEL_LOG: warn,state_res=warn
|
||||
TUWUNEL_ADDRESS: 0.0.0.0
|
||||
|
||||
@@ -26,7 +26,6 @@ services:
|
||||
# TUWUNEL_LOG: info # default is: "warn,state_res=warn"
|
||||
# TUWUNEL_ALLOW_ENCRYPTION: 'true'
|
||||
# TUWUNEL_ALLOW_FEDERATION: 'true'
|
||||
# TUWUNEL_ALLOW_CHECK_FOR_UPDATES: 'true'
|
||||
# TUWUNEL_ALLOW_INCOMING_PRESENCE: true
|
||||
# TUWUNEL_ALLOW_OUTGOING_PRESENCE: true
|
||||
# TUWUNEL_ALLOW_LOCAL_PRESENCE: true
|
||||
|
||||
@@ -20,7 +20,6 @@ services:
|
||||
TUWUNEL_REGISTRATION_TOKEN: 'YOUR_TOKEN' # A registration token is required when registration is allowed.
|
||||
#TUWUNEL_YES_I_AM_VERY_VERY_SURE_I_WANT_AN_OPEN_REGISTRATION_SERVER_PRONE_TO_ABUSE: 'true'
|
||||
TUWUNEL_ALLOW_FEDERATION: 'true'
|
||||
TUWUNEL_ALLOW_CHECK_FOR_UPDATES: 'true'
|
||||
TUWUNEL_TRUSTED_SERVERS: '["matrix.org"]'
|
||||
#TUWUNEL_LOG: warn,state_res=warn
|
||||
TUWUNEL_ADDRESS: 0.0.0.0
|
||||
|
||||
+43
-64
@@ -1,9 +1,9 @@
|
||||
# Generic deployment documentation
|
||||
|
||||
> ### Getting help
|
||||
> [!TIP]
|
||||
>
|
||||
> If you run into any problems while setting up Tuwunel [open an issue on
|
||||
> GitHub](https://github.com/matrix-construct/tuwunel/issues/new).
|
||||
> Getting help: If you run into any problems while setting up Tuwunel
|
||||
> [open an issue on GitHub](https://github.com/matrix-construct/tuwunel/issues/new).
|
||||
|
||||
## Installing Tuwunel
|
||||
|
||||
@@ -12,24 +12,23 @@ ### Static prebuilt binary
|
||||
You may simply download the binary that fits your machine architecture (x86_64
|
||||
or aarch64). Run `uname -m` to see what you need.
|
||||
|
||||
Prebuilt fully static musl binaries can be downloaded from the latest tagged
|
||||
Prebuilt fully static binaries can be downloaded from the latest tagged
|
||||
release [here](https://github.com/matrix-construct/tuwunel/releases/latest) or
|
||||
`main` CI branch workflow artifact output. These also include Debian/Ubuntu
|
||||
packages.
|
||||
`main` CI branch workflow artifact output. These also include `.deb` packages
|
||||
for Debian or Ubuntu and `.rpm` packages for Red Hat or Fedora.
|
||||
|
||||
These can be curl'd directly from. `ci-bins` are CI workflow binaries by commit
|
||||
hash/revision, and `releases` are tagged releases. Sort by descending last
|
||||
modified for the latest.
|
||||
For the **best** performance; if using an `x86_64` CPU made in the last ~10 years,
|
||||
we recommend using the `-v3-` optimised packages. See below for a command to check
|
||||
what your system supports. If the server refuses to start or exits with an "Illegal
|
||||
Instruction" error you will need `-v2-` or `-v1-` packages instead. The database
|
||||
backend, RocksDB, benefits from `-v2-` or greater as it features performance
|
||||
critical hardware accelerated CRC32 hashing/checksumming.
|
||||
|
||||
These binaries have jemalloc and io_uring statically linked and included with
|
||||
them, so no additional dynamic dependencies need to be installed.
|
||||
|
||||
For the **best** performance; if using an `x86_64` CPU made in the last ~15 years,
|
||||
we recommend using the `-haswell-` optimised binaries. This sets
|
||||
`-march=haswell` which is the most compatible and highest performance with
|
||||
optimised binaries. The database backend, RocksDB, most benefits from this as it
|
||||
will then use hardware accelerated CRC32 hashing/checksumming which is critical
|
||||
for performance.
|
||||
Linux users can run this script to display which optimization levels they may
|
||||
choose:
|
||||
```
|
||||
cat /proc/cpuinfo | grep -Po '(avx|sse)[235]' | sort -u | sed 's/avx5/v4/;s/avx2/v3/;s/sse3/v2/;s/sse2/v1/' | sort
|
||||
```
|
||||
|
||||
### Compiling
|
||||
|
||||
@@ -142,69 +141,49 @@ ## Setting the correct file permissions
|
||||
|
||||
## Setting up the Reverse Proxy
|
||||
|
||||
We recommend Caddy as a reverse proxy, as it is trivial to use, handling TLS certificates, reverse proxy headers, etc transparently with proper defaults.
|
||||
For other software, please refer to their respective documentation or online guides.
|
||||
We recommend Caddy as a reverse proxy, as it is trivial to use, handling TLS certificates, reverse proxy headers, etc. transparently with proper defaults. However, Nginx is also well-supported and widely used.
|
||||
|
||||
### Caddy
|
||||
**Choose your reverse proxy:**
|
||||
|
||||
After installing Caddy via your preferred method, create `/etc/caddy/conf.d/tuwunel_caddyfile`
|
||||
and enter this (substitute for your server name).
|
||||
- **[Caddy Setup Guide](reverse-proxy-caddy.md)** - Recommended for ease of use and automatic TLS
|
||||
- **[Nginx Setup Guide](reverse-proxy-nginx.md)** - Popular choice with extensive documentation
|
||||
- **[Traefik Setup Guide](reverse-proxy-traefik.md)** - _Please help us document this choice_
|
||||
|
||||
```caddyfile
|
||||
your.server.name, your.server.name:8448 {
|
||||
# TCP reverse_proxy
|
||||
reverse_proxy 127.0.0.1:6167
|
||||
# UNIX socket
|
||||
#reverse_proxy unix//run/tuwunel/tuwunel.sock
|
||||
}
|
||||
```
|
||||
### Quick Overview
|
||||
|
||||
That's it! Just start and enable the service and you're set.
|
||||
Regardless of which reverse proxy you choose, you will need to:
|
||||
|
||||
```bash
|
||||
sudo systemctl enable --now caddy
|
||||
```
|
||||
1. **Reverse proxy the following routes:**
|
||||
- `/_matrix/` - core Matrix C-S and S-S APIs
|
||||
- `/_tuwunel/` - ad-hoc Tuwunel routes such as `/local_user_count` and `/server_version`
|
||||
|
||||
### Other Reverse Proxies
|
||||
2. **Optionally reverse proxy (recommended):**
|
||||
- `/.well-known/matrix/client` and `/.well-known/matrix/server` if using Tuwunel to perform delegation (see the `[global.well_known]` config section)
|
||||
- `/.well-known/matrix/support` if using Tuwunel to send the homeserver admin contact and support page (formerly known as MSC1929)
|
||||
- `/` if you would like to see `hewwo from tuwunel woof!` at the root
|
||||
|
||||
As we would prefer our users to use Caddy, we will not provide configuration files for other proxys.
|
||||
3. **Handle ports:**
|
||||
- Port 443 (HTTPS) for client-server API
|
||||
- Port 8448 for federation (if federating with other homeservers)
|
||||
|
||||
You will need to reverse proxy everything under following routes:
|
||||
- `/_matrix/` - core Matrix C-S and S-S APIs
|
||||
- `/_tuwunel/` - ad-hoc Tuwunel routes such as `/local_user_count` and
|
||||
`/server_version`
|
||||
|
||||
You can optionally reverse proxy the following individual routes:
|
||||
- `/.well-known/matrix/client` and `/.well-known/matrix/server` if using
|
||||
Tuwunel to perform delegation (see the `[global.well_known]` config section)
|
||||
- `/.well-known/matrix/support` if using Tuwunel to send the homeserver admin
|
||||
contact and support page (formerly known as MSC1929)
|
||||
- `/` if you would like to see `hewwo from tuwunel woof!` at the root
|
||||
|
||||
See the following spec pages for more details on these files:
|
||||
See the following spec pages for more details on well-known files:
|
||||
- [`/.well-known/matrix/server`](https://spec.matrix.org/latest/client-server-api/#getwell-knownmatrixserver)
|
||||
- [`/.well-known/matrix/client`](https://spec.matrix.org/latest/client-server-api/#getwell-knownmatrixclient)
|
||||
- [`/.well-known/matrix/support`](https://spec.matrix.org/latest/client-server-api/#getwell-knownmatrixsupport)
|
||||
|
||||
Examples of delegation:
|
||||
- <https://puppygock.gay/.well-known/matrix/server>
|
||||
- <https://puppygock.gay/.well-known/matrix/client>
|
||||
- <https://matrix.org/.well-known/matrix/server>
|
||||
- <https://matrix.org/.well-known/matrix/client>
|
||||
|
||||
For Apache and Nginx there are many examples available online.
|
||||
### Other Reverse Proxies
|
||||
|
||||
Lighttpd is not supported as it seems to mess with the `X-Matrix` Authorization
|
||||
header, making federation non-functional. If a workaround is found, feel free to share to get it added to the documentation here.
|
||||
_Specific contributions for other proxies are welcome!_
|
||||
|
||||
If using Apache, you need to use `nocanon` in your `ProxyPass` directive to prevent httpd from messing with the `X-Matrix` header (note that Apache isn't very good as a general reverse proxy and we discourage the usage of it if you can).
|
||||
**Not Recommended:**
|
||||
- **Apache**: While possible, Apache requires special configuration (`nocanon` in `ProxyPass`) to prevent corruption of the `X-Matrix` header.
|
||||
- **Lighttpd**: Its proxy module alters the `X-Matrix` authorization header, breaking federation functionality.
|
||||
|
||||
If using Nginx, you need to give Tuwunel the request URI using `$request_uri`, or like so:
|
||||
- `proxy_pass http://127.0.0.1:6167$request_uri;`
|
||||
- `proxy_pass http://127.0.0.1:6167;`
|
||||
|
||||
Nginx users need to increase `client_max_body_size` (default is 1M) to match
|
||||
`max_request_size` defined in tuwunel.toml.
|
||||
|
||||
## You're done
|
||||
## You are done
|
||||
|
||||
Now you can start Tuwunel with:
|
||||
|
||||
|
||||
@@ -2,7 +2,8 @@ # Tuwunel for Kubernetes
|
||||
|
||||
Tuwunel doesn't support horizontal scalability or distributed loading
|
||||
natively, however a community maintained Helm Chart is available here to run
|
||||
Tuwunel on Kubernetes: <https://gitlab.cronce.io/charts/conduwuit>
|
||||
Tuwunel on Kubernetes: <https://github.com/AreYouLoco/tuwunel-helm> and the
|
||||
legacy conduwuit version: <https://gitlab.cronce.io/charts/conduwuit>.
|
||||
|
||||
Should changes need to be made, please reach out to the maintainer in our
|
||||
Matrix room as this is not maintained/controlled by the Tuwunel maintainers.
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
# Reverse Proxy Setup - Caddy
|
||||
|
||||
[<= Back to Generic Deployment Guide](generic.md#setting-up-the-reverse-proxy)
|
||||
|
||||
We recommend Caddy as a reverse proxy, as it is trivial to use, handling TLS certificates, reverse proxy headers, etc. transparently with proper defaults.
|
||||
|
||||
## Installation
|
||||
|
||||
Install Caddy via your preferred method. Refer to the [official Caddy installation guide](https://caddyserver.com/docs/install) for your distribution.
|
||||
|
||||
## Configuration
|
||||
|
||||
After installing Caddy, create `/etc/caddy/conf.d/tuwunel_caddyfile` and enter this (substitute `your.server.name` with your actual server name):
|
||||
|
||||
```caddyfile
|
||||
your.server.name, your.server.name:8448 {
|
||||
# TCP reverse_proxy
|
||||
reverse_proxy localhost:8008
|
||||
# UNIX socket (alternative - comment out the line above and uncomment this)
|
||||
#reverse_proxy unix//run/tuwunel/tuwunel.sock
|
||||
}
|
||||
```
|
||||
|
||||
### What this does
|
||||
|
||||
- Handles both port 443 (HTTPS) and port 8448 (Matrix federation) automatically
|
||||
- Automatically provisions and renews TLS certificates via Let's Encrypt
|
||||
- Sets all necessary reverse proxy headers correctly
|
||||
- Routes all traffic to Tuwunel listening on `localhost:8008`
|
||||
|
||||
That's it! Just start and enable the service and you're set.
|
||||
|
||||
```bash
|
||||
sudo systemctl enable --now caddy
|
||||
```
|
||||
|
||||
## Verification
|
||||
|
||||
After starting Caddy, verify it's working by checking:
|
||||
|
||||
```bash
|
||||
curl https://your.server.name/_tuwunel/server_version
|
||||
curl https://your.server.name:8448/_tuwunel/server_version
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
[=> Continue with "You're Done"](generic.md#you-are-done)
|
||||
@@ -0,0 +1,164 @@
|
||||
# Reverse Proxy Setup - Nginx
|
||||
|
||||
[<= Back to Generic Deployment Guide](generic.md#setting-up-the-reverse-proxy)
|
||||
|
||||
This guide shows you how to configure Nginx as a reverse proxy for Tuwunel with TLS support.
|
||||
|
||||
## Installation
|
||||
|
||||
Install Nginx via your preferred method. Most distributions include Nginx in their package repositories:
|
||||
|
||||
```bash
|
||||
# Debian/Ubuntu
|
||||
sudo apt install nginx
|
||||
|
||||
# Red Hat/Fedora
|
||||
sudo dnf install nginx
|
||||
|
||||
# Arch Linux
|
||||
sudo pacman -S nginx
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
Create a new configuration file at `/etc/nginx/sites-available/tuwunel` (or `/etc/nginx/conf.d/tuwunel.conf` on some distributions):
|
||||
|
||||
```nginx
|
||||
# Client-Server API over HTTPS (port 443)
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
listen [::]:443 ssl http2;
|
||||
server_name matrix.example.com;
|
||||
|
||||
# Nginx standard body size is 1MB, which is quite small for media uploads
|
||||
# Increase this to match the max_request_size in your tuwunel.toml
|
||||
client_max_body_size 100M;
|
||||
|
||||
# Forward requests to Tuwunel (listening on 127.0.0.1:8008)
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:8008;
|
||||
|
||||
# Preserve host and scheme - critical for proper Matrix operation
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Forwarded-For $remote_addr;
|
||||
proxy_set_header X-Forwarded-Proto https;
|
||||
}
|
||||
|
||||
# TLS configuration (Let's Encrypt example using certbot)
|
||||
ssl_certificate /etc/letsencrypt/live/matrix.example.com/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/matrix.example.com/privkey.pem;
|
||||
}
|
||||
|
||||
# Matrix Federation over HTTPS (port 8448)
|
||||
# Only needed if you want to federate with other homeservers
|
||||
# Don't forget to open port 8448 in your firewall!
|
||||
server {
|
||||
listen 8448 ssl http2;
|
||||
listen [::]:8448 ssl http2;
|
||||
server_name matrix.example.com;
|
||||
|
||||
# Same body size increase for larger files
|
||||
client_max_body_size 100M;
|
||||
|
||||
# Forward to the same local port as client-server API
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:8008;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Forwarded-For $remote_addr;
|
||||
proxy_set_header X-Forwarded-Proto https;
|
||||
}
|
||||
|
||||
# TLS configuration (same certificates as above)
|
||||
ssl_certificate /etc/letsencrypt/live/matrix.example.com/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/matrix.example.com/privkey.pem;
|
||||
}
|
||||
```
|
||||
|
||||
### Important Notes
|
||||
|
||||
- **Replace `matrix.example.com`** with your actual server name
|
||||
- **`client_max_body_size`**: Must match or exceed `max_request_size` in your `tuwunel.toml`
|
||||
- **Do NOT use `$request_uri`** in `proxy_pass` - while some guides suggest this, it's not necessary for Tuwunel and can cause issues
|
||||
- **IPv6**: The `listen [::]:443` and `listen [::]:8448` lines enable IPv6 support. Remove them if you don't need IPv6
|
||||
|
||||
### TLS Certificates
|
||||
|
||||
The example above uses Let's Encrypt certificates via certbot. To obtain certificates:
|
||||
|
||||
```bash
|
||||
sudo certbot certonly --nginx -d matrix.example.com
|
||||
```
|
||||
|
||||
Certbot will automatically handle renewal. Make sure to reload Nginx after certificate renewal:
|
||||
|
||||
```bash
|
||||
sudo systemctl reload nginx
|
||||
```
|
||||
|
||||
### Optional: Timeout Configuration
|
||||
|
||||
The default Nginx timeouts are usually sufficient for Matrix operations. Element's long-polling `/sync` requests typically run for 30 seconds, which is within Nginx's default timeouts.
|
||||
|
||||
However, if you experience federation retries or dropped long-poll connections, you can extend the timeouts by adding these lines inside your `location /` blocks:
|
||||
|
||||
```nginx
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:8008;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Forwarded-For $remote_addr;
|
||||
proxy_set_header X-Forwarded-Proto https;
|
||||
|
||||
# Optional: Extend timeouts if experiencing issues
|
||||
proxy_read_timeout 300s;
|
||||
proxy_send_timeout 300s;
|
||||
}
|
||||
```
|
||||
|
||||
## Enable the Configuration
|
||||
|
||||
If using sites-available/sites-enabled structure:
|
||||
|
||||
```bash
|
||||
sudo ln -s /etc/nginx/sites-available/tuwunel /etc/nginx/sites-enabled/
|
||||
```
|
||||
|
||||
Test the configuration:
|
||||
|
||||
```bash
|
||||
sudo nginx -t
|
||||
```
|
||||
|
||||
If the test passes, reload Nginx:
|
||||
|
||||
```bash
|
||||
sudo systemctl reload nginx
|
||||
```
|
||||
|
||||
Enable Nginx to start on boot:
|
||||
|
||||
```bash
|
||||
sudo systemctl enable nginx
|
||||
```
|
||||
|
||||
## Verification
|
||||
|
||||
After configuring Nginx, verify it's working by checking:
|
||||
|
||||
```bash
|
||||
curl https://matrix.example.com/_tuwunel/server_version
|
||||
curl https://matrix.example.com:8448/_tuwunel/server_version
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Apache Compatibility Note
|
||||
|
||||
If you're considering Apache instead of Nginx: Apache is not well-suited as a reverse proxy for Matrix homeservers. If you must use Apache, you need to use `nocanon` in your `ProxyPass` directive to prevent httpd from corrupting the `X-Matrix` authorization header, which will break federation.
|
||||
|
||||
### Lighttpd is Not Supported
|
||||
|
||||
Lighttpd has known issues with the `X-Matrix` authorization header, making federation non-functional. We do not recommend using Lighttpd with Tuwunel.
|
||||
|
||||
---
|
||||
|
||||
[=> Continue with "You're Done"](generic.md#you-are-done)
|
||||
@@ -0,0 +1,128 @@
|
||||
# Reverse Proxy Setup - Traefik
|
||||
|
||||
[<= Back to Generic Deployment Guide](generic.md#setting-up-the-reverse-proxy)
|
||||
|
||||
## Installation
|
||||
|
||||
Install Traefik via your preferred method. You can read the official [docker quickstart guide](https://doc.traefik.io/traefik/getting-started/docker/) or the [in-depth walkthrough](https://doc.traefik.io/traefik/setup/docker/)
|
||||
|
||||
## Configuration
|
||||
### TLS certificates
|
||||
|
||||
You can setup auto renewing certificates with different kinds of [acme challenges](https://doc.traefik.io/traefik/reference/install-configuration/tls/certificate-resolvers/acme/).
|
||||
### Router configurations
|
||||
Add tuwunel to your traefik's network.
|
||||
|
||||
```yaml
|
||||
services:
|
||||
tuwunel:
|
||||
# ...
|
||||
networks:
|
||||
- proxy # your traefik network name
|
||||
networks:
|
||||
proxy: # your traefik network name
|
||||
external: true
|
||||
```
|
||||
|
||||
Be sure to change the `your.server.name` to your actual tuwunel domain. and the `yourcertresolver` should be changed to whatever you named it in your traefik config.
|
||||
|
||||
You only have to do any one of these methods below.
|
||||
|
||||
|
||||
### Labels
|
||||
To use labels with traefik you need to configure a [docker provider](https://doc.traefik.io/traefik/reference/install-configuration/providers/docker/).
|
||||
|
||||
Then add the labels in your tuwunel's docker compose file.
|
||||
```yaml
|
||||
services:
|
||||
tuwunel:
|
||||
# ...
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.tuwunel.entrypoints=web"
|
||||
- "traefik.http.routers.tuwunel.rule=Host(`your.server.name`)"
|
||||
- "traefik.http.routers.tuwunel.middlewares=https-redirect@file"
|
||||
- "traefik.http.routers.tuwunel-secure.entrypoints=websecure"
|
||||
- "traefik.http.routers.tuwunel-secure.rule=Host(`your.server.name`)"
|
||||
- "traefik.http.routers.tuwunel-secure.tls=true"
|
||||
- "traefik.http.routers.tuwunel-secure.service=tuwunel"
|
||||
- "traefik.http.services.tuwunel.loadbalancer.server.port=6167"
|
||||
- "traefik.http.routers.tuwunel-secure.tls.certresolver=yourcertresolver"
|
||||
- "traefik.docker.network=proxy"
|
||||
```
|
||||
### Config File
|
||||
To use the config file you need to configure a [file provider](https://doc.traefik.io/traefik/reference/install-configuration/providers/others/file/).
|
||||
|
||||
Then add this into your config file.
|
||||
```yaml
|
||||
http:
|
||||
routers:
|
||||
tuwunel:
|
||||
entryPoints:
|
||||
- "web"
|
||||
- "websecure"
|
||||
rule: "Host(`your.server.name`)"
|
||||
middlewares:
|
||||
- https-redirect
|
||||
tls:
|
||||
certResolver: "yourcertresolver"
|
||||
service: tuwunel
|
||||
services:
|
||||
tuwunel:
|
||||
loadBalancer:
|
||||
servers:
|
||||
# this url should point to your tuwunel installation.
|
||||
# this should work if your tuwunel container is named tuwunel and is in the same network as traefik.
|
||||
- url: "http://tuwunel:6167"
|
||||
passHostHeader: true
|
||||
```
|
||||
### Federation
|
||||
If you will use a .well-known file you can use traefik to redirect .well-known/matrix to tuwunel built-in .well-known file.
|
||||
|
||||
replace the rule in either of the methods from
|
||||
```
|
||||
Host(`your.server.name`)
|
||||
```
|
||||
to
|
||||
```
|
||||
Host(`your.tuwunel.domain`) || Host(`your.server.name`) && PathPrefix(`/.well-known/matrix`)
|
||||
```
|
||||
If you are not using a .well-known file you will need to add and expose port 8448 to a [traefik entrypoint](https://doc.traefik.io/traefik/reference/install-configuration/entrypoints/).
|
||||
|
||||
You can then add these to your preferred traefik config method.
|
||||
you should replace `matrixfederationentry` with what you named your entrypoint.
|
||||
|
||||
Labels:
|
||||
```yaml
|
||||
- "traefik.http.routers.matrix-federation.entrypoints=matrixfederationentry"
|
||||
- "traefik.http.routers.matrix-federation.rule=Host(`your.server.name`)"
|
||||
- "traefik.http.routers.matrix-federation.tls=true"
|
||||
- "traefik.http.routers.matrix-federation.service=matrix-federation"
|
||||
- "traefik.http.services.matrix-federation.loadbalancer.server.port=6167"
|
||||
- "traefik.http.routers.matrix-federation.tls.certresolver=yourcertresolver"
|
||||
```
|
||||
Config file:
|
||||
```yaml
|
||||
entryPoints:
|
||||
- "web"
|
||||
- "websecure"
|
||||
- "matrixfederationentry"
|
||||
```
|
||||
> [!IMPORTANT]
|
||||
>
|
||||
> [Encoded Character Filtering](https://doc.traefik.io/traefik/security/request-path/#encoded-character-filtering)
|
||||
> options must be set to `true`. This only applies to traefik version 3.6.4 to 3.6.6 and 2.11.32 to 2.11.34
|
||||
|
||||
|
||||
## Verification
|
||||
|
||||
After starting Traefik, verify it's working by checking:
|
||||
|
||||
```bash
|
||||
curl https://your.server.name/_tuwunel/server_version
|
||||
curl https://your.server.name:8448/_tuwunel/server_version
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
[=> Continue with "You're Done"](generic.md#you-are-done)
|
||||
@@ -1,5 +1,5 @@
|
||||
[Container]
|
||||
Environment=TUWUNEL_SERVER_NAME=your.domain.here TUWUNEL_DATABASE_PATH=/var/lib/tuwunel TUWUNEL_PORT=6167 TUWUNEL_MAX_REQUEST_SIZE=20000000 TUWUNEL_ALLOW_REGISTRATION=true TUWUNEL_REGISTRATION_TOKEN=YOUR_TOKEN TUWUNEL_ALLOW_FEDERATION=true TUWUNEL_ALLOW_CHECK_FOR_UPDATES=true TUWUNEL_TRUSTED_SERVERS=["matrix.org"] TUWUNEL_ADDRESS=0.0.0.0 # Add TUWUNEL_CONFIG: '/etc/tuwunel.toml' if the config is mapped
|
||||
Environment=TUWUNEL_SERVER_NAME=your.domain.here TUWUNEL_DATABASE_PATH=/var/lib/tuwunel TUWUNEL_PORT=6167 TUWUNEL_MAX_REQUEST_SIZE=20000000 TUWUNEL_ALLOW_REGISTRATION=true TUWUNEL_REGISTRATION_TOKEN=YOUR_TOKEN TUWUNEL_ALLOW_FEDERATION=true TUWUNEL_TRUSTED_SERVERS=["matrix.org"] TUWUNEL_ADDRESS=0.0.0.0 # Add TUWUNEL_CONFIG: '/etc/tuwunel.toml' if the config is mapped
|
||||
Image=docker.io/jevolk/tuwunel:latest
|
||||
PublishPort=8448:6167
|
||||
Volume=/path/to/db:/var/lib/tuwunel
|
||||
|
||||
@@ -0,0 +1,299 @@
|
||||
# Matrix RTC/Element Call Setup
|
||||
|
||||
## Notes
|
||||
- `yourdomain.com` is whatever you have set as `server_name` in your tuwunel.toml. This needs to be replaced with the actual domain. It is assumed that you will be hosting MatrixRTC at `matrix-rtc.yourdomain.com`. If you wish to host this service at a different subdomain, this needs to be replaced as well.
|
||||
- This guide provides example configuration for Caddy and Nginx reverse proxies. Others can be used, but the configuration will need to be adapted.
|
||||
|
||||
## Instructions
|
||||
### 1. Set Up DNS
|
||||
Create a DNS record for `matrix-rtc.yourdomain.com` pointing to your server.
|
||||
|
||||
### 2. Create Docker Containers
|
||||
1. Create a directory for your MatrixRTC setup e.g. `mkdir /opt/matrix-rtc`.
|
||||
2. Change directory to your new directory. e.g. `cd /opt/matrix-rtc`.
|
||||
3. Create and open a compose.yaml file for MatrixRTC. e.g. `nano compose.yaml`.
|
||||
4. Add the following. `mrtckey` and `mrtcsecret` should be random strings. It is suggested that `mrtckey` is 20 characters and `mrtcsecret` is 64 characters.
|
||||
```yaml
|
||||
services:
|
||||
matrix-rtc-jwt:
|
||||
image: ghcr.io/element-hq/lk-jwt-service:latest
|
||||
container_name: matrix-rtc-jwt
|
||||
environment:
|
||||
- LIVEKIT_JWT_PORT=8081
|
||||
- LIVEKIT_URL=wss://matrix-rtc.yourdomain.com
|
||||
- LIVEKIT_KEY=mrtckey
|
||||
- LIVEKIT_SECRET=mrtcsecret
|
||||
- LIVEKIT_FULL_ACCESS_HOMESERVERS=yourdomain.com
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "8081:8081"
|
||||
|
||||
matrix-rtc-livekit:
|
||||
image: livekit/livekit-server:latest
|
||||
container_name: matrix-rtc-livekit
|
||||
command: --config /etc/livekit.yaml
|
||||
ports:
|
||||
- 7880:7880/tcp
|
||||
- 7881:7881/tcp
|
||||
- 50100-50200:50100-50200/udp
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- ./livekit.yaml:/etc/livekit.yaml:ro
|
||||
```
|
||||
4. Close the file.
|
||||
5. Create and open a livekit.yaml file. e.g. `nano livekit.yaml`.
|
||||
6. Add the following. `mrtckey` and `mrtcsecret` should be the same as those from compose.yaml.
|
||||
```yaml
|
||||
port: 7880
|
||||
bind_addresses:
|
||||
- ""
|
||||
rtc:
|
||||
tcp_port: 7881
|
||||
port_range_start: 50100
|
||||
port_range_end: 50200
|
||||
use_external_ip: true
|
||||
enable_loopback_candidate: false
|
||||
keys:
|
||||
mrtckey: "mrtcsecret"
|
||||
```
|
||||
7. Close the file.
|
||||
|
||||
### 3. Configure .well-known
|
||||
#### 3.1. .well-known served by Tuwunel
|
||||
***Follow this step if your .well-known configuration is served by tuwunel. Otherwise follow Step 3.2***
|
||||
1. Open your tuwunel.toml file. e.g. `nano /etc/tuwunel/tuwunel.toml`.
|
||||
2. Find the line reading `#rtc_transports = []` and replace it with:
|
||||
```toml
|
||||
[[global.well_known.rtc_transports]]
|
||||
type = "livekit"
|
||||
livekit_service_url = "https://matrix-rtc.yourdomain.com"
|
||||
```
|
||||
3. Close the file.
|
||||
|
||||
#### 3.2. .well-known served independently
|
||||
***Follow this step if you serve your .well-known/matrix files directly. Otherwise follow Step 3.1***
|
||||
1. Open your `.well-known/matrix/client` file. e.g. `nano /var//www/.well-known/matrix/client`.
|
||||
2. Add the following:
|
||||
```json
|
||||
"org.matrix.msc4143.rtc_foci": [
|
||||
{
|
||||
"type": "livekit",
|
||||
"livekit_service_url": "https://matrix-rtc.yourdomain.com"
|
||||
}
|
||||
]
|
||||
```
|
||||
The final file should look something like this:
|
||||
```json
|
||||
{
|
||||
"m.homeserver": {
|
||||
"base_url":"https://matrix.yourdomain.com"
|
||||
},
|
||||
"org.matrix.msc4143.rtc_foci": [
|
||||
{
|
||||
"type": "livekit",
|
||||
"livekit_service_url": "https://matrix-rtc.yourdomain.com"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
```
|
||||
3. Close the file.
|
||||
|
||||
### 4. Configure Firewall
|
||||
You will need to allow ports `7881/tcp` and `50100:50200/udp` through your firewall. If you use UFW, the commands are: `ufw allow 7881/tcp` and `ufw allow 50100:50200/udp`.
|
||||
|
||||
### 5. Configure Reverse Proxy
|
||||
As reverse proxies can be installed in different ways, step by step instructions are not given for this section.
|
||||
If you use Caddy as your reverse proxy, follow step 5.1. If you use Nginx, follow step 5.2.
|
||||
|
||||
#### 5.1. Caddy
|
||||
1. Add the following to your Caddyfile. If you are running Caddy in Docker, replace `localhost` with `matrix-rtc-jwt` in the first instance, and `matrix-rtc-livekit` in the second.
|
||||
```
|
||||
matrix-rtc.yourdomain.com {
|
||||
# This is matrix-rtc-jwt
|
||||
@jwt_service {
|
||||
path /sfu/get* /healthz*
|
||||
}
|
||||
handle @jwt_service {
|
||||
reverse_proxy localhost:8081 {
|
||||
header_up Host {host}
|
||||
header_up X-Forwarded-Server {host}
|
||||
header_up X-Real-IP {remote}
|
||||
header_up X-Forwarded-For {remote}
|
||||
header_up X-Forwarded-Proto {scheme}
|
||||
}
|
||||
}
|
||||
# This is livekit
|
||||
handle {
|
||||
reverse_proxy localhost:7880 {
|
||||
header_up Connection "upgrade"
|
||||
header_up Upgrade {http.request.header.Upgrade}
|
||||
header_up Host {host}
|
||||
header_up X-Forwarded-Server {host}
|
||||
header_up X-Real-IP {remote}
|
||||
header_up X-Forwarded-For {remote}
|
||||
header_up X-Forwarded-Proto {scheme}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
2. Restart Caddy.
|
||||
|
||||
#### 5.2. Nginx
|
||||
1. Add the following to your Nginx configuration. If you are running Nginx in Docker, replace `localhost` with `matrix-rtc-jwt` in the first instance, and `matrix-rtc-livekit` in the second.
|
||||
```
|
||||
server {
|
||||
listen 443 ssl;
|
||||
listen [::]:443 ssl;
|
||||
http2 on;
|
||||
server_name matrix-rtc.yourdomain.com;
|
||||
|
||||
# Logging
|
||||
access_log /var/log/nginx/matrix-rtc.yourdomain.com.log;
|
||||
error_log /var/log/nginx/matrix-rtc.yourdomain.com.error;
|
||||
|
||||
# TLS example for certificate obtained from Let's Encrypt.
|
||||
ssl_certificate /etc/letsencrypt/live/matrix-rtc.yourdomain.com/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/matrix-rtc.yourdomain.com/privkey.pem;
|
||||
|
||||
# lk-jwt-service
|
||||
location ~ ^(/sfu/get|/healthz) {
|
||||
proxy_pass http://localhost:8081;
|
||||
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Forwarded-Server $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
# livekit
|
||||
location / {
|
||||
proxy_pass http://localhost:7880;
|
||||
proxy_http_version 1.1;
|
||||
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Forwarded-Server $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
|
||||
# Optional timeouts per LiveKit
|
||||
proxy_read_timeout 300s;
|
||||
proxy_send_timeout 300s;
|
||||
}
|
||||
}
|
||||
```
|
||||
2. Restart Nginx.
|
||||
|
||||
#### 5.3. Traefik
|
||||
1. Add your `matrix-rtc-jwt` `matrix-rtc-livekit` to your traefik's network
|
||||
```yaml
|
||||
services:
|
||||
matrix-rtc-jwt:
|
||||
# ...
|
||||
networks:
|
||||
- proxy # your traefik network name
|
||||
|
||||
matrix-rtc-livekit:
|
||||
# ...
|
||||
networks:
|
||||
- proxy # your traefik network name
|
||||
|
||||
networks:
|
||||
proxy: # your traefik network name
|
||||
external: true
|
||||
```
|
||||
2. Configure with either one of the methods below
|
||||
|
||||
2.1 Labels
|
||||
```yaml
|
||||
services:
|
||||
matrix-rtc-jwt:
|
||||
# ...
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.matrixrtcjwt.entrypoints=websecure"
|
||||
- "traefik.http.routers.matrixrtcjwt.rule=Host(`matrix-rtc.yourdomain.com`) && PathPrefix(`/sfu/get`) || PathPrefix(`/healthz`)"
|
||||
- "traefik.http.routers.matrixrtcjwt.tls=true"
|
||||
- "traefik.http.routers.matrixrtcjwt.service=matrixrtcjwt"
|
||||
- "traefik.http.services.matrixrtcjwt.loadbalancer.server.port=8081"
|
||||
- "traefik.http.routers.matrixrtcjwt.tls.certresolver=yourcertresolver" # change to your cert resolver's name
|
||||
- "traefik.docker.network=proxy" # your traefik network name
|
||||
|
||||
matrix-rtc-livekit:
|
||||
# ...
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.livekit.entrypoints=websecure"
|
||||
- "traefik.http.routers.livekit.rule=Host(`matrix-rtc.yourdomain.com`)"
|
||||
- "traefik.http.routers.livekit.tls=true"
|
||||
- "traefik.http.routers.livekit.service=livekit"
|
||||
- "traefik.http.services.livekit.loadbalancer.server.port=7880"
|
||||
- "traefik.http.routers.livekit.tls.certresolver=yourcertresolver" # change to your cert resolver's name
|
||||
- "traefik.docker.network=proxy" # your traefik network name
|
||||
```
|
||||
2.2 Config file
|
||||
```yaml
|
||||
http:
|
||||
routers:
|
||||
matrixrtcjwt:
|
||||
entryPoints:
|
||||
- "websecure"
|
||||
rule: "Host(`matrix-rtc.yourdomain.com`) && PathPrefix(`/sfu/get`) || PathPrefix(`/healthz`)"
|
||||
tls:
|
||||
certResolver: "yourcertresolver" # change to your cert resolver's name
|
||||
service: matrixrtcjwt
|
||||
livekit:
|
||||
entryPoints:
|
||||
- "websecure"
|
||||
rule: "Host(`matrix-rtc.yourdomain.com`)"
|
||||
tls:
|
||||
certResolver: "yourcertresolver" # change to your cert resolver's name
|
||||
service: livekit
|
||||
services:
|
||||
matrixrtcjwt:
|
||||
loadBalancer:
|
||||
servers:
|
||||
- url: "http://matrix-rtc-jwt:8081"
|
||||
passHostHeader: true
|
||||
livekit:
|
||||
loadBalancer:
|
||||
servers:
|
||||
- url: "http://matrix-rtc-livekit:7880"
|
||||
passHostHeader: true
|
||||
```
|
||||
### 6. Start Docker Containers
|
||||
1. Ensure you are in your matrix-rtc directory. e.g. `cd /opt/matrix-rtc`.
|
||||
2. Start containers: `docker compose up -d`.
|
||||
|
||||
Element Call should now be working.
|
||||
|
||||
## Additional Configuration
|
||||
### TURN Integration
|
||||
If you follow this guide, and also set up Coturn as per the tuwunel documentation, there will be a port clash between the two services. To avoid this, the following must be added to your `coturn.conf`:
|
||||
```
|
||||
min-port=50201
|
||||
max-port=65535
|
||||
```
|
||||
|
||||
If you have Coturn configured, you can use it as a TURN server for Livekit to improve call reliability. As Coturn allows multiple instances of `static-auth-secret`, it is suggested that the secret used for Livekit is different to that used for tuwunel.
|
||||
|
||||
1. Create a secret for Coturn. It is suggested that this should be a random 64 character alphanumeric string.
|
||||
2. Add the following line to the end of your `turnserver.conf`. `AUTH_SECRET` is the secret created in Step 1.
|
||||
```
|
||||
static-auth-secret=AUTH_SECRET
|
||||
```
|
||||
3. Add the following to the end of the `rtc` block in your `livekit.yaml`. `AUTH_SECRET` is the same as above. `turn.yourdomain.com` should be replaced with your actual TURN domain.
|
||||
```
|
||||
turn_servers:
|
||||
- host: turn.yourdomain.com
|
||||
port: 5349
|
||||
protocol: tls
|
||||
secret: "AUTH_SECRET"
|
||||
```
|
||||
|
||||
### Using the Livekit Built In TURN Server
|
||||
It is also possible to use the built in Livekit TURN server. Getting this to work can be a somewhat involved process, and a TURN server is not usually required for Matrix RTC calls. Consequently, instructions are not provided here at this time. If you would like to configure this, more information can be found [here](https://docs.livekit.io/transport/self-hosting/deployment/#improving-connectivity-with-turn).
|
||||
+100
-46
@@ -1,17 +1,11 @@
|
||||
# Troubleshooting Tuwunel
|
||||
|
||||
> ## Docker users ⚠️
|
||||
>
|
||||
> Docker is extremely UX unfriendly. Because of this, a ton of issues or support
|
||||
> is actually Docker support, not tuwunel support. We also cannot document the
|
||||
> ever-growing list of Docker issues here.
|
||||
>
|
||||
> [!IMPORTANT]
|
||||
> If you intend on asking for support and you are using Docker, **PLEASE**
|
||||
> triple validate your issues are **NOT** because you have a misconfiguration in
|
||||
> your Docker setup.
|
||||
>
|
||||
> If there are things like Compose file issues or Dockerhub image issues, those
|
||||
> can still be mentioned as long as they're something we can fix.
|
||||
> your Docker setup. We must remain focused on supporting Tuwunel issues and
|
||||
> cannot budget our time for generic Docker support. Compose file issues or
|
||||
> Dockerhub image issues are okay if they are something we can fix.
|
||||
|
||||
## Tuwunel and Matrix issues
|
||||
|
||||
@@ -93,48 +87,107 @@ ## RocksDB / database issues
|
||||
|
||||
#### Database corruption
|
||||
|
||||
If your database is corrupted *and* is failing to start (e.g. checksum
|
||||
mismatch), it may be recoverable but careful steps must be taken, and there is
|
||||
no guarantee it may be recoverable.
|
||||
There are many causes and varieties of database corruption. There are several
|
||||
methods for mitigation, each with outcomes ranging from a recovered state down
|
||||
to a savage state. This guide has been simplified into a set of universal steps
|
||||
which everyone can follow from the top until they have recovered or reach the
|
||||
end. The details and implications will be explained within each step.
|
||||
|
||||
The first thing that can be done is launching Tuwunel with the
|
||||
`rocksdb_repair` config option set to true. This will tell RocksDB to attempt to
|
||||
repair itself at launch. If this does not work, disable the option and continue
|
||||
reading.
|
||||
> [!TIP]
|
||||
> All command-line `-O` options can be expressed as environment variables or in
|
||||
> the config file based on your deployment's requirements. Note that
|
||||
> `--maintenance` is equivalent to configuring `startup_netburst = false` and
|
||||
> `listening = false`.
|
||||
|
||||
RocksDB has the following recovery modes:
|
||||
> [!IMPORTANT]
|
||||
> Always create a backup of the database before running any operation. This is
|
||||
> critical for steps 3 and above.
|
||||
|
||||
- `TolerateCorruptedTailRecords`
|
||||
- `AbsoluteConsistency`
|
||||
- `PointInTime`
|
||||
- `SkipAnyCorruptedRecord`
|
||||
**0. Start the server with the following options:**
|
||||
|
||||
By default, Tuwunel uses `TolerateCorruptedTailRecords` as generally these may
|
||||
be due to bad federation and we can re-fetch the correct data over federation.
|
||||
The RocksDB default is `PointInTime` which will attempt to restore a "snapshot"
|
||||
of the data when it was last known to be good. This data can be either a few
|
||||
seconds old, or multiple minutes prior. `PointInTime` may not be suitable for
|
||||
default usage due to clients and servers possibly not being able to handle
|
||||
sudden "backwards time travels", and `AbsoluteConsistency` may be too strict.
|
||||
`tuwunel --maintenance -O rocksdb_recovery_mode=0`
|
||||
|
||||
`AbsoluteConsistency` will fail to start the database if any sign of corruption
|
||||
is detected. `SkipAnyCorruptedRecord` will skip all forms of corruption unless
|
||||
it forbids the database from opening (e.g. too severe). Usage of
|
||||
`SkipAnyCorruptedRecord` voids any support as this may cause more damage and/or
|
||||
leave your database in a permanently inconsistent state, but it may do something
|
||||
if `PointInTime` does not work as a last ditch effort.
|
||||
This is actually a "control" and not a method of recovery. If the server starts
|
||||
you either do not have corruption or have deep corruption indicated by very
|
||||
specific errors from rocksdb citing corruption during runtime. If you are
|
||||
certain there is deep corruption skip to step 4, otherwise you are finished
|
||||
without any modifications.
|
||||
|
||||
With this in mind:
|
||||
**1. Start the server in Tolerate-Corrupted-Tail-Records mode:**
|
||||
|
||||
- First start Tuwunel with the `PointInTime` recovery method. See the [example
|
||||
config](configuration/examples.md) for how to do this using
|
||||
`rocksdb_recovery_mode`
|
||||
- If your database successfully opens, clients are recommended to clear their
|
||||
client cache to account for the rollback
|
||||
- Leave your Tuwunel running in `PointInTime` for at least 30-60 minutes so as
|
||||
much possible corruption is restored
|
||||
- If all goes will, you should be able to restore back to using
|
||||
`TolerateCorruptedTailRecords` and you have successfully recovered your database
|
||||
`tuwunel --maintenance -O rocksdb_recovery_mode=1`
|
||||
|
||||
The most common corruption scenario is from a loss of power to the hardware
|
||||
(not an application crash, though it is still possible). This is remediated
|
||||
by dropping the most recently written record. It is highly unlikely there will
|
||||
be any impact on the application from this loss. In the best-case the same data
|
||||
is often re-requested over the federation or replaced by a client. In the
|
||||
worst-case clients may need to clear-cache & reload to guarantee correctness.
|
||||
If the server starts you are finished.
|
||||
|
||||
**2. Start the server in Point-In-Time mode:**
|
||||
|
||||
`tuwunel --maintenance -O rocksdb_recovery_mode=2`
|
||||
|
||||
Similar to the corruption scenario above but for more severe cases. The most
|
||||
recent records are discarded back to the point where there is no corruption.
|
||||
It is highly unlikely there will be any impact on the application from this
|
||||
loss, but it is more likely than above that clients may need to clear-cache
|
||||
& reload to correctly resynchronize with the server.
|
||||
|
||||
**3. Start the server in Skip-Any-Corrupted-Record mode:**
|
||||
|
||||
> [!WARNING]
|
||||
> Salvage mode potentially impacting the application's ability to function.
|
||||
> We cannot provide support for users who have entered this mode.
|
||||
|
||||
`tuwunel --maintenance -O rocksdb_recovery_mode=3`
|
||||
|
||||
Similar to the prior corruption scenarios but for the most severe cases.
|
||||
The database will be inconsistent. It is theoretically possible for the
|
||||
server to continue functioning without notable issue in the best case, but
|
||||
it is completely uncertain what the effect of this operation will be. If
|
||||
the server starts you should immediately export your messages, encryption
|
||||
keys, etc, in a salvage effort and prepare to reinstall.
|
||||
|
||||
**4. Start the server in repair mode.**
|
||||
|
||||
> [!WARNING]
|
||||
> Salvage mode potentially impacting the application's ability to function.
|
||||
> We cannot provide support for users who have entered this mode.
|
||||
|
||||
> [!CAUTION]
|
||||
> Always create a backup of the database before entering this mode. The repair
|
||||
> is not configurable and not interactive. It may automatically remove more
|
||||
> data than anticipated, preventing further salvage efforts.
|
||||
|
||||
`tuwunel --maintenance -O rocksdb_repair=true`
|
||||
|
||||
For corruption affecting the bulk database tables not covered by any journal.
|
||||
This will leave the database in an inconsistent and unpredictable state. It
|
||||
is theoretically possible to continue operating the server depending on which
|
||||
records were dropped, such as some historical records which are no longer
|
||||
essential. Nevertheless the impact of this operation is impossible to assess
|
||||
and a successful recovery should be used to salvage data prior to reinstall.
|
||||
|
||||
Once finished, restart the server without `rocksdb_repair`. If no errors
|
||||
persist, restart the server again without maintenance mode.
|
||||
|
||||
**5. Utilize an external repair tool.**
|
||||
|
||||
> [!WARNING]
|
||||
> Salvage mode potentially impacting the application's ability to function.
|
||||
> We cannot provide support for users who have entered this mode.
|
||||
|
||||
```
|
||||
git clone https://github.com/facebook/rocksdb
|
||||
cd rocksdb
|
||||
make -j$(nproc) ldb
|
||||
./ldb repair --db=/var/lib/tuwunel/ 2>./repair-log.txt
|
||||
```
|
||||
|
||||
For situations when the repair mode in step 4 failed or produced unexpected
|
||||
results.
|
||||
|
||||
## Debugging
|
||||
|
||||
@@ -147,7 +200,8 @@ #### Debug/Trace log level
|
||||
Tuwunel builds without debug or trace log levels at compile time by default
|
||||
for substantial performance gains in CPU usage and improved compile times. If
|
||||
you need to access debug/trace log levels, you will need to build without the
|
||||
`release_max_log_level` feature or use our provided static debug binaries.
|
||||
`release_max_log_level` feature or use our provided release-logging binaries
|
||||
and images.
|
||||
|
||||
#### Changing log level dynamically
|
||||
|
||||
|
||||
Generated
+100
-140
@@ -10,11 +10,11 @@
|
||||
"nixpkgs-stable": "nixpkgs-stable"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1748532342,
|
||||
"narHash": "sha256-CvaKOUq8G10sghKpZhEB2UYjJoWhEkrDFggDgi7piUI=",
|
||||
"lastModified": 1758711588,
|
||||
"narHash": "sha256-0nZlCCDC5PfndsQJXXtcyrtrfW49I3KadGMDlutzaGU=",
|
||||
"owner": "zhaofengli",
|
||||
"repo": "attic",
|
||||
"rev": "ce9373715fe3fac7a174a65a7e6d6baeba8cb4f9",
|
||||
"rev": "12cbeca141f46e1ade76728bce8adc447f2166c6",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -29,14 +29,14 @@
|
||||
"devenv": "devenv",
|
||||
"flake-compat": "flake-compat_2",
|
||||
"git-hooks": "git-hooks",
|
||||
"nixpkgs": "nixpkgs_4"
|
||||
"nixpkgs": "nixpkgs_2"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1748883665,
|
||||
"narHash": "sha256-R0W7uAg+BLoHjMRMQ8+oiSbTq8nkGz5RDpQ+ZfxxP3A=",
|
||||
"lastModified": 1763236786,
|
||||
"narHash": "sha256-JB19RGXDr6loKSdqwvA15jhRHwf6+9Crq2glqqVar84=",
|
||||
"owner": "cachix",
|
||||
"repo": "cachix",
|
||||
"rev": "f707778d902af4d62d8dd92c269f8e70de09acbe",
|
||||
"rev": "938a275857047c300596092beaabaee6d892e243",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -58,16 +58,21 @@
|
||||
],
|
||||
"git-hooks": [
|
||||
"cachix",
|
||||
"devenv"
|
||||
"devenv",
|
||||
"git-hooks"
|
||||
],
|
||||
"nixpkgs": "nixpkgs_2"
|
||||
"nixpkgs": [
|
||||
"cachix",
|
||||
"devenv",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1744206633,
|
||||
"narHash": "sha256-pb5aYkE8FOoa4n123slgHiOf1UbNSnKe5pEZC+xXD5g=",
|
||||
"lastModified": 1752264895,
|
||||
"narHash": "sha256-1zBPE/PNAkPNUsOWFET4J0cjlvziH8DOekesDmjND+w=",
|
||||
"owner": "cachix",
|
||||
"repo": "cachix",
|
||||
"rev": "8a60090640b96f9df95d1ab99e5763a586be1404",
|
||||
"rev": "47053aef762f452e816e44eb9a23fbc3827b241a",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -80,11 +85,11 @@
|
||||
"complement": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1741891349,
|
||||
"narHash": "sha256-YvrzOWcX7DH1drp5SGa+E/fc7wN3hqFtPbqPjZpOu1Q=",
|
||||
"lastModified": 1761739261,
|
||||
"narHash": "sha256-XdzSBbJIYG6thrHbo44/qBiMu5R4bayfy/dlWo9AXBA=",
|
||||
"owner": "matrix-construct",
|
||||
"repo": "complement",
|
||||
"rev": "e587b3df569cba411aeac7c20b6366d03c143745",
|
||||
"rev": "350d7666cab14cb0051ef53da7a1b0b3216d7269",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -95,18 +100,12 @@
|
||||
}
|
||||
},
|
||||
"crane": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"attic",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1722960479,
|
||||
"narHash": "sha256-NhCkJJQhD5GUib8zN9JrmYGMwt4lCRp6ZVNzIiYCl0Y=",
|
||||
"lastModified": 1751562746,
|
||||
"narHash": "sha256-smpugNIkmDeicNz301Ll1bD7nFOty97T79m4GUMUczA=",
|
||||
"owner": "ipetkov",
|
||||
"repo": "crane",
|
||||
"rev": "4c6c77920b8d44cd6660c1621dea6b3fc4b4c4f4",
|
||||
"rev": "aed2020fd3dc26e1e857d4107a5a67a33ab6c1fd",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -117,11 +116,11 @@
|
||||
},
|
||||
"crane_2": {
|
||||
"locked": {
|
||||
"lastModified": 1748970125,
|
||||
"narHash": "sha256-UDyigbDGv8fvs9aS95yzFfOKkEjx1LO3PL3DsKopohA=",
|
||||
"lastModified": 1763511871,
|
||||
"narHash": "sha256-KKZWi+ij7oT0Ag8yC6MQkzfHGcytyjMJDD+47ZV1YNU=",
|
||||
"owner": "ipetkov",
|
||||
"repo": "crane",
|
||||
"rev": "323b5746d89e04b22554b061522dfce9e4c49b18",
|
||||
"rev": "099f9014bc8d0cd6e445470ea1df0fd691d5a548",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -138,6 +137,7 @@
|
||||
"cachix",
|
||||
"flake-compat"
|
||||
],
|
||||
"flake-parts": "flake-parts_2",
|
||||
"git-hooks": [
|
||||
"cachix",
|
||||
"git-hooks"
|
||||
@@ -149,11 +149,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1748273445,
|
||||
"narHash": "sha256-5V0dzpNgQM0CHDsMzh+ludYeu1S+Y+IMjbaskSSdFh0=",
|
||||
"lastModified": 1760560333,
|
||||
"narHash": "sha256-goJQdVl9oDgCxF9CggPUw1DvB4gsot1jzMmz9px8Du8=",
|
||||
"owner": "cachix",
|
||||
"repo": "devenv",
|
||||
"rev": "668a50d8b7bdb19a0131f53c9f6c25c9071e1ffb",
|
||||
"rev": "0a4043938f540027e562c5a0feebbe6be872c3ea",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -170,11 +170,11 @@
|
||||
"rust-analyzer-src": "rust-analyzer-src"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1749883145,
|
||||
"narHash": "sha256-RlcGw3vAnbI3cfZn8aFaovNUd7312VZh+/FDWkqdA7E=",
|
||||
"lastModified": 1763707297,
|
||||
"narHash": "sha256-Bd9VGavwFBLpyU4pjiWfv73gUibNj8dc3xmOW8ff3bI=",
|
||||
"owner": "nix-community",
|
||||
"repo": "fenix",
|
||||
"rev": "a804172f150bcf81262655324e583bb0cd0f28dd",
|
||||
"rev": "7c2d3a165a4a080fdcb6c191d8f9768281c99f75",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -187,11 +187,11 @@
|
||||
"flake-compat": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1696426674,
|
||||
"narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
|
||||
"lastModified": 1747046372,
|
||||
"narHash": "sha256-CIVLLkVgvHYbgI2UpXvIIBJ12HWgX+fjA8Xf8PUmqCY=",
|
||||
"owner": "edolstra",
|
||||
"repo": "flake-compat",
|
||||
"rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
|
||||
"rev": "9100a0f413b0c601e0533d1d94ffd501ce2e7885",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -219,11 +219,11 @@
|
||||
"flake-compat_3": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1747046372,
|
||||
"narHash": "sha256-CIVLLkVgvHYbgI2UpXvIIBJ12HWgX+fjA8Xf8PUmqCY=",
|
||||
"lastModified": 1761588595,
|
||||
"narHash": "sha256-XKUZz9zewJNUj46b4AJdiRZJAvSZ0Dqj2BNfXvFlJC4=",
|
||||
"owner": "edolstra",
|
||||
"repo": "flake-compat",
|
||||
"rev": "9100a0f413b0c601e0533d1d94ffd501ce2e7885",
|
||||
"rev": "f387cd2afec9419c8ee37694406ca490c3f34ee5",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -241,11 +241,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1722555600,
|
||||
"narHash": "sha256-XOQkdLafnb/p9ij77byFQjDf5m5QYl9b2REiVClC+x4=",
|
||||
"lastModified": 1751413152,
|
||||
"narHash": "sha256-Tyw1RjYEsp5scoigs1384gIg6e0GoBVjms4aXFfRssQ=",
|
||||
"owner": "hercules-ci",
|
||||
"repo": "flake-parts",
|
||||
"rev": "8471fe90ad337a8074e957b69ca4d0089218391d",
|
||||
"rev": "77826244401ea9de6e3bac47c2db46005e1f30b5",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -259,16 +259,15 @@
|
||||
"nixpkgs-lib": [
|
||||
"cachix",
|
||||
"devenv",
|
||||
"nix",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1712014858,
|
||||
"narHash": "sha256-sB4SWl2lX95bExY2gMFG5HIzvva5AVMJd4Igm+GpZNw=",
|
||||
"lastModified": 1756770412,
|
||||
"narHash": "sha256-+uWLQZccFHwqpGqr2Yt5VsW/PbeJVTn9Dk6SHWhNRPw=",
|
||||
"owner": "hercules-ci",
|
||||
"repo": "flake-parts",
|
||||
"rev": "9126214d0a59633752a136528f5f3b9aa8565b7d",
|
||||
"rev": "4524271976b625a4a605beefd893f270620fd751",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -309,11 +308,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1747372754,
|
||||
"narHash": "sha256-2Y53NGIX2vxfie1rOW0Qb86vjRZ7ngizoo+bnXU9D9k=",
|
||||
"lastModified": 1760392170,
|
||||
"narHash": "sha256-WftxJgr2MeDDFK47fQKywzC72L2jRc/PWcyGdjaDzkw=",
|
||||
"owner": "cachix",
|
||||
"repo": "git-hooks.nix",
|
||||
"rev": "80479b6ec16fefd9c1db3ea13aeb038c60530f46",
|
||||
"rev": "46d55f0aeb1d567a78223e69729734f3dca25a85",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -344,30 +343,14 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"libgit2": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1697646580,
|
||||
"narHash": "sha256-oX4Z3S9WtJlwvj0uH9HlYcWv+x1hqp8mhXl7HsLu2f0=",
|
||||
"owner": "libgit2",
|
||||
"repo": "libgit2",
|
||||
"rev": "45fd9ed7ae1a9b74b957ef4f337bc3c8b3df01b5",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "libgit2",
|
||||
"repo": "libgit2",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"liburing": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1749816983,
|
||||
"narHash": "sha256-p5hXfDe53Y4MVwL2+wKZYpy4OPGvqFFnOEvkMsFAO6c=",
|
||||
"lastModified": 1763758538,
|
||||
"narHash": "sha256-cDsxLOqeC7imBcArolTHvejSnWoadgpvDy1DJ2/3MOw=",
|
||||
"owner": "axboe",
|
||||
"repo": "liburing",
|
||||
"rev": "ad83d3ab64894c16eaf21ef869656a5bddb93ca4",
|
||||
"rev": "e1ef1e680ee38ed9116989155fca47921698c25f",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -381,11 +364,24 @@
|
||||
"inputs": {
|
||||
"flake-compat": [
|
||||
"cachix",
|
||||
"devenv"
|
||||
"devenv",
|
||||
"flake-compat"
|
||||
],
|
||||
"flake-parts": [
|
||||
"cachix",
|
||||
"devenv",
|
||||
"flake-parts"
|
||||
],
|
||||
"git-hooks-nix": [
|
||||
"cachix",
|
||||
"devenv",
|
||||
"git-hooks"
|
||||
],
|
||||
"nixpkgs": [
|
||||
"cachix",
|
||||
"devenv",
|
||||
"nixpkgs"
|
||||
],
|
||||
"flake-parts": "flake-parts_2",
|
||||
"libgit2": "libgit2",
|
||||
"nixpkgs": "nixpkgs_3",
|
||||
"nixpkgs-23-11": [
|
||||
"cachix",
|
||||
"devenv"
|
||||
@@ -393,34 +389,30 @@
|
||||
"nixpkgs-regression": [
|
||||
"cachix",
|
||||
"devenv"
|
||||
],
|
||||
"pre-commit-hooks": [
|
||||
"cachix",
|
||||
"devenv"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1745930071,
|
||||
"narHash": "sha256-bYyjarS3qSNqxfgc89IoVz8cAFDkF9yPE63EJr+h50s=",
|
||||
"owner": "domenkozar",
|
||||
"lastModified": 1758763079,
|
||||
"narHash": "sha256-Bx1A+lShhOWwMuy3uDzZQvYiBKBFcKwy6G6NEohhv6A=",
|
||||
"owner": "cachix",
|
||||
"repo": "nix",
|
||||
"rev": "b455edf3505f1bf0172b39a735caef94687d0d9c",
|
||||
"rev": "6f0140527c2b0346df4afad7497baa08decb929f",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "domenkozar",
|
||||
"ref": "devenv-2.24",
|
||||
"owner": "cachix",
|
||||
"ref": "devenv-2.30.5",
|
||||
"repo": "nix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nix-filter": {
|
||||
"locked": {
|
||||
"lastModified": 1731533336,
|
||||
"narHash": "sha256-oRam5PS1vcrr5UPgALW0eo1m/5/pls27Z/pabHNy2Ms=",
|
||||
"lastModified": 1757882181,
|
||||
"narHash": "sha256-+cCxYIh2UNalTz364p+QYmWHs0P+6wDhiWR4jDIKQIU=",
|
||||
"owner": "numtide",
|
||||
"repo": "nix-filter",
|
||||
"rev": "f7653272fd234696ae94229839a99b73c9ab7de0",
|
||||
"rev": "59c44d1909c72441144b93cf0f054be7fe764de5",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -438,11 +430,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1729742964,
|
||||
"narHash": "sha256-B4mzTcQ0FZHdpeWcpDYPERtyjJd/NIuaQ9+BV1h+MpA=",
|
||||
"lastModified": 1737420293,
|
||||
"narHash": "sha256-F1G5ifvqTpJq7fdkT34e/Jy9VCyzd5XfJ9TO8fHhJWE=",
|
||||
"owner": "nix-community",
|
||||
"repo": "nix-github-actions",
|
||||
"rev": "e04df33f62cdcf93d73e9a04142464753a16db67",
|
||||
"rev": "f4158fa080ef4503c8f4c820967d946c2af31ec9",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -453,11 +445,11 @@
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1726042813,
|
||||
"narHash": "sha256-LnNKCCxnwgF+575y0pxUdlGZBO/ru1CtGHIqQVfvjlA=",
|
||||
"lastModified": 1751949589,
|
||||
"narHash": "sha256-mgFxAPLWw0Kq+C8P3dRrZrOYEQXOtKuYVlo9xvPntt8=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "159be5db480d1df880a0135ca0bfed84c2f88353",
|
||||
"rev": "9b008d60392981ad674e04016d25619281550a9d",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -469,27 +461,27 @@
|
||||
},
|
||||
"nixpkgs-stable": {
|
||||
"locked": {
|
||||
"lastModified": 1724316499,
|
||||
"narHash": "sha256-Qb9MhKBUTCfWg/wqqaxt89Xfi6qTD3XpTzQ9eXi3JmE=",
|
||||
"lastModified": 1751741127,
|
||||
"narHash": "sha256-t75Shs76NgxjZSgvvZZ9qOmz5zuBE8buUaYD28BMTxg=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "797f7dc49e0bc7fab4b57c021cdf68f595e47841",
|
||||
"rev": "29e290002bfff26af1db6f64d070698019460302",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixos-24.05",
|
||||
"ref": "nixos-25.05",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_2": {
|
||||
"locked": {
|
||||
"lastModified": 1733212471,
|
||||
"narHash": "sha256-M1+uCoV5igihRfcUKrr1riygbe73/dzNnzPsmaLCmpo=",
|
||||
"lastModified": 1760524057,
|
||||
"narHash": "sha256-EVAqOteLBFmd7pKkb0+FIUyzTF61VKi7YmvP1tw4nEw=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "55d15ad12a74eb7d4646254e13638ad0c4128776",
|
||||
"rev": "544961dfcce86422ba200ed9a0b00dd4b1486ec5",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -501,43 +493,11 @@
|
||||
},
|
||||
"nixpkgs_3": {
|
||||
"locked": {
|
||||
"lastModified": 1717432640,
|
||||
"narHash": "sha256-+f9c4/ZX5MWDOuB1rKoWj+lBNm0z0rs4CK47HBLxy1o=",
|
||||
"lastModified": 1763618868,
|
||||
"narHash": "sha256-v5afmLjn/uyD9EQuPBn7nZuaZVV9r+JerayK/4wvdWA=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "88269ab3044128b7c2f4c7d68448b2fb50456870",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "release-24.05",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_4": {
|
||||
"locked": {
|
||||
"lastModified": 1748190013,
|
||||
"narHash": "sha256-R5HJFflOfsP5FBtk+zE8FpL8uqE7n62jqOsADvVshhE=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "62b852f6c6742134ade1abdd2a21685fd617a291",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixos-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_5": {
|
||||
"locked": {
|
||||
"lastModified": 1749871736,
|
||||
"narHash": "sha256-K9yBph93OLTNw02Q6e9CYFGrUhvEXnh45vrZqIRWfvQ=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "6afe187897bef7933475e6af374c893f4c84a293",
|
||||
"rev": "a8d610af3f1a5fb71e23e08434d8d61a466fc942",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -550,11 +510,11 @@
|
||||
"rocksdb": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1749358049,
|
||||
"narHash": "sha256-ZSjvAZBfZkJrBIpw8ANZMbJVb8AeuogvuAipGVE4Qe4=",
|
||||
"lastModified": 1763593074,
|
||||
"narHash": "sha256-aOV/jJjRjNJ3hrRqhCsXlIz05NvEhDF/j5Q5UOQuvp8=",
|
||||
"owner": "matrix-construct",
|
||||
"repo": "rocksdb",
|
||||
"rev": "cf7f65d0b377af019661c240f9165b3ef60640c3",
|
||||
"rev": "9a3a213b55df0b11408102c899a940675c0d90e4",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -575,18 +535,18 @@
|
||||
"flake-utils": "flake-utils",
|
||||
"liburing": "liburing",
|
||||
"nix-filter": "nix-filter",
|
||||
"nixpkgs": "nixpkgs_5",
|
||||
"nixpkgs": "nixpkgs_3",
|
||||
"rocksdb": "rocksdb"
|
||||
}
|
||||
},
|
||||
"rust-analyzer-src": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1749829309,
|
||||
"narHash": "sha256-t6x6/PKg8Shnkd3htrxf3WMgycfRLRWvN9JHAmGWf+s=",
|
||||
"lastModified": 1763648203,
|
||||
"narHash": "sha256-/WJdebbRD+m5vr2xy/bJdCpqd7YHSMapjuXAM/0lvtA=",
|
||||
"owner": "rust-lang",
|
||||
"repo": "rust-analyzer",
|
||||
"rev": "a497f4114ccf24978accb56190e60d1e1659e0c7",
|
||||
"rev": "eaaa2da9fbbfd7a79ff501e0563351cb2004574a",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
{ inputs
|
||||
{
|
||||
inputs,
|
||||
|
||||
# Dependencies
|
||||
, main
|
||||
, mdbook
|
||||
, stdenv
|
||||
# Dependencies
|
||||
main,
|
||||
mdbook,
|
||||
stdenv,
|
||||
}:
|
||||
|
||||
stdenv.mkDerivation {
|
||||
|
||||
@@ -6,6 +6,7 @@ allow_public_room_directory_over_federation = true
|
||||
allow_public_room_directory_without_auth = true
|
||||
allow_registration = true
|
||||
database_path = "/database"
|
||||
error_on_unknown_config_opts = true
|
||||
log = "trace,h2=debug,hyper=debug"
|
||||
port = [8008, 8448]
|
||||
trusted_servers = []
|
||||
@@ -21,7 +22,6 @@ media_startup_check = true
|
||||
prune_missing_media = true
|
||||
log_colors = true
|
||||
admin_room_notices = false
|
||||
allow_check_for_updates = false
|
||||
intentionally_unknown_config_option_for_testing = true
|
||||
rocksdb_log_level = "info"
|
||||
rocksdb_max_log_files = 1
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
# Dependencies
|
||||
{ bashInteractive
|
||||
, buildEnv
|
||||
, coreutils
|
||||
, dockerTools
|
||||
, lib
|
||||
, main
|
||||
, stdenv
|
||||
, tini
|
||||
, writeShellScriptBin
|
||||
{
|
||||
bashInteractive,
|
||||
buildEnv,
|
||||
coreutils,
|
||||
dockerTools,
|
||||
lib,
|
||||
main,
|
||||
stdenv,
|
||||
tini,
|
||||
writeShellScriptBin,
|
||||
}:
|
||||
|
||||
let
|
||||
@@ -16,24 +17,24 @@ let
|
||||
all_features = true;
|
||||
disable_release_max_log_level = true;
|
||||
disable_features = [
|
||||
# console/CLI stuff isn't used or relevant for complement
|
||||
"console"
|
||||
"tokio_console"
|
||||
# sentry telemetry isn't useful for complement, disabled by default anyways
|
||||
"sentry_telemetry"
|
||||
"perf_measurements"
|
||||
# this is non-functional on nix for some reason
|
||||
"hardened_malloc"
|
||||
# dont include experimental features
|
||||
"experimental"
|
||||
# compression isn't needed for complement
|
||||
"brotli_compression"
|
||||
"gzip_compression"
|
||||
"zstd_compression"
|
||||
# complement doesn't need hot reloading
|
||||
"tuwunel_mods"
|
||||
# complement doesn't have URL preview media tests
|
||||
"url_preview"
|
||||
# console/CLI stuff isn't used or relevant for complement
|
||||
"console"
|
||||
"tokio_console"
|
||||
# sentry telemetry isn't useful for complement, disabled by default anyways
|
||||
"sentry_telemetry"
|
||||
"perf_measurements"
|
||||
# this is non-functional on nix for some reason
|
||||
"hardened_malloc"
|
||||
# dont include experimental features
|
||||
"experimental"
|
||||
# compression isn't needed for complement
|
||||
"brotli_compression"
|
||||
"gzip_compression"
|
||||
"zstd_compression"
|
||||
# complement doesn't need hot reloading
|
||||
"tuwunel_mods"
|
||||
# complement doesn't have URL preview media tests
|
||||
"url_preview"
|
||||
];
|
||||
};
|
||||
|
||||
@@ -68,11 +69,18 @@ dockerTools.buildImage {
|
||||
"${lib.getExe start}"
|
||||
];
|
||||
|
||||
Entrypoint = if !stdenv.hostPlatform.isDarwin
|
||||
Entrypoint =
|
||||
if
|
||||
!stdenv.hostPlatform.isDarwin
|
||||
# Use the `tini` init system so that signals (e.g. ctrl+c/SIGINT)
|
||||
# are handled as expected
|
||||
then [ "${lib.getExe' tini "tini"}" "--" ]
|
||||
else [];
|
||||
then
|
||||
[
|
||||
"${lib.getExe' tini "tini"}"
|
||||
"--"
|
||||
]
|
||||
else
|
||||
[ ];
|
||||
|
||||
Env = [
|
||||
"TUWUNEL_TLS__KEY=${./private_key.key}"
|
||||
@@ -82,8 +90,8 @@ dockerTools.buildImage {
|
||||
];
|
||||
|
||||
ExposedPorts = {
|
||||
"8008/tcp" = {};
|
||||
"8448/tcp" = {};
|
||||
"8008/tcp" = { };
|
||||
"8448/tcp" = { };
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,38 +1,35 @@
|
||||
{ lib
|
||||
, pkgsBuildHost
|
||||
, rust
|
||||
, stdenv
|
||||
{
|
||||
lib,
|
||||
pkgsBuildHost,
|
||||
rust,
|
||||
stdenv,
|
||||
}:
|
||||
|
||||
lib.optionalAttrs stdenv.hostPlatform.isStatic {
|
||||
ROCKSDB_STATIC = "";
|
||||
}
|
||||
//
|
||||
{
|
||||
CARGO_BUILD_RUSTFLAGS =
|
||||
lib.concatStringsSep
|
||||
" "
|
||||
([]
|
||||
# This disables PIE for static builds, which isn't great in terms
|
||||
# of security. Unfortunately, my hand is forced because nixpkgs'
|
||||
# `libstdc++.a` is built without `-fPIE`, which precludes us from
|
||||
# leaving PIE enabled.
|
||||
++ lib.optionals
|
||||
stdenv.hostPlatform.isStatic
|
||||
[ "-C" "relocation-model=static" ]
|
||||
++ lib.optionals
|
||||
(stdenv.buildPlatform.config != stdenv.hostPlatform.config)
|
||||
[
|
||||
"-l"
|
||||
"c"
|
||||
// {
|
||||
CARGO_BUILD_RUSTFLAGS = lib.concatStringsSep " " (
|
||||
[ ]
|
||||
# This disables PIE for static builds, which isn't great in terms
|
||||
# of security. Unfortunately, my hand is forced because nixpkgs'
|
||||
# `libstdc++.a` is built without `-fPIE`, which precludes us from
|
||||
# leaving PIE enabled.
|
||||
++ lib.optionals stdenv.hostPlatform.isStatic [
|
||||
"-C"
|
||||
"relocation-model=static"
|
||||
]
|
||||
++ lib.optionals (stdenv.buildPlatform.config != stdenv.hostPlatform.config) [
|
||||
"-l"
|
||||
"c"
|
||||
|
||||
"-l"
|
||||
"stdc++"
|
||||
"-l"
|
||||
"stdc++"
|
||||
|
||||
"-L"
|
||||
"${stdenv.cc.cc.lib}/${stdenv.hostPlatform.config}/lib"
|
||||
]
|
||||
);
|
||||
"-L"
|
||||
"${stdenv.cc.cc.lib}/${stdenv.hostPlatform.config}/lib"
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
# What follows is stolen from [here][0]. Its purpose is to properly
|
||||
@@ -41,26 +38,21 @@ lib.optionalAttrs stdenv.hostPlatform.isStatic {
|
||||
# run on the build platform (I think).
|
||||
#
|
||||
# [0]: https://github.com/NixOS/nixpkgs/blob/nixpkgs-unstable/pkgs/build-support/rust/lib/default.nix#L48-L68
|
||||
//
|
||||
(
|
||||
// (
|
||||
let
|
||||
inherit (rust.lib) envVars;
|
||||
in
|
||||
lib.optionalAttrs
|
||||
(stdenv.targetPlatform.rust.rustcTarget
|
||||
!= stdenv.hostPlatform.rust.rustcTarget)
|
||||
(
|
||||
let
|
||||
inherit (stdenv.targetPlatform.rust) cargoEnvVarTarget;
|
||||
in
|
||||
{
|
||||
"CC_${cargoEnvVarTarget}" = envVars.ccForTarget;
|
||||
"CXX_${cargoEnvVarTarget}" = envVars.cxxForTarget;
|
||||
"CARGO_TARGET_${cargoEnvVarTarget}_LINKER" = envVars.ccForTarget;
|
||||
}
|
||||
)
|
||||
//
|
||||
(
|
||||
lib.optionalAttrs (stdenv.targetPlatform.rust.rustcTarget != stdenv.hostPlatform.rust.rustcTarget) (
|
||||
let
|
||||
inherit (stdenv.targetPlatform.rust) cargoEnvVarTarget;
|
||||
in
|
||||
{
|
||||
"CC_${cargoEnvVarTarget}" = envVars.ccForTarget;
|
||||
"CXX_${cargoEnvVarTarget}" = envVars.cxxForTarget;
|
||||
"CARGO_TARGET_${cargoEnvVarTarget}_LINKER" = envVars.ccForTarget;
|
||||
}
|
||||
)
|
||||
// (
|
||||
let
|
||||
inherit (stdenv.hostPlatform.rust) cargoEnvVarTarget rustcTarget;
|
||||
in
|
||||
@@ -71,8 +63,7 @@ lib.optionalAttrs stdenv.hostPlatform.isStatic {
|
||||
CARGO_BUILD_TARGET = rustcTarget;
|
||||
}
|
||||
)
|
||||
//
|
||||
(
|
||||
// (
|
||||
let
|
||||
inherit (stdenv.buildPlatform.rust) cargoEnvVarTarget;
|
||||
in
|
||||
|
||||
+204
-149
@@ -1,87 +1,94 @@
|
||||
# Dependencies (keep sorted)
|
||||
{ craneLib
|
||||
, inputs
|
||||
, jq
|
||||
, lib
|
||||
, libiconv
|
||||
, liburing
|
||||
, pkgsBuildHost
|
||||
, rocksdb
|
||||
, removeReferencesTo
|
||||
, rust
|
||||
, rust-jemalloc-sys
|
||||
, stdenv
|
||||
{
|
||||
craneLib,
|
||||
inputs,
|
||||
jq,
|
||||
lib,
|
||||
libiconv,
|
||||
liburing,
|
||||
pkgsBuildHost,
|
||||
rocksdb,
|
||||
removeReferencesTo,
|
||||
rust,
|
||||
autoPatchelfHook,
|
||||
rust-jemalloc-sys-unprefixed,
|
||||
stdenv,
|
||||
|
||||
# Options (keep sorted)
|
||||
, all_features ? false
|
||||
, default_features ? true
|
||||
# default list of disabled features
|
||||
, disable_features ? [
|
||||
# dont include experimental features
|
||||
"experimental"
|
||||
# jemalloc profiling/stats features are expensive and shouldn't
|
||||
# be expected on non-debug builds.
|
||||
"jemalloc_prof"
|
||||
"jemalloc_stats"
|
||||
# this is non-functional on nix for some reason
|
||||
"hardened_malloc"
|
||||
# tuwunel_mods is a development-only hot reload feature
|
||||
"tuwunel_mods"
|
||||
]
|
||||
, disable_release_max_log_level ? false
|
||||
, features ? []
|
||||
, profile ? "release"
|
||||
# rocksdb compiled with -march=haswell and target-cpu=haswell rustflag
|
||||
# haswell is pretty much any x86 cpu made in the last 12 years, and
|
||||
# supports modern CPU extensions that rocksdb can make use of.
|
||||
# disable if trying to make a portable x86_64 build for very old hardware
|
||||
, x86_64_haswell_target_optimised ? false
|
||||
# Options (keep sorted)
|
||||
all_features ? false,
|
||||
default_features ? true,
|
||||
# default list of disabled features
|
||||
disable_features ? [
|
||||
# dont include experimental features
|
||||
"experimental"
|
||||
# jemalloc profiling/stats features are expensive and shouldn't
|
||||
# be expected on non-debug builds.
|
||||
"jemalloc_prof"
|
||||
"jemalloc_stats"
|
||||
# tuwunel_mods is a development-only hot reload feature
|
||||
"tuwunel_mods"
|
||||
],
|
||||
disable_release_max_log_level ? false,
|
||||
features ? [ ],
|
||||
profile ? "release",
|
||||
# rocksdb compiled with -march=haswell and target-cpu=haswell rustflag
|
||||
# haswell is pretty much any x86 cpu made in the last 12 years, and
|
||||
# supports modern CPU extensions that rocksdb can make use of.
|
||||
# disable if trying to make a portable x86_64 build for very old hardware
|
||||
x86_64_haswell_target_optimised ? false,
|
||||
}:
|
||||
|
||||
let
|
||||
# We perform default-feature unification in nix, because some of the dependencies
|
||||
# on the nix side depend on feature values.
|
||||
crateFeatures = path:
|
||||
let manifest = lib.importTOML "${path}/Cargo.toml"; in
|
||||
lib.remove "default" (lib.attrNames manifest.features);
|
||||
crateDefaultFeatures = path:
|
||||
(lib.importTOML "${path}/Cargo.toml").features.default;
|
||||
allDefaultFeatures = crateDefaultFeatures "${inputs.self}/src/main";
|
||||
allFeatures = crateFeatures "${inputs.self}/src/main";
|
||||
features' = lib.unique
|
||||
(features ++
|
||||
lib.optionals default_features allDefaultFeatures ++
|
||||
lib.optionals all_features allFeatures);
|
||||
disable_features' = disable_features ++ lib.optionals disable_release_max_log_level ["release_max_log_level"];
|
||||
features'' = lib.subtractLists disable_features' features';
|
||||
# We perform default-feature unification in nix, because some of the dependencies
|
||||
# on the nix side depend on feature values.
|
||||
crateFeatures =
|
||||
path:
|
||||
let
|
||||
manifest = lib.importTOML "${path}/Cargo.toml";
|
||||
in
|
||||
lib.remove "default" (lib.attrNames manifest.features);
|
||||
crateDefaultFeatures = path: (lib.importTOML "${path}/Cargo.toml").features.default;
|
||||
allDefaultFeatures = crateDefaultFeatures "${inputs.self}/src/main";
|
||||
allFeatures = crateFeatures "${inputs.self}/src/main";
|
||||
features' = lib.unique (
|
||||
features
|
||||
++ lib.optionals default_features allDefaultFeatures
|
||||
++ lib.optionals all_features allFeatures
|
||||
);
|
||||
disable_features' =
|
||||
disable_features ++ lib.optionals disable_release_max_log_level [ "release_max_log_level" ];
|
||||
features'' = lib.subtractLists disable_features' features';
|
||||
|
||||
featureEnabled = feature : builtins.elem feature features'';
|
||||
featureEnabled = feature: builtins.elem feature features'';
|
||||
|
||||
enableLiburing = featureEnabled "io_uring" && !stdenv.hostPlatform.isDarwin;
|
||||
enableLiburing = featureEnabled "io_uring" && !stdenv.hostPlatform.isDarwin;
|
||||
|
||||
# This derivation will set the JEMALLOC_OVERRIDE variable, causing the
|
||||
# tikv-jemalloc-sys crate to use the nixpkgs jemalloc instead of building it's
|
||||
# own. In order for this to work, we need to set flags on the build that match
|
||||
# whatever flags tikv-jemalloc-sys was going to use. These are dependent on
|
||||
# which features we enable in tikv-jemalloc-sys.
|
||||
rust-jemalloc-sys' = (rust-jemalloc-sys.override {
|
||||
# tikv-jemalloc-sys/unprefixed_malloc_on_supported_platforms feature
|
||||
unprefixed = true;
|
||||
}).overrideAttrs (old: {
|
||||
configureFlags = old.configureFlags ++
|
||||
# we dont need docs
|
||||
[ "--disable-doc" ] ++
|
||||
# we dont need cxx/C++ integration
|
||||
[ "--disable-cxx" ] ++
|
||||
# tikv-jemalloc-sys/profiling feature
|
||||
lib.optional (featureEnabled "jemalloc_prof") "--enable-prof" ++
|
||||
# tikv-jemalloc-sys/stats feature
|
||||
(if (featureEnabled "jemalloc_stats") then [ "--enable-stats" ] else [ "--disable-stats" ]);
|
||||
});
|
||||
# This derivation will set the JEMALLOC_OVERRIDE variable, causing the
|
||||
# tikv-jemalloc-sys crate to use the nixpkgs jemalloc instead of building it's
|
||||
# own. In order for this to work, we need to set flags on the build that match
|
||||
# whatever flags tikv-jemalloc-sys was going to use. These are dependent on
|
||||
# which features we enable in tikv-jemalloc-sys.
|
||||
rust-jemalloc-sys' =
|
||||
# tikv-jemalloc-sys/unprefixed_malloc_on_supported_platforms feature
|
||||
rust-jemalloc-sys-unprefixed.overrideAttrs (old: {
|
||||
configureFlags =
|
||||
old.configureFlags
|
||||
++
|
||||
# we dont need docs
|
||||
[ "--disable-doc" ]
|
||||
++
|
||||
# we dont need cxx/C++ integration
|
||||
[ "--disable-cxx" ]
|
||||
++
|
||||
# tikv-jemalloc-sys/profiling feature
|
||||
lib.optional (featureEnabled "jemalloc_prof") "--enable-prof"
|
||||
++
|
||||
# tikv-jemalloc-sys/stats feature
|
||||
(if (featureEnabled "jemalloc_stats") then [ "--enable-stats" ] else [ "--disable-stats" ]);
|
||||
});
|
||||
|
||||
buildDepsOnlyEnv =
|
||||
let
|
||||
rocksdb' = (rocksdb.override {
|
||||
rocksdb' =
|
||||
(rocksdb.override {
|
||||
jemalloc = lib.optional (featureEnabled "jemalloc") rust-jemalloc-sys';
|
||||
# rocksdb fails to build with prefixed jemalloc, which is required on
|
||||
# darwin due to [1]. In this case, fall back to building rocksdb with
|
||||
@@ -94,24 +101,32 @@ buildDepsOnlyEnv =
|
||||
# for some reason enableLiburing in nixpkgs rocksdb is default true
|
||||
# which breaks Darwin entirely
|
||||
enableLiburing = enableLiburing;
|
||||
}).overrideAttrs (old: {
|
||||
enableLiburing = enableLiburing;
|
||||
cmakeFlags = (if x86_64_haswell_target_optimised then (lib.subtractLists [
|
||||
# dont make a portable build if x86_64_haswell_target_optimised is enabled
|
||||
"-DPORTABLE=1"
|
||||
] old.cmakeFlags
|
||||
++ [ "-DPORTABLE=haswell" ]) else ([ "-DPORTABLE=1" ])
|
||||
)
|
||||
++ old.cmakeFlags;
|
||||
}).overrideAttrs
|
||||
(old: {
|
||||
enableLiburing = enableLiburing;
|
||||
cmakeFlags =
|
||||
(
|
||||
if x86_64_haswell_target_optimised then
|
||||
(
|
||||
lib.subtractLists [
|
||||
# dont make a portable build if x86_64_haswell_target_optimised is enabled
|
||||
"-DPORTABLE=1"
|
||||
] old.cmakeFlags
|
||||
++ [ "-DPORTABLE=haswell" ]
|
||||
)
|
||||
else
|
||||
([ "-DPORTABLE=1" ])
|
||||
)
|
||||
++ old.cmakeFlags;
|
||||
|
||||
# outputs has "tools" which we dont need or use
|
||||
outputs = [ "out" ];
|
||||
# outputs has "tools" which we dont need or use
|
||||
outputs = [ "out" ];
|
||||
|
||||
# preInstall hooks has stuff for messing with ldb/sst_dump which we dont need or use
|
||||
preInstall = "";
|
||||
});
|
||||
in
|
||||
{
|
||||
# preInstall hooks has stuff for messing with ldb/sst_dump which we dont need or use
|
||||
preInstall = "";
|
||||
});
|
||||
|
||||
buildDepsOnlyEnv = {
|
||||
# https://crane.dev/faq/rebuilds-bindgen.html
|
||||
NIX_OUTPATH_USED_AS_RANDOM_SEED = "aaaaaaaaaa";
|
||||
|
||||
@@ -119,68 +134,73 @@ buildDepsOnlyEnv =
|
||||
ROCKSDB_INCLUDE_DIR = "${rocksdb'}/include";
|
||||
ROCKSDB_LIB_DIR = "${rocksdb'}/lib";
|
||||
}
|
||||
//
|
||||
(import ./cross-compilation-env.nix {
|
||||
// (import ./cross-compilation-env.nix {
|
||||
# Keep sorted
|
||||
inherit
|
||||
lib
|
||||
pkgsBuildHost
|
||||
rust
|
||||
stdenv;
|
||||
stdenv
|
||||
;
|
||||
});
|
||||
|
||||
buildPackageEnv = {
|
||||
TUWUNEL_VERSION_EXTRA = inputs.self.shortRev or inputs.self.dirtyShortRev or "";
|
||||
} // buildDepsOnlyEnv // {
|
||||
# Only needed in static stdenv because these are transitive dependencies of rocksdb
|
||||
CARGO_BUILD_RUSTFLAGS = buildDepsOnlyEnv.CARGO_BUILD_RUSTFLAGS
|
||||
+ lib.optionalString (enableLiburing && stdenv.hostPlatform.isStatic)
|
||||
" -L${lib.getLib liburing}/lib -luring"
|
||||
+ lib.optionalString x86_64_haswell_target_optimised
|
||||
" -Ctarget-cpu=haswell";
|
||||
};
|
||||
buildPackageEnv = {
|
||||
TUWUNEL_VERSION_EXTRA = inputs.self.shortRev or inputs.self.dirtyShortRev or "";
|
||||
TUWUNEL_DATABASE_PATH = "/var/tmp/tuwunel.db";
|
||||
}
|
||||
// buildDepsOnlyEnv
|
||||
// {
|
||||
# Only needed in static stdenv because these are transitive dependencies of rocksdb
|
||||
CARGO_BUILD_RUSTFLAGS =
|
||||
buildDepsOnlyEnv.CARGO_BUILD_RUSTFLAGS
|
||||
+ lib.optionalString (
|
||||
enableLiburing && stdenv.hostPlatform.isStatic
|
||||
) " -L${lib.getLib liburing}/lib -luring"
|
||||
+ lib.optionalString x86_64_haswell_target_optimised " -Ctarget-cpu=haswell";
|
||||
};
|
||||
|
||||
commonAttrs = {
|
||||
inherit
|
||||
(craneLib.crateNameFromCargoToml {
|
||||
cargoToml = "${inputs.self}/Cargo.toml";
|
||||
})
|
||||
pname
|
||||
version
|
||||
;
|
||||
|
||||
src =
|
||||
let
|
||||
filter = inputs.nix-filter.lib;
|
||||
in
|
||||
filter {
|
||||
root = inputs.self;
|
||||
|
||||
commonAttrs = {
|
||||
inherit
|
||||
(craneLib.crateNameFromCargoToml {
|
||||
cargoToml = "${inputs.self}/Cargo.toml";
|
||||
})
|
||||
pname
|
||||
version;
|
||||
|
||||
src = let filter = inputs.nix-filter.lib; in filter {
|
||||
root = inputs.self;
|
||||
|
||||
# Keep sorted
|
||||
include = [
|
||||
".cargo"
|
||||
"Cargo.lock"
|
||||
"Cargo.toml"
|
||||
"src"
|
||||
];
|
||||
};
|
||||
# Keep sorted
|
||||
include = [
|
||||
".cargo"
|
||||
"Cargo.lock"
|
||||
"Cargo.toml"
|
||||
"src"
|
||||
];
|
||||
};
|
||||
|
||||
doCheck = true;
|
||||
|
||||
cargoExtraArgs = "--no-default-features --locked "
|
||||
+ lib.optionalString
|
||||
(features'' != [])
|
||||
"--features " + (builtins.concatStringsSep "," features'');
|
||||
cargoExtraArgs =
|
||||
"--no-default-features --locked "
|
||||
+ lib.optionalString (features'' != [ ]) "--features "
|
||||
+ (builtins.concatStringsSep "," features'');
|
||||
|
||||
dontStrip = profile == "dev" || profile == "test";
|
||||
dontPatchELF = profile == "dev" || profile == "test";
|
||||
|
||||
buildInputs = lib.optional (featureEnabled "jemalloc") rust-jemalloc-sys'
|
||||
# needed to build Rust applications on macOS
|
||||
++ lib.optionals stdenv.hostPlatform.isDarwin [
|
||||
buildInputs =
|
||||
lib.optional (featureEnabled "jemalloc") rust-jemalloc-sys-unprefixed
|
||||
# needed to build Rust applications on macOS
|
||||
++ lib.optionals stdenv.hostPlatform.isDarwin [
|
||||
# https://github.com/NixOS/nixpkgs/issues/206242
|
||||
# ld: library not found for -liconv
|
||||
libiconv
|
||||
# https://stackoverflow.com/questions/69869574/properly-adding-darwin-apple-sdk-to-a-nix-shell
|
||||
# https://discourse.nixos.org/t/compile-a-rust-binary-on-macos-dbcrossbar/8612
|
||||
pkgsBuildHost.darwin.apple_sdk.frameworks.Security
|
||||
];
|
||||
|
||||
nativeBuildInputs = [
|
||||
@@ -194,27 +214,62 @@ commonAttrs = {
|
||||
# differing values for `NIX_CFLAGS_COMPILE`, which contributes to spurious
|
||||
# rebuilds of bindgen and its depedents.
|
||||
jq
|
||||
];
|
||||
};
|
||||
];
|
||||
};
|
||||
in
|
||||
|
||||
craneLib.buildPackage ( commonAttrs // {
|
||||
cargoArtifacts = craneLib.buildDepsOnly (commonAttrs // {
|
||||
env = buildDepsOnlyEnv;
|
||||
});
|
||||
craneLib.buildPackage (
|
||||
commonAttrs
|
||||
// rec {
|
||||
cargoArtifacts = craneLib.buildDepsOnly (
|
||||
commonAttrs
|
||||
// {
|
||||
env = buildDepsOnlyEnv;
|
||||
}
|
||||
);
|
||||
|
||||
doCheck = true;
|
||||
# Adds runpath settings to the resulting binary
|
||||
buildInputs = (commonAttrs.buildInputs or [ ]) ++ [
|
||||
rocksdb'
|
||||
];
|
||||
nativeBuildInputs = (commonAttrs.nativeBuildInputs or [ ]) ++ [
|
||||
autoPatchelfHook
|
||||
];
|
||||
# This is needed for tests to link
|
||||
LD_LIBRARY_PATH = lib.makeLibraryPath buildInputs;
|
||||
|
||||
cargoExtraArgs = "--no-default-features --locked "
|
||||
+ lib.optionalString
|
||||
(features'' != [])
|
||||
"--features " + (builtins.concatStringsSep "," features'');
|
||||
nativeCheckInputs = [
|
||||
pkgsBuildHost.libredirect.hook
|
||||
];
|
||||
|
||||
env = buildPackageEnv;
|
||||
preCheck =
|
||||
let
|
||||
fakeResolvConf = pkgsBuildHost.writeTextFile {
|
||||
name = "resolv.conf";
|
||||
text = ''
|
||||
nameserver 0.0.0.0
|
||||
'';
|
||||
};
|
||||
in
|
||||
''
|
||||
export NIX_REDIRECTS="/etc/resolv.conf=${fakeResolvConf}"
|
||||
export TUWUNEL_DATABASE_PATH="$(mktemp -d)/smoketest.db"
|
||||
'';
|
||||
doCheck = true;
|
||||
|
||||
doBenchmark = false;
|
||||
|
||||
cargoExtraArgs =
|
||||
"--no-default-features --locked "
|
||||
+ lib.optionalString (features'' != [ ]) "--features "
|
||||
+ (builtins.concatStringsSep "," features'');
|
||||
|
||||
passthru = {
|
||||
env = buildPackageEnv;
|
||||
};
|
||||
|
||||
meta.mainProgram = commonAttrs.pname;
|
||||
})
|
||||
passthru = {
|
||||
env = buildPackageEnv;
|
||||
};
|
||||
|
||||
meta.mainProgram = commonAttrs.pname;
|
||||
}
|
||||
)
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
{ inputs
|
||||
{
|
||||
inputs,
|
||||
|
||||
# Dependencies
|
||||
, dockerTools
|
||||
, lib
|
||||
, main
|
||||
, stdenv
|
||||
, tini
|
||||
# Dependencies
|
||||
dockerTools,
|
||||
lib,
|
||||
main,
|
||||
stdenv,
|
||||
tini,
|
||||
}:
|
||||
|
||||
dockerTools.buildLayeredImage {
|
||||
@@ -17,11 +18,18 @@ dockerTools.buildLayeredImage {
|
||||
main
|
||||
];
|
||||
config = {
|
||||
Entrypoint = if !stdenv.hostPlatform.isDarwin
|
||||
Entrypoint =
|
||||
if
|
||||
!stdenv.hostPlatform.isDarwin
|
||||
# Use the `tini` init system so that signals (e.g. ctrl+c/SIGINT)
|
||||
# are handled as expected
|
||||
then [ "${lib.getExe' tini "tini"}" "--" ]
|
||||
else [];
|
||||
then
|
||||
[
|
||||
"${lib.getExe' tini "tini"}"
|
||||
"--"
|
||||
]
|
||||
else
|
||||
[ ];
|
||||
Cmd = [
|
||||
"${lib.getExe main}"
|
||||
];
|
||||
@@ -29,9 +37,10 @@ dockerTools.buildLayeredImage {
|
||||
"RUST_BACKTRACE=full"
|
||||
];
|
||||
Labels = {
|
||||
"org.opencontainers.image.authors" = "June Clementine Strawberry <june@girlboss.ceo> and Jason Volk
|
||||
"org.opencontainers.image.authors" =
|
||||
"June Clementine Strawberry <june@girlboss.ceo> and Jason Volk
|
||||
<jason@zemos.net>";
|
||||
"org.opencontainers.image.created" ="@${toString inputs.self.lastModified}";
|
||||
"org.opencontainers.image.created" = "@${toString inputs.self.lastModified}";
|
||||
"org.opencontainers.image.description" = "a very cool Matrix chat homeserver written in Rust";
|
||||
"org.opencontainers.image.documentation" = "https://conduwuit.puppyirl.gay/";
|
||||
"org.opencontainers.image.licenses" = "Apache-2.0";
|
||||
|
||||
+1
-2
@@ -2,11 +2,9 @@
|
||||
Description=Tuwunel Matrix homeserver
|
||||
Wants=network-online.target
|
||||
After=network-online.target
|
||||
Alias=matrix-tuwunel.service
|
||||
Documentation=https://tuwunel.chat/
|
||||
|
||||
[Service]
|
||||
DynamicUser=yes
|
||||
User=tuwunel
|
||||
Group=tuwunel
|
||||
Type=notify
|
||||
@@ -63,3 +61,4 @@ StartLimitBurst=5
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
Alias=matrix-tuwunel.service
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@
|
||||
# If you're having trouble making the relevant changes, bug a maintainer.
|
||||
|
||||
[toolchain]
|
||||
channel = "1.86.0"
|
||||
channel = "1.91.1"
|
||||
profile = "minimal"
|
||||
components = [
|
||||
# For rust-analyzer
|
||||
|
||||
+10
-10
@@ -11,6 +11,7 @@ version.workspace = true
|
||||
|
||||
[lib]
|
||||
path = "mod.rs"
|
||||
bench = false
|
||||
crate-type = [
|
||||
"rlib",
|
||||
# "dylib",
|
||||
@@ -18,46 +19,46 @@ crate-type = [
|
||||
|
||||
[features]
|
||||
brotli_compression = [
|
||||
"tuwunel-api/brotli_compression",
|
||||
"tuwunel-core/brotli_compression",
|
||||
"tuwunel-service/brotli_compression",
|
||||
]
|
||||
bzip2_compression = [
|
||||
"tuwunel-database/bzip2_compression",
|
||||
"tuwunel-service/bzip2_compression",
|
||||
]
|
||||
gzip_compression = [
|
||||
"tuwunel-api/gzip_compression",
|
||||
"tuwunel-core/gzip_compression",
|
||||
"tuwunel-service/gzip_compression",
|
||||
]
|
||||
io_uring = [
|
||||
"tuwunel-api/io_uring",
|
||||
"tuwunel-database/io_uring",
|
||||
"tuwunel-service/io_uring",
|
||||
]
|
||||
jemalloc = [
|
||||
"tuwunel-api/jemalloc",
|
||||
"tuwunel-core/jemalloc",
|
||||
"tuwunel-database/jemalloc",
|
||||
"tuwunel-service/jemalloc",
|
||||
]
|
||||
jemalloc_conf = [
|
||||
"tuwunel-api/jemalloc_conf",
|
||||
"tuwunel-core/jemalloc_conf",
|
||||
"tuwunel-database/jemalloc_conf",
|
||||
"tuwunel-service/jemalloc_conf",
|
||||
]
|
||||
jemalloc_prof = [
|
||||
"tuwunel-api/jemalloc_prof",
|
||||
"tuwunel-core/jemalloc_prof",
|
||||
"tuwunel-database/jemalloc_prof",
|
||||
"tuwunel-service/jemalloc_prof",
|
||||
]
|
||||
jemalloc_stats = [
|
||||
"tuwunel-api/jemalloc_stats",
|
||||
"tuwunel-core/jemalloc_stats",
|
||||
"tuwunel-database/jemalloc_stats",
|
||||
"tuwunel-service/jemalloc_stats",
|
||||
]
|
||||
lz4_compression = [
|
||||
"tuwunel-database/lz4_compression",
|
||||
"tuwunel-service/lz4_compression",
|
||||
]
|
||||
release_max_log_level = [
|
||||
"tuwunel-api/release_max_log_level",
|
||||
"tuwunel-core/release_max_log_level",
|
||||
"tuwunel-database/release_max_log_level",
|
||||
"tuwunel-service/release_max_log_level",
|
||||
@@ -67,15 +68,14 @@ release_max_log_level = [
|
||||
"log/release_max_level_info",
|
||||
]
|
||||
zstd_compression = [
|
||||
"tuwunel-api/zstd_compression",
|
||||
"tuwunel-core/zstd_compression",
|
||||
"tuwunel-database/zstd_compression",
|
||||
"tuwunel-service/zstd_compression",
|
||||
]
|
||||
|
||||
[dependencies]
|
||||
base64.workspace = true
|
||||
clap.workspace = true
|
||||
tuwunel-api.workspace = true
|
||||
tuwunel-core.workspace = true
|
||||
tuwunel-database.workspace = true
|
||||
tuwunel-macros.workspace = true
|
||||
|
||||
+15
-9
@@ -2,10 +2,16 @@
|
||||
use tuwunel_core::Result;
|
||||
|
||||
use crate::{
|
||||
appservice, appservice::AppserviceCommand, check, check::CheckCommand, context::Context,
|
||||
debug, debug::DebugCommand, federation, federation::FederationCommand, media,
|
||||
media::MediaCommand, query, query::QueryCommand, room, room::RoomCommand, server,
|
||||
server::ServerCommand, user, user::UserCommand,
|
||||
appservice::{self, AppserviceCommand},
|
||||
context::Context,
|
||||
debug::{self, DebugCommand},
|
||||
federation::{self, FederationCommand},
|
||||
media::{self, MediaCommand},
|
||||
query::{self, QueryCommand},
|
||||
room::{self, RoomCommand},
|
||||
server::{self, ServerCommand},
|
||||
token::{self, TokenCommand},
|
||||
user::{self, UserCommand},
|
||||
};
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
@@ -35,10 +41,6 @@ pub(super) enum AdminCommand {
|
||||
/// - Commands for managing media
|
||||
Media(MediaCommand),
|
||||
|
||||
#[command(subcommand)]
|
||||
/// - Commands for checking integrity
|
||||
Check(CheckCommand),
|
||||
|
||||
#[command(subcommand)]
|
||||
/// - Commands for debugging things
|
||||
Debug(DebugCommand),
|
||||
@@ -46,6 +48,10 @@ pub(super) enum AdminCommand {
|
||||
#[command(subcommand)]
|
||||
/// - Low-level queries for database getters and iterators
|
||||
Query(QueryCommand),
|
||||
|
||||
#[command(subcommand)]
|
||||
/// - Commands for managing registration tokens
|
||||
Token(TokenCommand),
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all, name = "command")]
|
||||
@@ -61,6 +67,6 @@ pub(super) async fn process(command: AdminCommand, context: &Context<'_>) -> Res
|
||||
| Server(command) => server::process(command, context).await,
|
||||
| Debug(command) => debug::process(command, context).await,
|
||||
| Query(command) => query::process(command, context).await,
|
||||
| Check(command) => check::process(command, context).await,
|
||||
| Token(command) => token::process(command, context).await,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
use futures::StreamExt;
|
||||
use tuwunel_core::Result;
|
||||
use tuwunel_macros::implement;
|
||||
|
||||
use crate::Context;
|
||||
|
||||
/// Uses the iterator in `src/database/key_value/users.rs` to iterator over
|
||||
/// every user in our database (remote and local). Reports total count, any
|
||||
/// errors if there were any, etc
|
||||
#[implement(Context, params = "<'_>")]
|
||||
pub(super) async fn check_all_users(&self) -> Result {
|
||||
let timer = tokio::time::Instant::now();
|
||||
let users = self
|
||||
.services
|
||||
.users
|
||||
.iter()
|
||||
.collect::<Vec<_>>()
|
||||
.await;
|
||||
let query_time = timer.elapsed();
|
||||
|
||||
let total = users.len();
|
||||
let err_count = users.iter().filter(|_user| false).count();
|
||||
let ok_count = users.iter().filter(|_user| true).count();
|
||||
|
||||
self.write_str(&format!(
|
||||
"Database query completed in {query_time:?}:\n\n```\nTotal entries: \
|
||||
{total:?}\nFailure/Invalid user count: {err_count:?}\nSuccess/Valid user count: \
|
||||
{ok_count:?}\n```"
|
||||
))
|
||||
.await
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
mod commands;
|
||||
|
||||
use clap::Subcommand;
|
||||
use tuwunel_core::Result;
|
||||
|
||||
use crate::admin_command_dispatch;
|
||||
|
||||
#[admin_command_dispatch]
|
||||
#[derive(Debug, Subcommand)]
|
||||
pub(super) enum CheckCommand {
|
||||
CheckAllUsers,
|
||||
}
|
||||
@@ -23,14 +23,12 @@ pub(crate) fn write_fmt(
|
||||
arguments: fmt::Arguments<'_>,
|
||||
) -> impl Future<Output = Result> + Send + '_ + use<'_> {
|
||||
let buf = format!("{arguments}");
|
||||
self.output.lock().then(async move |mut output| {
|
||||
output
|
||||
.write_all(buf.as_bytes())
|
||||
.map_err(Into::into)
|
||||
.await
|
||||
})
|
||||
self.write_string(buf)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) async fn write_string(&self, s: String) -> Result { self.write_str(&s).await }
|
||||
|
||||
pub(crate) fn write_str<'a>(
|
||||
&'a self,
|
||||
s: &'a str,
|
||||
|
||||
+92
-88
@@ -28,10 +28,7 @@
|
||||
},
|
||||
warn,
|
||||
};
|
||||
use tuwunel_service::rooms::{
|
||||
short::{ShortEventId, ShortRoomId},
|
||||
state_compressor::HashSetCompressStateEvent,
|
||||
};
|
||||
use tuwunel_service::rooms::{short::ShortRoomId, state_compressor::HashSetCompressStateEvent};
|
||||
|
||||
use crate::admin_command;
|
||||
|
||||
@@ -45,7 +42,6 @@ pub(super) async fn echo(&self, message: Vec<String>) -> Result {
|
||||
pub(super) async fn get_auth_chain(&self, event_id: OwnedEventId) -> Result {
|
||||
let Ok(event) = self
|
||||
.services
|
||||
.rooms
|
||||
.timeline
|
||||
.get_pdu_json(&event_id)
|
||||
.await
|
||||
@@ -61,12 +57,17 @@ pub(super) async fn get_auth_chain(&self, event_id: OwnedEventId) -> Result {
|
||||
let room_id = <&RoomId>::try_from(room_id_str)
|
||||
.map_err(|_| err!(Database("Invalid room id field in event in database")))?;
|
||||
|
||||
let room_version = self
|
||||
.services
|
||||
.state
|
||||
.get_room_version(room_id)
|
||||
.await?;
|
||||
|
||||
let start = Instant::now();
|
||||
let count = self
|
||||
.services
|
||||
.rooms
|
||||
.auth_chain
|
||||
.event_ids_iter(room_id, once(event_id.as_ref()))
|
||||
.event_ids_iter(room_id, &room_version, once(event_id.as_ref()))
|
||||
.ready_filter_map(Result::ok)
|
||||
.count()
|
||||
.await;
|
||||
@@ -87,9 +88,12 @@ pub(super) async fn parse_pdu(&self) -> Result {
|
||||
}
|
||||
|
||||
let string = self.body[1..self.body.len().saturating_sub(1)].join("\n");
|
||||
let rules = RoomVersionId::V6
|
||||
.rules()
|
||||
.expect("rules for V6 rooms");
|
||||
match serde_json::from_str(&string) {
|
||||
| Err(e) => return Err!("Invalid json in command body: {e}"),
|
||||
| Ok(value) => match ruma::signatures::reference_hash(&value, &RoomVersionId::V6) {
|
||||
| Ok(value) => match ruma::signatures::reference_hash(&value, &rules) {
|
||||
| Err(e) => return Err!("Could not parse PDU JSON: {e:?}"),
|
||||
| Ok(hash) => {
|
||||
let event_id = OwnedEventId::parse(format!("${hash}"));
|
||||
@@ -108,7 +112,6 @@ pub(super) async fn get_pdu(&self, event_id: OwnedEventId) -> Result {
|
||||
let mut outlier = false;
|
||||
let mut pdu_json = self
|
||||
.services
|
||||
.rooms
|
||||
.timeline
|
||||
.get_non_outlier_pdu_json(&event_id)
|
||||
.await;
|
||||
@@ -117,7 +120,6 @@ pub(super) async fn get_pdu(&self, event_id: OwnedEventId) -> Result {
|
||||
outlier = true;
|
||||
pdu_json = self
|
||||
.services
|
||||
.rooms
|
||||
.timeline
|
||||
.get_pdu_json(&event_id)
|
||||
.await;
|
||||
@@ -139,20 +141,11 @@ pub(super) async fn get_pdu(&self, event_id: OwnedEventId) -> Result {
|
||||
}
|
||||
|
||||
#[admin_command]
|
||||
pub(super) async fn get_short_pdu(
|
||||
&self,
|
||||
shortroomid: ShortRoomId,
|
||||
shorteventid: ShortEventId,
|
||||
) -> Result {
|
||||
let pdu_id: RawPduId = PduId {
|
||||
shortroomid,
|
||||
shorteventid: shorteventid.into(),
|
||||
}
|
||||
.into();
|
||||
pub(super) async fn get_short_pdu(&self, shortroomid: ShortRoomId, count: i64) -> Result {
|
||||
let pdu_id: RawPduId = PduId { shortroomid, count: count.into() }.into();
|
||||
|
||||
let pdu_json = self
|
||||
.services
|
||||
.rooms
|
||||
.timeline
|
||||
.get_pdu_json_from_id(&pdu_id)
|
||||
.await;
|
||||
@@ -249,17 +242,17 @@ pub(super) async fn get_remote_pdu(
|
||||
|
||||
match self
|
||||
.services
|
||||
.sending
|
||||
.send_federation_request(&server, ruma::api::federation::event::get_event::v1::Request {
|
||||
.federation
|
||||
.execute(&server, ruma::api::federation::event::get_event::v1::Request {
|
||||
event_id: event_id.clone(),
|
||||
include_unredacted_content: None,
|
||||
})
|
||||
.await
|
||||
{
|
||||
| Err(e) =>
|
||||
| Err(e) => {
|
||||
return Err!(
|
||||
"Remote server did not have PDU or failed sending request to remote server: {e}"
|
||||
),
|
||||
);
|
||||
},
|
||||
| Ok(response) => {
|
||||
let json: CanonicalJsonObject =
|
||||
serde_json::from_str(response.pdu.get()).map_err(|e| {
|
||||
@@ -273,32 +266,28 @@ pub(super) async fn get_remote_pdu(
|
||||
})?;
|
||||
|
||||
trace!("Attempting to parse PDU: {:?}", &response.pdu);
|
||||
let _parsed_pdu = {
|
||||
let (room_id, ..) = {
|
||||
let parsed_result = self
|
||||
.services
|
||||
.rooms
|
||||
.event_handler
|
||||
.parse_incoming_pdu(&response.pdu)
|
||||
.boxed()
|
||||
.await;
|
||||
|
||||
let (event_id, value, room_id) = match parsed_result {
|
||||
match parsed_result {
|
||||
| Ok(t) => t,
|
||||
| Err(e) => {
|
||||
warn!("Failed to parse PDU: {e}");
|
||||
info!("Full PDU: {:?}", &response.pdu);
|
||||
return Err!("Failed to parse PDU remote server {server} sent us: {e}");
|
||||
},
|
||||
};
|
||||
|
||||
vec![(event_id, value, room_id)]
|
||||
}
|
||||
};
|
||||
|
||||
info!("Attempting to handle event ID {event_id} as backfilled PDU");
|
||||
self.services
|
||||
.rooms
|
||||
.timeline
|
||||
.backfill_pdu(&server, response.pdu)
|
||||
.backfill_pdu(&room_id, &server, response.pdu)
|
||||
.await?;
|
||||
|
||||
let text = serde_json::to_string_pretty(&json)?;
|
||||
@@ -311,10 +300,9 @@ pub(super) async fn get_remote_pdu(
|
||||
|
||||
#[admin_command]
|
||||
pub(super) async fn get_room_state(&self, room: OwnedRoomOrAliasId) -> Result {
|
||||
let room_id = self.services.rooms.alias.resolve(&room).await?;
|
||||
let room_id = self.services.alias.maybe_resolve(&room).await?;
|
||||
let room_state: Vec<Raw<AnyStateEvent>> = self
|
||||
.services
|
||||
.rooms
|
||||
.state_accessor
|
||||
.room_state_full_pdus(&room_id)
|
||||
.map_ok(Event::into_format)
|
||||
@@ -346,11 +334,8 @@ pub(super) async fn ping(&self, server: OwnedServerName) -> Result {
|
||||
|
||||
match self
|
||||
.services
|
||||
.sending
|
||||
.send_federation_request(
|
||||
&server,
|
||||
ruma::api::federation::discovery::get_server_version::v1::Request {},
|
||||
)
|
||||
.federation
|
||||
.execute(&server, ruma::api::federation::discovery::get_server_version::v1::Request {})
|
||||
.await
|
||||
{
|
||||
| Err(e) => {
|
||||
@@ -405,8 +390,9 @@ pub(super) async fn change_log_level(&self, filter: Option<String>, reset: bool)
|
||||
.reload
|
||||
.reload(&old_filter_layer, Some(handles))
|
||||
{
|
||||
| Err(e) =>
|
||||
return Err!("Failed to modify and reload the global tracing log level: {e}"),
|
||||
| Err(e) => {
|
||||
return Err!("Failed to modify and reload the global tracing log level: {e}");
|
||||
},
|
||||
| Ok(()) => {
|
||||
let value = &self.services.server.config.log;
|
||||
let out = format!("Successfully changed log level back to config value {value}");
|
||||
@@ -428,12 +414,14 @@ pub(super) async fn change_log_level(&self, filter: Option<String>, reset: bool)
|
||||
.reload
|
||||
.reload(&new_filter_layer, Some(handles))
|
||||
{
|
||||
| Ok(()) =>
|
||||
| Ok(()) => {
|
||||
return self
|
||||
.write_str("Successfully changed log level")
|
||||
.await,
|
||||
| Err(e) =>
|
||||
return Err!("Failed to modify and reload the global tracing log level: {e}"),
|
||||
.await;
|
||||
},
|
||||
| Err(e) => {
|
||||
return Err!("Failed to modify and reload the global tracing log level: {e}");
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -492,7 +480,6 @@ pub(super) async fn verify_pdu(&self, event_id: OwnedEventId) -> Result {
|
||||
|
||||
let mut event = self
|
||||
.services
|
||||
.rooms
|
||||
.timeline
|
||||
.get_pdu_json(&event_id)
|
||||
.await?;
|
||||
@@ -517,7 +504,6 @@ pub(super) async fn verify_pdu(&self, event_id: OwnedEventId) -> Result {
|
||||
pub(super) async fn first_pdu_in_room(&self, room_id: OwnedRoomId) -> Result {
|
||||
if !self
|
||||
.services
|
||||
.rooms
|
||||
.state_cache
|
||||
.server_in_room(&self.services.server.name, &room_id)
|
||||
.await
|
||||
@@ -527,7 +513,6 @@ pub(super) async fn first_pdu_in_room(&self, room_id: OwnedRoomId) -> Result {
|
||||
|
||||
let first_pdu = self
|
||||
.services
|
||||
.rooms
|
||||
.timeline
|
||||
.first_pdu_in_room(&room_id)
|
||||
.await
|
||||
@@ -542,7 +527,6 @@ pub(super) async fn first_pdu_in_room(&self, room_id: OwnedRoomId) -> Result {
|
||||
pub(super) async fn latest_pdu_in_room(&self, room_id: OwnedRoomId) -> Result {
|
||||
if !self
|
||||
.services
|
||||
.rooms
|
||||
.state_cache
|
||||
.server_in_room(&self.services.server.name, &room_id)
|
||||
.await
|
||||
@@ -552,7 +536,6 @@ pub(super) async fn latest_pdu_in_room(&self, room_id: OwnedRoomId) -> Result {
|
||||
|
||||
let latest_pdu = self
|
||||
.services
|
||||
.rooms
|
||||
.timeline
|
||||
.latest_pdu_in_room(&room_id)
|
||||
.await
|
||||
@@ -571,7 +554,6 @@ pub(super) async fn force_set_room_state_from_server(
|
||||
) -> Result {
|
||||
if !self
|
||||
.services
|
||||
.rooms
|
||||
.state_cache
|
||||
.server_in_room(&self.services.server.name, &room_id)
|
||||
.await
|
||||
@@ -581,7 +563,6 @@ pub(super) async fn force_set_room_state_from_server(
|
||||
|
||||
let first_pdu = self
|
||||
.services
|
||||
.rooms
|
||||
.timeline
|
||||
.latest_pdu_in_room(&room_id)
|
||||
.await
|
||||
@@ -589,7 +570,6 @@ pub(super) async fn force_set_room_state_from_server(
|
||||
|
||||
let room_version = self
|
||||
.services
|
||||
.rooms
|
||||
.state
|
||||
.get_room_version(&room_id)
|
||||
.await?;
|
||||
@@ -598,8 +578,8 @@ pub(super) async fn force_set_room_state_from_server(
|
||||
|
||||
let remote_state_response = self
|
||||
.services
|
||||
.sending
|
||||
.send_federation_request(&server_name, get_room_state::v1::Request {
|
||||
.federation
|
||||
.execute(&server_name, get_room_state::v1::Request {
|
||||
room_id: room_id.clone(),
|
||||
event_id: first_pdu.event_id().to_owned(),
|
||||
})
|
||||
@@ -608,7 +588,6 @@ pub(super) async fn force_set_room_state_from_server(
|
||||
for pdu in remote_state_response.pdus.clone() {
|
||||
match self
|
||||
.services
|
||||
.rooms
|
||||
.event_handler
|
||||
.parse_incoming_pdu(&pdu)
|
||||
.await
|
||||
@@ -627,24 +606,33 @@ pub(super) async fn force_set_room_state_from_server(
|
||||
.server_keys
|
||||
.validate_and_add_event_id(pdu, &room_version)
|
||||
}) {
|
||||
let Ok((event_id, value)) = result.await else {
|
||||
let Ok((event_id, mut value)) = result.await else {
|
||||
continue;
|
||||
};
|
||||
|
||||
let pdu = PduEvent::from_id_val(&event_id, value.clone()).map_err(|e| {
|
||||
let invalid_pdu_err = |e| {
|
||||
debug_error!("Invalid PDU in fetching remote room state PDUs response: {value:#?}");
|
||||
err!(BadServerResponse(debug_error!("Invalid PDU in send_join response: {e:?}")))
|
||||
})?;
|
||||
};
|
||||
|
||||
let pdu = if value["type"] == "m.room.create" {
|
||||
PduEvent::from_rid_val(&room_id, &event_id, value.clone()).map_err(invalid_pdu_err)?
|
||||
} else {
|
||||
PduEvent::from_id_val(&event_id, value.clone()).map_err(invalid_pdu_err)?
|
||||
};
|
||||
|
||||
if !value.contains_key("room_id") {
|
||||
let room_id = CanonicalJsonValue::String(room_id.as_str().into());
|
||||
value.insert("room_id".into(), room_id);
|
||||
}
|
||||
|
||||
self.services
|
||||
.rooms
|
||||
.outlier
|
||||
.timeline
|
||||
.add_pdu_outlier(&event_id, &value);
|
||||
|
||||
if let Some(state_key) = &pdu.state_key {
|
||||
let shortstatekey = self
|
||||
.services
|
||||
.rooms
|
||||
.short
|
||||
.get_or_create_shortstatekey(&pdu.kind.to_string().into(), state_key)
|
||||
.await;
|
||||
@@ -667,14 +655,12 @@ pub(super) async fn force_set_room_state_from_server(
|
||||
};
|
||||
|
||||
self.services
|
||||
.rooms
|
||||
.outlier
|
||||
.timeline
|
||||
.add_pdu_outlier(&event_id, &value);
|
||||
}
|
||||
|
||||
let new_room_state = self
|
||||
.services
|
||||
.rooms
|
||||
.event_handler
|
||||
.resolve_state(&room_id, &room_version, state)
|
||||
.await?;
|
||||
@@ -686,21 +672,13 @@ pub(super) async fn force_set_room_state_from_server(
|
||||
removed,
|
||||
} = self
|
||||
.services
|
||||
.rooms
|
||||
.state_compressor
|
||||
.save_state(room_id.clone().as_ref(), new_room_state)
|
||||
.await?;
|
||||
|
||||
let state_lock = self
|
||||
.services
|
||||
.rooms
|
||||
.state
|
||||
.mutex
|
||||
.lock(&*room_id)
|
||||
.await;
|
||||
let state_lock = self.services.state.mutex.lock(&*room_id).await;
|
||||
|
||||
self.services
|
||||
.rooms
|
||||
.state
|
||||
.force_state(room_id.clone().as_ref(), short_state_hash, added, removed, &state_lock)
|
||||
.await?;
|
||||
@@ -710,7 +688,6 @@ pub(super) async fn force_set_room_state_from_server(
|
||||
the room's m.room.member state"
|
||||
);
|
||||
self.services
|
||||
.rooms
|
||||
.state_cache
|
||||
.update_joined_count(&room_id)
|
||||
.await;
|
||||
@@ -937,7 +914,7 @@ pub(super) async fn database_files(&self, map: Option<String>, level: Option<i32
|
||||
let mut files: Vec<_> = self
|
||||
.services
|
||||
.db
|
||||
.db
|
||||
.engine
|
||||
.file_list()
|
||||
.collect::<Result<_>>()?;
|
||||
|
||||
@@ -993,10 +970,10 @@ pub(super) async fn create_jwt(
|
||||
#[derive(Serialize)]
|
||||
struct Claim {
|
||||
sub: String,
|
||||
iss: String,
|
||||
aud: String,
|
||||
exp: usize,
|
||||
nbf: usize,
|
||||
iss: Option<String>,
|
||||
aud: Option<String>,
|
||||
exp: Option<usize>,
|
||||
nbf: Option<usize>,
|
||||
}
|
||||
|
||||
let config = &self.services.config.jwt;
|
||||
@@ -1013,21 +990,19 @@ struct Claim {
|
||||
let claim = Claim {
|
||||
sub: user,
|
||||
|
||||
iss: issuer.unwrap_or_default(),
|
||||
iss: issuer,
|
||||
|
||||
aud: audience.unwrap_or_default(),
|
||||
aud: audience,
|
||||
|
||||
exp: exp_from_now
|
||||
.and_then(|val| now_secs().checked_add(val))
|
||||
.map(TryInto::try_into)
|
||||
.and_then(Result::ok)
|
||||
.unwrap_or(usize::MAX),
|
||||
.and_then(Result::ok),
|
||||
|
||||
nbf: nbf_from_now
|
||||
.and_then(|val| now_secs().checked_add(val))
|
||||
.map(TryInto::try_into)
|
||||
.and_then(Result::ok)
|
||||
.unwrap_or(0),
|
||||
.and_then(Result::ok),
|
||||
};
|
||||
|
||||
encode(&header, &claim, &key)
|
||||
@@ -1035,3 +1010,32 @@ struct Claim {
|
||||
.map(async |token| self.write_str(&token).await)?
|
||||
.await
|
||||
}
|
||||
|
||||
#[admin_command]
|
||||
pub(super) async fn resync_database(&self) -> Result {
|
||||
if !self.services.db.is_secondary() {
|
||||
return Err!("Not a secondary instance.");
|
||||
}
|
||||
|
||||
self.services
|
||||
.db
|
||||
.engine
|
||||
.update()
|
||||
.map_err(|e| err!("Failed to update from primary: {e:?}"))
|
||||
}
|
||||
|
||||
#[admin_command]
|
||||
pub(super) async fn get_retained_pdu(&self, event_id: OwnedEventId) -> Result {
|
||||
let pdu = self
|
||||
.services
|
||||
.retention
|
||||
.get_original_pdu_json(&event_id)
|
||||
.await?;
|
||||
|
||||
let text = serde_json::to_string_pretty(&pdu)?;
|
||||
|
||||
self.write_str(&format!("Original PDU:\n```json\n{text}\n```"))
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
+13
-15
@@ -4,7 +4,7 @@
|
||||
use clap::Subcommand;
|
||||
use ruma::{OwnedEventId, OwnedRoomId, OwnedRoomOrAliasId, OwnedServerName};
|
||||
use tuwunel_core::Result;
|
||||
use tuwunel_service::rooms::short::{ShortEventId, ShortRoomId};
|
||||
use tuwunel_service::rooms::short::ShortRoomId;
|
||||
|
||||
use self::tester::TesterCommand;
|
||||
use crate::admin_command_dispatch;
|
||||
@@ -43,8 +43,8 @@ pub(super) enum DebugCommand {
|
||||
/// Shortroomid integer
|
||||
shortroomid: ShortRoomId,
|
||||
|
||||
/// Shorteventid integer
|
||||
shorteventid: ShortEventId,
|
||||
/// PduCount integer
|
||||
count: i64,
|
||||
},
|
||||
|
||||
/// - Attempts to retrieve a PDU from a remote server. Inserts it into our
|
||||
@@ -72,15 +72,6 @@ pub(super) enum DebugCommand {
|
||||
},
|
||||
|
||||
/// - Gets all the room state events for the specified room.
|
||||
///
|
||||
/// This is functionally equivalent to `GET
|
||||
/// /_matrix/client/v3/rooms/{roomid}/state`, except the admin command does
|
||||
/// *not* check if the sender user is allowed to see state events. This is
|
||||
/// done because it's implied that server admins here have database access
|
||||
/// and can see/get room info themselves anyways if they were malicious
|
||||
/// admins.
|
||||
///
|
||||
/// Of course the check is still done on the actual client API.
|
||||
GetRoomState {
|
||||
/// Room ID
|
||||
room_id: OwnedRoomOrAliasId,
|
||||
@@ -125,13 +116,13 @@ pub(super) enum DebugCommand {
|
||||
reset: bool,
|
||||
},
|
||||
|
||||
/// - Verify json signatures
|
||||
/// - Sign JSON blob
|
||||
///
|
||||
/// This command needs a JSON blob provided in a Markdown code block below
|
||||
/// the command.
|
||||
SignJson,
|
||||
|
||||
/// - Verify json signatures
|
||||
/// - Verify JSON signatures
|
||||
///
|
||||
/// This command needs a JSON blob provided in a Markdown code block below
|
||||
/// the command.
|
||||
@@ -256,9 +247,16 @@ pub(super) enum DebugCommand {
|
||||
audience: Option<String>,
|
||||
},
|
||||
|
||||
/// - Synchronize database with primary (secondary only)
|
||||
ResyncDatabase,
|
||||
|
||||
/// - Retrieves the saved original PDU before it has been redacted
|
||||
GetRetainedPdu {
|
||||
event_id: OwnedEventId,
|
||||
},
|
||||
|
||||
/// - Developer test stubs
|
||||
#[command(subcommand)]
|
||||
#[allow(non_snake_case)]
|
||||
#[clap(hide(true))]
|
||||
Tester(TesterCommand),
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ async fn timer(&self) -> Result {
|
||||
|
||||
#[inline(never)]
|
||||
#[rustfmt::skip]
|
||||
#[allow(unused_variables)]
|
||||
#[expect(unused_variables)]
|
||||
fn timed(body: &[&str]) {
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
use std::fmt::Write;
|
||||
|
||||
use futures::StreamExt;
|
||||
use ruma::{OwnedRoomId, OwnedServerName, OwnedUserId};
|
||||
use tuwunel_core::{Err, Result};
|
||||
@@ -8,43 +6,19 @@
|
||||
|
||||
#[admin_command]
|
||||
pub(super) async fn disable_room(&self, room_id: OwnedRoomId) -> Result {
|
||||
self.services
|
||||
.rooms
|
||||
.metadata
|
||||
.disable_room(&room_id, true);
|
||||
self.services.metadata.disable_room(&room_id);
|
||||
self.write_str("Room disabled.").await
|
||||
}
|
||||
|
||||
#[admin_command]
|
||||
pub(super) async fn enable_room(&self, room_id: OwnedRoomId) -> Result {
|
||||
self.services
|
||||
.rooms
|
||||
.metadata
|
||||
.disable_room(&room_id, false);
|
||||
self.services.metadata.enable_room(&room_id);
|
||||
self.write_str("Room enabled.").await
|
||||
}
|
||||
|
||||
#[admin_command]
|
||||
pub(super) async fn incoming_federation(&self) -> Result {
|
||||
let msg = {
|
||||
let map = self
|
||||
.services
|
||||
.rooms
|
||||
.event_handler
|
||||
.federation_handletime
|
||||
.read()
|
||||
.expect("locked");
|
||||
|
||||
let mut msg = format!("Handling {} incoming pdus:\n", map.len());
|
||||
for (r, (e, i)) in map.iter() {
|
||||
let elapsed = i.elapsed();
|
||||
writeln!(msg, "{} {}: {}m{}s", r, e, elapsed.as_secs() / 60, elapsed.as_secs() % 60)?;
|
||||
}
|
||||
|
||||
msg
|
||||
};
|
||||
|
||||
self.write_str(&msg).await
|
||||
Err!("This command is temporarily disabled")
|
||||
}
|
||||
|
||||
#[admin_command]
|
||||
@@ -102,7 +76,6 @@ pub(super) async fn remote_user_in_rooms(&self, user_id: OwnedUserId) -> Result
|
||||
|
||||
let mut rooms: Vec<(OwnedRoomId, u64, String)> = self
|
||||
.services
|
||||
.rooms
|
||||
.state_cache
|
||||
.rooms_joined(&user_id)
|
||||
.then(|room_id| get_room_info(self.services, room_id))
|
||||
|
||||
@@ -37,7 +37,6 @@ pub(super) async fn delete(
|
||||
// parsing the PDU for any MXC URLs begins here
|
||||
match self
|
||||
.services
|
||||
.rooms
|
||||
.timeline
|
||||
.get_pdu_json(&event_id)
|
||||
.await
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#![allow(rustdoc::broken_intra_doc_links)]
|
||||
#![expect(rustdoc::broken_intra_doc_links)]
|
||||
mod commands;
|
||||
|
||||
use clap::Subcommand;
|
||||
@@ -90,10 +90,10 @@ pub(super) enum MediaCommand {
|
||||
#[arg(short, long, default_value("10000"))]
|
||||
timeout: u32,
|
||||
|
||||
#[arg(short, long, default_value("800"))]
|
||||
#[arg(long, default_value("800"))]
|
||||
width: u32,
|
||||
|
||||
#[arg(short, long, default_value("800"))]
|
||||
#[arg(long, default_value("800"))]
|
||||
height: u32,
|
||||
},
|
||||
}
|
||||
|
||||
+4
-5
@@ -1,7 +1,4 @@
|
||||
#![recursion_limit = "192"]
|
||||
#![allow(clippy::wildcard_imports)]
|
||||
#![allow(clippy::enum_glob_use)]
|
||||
#![allow(clippy::too_many_arguments)]
|
||||
#![expect(clippy::too_many_arguments)]
|
||||
|
||||
pub(crate) mod admin;
|
||||
pub(crate) mod context;
|
||||
@@ -10,13 +7,13 @@
|
||||
pub(crate) mod utils;
|
||||
|
||||
pub(crate) mod appservice;
|
||||
pub(crate) mod check;
|
||||
pub(crate) mod debug;
|
||||
pub(crate) mod federation;
|
||||
pub(crate) mod media;
|
||||
pub(crate) mod query;
|
||||
pub(crate) mod room;
|
||||
pub(crate) mod server;
|
||||
pub(crate) mod token;
|
||||
pub(crate) mod user;
|
||||
|
||||
pub(crate) use tuwunel_macros::{admin_command, admin_command_dispatch};
|
||||
@@ -25,6 +22,8 @@
|
||||
|
||||
pub(crate) const PAGE_SIZE: usize = 100;
|
||||
|
||||
use log as _;
|
||||
|
||||
tuwunel_core::mod_ctor! {}
|
||||
tuwunel_core::mod_dtor! {}
|
||||
tuwunel_core::rustc_flags_capture! {}
|
||||
|
||||
@@ -54,7 +54,7 @@ async fn handle_command(services: Arc<Services>, command: CommandInput) -> Proce
|
||||
|
||||
async fn process_command(services: Arc<Services>, input: &CommandInput) -> ProcessorResult {
|
||||
let (command, args, body) = match parse(&services, input) {
|
||||
| Err(error) => return Err(error),
|
||||
| Err(error) => return Err(Box::new(error)),
|
||||
| Ok(parsed) => parsed,
|
||||
};
|
||||
|
||||
@@ -90,12 +90,14 @@ async fn process_command(services: Arc<Services>, input: &CommandInput) -> Proce
|
||||
write!(&mut logs, "Command failed with error:\n```\n{error:#?}\n```")
|
||||
.expect("output buffer");
|
||||
|
||||
Err(reply(RoomMessageEventContent::notice_markdown(logs), context.reply_id))
|
||||
Err(Box::new(reply(
|
||||
RoomMessageEventContent::notice_markdown(logs),
|
||||
context.reply_id,
|
||||
)))
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::result_large_err)]
|
||||
fn handle_panic(error: &Error, command: &CommandInput) -> ProcessorResult {
|
||||
let link =
|
||||
"Please submit a [bug report](https://github.com/matrix-construct/tuwunel/issues/new). \
|
||||
@@ -103,7 +105,7 @@ fn handle_panic(error: &Error, command: &CommandInput) -> ProcessorResult {
|
||||
let msg = format!("Panic occurred while processing command:\n```\n{error:#?}\n```\n{link}");
|
||||
let content = RoomMessageEventContent::notice_markdown(msg);
|
||||
error!("Panic while processing command: {error:?}");
|
||||
Err(reply(content, command.reply_id.as_deref()))
|
||||
Err(Box::new(reply(content, command.reply_id.as_deref())))
|
||||
}
|
||||
|
||||
/// Parse and process a message from the admin room
|
||||
@@ -171,7 +173,7 @@ fn capture_create(context: &Context<'_>) -> (Arc<Capture>, Arc<Mutex<String>>) {
|
||||
}
|
||||
|
||||
/// Parse chat messages from the admin room into an AdminCommand object
|
||||
#[allow(clippy::result_large_err)]
|
||||
#[expect(clippy::result_large_err)]
|
||||
fn parse<'a>(
|
||||
services: &Arc<Services>,
|
||||
input: &'a CommandInput,
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
use futures::StreamExt;
|
||||
use ruma::{OwnedRoomId, OwnedUserId};
|
||||
use tuwunel_core::Result;
|
||||
use tuwunel_database::Deserialized;
|
||||
|
||||
use crate::{admin_command, admin_command_dispatch};
|
||||
|
||||
@@ -46,7 +47,7 @@ async fn changes_since(
|
||||
.await;
|
||||
let query_time = timer.elapsed();
|
||||
|
||||
self.write_str(&format!("Query completed in {query_time:?}:\n\n```rs\n{results:#?}\n```"))
|
||||
self.write_str(&format!("Query completed in {query_time:?}:\n\n```rs\n{results:?}\n```"))
|
||||
.await
|
||||
}
|
||||
|
||||
@@ -58,11 +59,12 @@ async fn account_data_get(
|
||||
room_id: Option<OwnedRoomId>,
|
||||
) -> Result {
|
||||
let timer = tokio::time::Instant::now();
|
||||
let results = self
|
||||
let results: serde_json::Value = self
|
||||
.services
|
||||
.account_data
|
||||
.get_raw(room_id.as_deref(), &user_id, &kind)
|
||||
.await;
|
||||
.await
|
||||
.deserialized()?;
|
||||
let query_time = timer.elapsed();
|
||||
|
||||
self.write_str(&format!("Query completed in {query_time:?}:\n\n```rs\n{results:#?}\n```"))
|
||||
|
||||
@@ -32,7 +32,7 @@ pub(super) async fn process(subcommand: GlobalsCommand, context: &Context<'_>) -
|
||||
},
|
||||
| GlobalsCommand::CurrentCount => {
|
||||
let timer = tokio::time::Instant::now();
|
||||
let results = services.globals.db.current_count();
|
||||
let results = services.globals.current_count();
|
||||
let query_time = timer.elapsed();
|
||||
|
||||
write!(context, "Query completed in {query_time:?}:\n\n```rs\n{results:#?}\n```")
|
||||
|
||||
+14
-4
@@ -1,6 +1,7 @@
|
||||
mod account_data;
|
||||
mod appservice;
|
||||
mod globals;
|
||||
mod oauth;
|
||||
mod presence;
|
||||
mod pusher;
|
||||
mod raw;
|
||||
@@ -10,6 +11,7 @@
|
||||
mod room_timeline;
|
||||
mod sending;
|
||||
mod short;
|
||||
mod sync;
|
||||
mod users;
|
||||
|
||||
use clap::Subcommand;
|
||||
@@ -17,10 +19,10 @@
|
||||
|
||||
use self::{
|
||||
account_data::AccountDataCommand, appservice::AppserviceCommand, globals::GlobalsCommand,
|
||||
presence::PresenceCommand, pusher::PusherCommand, raw::RawCommand, resolver::ResolverCommand,
|
||||
room_alias::RoomAliasCommand, room_state_cache::RoomStateCacheCommand,
|
||||
room_timeline::RoomTimelineCommand, sending::SendingCommand, short::ShortCommand,
|
||||
users::UsersCommand,
|
||||
oauth::OauthCommand, presence::PresenceCommand, pusher::PusherCommand, raw::RawCommand,
|
||||
resolver::ResolverCommand, room_alias::RoomAliasCommand,
|
||||
room_state_cache::RoomStateCacheCommand, room_timeline::RoomTimelineCommand,
|
||||
sending::SendingCommand, short::ShortCommand, sync::SyncCommand, users::UsersCommand,
|
||||
};
|
||||
use crate::admin_command_dispatch;
|
||||
|
||||
@@ -76,6 +78,14 @@ pub(super) enum QueryCommand {
|
||||
#[command(subcommand)]
|
||||
Short(ShortCommand),
|
||||
|
||||
/// - sync service
|
||||
#[command(subcommand)]
|
||||
Sync(SyncCommand),
|
||||
|
||||
/// - oauth service
|
||||
#[command(subcommand)]
|
||||
Oauth(OauthCommand),
|
||||
|
||||
/// - raw service
|
||||
#[command(subcommand)]
|
||||
Raw(RawCommand),
|
||||
|
||||
@@ -0,0 +1,300 @@
|
||||
use clap::Subcommand;
|
||||
use futures::{StreamExt, TryStreamExt};
|
||||
use ruma::OwnedUserId;
|
||||
use tuwunel_core::{
|
||||
Err, Result, apply,
|
||||
either::{Either, Left, Right},
|
||||
err,
|
||||
itertools::Itertools,
|
||||
utils::stream::{IterStream, ReadyExt},
|
||||
};
|
||||
use tuwunel_service::oauth::{Provider, ProviderId, SessionId};
|
||||
|
||||
use crate::{admin_command, admin_command_dispatch};
|
||||
|
||||
#[admin_command_dispatch(handler_prefix = "oauth")]
|
||||
#[derive(Debug, Subcommand)]
|
||||
/// Query OAuth service state
|
||||
pub(crate) enum OauthCommand {
|
||||
/// Associate existing user with future authorization claims.
|
||||
Associate {
|
||||
/// ID of configured provider to listen on.
|
||||
provider: String,
|
||||
|
||||
/// MXID of local user to associate.
|
||||
user_id: OwnedUserId,
|
||||
|
||||
/// List of claims to match in key=value format.
|
||||
#[arg(long, required = true)]
|
||||
claim: Vec<String>,
|
||||
},
|
||||
|
||||
/// List configured OAuth providers.
|
||||
ListProviders,
|
||||
|
||||
/// List users associated with any OAuth session
|
||||
ListUsers,
|
||||
|
||||
/// List session ID's
|
||||
ListSessions {
|
||||
#[arg(long)]
|
||||
user: Option<OwnedUserId>,
|
||||
},
|
||||
|
||||
/// Show active configuration of a provider.
|
||||
ShowProvider {
|
||||
id: ProviderId,
|
||||
|
||||
#[arg(long)]
|
||||
config: bool,
|
||||
},
|
||||
|
||||
/// Show session state
|
||||
ShowSession {
|
||||
id: SessionId,
|
||||
},
|
||||
|
||||
/// Show user sessions
|
||||
ShowUser {
|
||||
user_id: OwnedUserId,
|
||||
},
|
||||
|
||||
/// Token introspection request to provider.
|
||||
TokenInfo {
|
||||
id: SessionId,
|
||||
},
|
||||
|
||||
/// Revoke token for user_id or sess_id.
|
||||
Revoke {
|
||||
#[arg(value_parser = session_or_user_id)]
|
||||
id: Either<SessionId, OwnedUserId>,
|
||||
},
|
||||
|
||||
/// Remove oauth state (DANGER!)
|
||||
Delete {
|
||||
#[arg(value_parser = session_or_user_id)]
|
||||
id: Either<SessionId, OwnedUserId>,
|
||||
|
||||
#[arg(long)]
|
||||
force: bool,
|
||||
},
|
||||
}
|
||||
|
||||
type SessionOrUserId = Either<SessionId, OwnedUserId>;
|
||||
|
||||
fn session_or_user_id(input: &str) -> Result<SessionOrUserId> {
|
||||
OwnedUserId::parse(input)
|
||||
.map(Right)
|
||||
.or_else(|_| Ok(Left(input.to_owned())))
|
||||
}
|
||||
|
||||
#[admin_command]
|
||||
pub(super) async fn oauth_associate(
|
||||
&self,
|
||||
provider: String,
|
||||
user_id: OwnedUserId,
|
||||
claim: Vec<String>,
|
||||
) -> Result {
|
||||
if !self.services.globals.user_is_local(&user_id) {
|
||||
return Err!(Request(NotFound("User {user_id:?} does not belong to this server.")));
|
||||
}
|
||||
|
||||
if !self.services.users.exists(&user_id).await {
|
||||
return Err!(Request(NotFound("User {user_id:?} is not registered")));
|
||||
}
|
||||
|
||||
let provider = self
|
||||
.services
|
||||
.oauth
|
||||
.providers
|
||||
.get(&provider)
|
||||
.await?;
|
||||
|
||||
let claim = claim
|
||||
.iter()
|
||||
.map(|kv| {
|
||||
let (key, val) = kv
|
||||
.split_once('=')
|
||||
.ok_or_else(|| err!("Missing '=' in --claim {kv}=???"))?;
|
||||
|
||||
if !key.is_empty() && !val.is_empty() {
|
||||
Ok((key, val))
|
||||
} else {
|
||||
Err!("Missing key or value in --claim=key=value argument")
|
||||
}
|
||||
})
|
||||
.map_ok(apply!(2, ToOwned::to_owned))
|
||||
.collect::<Result<_>>()?;
|
||||
|
||||
let _replaced = self
|
||||
.services
|
||||
.oauth
|
||||
.sessions
|
||||
.set_user_association_pending(provider.id(), &user_id, claim);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[admin_command]
|
||||
pub(super) async fn oauth_list_providers(&self) -> Result {
|
||||
self.services
|
||||
.config
|
||||
.identity_provider
|
||||
.values()
|
||||
.try_stream()
|
||||
.map_ok(Provider::id)
|
||||
.map_ok(|id| format!("{id}\n"))
|
||||
.try_for_each(async |id| self.write_str(&id).await)
|
||||
.await
|
||||
}
|
||||
|
||||
#[admin_command]
|
||||
pub(super) async fn oauth_list_users(&self) -> Result {
|
||||
self.services
|
||||
.oauth
|
||||
.sessions
|
||||
.users()
|
||||
.map(|id| format!("{id}\n"))
|
||||
.map(Ok)
|
||||
.try_for_each(async |id: String| self.write_str(&id).await)
|
||||
.await
|
||||
}
|
||||
|
||||
#[admin_command]
|
||||
pub(super) async fn oauth_list_sessions(&self, user_id: Option<OwnedUserId>) -> Result {
|
||||
if let Some(user_id) = user_id.as_deref() {
|
||||
return self
|
||||
.services
|
||||
.oauth
|
||||
.sessions
|
||||
.get_sess_id_by_user(user_id)
|
||||
.map_ok(|id| format!("{id}\n"))
|
||||
.try_for_each(async |id: String| self.write_str(&id).await)
|
||||
.await;
|
||||
}
|
||||
|
||||
self.services
|
||||
.oauth
|
||||
.sessions
|
||||
.stream()
|
||||
.ready_filter_map(|sess| sess.sess_id)
|
||||
.map(|sess_id| format!("{sess_id:?}\n"))
|
||||
.for_each(async |id: String| {
|
||||
self.write_str(&id).await.ok();
|
||||
})
|
||||
.await;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[admin_command]
|
||||
pub(super) async fn oauth_show_provider(&self, id: ProviderId, config: bool) -> Result {
|
||||
if config {
|
||||
let config = self.services.oauth.providers.get_config(&id)?;
|
||||
|
||||
self.write_str(&format!("{config:#?}\n")).await?;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let provider = self.services.oauth.providers.get(&id).await?;
|
||||
|
||||
self.write_str(&format!("{provider:#?}\n")).await
|
||||
}
|
||||
|
||||
#[admin_command]
|
||||
pub(super) async fn oauth_show_session(&self, id: SessionId) -> Result {
|
||||
let session = self.services.oauth.sessions.get(&id).await?;
|
||||
|
||||
self.write_str(&format!("{session:#?}\n")).await
|
||||
}
|
||||
|
||||
#[admin_command]
|
||||
pub(super) async fn oauth_show_user(&self, user_id: OwnedUserId) -> Result {
|
||||
self.services
|
||||
.oauth
|
||||
.sessions
|
||||
.get_sess_id_by_user(&user_id)
|
||||
.try_for_each(async |id| {
|
||||
let session = self.services.oauth.sessions.get(&id).await?;
|
||||
|
||||
self.write_str(&format!("{session:#?}\n")).await
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
#[admin_command]
|
||||
pub(super) async fn oauth_token_info(&self, id: SessionId) -> Result {
|
||||
let session = self.services.oauth.sessions.get(&id).await?;
|
||||
|
||||
let provider = self
|
||||
.services
|
||||
.oauth
|
||||
.sessions
|
||||
.provider(&session)
|
||||
.await?;
|
||||
|
||||
let tokeninfo = self
|
||||
.services
|
||||
.oauth
|
||||
.request_tokeninfo((&provider, &session))
|
||||
.await?;
|
||||
|
||||
self.write_str(&format!("{tokeninfo:#?}\n")).await
|
||||
}
|
||||
|
||||
#[admin_command]
|
||||
pub(super) async fn oauth_revoke(&self, id: SessionOrUserId) -> Result {
|
||||
match id {
|
||||
| Left(sess_id) => {
|
||||
let session = self.services.oauth.sessions.get(&sess_id).await?;
|
||||
|
||||
let provider = self
|
||||
.services
|
||||
.oauth
|
||||
.sessions
|
||||
.provider(&session)
|
||||
.await?;
|
||||
|
||||
self.services
|
||||
.oauth
|
||||
.revoke_token((&provider, &session))
|
||||
.await
|
||||
.ok();
|
||||
},
|
||||
| Right(user_id) =>
|
||||
self.services
|
||||
.oauth
|
||||
.revoke_user_tokens(&user_id)
|
||||
.await,
|
||||
}
|
||||
|
||||
self.write_str("revoked").await
|
||||
}
|
||||
|
||||
#[admin_command]
|
||||
pub(super) async fn oauth_delete(&self, id: SessionOrUserId, force: bool) -> Result {
|
||||
if !force {
|
||||
return Err!(
|
||||
"Deleting these records can cause registration conflicts. Use --force to be sure."
|
||||
);
|
||||
}
|
||||
|
||||
match id {
|
||||
| Left(sess_id) => {
|
||||
self.services
|
||||
.oauth
|
||||
.sessions
|
||||
.delete(&sess_id)
|
||||
.await;
|
||||
},
|
||||
| Right(user_id) => {
|
||||
self.services
|
||||
.oauth
|
||||
.delete_user_sessions(&user_id)
|
||||
.await;
|
||||
},
|
||||
}
|
||||
|
||||
self.write_str("deleted any oauth state for {id}")
|
||||
.await
|
||||
}
|
||||
@@ -19,6 +19,9 @@ pub(crate) enum PresenceCommand {
|
||||
PresenceSince {
|
||||
/// UNIX timestamp since (u64)
|
||||
since: u64,
|
||||
|
||||
/// Upper-bound of since
|
||||
to: Option<u64>,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -34,11 +37,11 @@ pub(super) async fn process(subcommand: PresenceCommand, context: &Context<'_>)
|
||||
|
||||
write!(context, "Query completed in {query_time:?}:\n\n```rs\n{results:#?}\n```")
|
||||
},
|
||||
| PresenceCommand::PresenceSince { since } => {
|
||||
| PresenceCommand::PresenceSince { since, to } => {
|
||||
let timer = tokio::time::Instant::now();
|
||||
let results: Vec<(_, _, _)> = services
|
||||
.presence
|
||||
.presence_since(since)
|
||||
.presence_since(since, to)
|
||||
.map(|(user_id, count, bytes)| (user_id.to_owned(), count, bytes.to_vec()))
|
||||
.collect()
|
||||
.await;
|
||||
|
||||
+41
-14
@@ -1,9 +1,9 @@
|
||||
use clap::Subcommand;
|
||||
use ruma::OwnedUserId;
|
||||
use tuwunel_core::Result;
|
||||
use tuwunel_macros::{admin_command, admin_command_dispatch};
|
||||
|
||||
use crate::Context;
|
||||
|
||||
#[admin_command_dispatch]
|
||||
#[derive(Debug, Subcommand)]
|
||||
pub(crate) enum PusherCommand {
|
||||
/// - Returns all the pushers for the user.
|
||||
@@ -11,19 +11,46 @@ pub(crate) enum PusherCommand {
|
||||
/// Full user ID
|
||||
user_id: OwnedUserId,
|
||||
},
|
||||
|
||||
/// - Manually delete a pusher for a user.
|
||||
RemovePusher {
|
||||
/// Full user ID
|
||||
user_id: OwnedUserId,
|
||||
|
||||
/// Pushkey
|
||||
pushkey: String,
|
||||
},
|
||||
}
|
||||
|
||||
pub(super) async fn process(subcommand: PusherCommand, context: &Context<'_>) -> Result {
|
||||
let services = context.services;
|
||||
#[admin_command]
|
||||
pub(super) async fn get_pushers(&self, user_id: OwnedUserId) -> Result {
|
||||
let timer = tokio::time::Instant::now();
|
||||
let results = self.services.pusher.get_pushers(&user_id).await;
|
||||
let query_time = timer.elapsed();
|
||||
|
||||
match subcommand {
|
||||
| PusherCommand::GetPushers { user_id } => {
|
||||
let timer = tokio::time::Instant::now();
|
||||
let results = services.pusher.get_pushers(&user_id).await;
|
||||
let query_time = timer.elapsed();
|
||||
|
||||
write!(context, "Query completed in {query_time:?}:\n\n```rs\n{results:#?}\n```")
|
||||
},
|
||||
}
|
||||
.await
|
||||
self.write_string(format!("Query completed in {query_time:?}:\n\n```rs\n{results:#?}```"))
|
||||
.await
|
||||
}
|
||||
|
||||
#[admin_command]
|
||||
pub(super) async fn remove_pusher(&self, user_id: OwnedUserId, pushkey: String) -> Result {
|
||||
let exists = self
|
||||
.services
|
||||
.pusher
|
||||
.get_pusher(&user_id, &pushkey)
|
||||
.await
|
||||
.is_ok();
|
||||
|
||||
self.services
|
||||
.pusher
|
||||
.delete_pusher(&user_id, &pushkey)
|
||||
.await;
|
||||
|
||||
let message = if exists {
|
||||
"Pusher deleted."
|
||||
} else {
|
||||
"Pusher was not found but deletion was still attempted."
|
||||
};
|
||||
|
||||
self.write_str(message).await
|
||||
}
|
||||
|
||||
+225
-156
@@ -1,57 +1,88 @@
|
||||
use std::{borrow::Cow, collections::BTreeMap, ops::Deref, sync::Arc};
|
||||
use std::{collections::BTreeMap, fmt::Write, sync::Arc};
|
||||
|
||||
use base64::prelude::*;
|
||||
use clap::Subcommand;
|
||||
use futures::{FutureExt, Stream, StreamExt, TryStreamExt};
|
||||
use futures::{FutureExt, StreamExt, TryStreamExt};
|
||||
use tokio::time::Instant;
|
||||
use tuwunel_core::{
|
||||
Err, Result, apply, at, is_zero,
|
||||
Err, Result, apply, at, err, is_zero,
|
||||
itertools::Itertools,
|
||||
utils::{
|
||||
TryReadyExt,
|
||||
math::Expected,
|
||||
stream::{IterStream, ReadyExt, TryIgnore, TryParallelExt},
|
||||
string::EMPTY,
|
||||
},
|
||||
};
|
||||
use tuwunel_database::Map;
|
||||
use tuwunel_database::{KeyVal, Map};
|
||||
use tuwunel_service::Services;
|
||||
|
||||
use crate::{admin_command, admin_command_dispatch};
|
||||
|
||||
#[admin_command_dispatch]
|
||||
#[admin_command_dispatch(handler_prefix = "raw")]
|
||||
#[derive(Debug, Subcommand)]
|
||||
#[allow(clippy::enum_variant_names)]
|
||||
/// Query tables from database
|
||||
pub(crate) enum RawCommand {
|
||||
/// - List database maps
|
||||
RawMaps,
|
||||
Maps,
|
||||
|
||||
/// - Raw database query
|
||||
RawGet {
|
||||
Get {
|
||||
/// Map name
|
||||
map: String,
|
||||
|
||||
/// Key
|
||||
key: String,
|
||||
},
|
||||
|
||||
/// - Raw database delete (for string keys)
|
||||
RawDel {
|
||||
/// Map name
|
||||
map: String,
|
||||
|
||||
/// Key
|
||||
key: String,
|
||||
/// Encode as base64
|
||||
#[arg(long, short)]
|
||||
base64: bool,
|
||||
},
|
||||
|
||||
/// - Raw database keys iteration
|
||||
RawKeys {
|
||||
Keys {
|
||||
/// Map name
|
||||
map: String,
|
||||
|
||||
/// Key prefix
|
||||
prefix: Option<String>,
|
||||
|
||||
/// Limit
|
||||
#[arg(short, long)]
|
||||
limit: Option<usize>,
|
||||
|
||||
/// Lower bound
|
||||
#[arg(short, long)]
|
||||
from: Option<String>,
|
||||
|
||||
/// Reverse iteration order
|
||||
#[arg(short, long, default_value("false"))]
|
||||
backwards: bool,
|
||||
},
|
||||
|
||||
/// - Raw database items iteration
|
||||
Iter {
|
||||
/// Map name
|
||||
map: String,
|
||||
|
||||
/// Key prefix
|
||||
prefix: Option<String>,
|
||||
|
||||
/// Limit
|
||||
#[arg(short, long)]
|
||||
limit: Option<usize>,
|
||||
|
||||
/// Lower bound
|
||||
#[arg(short, long)]
|
||||
from: Option<String>,
|
||||
|
||||
/// Reverse iteration order
|
||||
#[arg(short, long, default_value("false"))]
|
||||
backwards: bool,
|
||||
},
|
||||
|
||||
/// - Raw database key size breakdown
|
||||
RawKeysSizes {
|
||||
KeysSizes {
|
||||
/// Map name
|
||||
map: Option<String>,
|
||||
|
||||
@@ -60,7 +91,7 @@ pub(crate) enum RawCommand {
|
||||
},
|
||||
|
||||
/// - Raw database keys total bytes
|
||||
RawKeysTotal {
|
||||
KeysTotal {
|
||||
/// Map name
|
||||
map: Option<String>,
|
||||
|
||||
@@ -69,7 +100,7 @@ pub(crate) enum RawCommand {
|
||||
},
|
||||
|
||||
/// - Raw database values size breakdown
|
||||
RawValsSizes {
|
||||
ValsSizes {
|
||||
/// Map name
|
||||
map: Option<String>,
|
||||
|
||||
@@ -78,7 +109,7 @@ pub(crate) enum RawCommand {
|
||||
},
|
||||
|
||||
/// - Raw database values total bytes
|
||||
RawValsTotal {
|
||||
ValsTotal {
|
||||
/// Map name
|
||||
map: Option<String>,
|
||||
|
||||
@@ -86,43 +117,8 @@ pub(crate) enum RawCommand {
|
||||
prefix: Option<String>,
|
||||
},
|
||||
|
||||
/// - Raw database items iteration
|
||||
RawIter {
|
||||
/// Map name
|
||||
map: String,
|
||||
|
||||
/// Key prefix
|
||||
prefix: Option<String>,
|
||||
},
|
||||
|
||||
/// - Raw database keys iteration
|
||||
RawKeysFrom {
|
||||
/// Map name
|
||||
map: String,
|
||||
|
||||
/// Lower-bound
|
||||
start: String,
|
||||
|
||||
/// Limit
|
||||
#[arg(short, long)]
|
||||
limit: Option<usize>,
|
||||
},
|
||||
|
||||
/// - Raw database items iteration
|
||||
RawIterFrom {
|
||||
/// Map name
|
||||
map: String,
|
||||
|
||||
/// Lower-bound
|
||||
start: String,
|
||||
|
||||
/// Limit
|
||||
#[arg(short, long)]
|
||||
limit: Option<usize>,
|
||||
},
|
||||
|
||||
/// - Raw database record count
|
||||
RawCount {
|
||||
Count {
|
||||
/// Map name
|
||||
map: Option<String>,
|
||||
|
||||
@@ -130,10 +126,29 @@ pub(crate) enum RawCommand {
|
||||
prefix: Option<String>,
|
||||
},
|
||||
|
||||
/// - Compact database
|
||||
/// - Raw database delete (for string keys) DANGER!!!
|
||||
Del {
|
||||
/// Map name
|
||||
map: String,
|
||||
|
||||
/// Key
|
||||
key: String,
|
||||
},
|
||||
|
||||
/// - Clear database table DANGER!!!
|
||||
Clear {
|
||||
/// Map name
|
||||
map: String,
|
||||
|
||||
/// Confirm
|
||||
#[arg(long)]
|
||||
confirm: bool,
|
||||
},
|
||||
|
||||
/// - Compact database DANGER!!!
|
||||
Compact {
|
||||
#[arg(short, long, alias("column"))]
|
||||
map: Option<Vec<String>>,
|
||||
maps: Option<Vec<String>>,
|
||||
|
||||
#[arg(long)]
|
||||
start: Option<String>,
|
||||
@@ -160,9 +175,9 @@ pub(crate) enum RawCommand {
|
||||
}
|
||||
|
||||
#[admin_command]
|
||||
pub(super) async fn compact(
|
||||
pub(super) async fn raw_compact(
|
||||
&self,
|
||||
map: Option<Vec<String>>,
|
||||
maps: Option<Vec<String>>,
|
||||
start: Option<String>,
|
||||
stop: Option<String>,
|
||||
from: Option<usize>,
|
||||
@@ -172,26 +187,7 @@ pub(super) async fn compact(
|
||||
) -> Result {
|
||||
use tuwunel_database::compact::Options;
|
||||
|
||||
let default_all_maps: Option<_> = map.is_none().then(|| {
|
||||
self.services
|
||||
.db
|
||||
.keys()
|
||||
.map(Deref::deref)
|
||||
.map(ToOwned::to_owned)
|
||||
});
|
||||
|
||||
let maps: Vec<_> = map
|
||||
.unwrap_or_default()
|
||||
.into_iter()
|
||||
.chain(default_all_maps.into_iter().flatten())
|
||||
.map(|map| self.services.db.get(&map))
|
||||
.filter_map(Result::ok)
|
||||
.cloned()
|
||||
.collect();
|
||||
|
||||
if maps.is_empty() {
|
||||
return Err!("--map argument invalid. not found in database");
|
||||
}
|
||||
let maps = with_maps_or(maps.as_deref(), self.services)?;
|
||||
|
||||
let range = (
|
||||
start
|
||||
@@ -233,7 +229,9 @@ pub(super) async fn raw_count(&self, map: Option<String>, prefix: Option<String>
|
||||
let prefix = prefix.as_deref().unwrap_or(EMPTY);
|
||||
|
||||
let timer = Instant::now();
|
||||
let count = with_maps_or(map.as_deref(), self.services)
|
||||
let count = with_map_or(map.as_deref(), self.services)?
|
||||
.iter()
|
||||
.stream()
|
||||
.then(|map| map.raw_count_prefix(&prefix))
|
||||
.ready_fold(0_usize, usize::saturating_add)
|
||||
.await;
|
||||
@@ -244,16 +242,45 @@ pub(super) async fn raw_count(&self, map: Option<String>, prefix: Option<String>
|
||||
}
|
||||
|
||||
#[admin_command]
|
||||
pub(super) async fn raw_keys(&self, map: String, prefix: Option<String>) -> Result {
|
||||
pub(super) async fn raw_keys(
|
||||
&self,
|
||||
map: String,
|
||||
prefix: Option<String>,
|
||||
limit: Option<usize>,
|
||||
from: Option<String>,
|
||||
backwards: bool,
|
||||
) -> Result {
|
||||
writeln!(self, "```").boxed().await?;
|
||||
|
||||
let map = self.services.db.get(map.as_str())?;
|
||||
let timer = Instant::now();
|
||||
prefix
|
||||
.as_deref()
|
||||
.map_or_else(|| map.raw_keys().boxed(), |prefix| map.raw_keys_prefix(prefix).boxed())
|
||||
.map_ok(String::from_utf8_lossy)
|
||||
.try_for_each(|str| writeln!(self, "{str:?}"))
|
||||
|
||||
let stream = match from.as_ref().or(prefix.as_ref()) {
|
||||
| Some(from) =>
|
||||
if !backwards {
|
||||
map.raw_keys_from(from).boxed()
|
||||
} else {
|
||||
map.rev_raw_keys_from(from).boxed()
|
||||
},
|
||||
| None =>
|
||||
if !backwards {
|
||||
map.raw_keys().boxed()
|
||||
} else {
|
||||
map.rev_raw_keys().boxed()
|
||||
},
|
||||
};
|
||||
|
||||
let prefix = prefix.as_ref().map(String::as_bytes);
|
||||
|
||||
stream
|
||||
.ready_try_take_while(|k| {
|
||||
Ok(prefix
|
||||
.map(|prefix| k.starts_with(prefix))
|
||||
.unwrap_or(true))
|
||||
})
|
||||
.take(limit.unwrap_or(usize::MAX))
|
||||
.map_ok(encode)
|
||||
.try_for_each(|str| writeln!(self, "{str}"))
|
||||
.boxed()
|
||||
.await?;
|
||||
|
||||
@@ -267,7 +294,9 @@ pub(super) async fn raw_keys_sizes(&self, map: Option<String>, prefix: Option<St
|
||||
let prefix = prefix.as_deref().unwrap_or(EMPTY);
|
||||
|
||||
let timer = Instant::now();
|
||||
let result = with_maps_or(map.as_deref(), self.services)
|
||||
let result = with_map_or(map.as_deref(), self.services)?
|
||||
.iter()
|
||||
.stream()
|
||||
.map(|map| map.raw_keys_prefix(&prefix))
|
||||
.flatten()
|
||||
.ignore_err()
|
||||
@@ -289,7 +318,9 @@ pub(super) async fn raw_keys_total(&self, map: Option<String>, prefix: Option<St
|
||||
let prefix = prefix.as_deref().unwrap_or(EMPTY);
|
||||
|
||||
let timer = Instant::now();
|
||||
let result = with_maps_or(map.as_deref(), self.services)
|
||||
let result = with_map_or(map.as_deref(), self.services)?
|
||||
.iter()
|
||||
.stream()
|
||||
.map(|map| map.raw_keys_prefix(&prefix))
|
||||
.flatten()
|
||||
.ignore_err()
|
||||
@@ -307,7 +338,9 @@ pub(super) async fn raw_vals_sizes(&self, map: Option<String>, prefix: Option<St
|
||||
let prefix = prefix.as_deref().unwrap_or(EMPTY);
|
||||
|
||||
let timer = Instant::now();
|
||||
let result = with_maps_or(map.as_deref(), self.services)
|
||||
let result = with_map_or(map.as_deref(), self.services)?
|
||||
.iter()
|
||||
.stream()
|
||||
.map(|map| map.raw_stream_prefix(&prefix))
|
||||
.flatten()
|
||||
.ignore_err()
|
||||
@@ -330,7 +363,9 @@ pub(super) async fn raw_vals_total(&self, map: Option<String>, prefix: Option<St
|
||||
let prefix = prefix.as_deref().unwrap_or(EMPTY);
|
||||
|
||||
let timer = Instant::now();
|
||||
let result = with_maps_or(map.as_deref(), self.services)
|
||||
let result = with_map_or(map.as_deref(), self.services)?
|
||||
.iter()
|
||||
.stream()
|
||||
.map(|map| map.raw_stream_prefix(&prefix))
|
||||
.flatten()
|
||||
.ignore_err()
|
||||
@@ -345,40 +380,44 @@ pub(super) async fn raw_vals_total(&self, map: Option<String>, prefix: Option<St
|
||||
}
|
||||
|
||||
#[admin_command]
|
||||
pub(super) async fn raw_iter(&self, map: String, prefix: Option<String>) -> Result {
|
||||
writeln!(self, "```").await?;
|
||||
|
||||
let map = self.services.db.get(&map)?;
|
||||
let timer = Instant::now();
|
||||
prefix
|
||||
.as_deref()
|
||||
.map_or_else(|| map.raw_stream().boxed(), |prefix| map.raw_stream_prefix(prefix).boxed())
|
||||
.map_ok(apply!(2, String::from_utf8_lossy))
|
||||
.map_ok(apply!(2, Cow::into_owned))
|
||||
.try_for_each(|keyval| writeln!(self, "{keyval:?}"))
|
||||
.boxed()
|
||||
.await?;
|
||||
|
||||
let query_time = timer.elapsed();
|
||||
self.write_str(&format!("\n```\n\nQuery completed in {query_time:?}"))
|
||||
.await
|
||||
}
|
||||
|
||||
#[admin_command]
|
||||
pub(super) async fn raw_keys_from(
|
||||
pub(super) async fn raw_iter(
|
||||
&self,
|
||||
map: String,
|
||||
start: String,
|
||||
prefix: Option<String>,
|
||||
limit: Option<usize>,
|
||||
from: Option<String>,
|
||||
backwards: bool,
|
||||
) -> Result {
|
||||
writeln!(self, "```").await?;
|
||||
|
||||
let map = self.services.db.get(&map)?;
|
||||
let timer = Instant::now();
|
||||
map.raw_keys_from(&start)
|
||||
.map_ok(String::from_utf8_lossy)
|
||||
let stream = match from.as_ref().or(prefix.as_ref()) {
|
||||
| Some(from) =>
|
||||
if !backwards {
|
||||
map.raw_stream_from(from).boxed()
|
||||
} else {
|
||||
map.rev_raw_stream_from(from).boxed()
|
||||
},
|
||||
| None =>
|
||||
if !backwards {
|
||||
map.raw_stream().boxed()
|
||||
} else {
|
||||
map.rev_raw_stream().boxed()
|
||||
},
|
||||
};
|
||||
|
||||
let prefix = prefix.as_ref().map(String::as_bytes);
|
||||
|
||||
stream
|
||||
.ready_try_take_while(|(k, _): &KeyVal<'_>| {
|
||||
Ok(prefix
|
||||
.map(|prefix| k.starts_with(prefix))
|
||||
.unwrap_or(true))
|
||||
})
|
||||
.take(limit.unwrap_or(usize::MAX))
|
||||
.try_for_each(|str| writeln!(self, "{str:?}"))
|
||||
.map_ok(apply!(2, encode))
|
||||
.try_for_each(|(key, val)| writeln!(self, "{{{key} => {val}}}"))
|
||||
.boxed()
|
||||
.await?;
|
||||
|
||||
@@ -387,28 +426,6 @@ pub(super) async fn raw_keys_from(
|
||||
.await
|
||||
}
|
||||
|
||||
#[admin_command]
|
||||
pub(super) async fn raw_iter_from(
|
||||
&self,
|
||||
map: String,
|
||||
start: String,
|
||||
limit: Option<usize>,
|
||||
) -> Result {
|
||||
let map = self.services.db.get(&map)?;
|
||||
let timer = Instant::now();
|
||||
let result = map
|
||||
.raw_stream_from(&start)
|
||||
.map_ok(apply!(2, String::from_utf8_lossy))
|
||||
.map_ok(apply!(2, Cow::into_owned))
|
||||
.take(limit.unwrap_or(usize::MAX))
|
||||
.try_collect::<Vec<(String, String)>>()
|
||||
.await?;
|
||||
|
||||
let query_time = timer.elapsed();
|
||||
self.write_str(&format!("Query completed in {query_time:?}:\n\n```rs\n{result:#?}\n```"))
|
||||
.await
|
||||
}
|
||||
|
||||
#[admin_command]
|
||||
pub(super) async fn raw_del(&self, map: String, key: String) -> Result {
|
||||
let map = self.services.db.get(&map)?;
|
||||
@@ -421,13 +438,41 @@ pub(super) async fn raw_del(&self, map: String, key: String) -> Result {
|
||||
}
|
||||
|
||||
#[admin_command]
|
||||
pub(super) async fn raw_get(&self, map: String, key: String) -> Result {
|
||||
pub(super) async fn raw_clear(&self, map: String, confirm: bool) -> Result {
|
||||
let map = self.services.db.get(&map)?;
|
||||
|
||||
if !confirm {
|
||||
return Err!("Are you really sure you want to clear all data? Add the --confirm option.");
|
||||
}
|
||||
|
||||
let timer = Instant::now();
|
||||
let cork = self.services.db.cork();
|
||||
map.raw_keys()
|
||||
.ignore_err()
|
||||
.ready_for_each(|key| map.remove(&key))
|
||||
.boxed()
|
||||
.await;
|
||||
|
||||
drop(cork);
|
||||
let query_time = timer.elapsed();
|
||||
self.write_str(&format!("Operation completed in {query_time:?}"))
|
||||
.await
|
||||
}
|
||||
|
||||
#[admin_command]
|
||||
pub(super) async fn raw_get(&self, map: String, key: String, base64: bool) -> Result {
|
||||
let map = self.services.db.get(&map)?;
|
||||
let timer = Instant::now();
|
||||
let handle = map.get(&key).await?;
|
||||
|
||||
let query_time = timer.elapsed();
|
||||
let result = String::from_utf8_lossy(&handle);
|
||||
|
||||
let result = if base64 {
|
||||
BASE64_STANDARD.encode(&handle)
|
||||
} else {
|
||||
encode(&handle)
|
||||
};
|
||||
|
||||
self.write_str(&format!("Query completed in {query_time:?}:\n\n```rs\n{result:?}\n```"))
|
||||
.await
|
||||
}
|
||||
@@ -445,19 +490,43 @@ pub(super) async fn raw_maps(&self) -> Result {
|
||||
self.write_str(&format!("{list:#?}")).await
|
||||
}
|
||||
|
||||
fn with_maps_or<'a>(
|
||||
map: Option<&'a str>,
|
||||
services: &'a Services,
|
||||
) -> impl Stream<Item = &'a Arc<Map>> + Send + 'a {
|
||||
let default_all_maps = map
|
||||
.is_none()
|
||||
.then(|| services.db.keys().map(Deref::deref))
|
||||
.into_iter()
|
||||
.flatten();
|
||||
|
||||
map.into_iter()
|
||||
.chain(default_all_maps)
|
||||
.map(|map| services.db.get(map))
|
||||
.filter_map(Result::ok)
|
||||
.stream()
|
||||
fn with_map_or(map: Option<&str>, services: &Services) -> Result<Vec<Arc<Map>>> {
|
||||
with_maps_or(
|
||||
map.map(|map| [map])
|
||||
.as_ref()
|
||||
.map(<[&str; 1]>::as_slice),
|
||||
services,
|
||||
)
|
||||
}
|
||||
|
||||
fn with_maps_or<S: AsRef<str>>(maps: Option<&[S]>, services: &Services) -> Result<Vec<Arc<Map>>> {
|
||||
Ok(if let Some(maps) = maps {
|
||||
maps.iter()
|
||||
.map(|map| {
|
||||
let map = map.as_ref();
|
||||
services
|
||||
.db
|
||||
.get(map)
|
||||
.cloned()
|
||||
.map_err(|_| err!("map {map} not found"))
|
||||
})
|
||||
.try_collect()?
|
||||
} else {
|
||||
services.db.iter().map(|x| x.1.clone()).collect()
|
||||
})
|
||||
}
|
||||
|
||||
#[expect(clippy::as_conversions)]
|
||||
fn encode(data: &[u8]) -> String {
|
||||
let mut res = String::with_capacity(data.len().expected_mul(4));
|
||||
|
||||
for byte in data {
|
||||
if *byte < 0x20 || *byte > 0x7E {
|
||||
let _ = write!(res, "\\x{byte:02x}");
|
||||
} else {
|
||||
res.push(*byte as char);
|
||||
}
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
@@ -35,10 +35,10 @@ async fn destinations_cache(&self, server_name: Option<OwnedServerName>) -> Resu
|
||||
.boxed();
|
||||
|
||||
while let Some((name, CachedDest { dest, host, expire })) = destinations.next().await {
|
||||
if let Some(server_name) = server_name.as_ref() {
|
||||
if name != server_name {
|
||||
continue;
|
||||
}
|
||||
if let Some(server_name) = server_name.as_ref()
|
||||
&& name != server_name
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
let expire = time::format(expire, "%+");
|
||||
@@ -61,10 +61,10 @@ async fn overrides_cache(&self, server_name: Option<String>) -> Result {
|
||||
while let Some((name, CachedOverride { ips, port, expire, overriding })) =
|
||||
overrides.next().await
|
||||
{
|
||||
if let Some(server_name) = server_name.as_ref() {
|
||||
if name != server_name {
|
||||
continue;
|
||||
}
|
||||
if let Some(server_name) = server_name.as_ref()
|
||||
&& name != server_name
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
let expire = time::format(expire, "%+");
|
||||
|
||||
@@ -8,6 +8,13 @@
|
||||
#[derive(Debug, Subcommand)]
|
||||
/// All the getters and iterators from src/database/key_value/rooms/alias.rs
|
||||
pub(crate) enum RoomAliasCommand {
|
||||
/// - Resolve any local or remote alias.
|
||||
ResolveAlias {
|
||||
/// Full room alias
|
||||
alias: OwnedRoomAliasId,
|
||||
},
|
||||
|
||||
/// - Resolve an alias on this server.
|
||||
ResolveLocalAlias {
|
||||
/// Full room alias
|
||||
alias: OwnedRoomAliasId,
|
||||
@@ -28,13 +35,16 @@ pub(super) async fn process(subcommand: RoomAliasCommand, context: &Context<'_>)
|
||||
let services = context.services;
|
||||
|
||||
match subcommand {
|
||||
| RoomAliasCommand::ResolveAlias { alias } => {
|
||||
let timer = tokio::time::Instant::now();
|
||||
let results = services.alias.resolve_alias(&alias).await;
|
||||
let query_time = timer.elapsed();
|
||||
|
||||
write!(context, "Query completed in {query_time:?}:\n\n```rs\n{results:#?}\n```")
|
||||
},
|
||||
| RoomAliasCommand::ResolveLocalAlias { alias } => {
|
||||
let timer = tokio::time::Instant::now();
|
||||
let results = services
|
||||
.rooms
|
||||
.alias
|
||||
.resolve_local_alias(&alias)
|
||||
.await;
|
||||
let results = services.alias.resolve_local_alias(&alias).await;
|
||||
let query_time = timer.elapsed();
|
||||
|
||||
write!(context, "Query completed in {query_time:?}:\n\n```rs\n{results:#?}\n```")
|
||||
@@ -42,7 +52,6 @@ pub(super) async fn process(subcommand: RoomAliasCommand, context: &Context<'_>)
|
||||
| RoomAliasCommand::LocalAliasesForRoom { room_id } => {
|
||||
let timer = tokio::time::Instant::now();
|
||||
let aliases: Vec<_> = services
|
||||
.rooms
|
||||
.alias
|
||||
.local_aliases_for_room(&room_id)
|
||||
.map(ToOwned::to_owned)
|
||||
@@ -55,7 +64,6 @@ pub(super) async fn process(subcommand: RoomAliasCommand, context: &Context<'_>)
|
||||
| RoomAliasCommand::AllLocalAliases => {
|
||||
let timer = tokio::time::Instant::now();
|
||||
let aliases = services
|
||||
.rooms
|
||||
.alias
|
||||
.all_local_aliases()
|
||||
.map(|(room_id, alias)| (room_id.to_owned(), alias.to_owned()))
|
||||
|
||||
@@ -74,6 +74,10 @@ pub(crate) enum RoomStateCacheCommand {
|
||||
user_id: OwnedUserId,
|
||||
room_id: OwnedRoomId,
|
||||
},
|
||||
|
||||
UserMemberships {
|
||||
user_id: OwnedUserId,
|
||||
},
|
||||
}
|
||||
|
||||
pub(super) async fn process(subcommand: RoomStateCacheCommand, context: &Context<'_>) -> Result {
|
||||
@@ -83,7 +87,6 @@ pub(super) async fn process(subcommand: RoomStateCacheCommand, context: &Context
|
||||
| RoomStateCacheCommand::ServerInRoom { server, room_id } => {
|
||||
let timer = tokio::time::Instant::now();
|
||||
let result = services
|
||||
.rooms
|
||||
.state_cache
|
||||
.server_in_room(&server, &room_id)
|
||||
.await;
|
||||
@@ -98,7 +101,6 @@ pub(super) async fn process(subcommand: RoomStateCacheCommand, context: &Context
|
||||
| RoomStateCacheCommand::RoomServers { room_id } => {
|
||||
let timer = tokio::time::Instant::now();
|
||||
let results: Vec<_> = services
|
||||
.rooms
|
||||
.state_cache
|
||||
.room_servers(&room_id)
|
||||
.map(ToOwned::to_owned)
|
||||
@@ -115,7 +117,6 @@ pub(super) async fn process(subcommand: RoomStateCacheCommand, context: &Context
|
||||
| RoomStateCacheCommand::ServerRooms { server } => {
|
||||
let timer = tokio::time::Instant::now();
|
||||
let results: Vec<_> = services
|
||||
.rooms
|
||||
.state_cache
|
||||
.server_rooms(&server)
|
||||
.map(ToOwned::to_owned)
|
||||
@@ -132,7 +133,6 @@ pub(super) async fn process(subcommand: RoomStateCacheCommand, context: &Context
|
||||
| RoomStateCacheCommand::RoomMembers { room_id } => {
|
||||
let timer = tokio::time::Instant::now();
|
||||
let results: Vec<_> = services
|
||||
.rooms
|
||||
.state_cache
|
||||
.room_members(&room_id)
|
||||
.map(ToOwned::to_owned)
|
||||
@@ -149,7 +149,6 @@ pub(super) async fn process(subcommand: RoomStateCacheCommand, context: &Context
|
||||
| RoomStateCacheCommand::LocalUsersInRoom { room_id } => {
|
||||
let timer = tokio::time::Instant::now();
|
||||
let results: Vec<_> = services
|
||||
.rooms
|
||||
.state_cache
|
||||
.local_users_in_room(&room_id)
|
||||
.map(ToOwned::to_owned)
|
||||
@@ -166,7 +165,6 @@ pub(super) async fn process(subcommand: RoomStateCacheCommand, context: &Context
|
||||
| RoomStateCacheCommand::ActiveLocalUsersInRoom { room_id } => {
|
||||
let timer = tokio::time::Instant::now();
|
||||
let results: Vec<_> = services
|
||||
.rooms
|
||||
.state_cache
|
||||
.active_local_users_in_room(&room_id)
|
||||
.map(ToOwned::to_owned)
|
||||
@@ -183,7 +181,6 @@ pub(super) async fn process(subcommand: RoomStateCacheCommand, context: &Context
|
||||
| RoomStateCacheCommand::RoomJoinedCount { room_id } => {
|
||||
let timer = tokio::time::Instant::now();
|
||||
let results = services
|
||||
.rooms
|
||||
.state_cache
|
||||
.room_joined_count(&room_id)
|
||||
.await;
|
||||
@@ -198,7 +195,6 @@ pub(super) async fn process(subcommand: RoomStateCacheCommand, context: &Context
|
||||
| RoomStateCacheCommand::RoomInvitedCount { room_id } => {
|
||||
let timer = tokio::time::Instant::now();
|
||||
let results = services
|
||||
.rooms
|
||||
.state_cache
|
||||
.room_invited_count(&room_id)
|
||||
.await;
|
||||
@@ -213,7 +209,6 @@ pub(super) async fn process(subcommand: RoomStateCacheCommand, context: &Context
|
||||
| RoomStateCacheCommand::RoomUserOnceJoined { room_id } => {
|
||||
let timer = tokio::time::Instant::now();
|
||||
let results: Vec<_> = services
|
||||
.rooms
|
||||
.state_cache
|
||||
.room_useroncejoined(&room_id)
|
||||
.map(ToOwned::to_owned)
|
||||
@@ -230,7 +225,6 @@ pub(super) async fn process(subcommand: RoomStateCacheCommand, context: &Context
|
||||
| RoomStateCacheCommand::RoomMembersInvited { room_id } => {
|
||||
let timer = tokio::time::Instant::now();
|
||||
let results: Vec<_> = services
|
||||
.rooms
|
||||
.state_cache
|
||||
.room_members_invited(&room_id)
|
||||
.map(ToOwned::to_owned)
|
||||
@@ -247,7 +241,6 @@ pub(super) async fn process(subcommand: RoomStateCacheCommand, context: &Context
|
||||
| RoomStateCacheCommand::GetInviteCount { room_id, user_id } => {
|
||||
let timer = tokio::time::Instant::now();
|
||||
let results = services
|
||||
.rooms
|
||||
.state_cache
|
||||
.get_invite_count(&room_id, &user_id)
|
||||
.await;
|
||||
@@ -262,7 +255,6 @@ pub(super) async fn process(subcommand: RoomStateCacheCommand, context: &Context
|
||||
| RoomStateCacheCommand::GetLeftCount { room_id, user_id } => {
|
||||
let timer = tokio::time::Instant::now();
|
||||
let results = services
|
||||
.rooms
|
||||
.state_cache
|
||||
.get_left_count(&room_id, &user_id)
|
||||
.await;
|
||||
@@ -277,7 +269,6 @@ pub(super) async fn process(subcommand: RoomStateCacheCommand, context: &Context
|
||||
| RoomStateCacheCommand::RoomsJoined { user_id } => {
|
||||
let timer = tokio::time::Instant::now();
|
||||
let results: Vec<_> = services
|
||||
.rooms
|
||||
.state_cache
|
||||
.rooms_joined(&user_id)
|
||||
.map(ToOwned::to_owned)
|
||||
@@ -294,9 +285,8 @@ pub(super) async fn process(subcommand: RoomStateCacheCommand, context: &Context
|
||||
| RoomStateCacheCommand::RoomsInvited { user_id } => {
|
||||
let timer = tokio::time::Instant::now();
|
||||
let results: Vec<_> = services
|
||||
.rooms
|
||||
.state_cache
|
||||
.rooms_invited(&user_id)
|
||||
.rooms_invited_state(&user_id)
|
||||
.collect()
|
||||
.await;
|
||||
let query_time = timer.elapsed();
|
||||
@@ -310,9 +300,8 @@ pub(super) async fn process(subcommand: RoomStateCacheCommand, context: &Context
|
||||
| RoomStateCacheCommand::RoomsLeft { user_id } => {
|
||||
let timer = tokio::time::Instant::now();
|
||||
let results: Vec<_> = services
|
||||
.rooms
|
||||
.state_cache
|
||||
.rooms_left(&user_id)
|
||||
.rooms_left_state(&user_id)
|
||||
.collect()
|
||||
.await;
|
||||
let query_time = timer.elapsed();
|
||||
@@ -326,12 +315,27 @@ pub(super) async fn process(subcommand: RoomStateCacheCommand, context: &Context
|
||||
| RoomStateCacheCommand::InviteState { user_id, room_id } => {
|
||||
let timer = tokio::time::Instant::now();
|
||||
let results = services
|
||||
.rooms
|
||||
.state_cache
|
||||
.invite_state(&user_id, &room_id)
|
||||
.await;
|
||||
let query_time = timer.elapsed();
|
||||
|
||||
context
|
||||
.write_str(&format!(
|
||||
"Query completed in {query_time:?}:\n\n```rs\n{results:#?}\n```"
|
||||
))
|
||||
.await
|
||||
},
|
||||
| RoomStateCacheCommand::UserMemberships { user_id } => {
|
||||
let timer = tokio::time::Instant::now();
|
||||
let results = services
|
||||
.state_cache
|
||||
.all_user_memberships(&user_id)
|
||||
.map(|(membership, room_id)| (membership, room_id.to_owned()))
|
||||
.collect::<Vec<_>>()
|
||||
.await;
|
||||
let query_time = timer.elapsed();
|
||||
|
||||
context
|
||||
.write_str(&format!(
|
||||
"Query completed in {query_time:?}:\n\n```rs\n{results:#?}\n```"
|
||||
|
||||
@@ -27,16 +27,14 @@ pub(crate) enum RoomTimelineCommand {
|
||||
pub(super) async fn last(&self, room_id: OwnedRoomOrAliasId) -> Result {
|
||||
let room_id = self
|
||||
.services
|
||||
.rooms
|
||||
.alias
|
||||
.resolve(&room_id)
|
||||
.maybe_resolve(&room_id)
|
||||
.await?;
|
||||
|
||||
let result = self
|
||||
.services
|
||||
.rooms
|
||||
.timeline
|
||||
.last_timeline_count(None, &room_id)
|
||||
.last_timeline_count(None, &room_id, None)
|
||||
.await?;
|
||||
|
||||
self.write_str(&format!("{result:#?}")).await
|
||||
@@ -51,16 +49,14 @@ pub(super) async fn pdus(
|
||||
) -> Result {
|
||||
let room_id = self
|
||||
.services
|
||||
.rooms
|
||||
.alias
|
||||
.resolve(&room_id)
|
||||
.maybe_resolve(&room_id)
|
||||
.await?;
|
||||
|
||||
let from: Option<PduCount> = from.as_deref().map(str::parse).transpose()?;
|
||||
|
||||
let result: Vec<_> = self
|
||||
.services
|
||||
.rooms
|
||||
.timeline
|
||||
.pdus_rev(None, &room_id, from)
|
||||
.try_take(limit.unwrap_or(3))
|
||||
|
||||
@@ -21,7 +21,6 @@ pub(crate) enum ShortCommand {
|
||||
pub(super) async fn short_event_id(&self, event_id: OwnedEventId) -> Result {
|
||||
let shortid = self
|
||||
.services
|
||||
.rooms
|
||||
.short
|
||||
.get_shorteventid(&event_id)
|
||||
.await?;
|
||||
@@ -33,14 +32,12 @@ pub(super) async fn short_event_id(&self, event_id: OwnedEventId) -> Result {
|
||||
pub(super) async fn short_room_id(&self, room_id: OwnedRoomOrAliasId) -> Result {
|
||||
let room_id = self
|
||||
.services
|
||||
.rooms
|
||||
.alias
|
||||
.resolve(&room_id)
|
||||
.maybe_resolve(&room_id)
|
||||
.await?;
|
||||
|
||||
let shortid = self
|
||||
.services
|
||||
.rooms
|
||||
.short
|
||||
.get_shortroomid(&room_id)
|
||||
.await?;
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
use clap::Subcommand;
|
||||
use ruma::{OwnedDeviceId, OwnedUserId};
|
||||
use tuwunel_core::Result;
|
||||
use tuwunel_service::sync::into_connection_key;
|
||||
|
||||
use crate::{admin_command, admin_command_dispatch};
|
||||
|
||||
#[admin_command_dispatch]
|
||||
#[derive(Debug, Subcommand)]
|
||||
/// Query sync service state
|
||||
pub(crate) enum SyncCommand {
|
||||
/// List sliding-sync connections.
|
||||
ListConnections,
|
||||
|
||||
/// Show details of sliding sync connection by ID.
|
||||
ShowConnection {
|
||||
user_id: OwnedUserId,
|
||||
device_id: Option<OwnedDeviceId>,
|
||||
conn_id: Option<String>,
|
||||
},
|
||||
|
||||
/// Drop connections for a user, device, or all.
|
||||
DropConnections {
|
||||
user_id: Option<OwnedUserId>,
|
||||
device_id: Option<OwnedDeviceId>,
|
||||
conn_id: Option<String>,
|
||||
},
|
||||
}
|
||||
|
||||
#[admin_command]
|
||||
pub(super) async fn list_connections(&self) -> Result {
|
||||
let connections = self.services.sync.list_loaded_connections().await;
|
||||
|
||||
for connection_key in connections {
|
||||
self.write_str(&format!("{connection_key:?}\n"))
|
||||
.await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[admin_command]
|
||||
pub(super) async fn show_connection(
|
||||
&self,
|
||||
user_id: OwnedUserId,
|
||||
device_id: Option<OwnedDeviceId>,
|
||||
conn_id: Option<String>,
|
||||
) -> Result {
|
||||
let key = into_connection_key(user_id, device_id, conn_id);
|
||||
let cache = self
|
||||
.services
|
||||
.sync
|
||||
.get_loaded_connection(&key)
|
||||
.await?;
|
||||
|
||||
let out;
|
||||
{
|
||||
let cached = cache.lock().await;
|
||||
out = format!("{cached:#?}");
|
||||
};
|
||||
|
||||
self.write_str(out.as_str()).await
|
||||
}
|
||||
|
||||
#[admin_command]
|
||||
pub(super) async fn drop_connections(
|
||||
&self,
|
||||
user_id: Option<OwnedUserId>,
|
||||
device_id: Option<OwnedDeviceId>,
|
||||
conn_id: Option<String>,
|
||||
) -> Result {
|
||||
self.services
|
||||
.sync
|
||||
.clear_connections(
|
||||
user_id.as_deref(),
|
||||
device_id.as_deref(),
|
||||
conn_id.map(Into::into).as_ref(),
|
||||
)
|
||||
.await;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -13,8 +13,6 @@ pub(crate) enum UsersCommand {
|
||||
|
||||
IterUsers,
|
||||
|
||||
IterUsers2,
|
||||
|
||||
PasswordHash {
|
||||
user_id: OwnedUserId,
|
||||
},
|
||||
@@ -134,7 +132,6 @@ async fn get_shared_rooms(&self, user_a: OwnedUserId, user_b: OwnedUserId) -> Re
|
||||
let timer = tokio::time::Instant::now();
|
||||
let result: Vec<_> = self
|
||||
.services
|
||||
.rooms
|
||||
.state_cache
|
||||
.get_shared_rooms(&user_a, &user_b)
|
||||
.map(ToOwned::to_owned)
|
||||
@@ -258,22 +255,6 @@ async fn iter_users(&self) -> Result {
|
||||
.await
|
||||
}
|
||||
|
||||
#[admin_command]
|
||||
async fn iter_users2(&self) -> Result {
|
||||
let timer = tokio::time::Instant::now();
|
||||
let result: Vec<_> = self.services.users.stream().collect().await;
|
||||
let result: Vec<_> = result
|
||||
.into_iter()
|
||||
.map(ruma::UserId::as_bytes)
|
||||
.map(String::from_utf8_lossy)
|
||||
.collect();
|
||||
|
||||
let query_time = timer.elapsed();
|
||||
|
||||
self.write_str(&format!("Query completed in {query_time:?}:\n\n```rs\n{result:?}\n```"))
|
||||
.await
|
||||
}
|
||||
|
||||
#[admin_command]
|
||||
async fn count_users(&self) -> Result {
|
||||
let timer = tokio::time::Instant::now();
|
||||
|
||||
+8
-16
@@ -63,17 +63,15 @@ pub(super) async fn process(command: RoomAliasCommand, context: &Context<'_>) ->
|
||||
match (
|
||||
force,
|
||||
services
|
||||
.rooms
|
||||
.alias
|
||||
.resolve_local_alias(&room_alias)
|
||||
.await,
|
||||
) {
|
||||
| (true, Ok(id)) => {
|
||||
match services.rooms.alias.set_alias(
|
||||
&room_alias,
|
||||
&room_id,
|
||||
server_user,
|
||||
) {
|
||||
match services
|
||||
.alias
|
||||
.set_alias(&room_alias, &room_id, server_user)
|
||||
{
|
||||
| Err(err) => Err!("Failed to remove alias: {err}"),
|
||||
| Ok(()) =>
|
||||
context
|
||||
@@ -88,11 +86,10 @@ pub(super) async fn process(command: RoomAliasCommand, context: &Context<'_>) ->
|
||||
overwrite"
|
||||
),
|
||||
| (_, Err(_)) => {
|
||||
match services.rooms.alias.set_alias(
|
||||
&room_alias,
|
||||
&room_id,
|
||||
server_user,
|
||||
) {
|
||||
match services
|
||||
.alias
|
||||
.set_alias(&room_alias, &room_id, server_user)
|
||||
{
|
||||
| Err(err) => Err!("Failed to remove alias: {err}"),
|
||||
| Ok(()) => context.write_str("Successfully set alias").await,
|
||||
}
|
||||
@@ -101,14 +98,12 @@ pub(super) async fn process(command: RoomAliasCommand, context: &Context<'_>) ->
|
||||
},
|
||||
| RoomAliasCommand::Remove { .. } => {
|
||||
match services
|
||||
.rooms
|
||||
.alias
|
||||
.resolve_local_alias(&room_alias)
|
||||
.await
|
||||
{
|
||||
| Err(_) => Err!("Alias isn't in use."),
|
||||
| Ok(id) => match services
|
||||
.rooms
|
||||
.alias
|
||||
.remove_alias(&room_alias, server_user)
|
||||
.await
|
||||
@@ -123,7 +118,6 @@ pub(super) async fn process(command: RoomAliasCommand, context: &Context<'_>) ->
|
||||
},
|
||||
| RoomAliasCommand::Which { .. } => {
|
||||
match services
|
||||
.rooms
|
||||
.alias
|
||||
.resolve_local_alias(&room_alias)
|
||||
.await
|
||||
@@ -141,7 +135,6 @@ pub(super) async fn process(command: RoomAliasCommand, context: &Context<'_>) ->
|
||||
| RoomAliasCommand::List { room_id } =>
|
||||
if let Some(room_id) = room_id {
|
||||
let aliases: Vec<OwnedRoomAliasId> = services
|
||||
.rooms
|
||||
.alias
|
||||
.local_aliases_for_room(&room_id)
|
||||
.map(Into::into)
|
||||
@@ -160,7 +153,6 @@ pub(super) async fn process(command: RoomAliasCommand, context: &Context<'_>) ->
|
||||
context.write_str(&plain).await
|
||||
} else {
|
||||
let aliases = services
|
||||
.rooms
|
||||
.alias
|
||||
.all_local_aliases()
|
||||
.map(|(room_id, localpart)| (room_id.into(), localpart.into()))
|
||||
|
||||
+24
-23
@@ -16,27 +16,14 @@ pub(super) async fn list_rooms(
|
||||
let page = page.unwrap_or(1);
|
||||
let mut rooms = self
|
||||
.services
|
||||
.rooms
|
||||
.metadata
|
||||
.iter_ids()
|
||||
.filter_map(|room_id| async move {
|
||||
(!exclude_disabled
|
||||
|| !self
|
||||
.services
|
||||
.rooms
|
||||
.metadata
|
||||
.is_disabled(room_id)
|
||||
.await)
|
||||
.filter_map(async |room_id| {
|
||||
(!exclude_disabled || !self.services.metadata.is_disabled(room_id).await)
|
||||
.then_some(room_id)
|
||||
})
|
||||
.filter_map(|room_id| async move {
|
||||
(!exclude_banned
|
||||
|| !self
|
||||
.services
|
||||
.rooms
|
||||
.metadata
|
||||
.is_banned(room_id)
|
||||
.await)
|
||||
.filter_map(async |room_id| {
|
||||
(!exclude_banned || !self.services.metadata.is_banned(room_id).await)
|
||||
.then_some(room_id)
|
||||
})
|
||||
.then(|room_id| get_room_info(self.services, room_id))
|
||||
@@ -74,12 +61,26 @@ pub(super) async fn list_rooms(
|
||||
|
||||
#[admin_command]
|
||||
pub(super) async fn exists(&self, room_id: OwnedRoomId) -> Result {
|
||||
let result = self
|
||||
.services
|
||||
.rooms
|
||||
.metadata
|
||||
.exists(&room_id)
|
||||
.await;
|
||||
let result = self.services.metadata.exists(&room_id).await;
|
||||
|
||||
self.write_str(&format!("{result}")).await
|
||||
}
|
||||
|
||||
#[admin_command]
|
||||
pub(super) async fn delete_room(&self, room_id: OwnedRoomId, force: bool) -> Result {
|
||||
if self.services.admin.is_admin_room(&room_id).await {
|
||||
return Err!("Cannot delete admin room");
|
||||
}
|
||||
|
||||
let state_lock = self.services.state.mutex.lock(&room_id).await;
|
||||
|
||||
self.services
|
||||
.delete
|
||||
.delete_room(&room_id, force, state_lock)
|
||||
.await?;
|
||||
|
||||
self.write_str("Successfully deleted the room from our database.")
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use clap::Subcommand;
|
||||
use futures::StreamExt;
|
||||
use ruma::OwnedRoomId;
|
||||
use tuwunel_core::{Err, Result};
|
||||
use tuwunel_core::Result;
|
||||
|
||||
use crate::{Context, PAGE_SIZE, get_room_info};
|
||||
|
||||
@@ -29,18 +29,17 @@ pub(super) async fn process(command: RoomDirectoryCommand, context: &Context<'_>
|
||||
let services = context.services;
|
||||
match command {
|
||||
| RoomDirectoryCommand::Publish { room_id } => {
|
||||
services.rooms.directory.set_public(&room_id);
|
||||
services.directory.set_public(&room_id);
|
||||
context.write_str("Room published").await
|
||||
},
|
||||
| RoomDirectoryCommand::Unpublish { room_id } => {
|
||||
services.rooms.directory.set_not_public(&room_id);
|
||||
services.directory.set_not_public(&room_id);
|
||||
context.write_str("Room unpublished").await
|
||||
},
|
||||
| RoomDirectoryCommand::List { page } => {
|
||||
// TODO: i know there's a way to do this with clap, but i can't seem to find it
|
||||
let page = page.unwrap_or(1);
|
||||
let mut rooms: Vec<_> = services
|
||||
.rooms
|
||||
.directory
|
||||
.public_rooms()
|
||||
.then(|room_id| get_room_info(services, room_id))
|
||||
@@ -57,7 +56,11 @@ pub(super) async fn process(command: RoomDirectoryCommand, context: &Context<'_>
|
||||
.collect();
|
||||
|
||||
if rooms.is_empty() {
|
||||
return Err!("No more rooms.");
|
||||
context
|
||||
.write_str("No rooms are published.")
|
||||
.await?;
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let body = rooms
|
||||
|
||||
@@ -30,7 +30,6 @@ pub(crate) enum RoomInfoCommand {
|
||||
async fn list_joined_members(&self, room_id: OwnedRoomId, local_only: bool) -> Result {
|
||||
let room_name = self
|
||||
.services
|
||||
.rooms
|
||||
.state_accessor
|
||||
.get_name(&room_id)
|
||||
.await
|
||||
@@ -38,7 +37,6 @@ async fn list_joined_members(&self, room_id: OwnedRoomId, local_only: bool) -> R
|
||||
|
||||
let member_info: Vec<_> = self
|
||||
.services
|
||||
.rooms
|
||||
.state_cache
|
||||
.room_members(&room_id)
|
||||
.ready_filter(|user_id| {
|
||||
@@ -47,7 +45,7 @@ async fn list_joined_members(&self, room_id: OwnedRoomId, local_only: bool) -> R
|
||||
.unwrap_or(true)
|
||||
})
|
||||
.map(ToOwned::to_owned)
|
||||
.filter_map(|user_id| async move {
|
||||
.filter_map(async |user_id| {
|
||||
Some((
|
||||
self.services
|
||||
.users
|
||||
@@ -75,7 +73,6 @@ async fn list_joined_members(&self, room_id: OwnedRoomId, local_only: bool) -> R
|
||||
async fn view_room_topic(&self, room_id: OwnedRoomId) -> Result {
|
||||
let Ok(room_topic) = self
|
||||
.services
|
||||
.rooms
|
||||
.state_accessor
|
||||
.get_room_topic(&room_id)
|
||||
.await
|
||||
|
||||
@@ -56,4 +56,12 @@ pub(super) enum RoomCommand {
|
||||
Exists {
|
||||
room_id: OwnedRoomId,
|
||||
},
|
||||
|
||||
/// - Delete room
|
||||
DeleteRoom {
|
||||
room_id: OwnedRoomId,
|
||||
|
||||
#[arg(short, long)]
|
||||
force: bool,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
use clap::Subcommand;
|
||||
use futures::{FutureExt, StreamExt};
|
||||
use ruma::{OwnedRoomId, OwnedRoomOrAliasId, RoomAliasId, RoomId, RoomOrAliasId};
|
||||
use tuwunel_api::client::leave_room;
|
||||
use tuwunel_core::{
|
||||
Err, Result, debug,
|
||||
utils::{IterStream, ReadyExt},
|
||||
@@ -49,12 +48,12 @@ pub(crate) enum RoomModerationCommand {
|
||||
async fn ban_room(&self, room: OwnedRoomOrAliasId) -> Result {
|
||||
debug!("Got room alias or ID: {}", room);
|
||||
|
||||
let admin_room_alias = &self.services.globals.admin_alias;
|
||||
let admin_room_alias = &self.services.admin.admin_alias;
|
||||
|
||||
if let Ok(admin_room_id) = self.services.admin.get_admin_room().await {
|
||||
if room.to_string().eq(&admin_room_id) || room.to_string().eq(admin_room_alias) {
|
||||
return Err!("Not allowed to ban the admin room.");
|
||||
}
|
||||
if let Ok(admin_room_id) = self.services.admin.get_admin_room().await
|
||||
&& (room.to_string().eq(&admin_room_id) || room.to_string().eq(admin_room_alias))
|
||||
{
|
||||
return Err!("Not allowed to ban the admin room.");
|
||||
}
|
||||
|
||||
let room_id = if room.is_room_id() {
|
||||
@@ -70,10 +69,7 @@ async fn ban_room(&self, room: OwnedRoomOrAliasId) -> Result {
|
||||
};
|
||||
|
||||
debug!("Room specified is a room ID, banning room ID");
|
||||
self.services
|
||||
.rooms
|
||||
.metadata
|
||||
.ban_room(room_id, true);
|
||||
self.services.metadata.ban_room(room_id);
|
||||
|
||||
room_id.to_owned()
|
||||
} else if room.is_room_alias_id() {
|
||||
@@ -95,7 +91,6 @@ async fn ban_room(&self, room: OwnedRoomOrAliasId) -> Result {
|
||||
|
||||
let room_id = match self
|
||||
.services
|
||||
.rooms
|
||||
.alias
|
||||
.resolve_local_alias(room_alias)
|
||||
.await
|
||||
@@ -109,9 +104,8 @@ async fn ban_room(&self, room: OwnedRoomOrAliasId) -> Result {
|
||||
|
||||
match self
|
||||
.services
|
||||
.rooms
|
||||
.alias
|
||||
.resolve_alias(room_alias, None)
|
||||
.resolve_alias(room_alias)
|
||||
.await
|
||||
{
|
||||
| Ok((room_id, servers)) => {
|
||||
@@ -131,10 +125,7 @@ async fn ban_room(&self, room: OwnedRoomOrAliasId) -> Result {
|
||||
},
|
||||
};
|
||||
|
||||
self.services
|
||||
.rooms
|
||||
.metadata
|
||||
.ban_room(&room_id, true);
|
||||
self.services.metadata.ban_room(&room_id);
|
||||
|
||||
room_id
|
||||
} else {
|
||||
@@ -148,7 +139,6 @@ async fn ban_room(&self, room: OwnedRoomOrAliasId) -> Result {
|
||||
debug!("Making all users leave the room {room_id} and forgetting it");
|
||||
let mut users = self
|
||||
.services
|
||||
.rooms
|
||||
.state_cache
|
||||
.room_members(&room_id)
|
||||
.map(ToOwned::to_owned)
|
||||
@@ -161,27 +151,31 @@ async fn ban_room(&self, room: OwnedRoomOrAliasId) -> Result {
|
||||
evicting admins too)",
|
||||
);
|
||||
|
||||
if let Err(e) = leave_room(self.services, user_id, &room_id, None)
|
||||
let state_lock = self.services.state.mutex.lock(&room_id).await;
|
||||
|
||||
if let Err(e) = self
|
||||
.services
|
||||
.membership
|
||||
.leave(user_id, &room_id, None, false, &state_lock)
|
||||
.boxed()
|
||||
.await
|
||||
{
|
||||
warn!("Failed to leave room: {e}");
|
||||
}
|
||||
|
||||
drop(state_lock);
|
||||
|
||||
self.services
|
||||
.rooms
|
||||
.state_cache
|
||||
.forget(&room_id, user_id);
|
||||
}
|
||||
|
||||
self.services
|
||||
.rooms
|
||||
.alias
|
||||
.local_aliases_for_room(&room_id)
|
||||
.map(ToOwned::to_owned)
|
||||
.for_each(|local_alias| async move {
|
||||
.for_each(async |local_alias| {
|
||||
self.services
|
||||
.rooms
|
||||
.alias
|
||||
.remove_alias(&local_alias, &self.services.globals.server_user)
|
||||
.await
|
||||
@@ -190,15 +184,9 @@ async fn ban_room(&self, room: OwnedRoomOrAliasId) -> Result {
|
||||
.await;
|
||||
|
||||
// unpublish from room directory
|
||||
self.services
|
||||
.rooms
|
||||
.directory
|
||||
.set_not_public(&room_id);
|
||||
self.services.directory.set_not_public(&room_id);
|
||||
|
||||
self.services
|
||||
.rooms
|
||||
.metadata
|
||||
.disable_room(&room_id, true);
|
||||
self.services.metadata.disable_room(&room_id);
|
||||
|
||||
self.write_str(
|
||||
"Room banned, removed all our local users, and disabled incoming federation with room.",
|
||||
@@ -221,7 +209,7 @@ async fn ban_list_of_rooms(&self) -> Result {
|
||||
.drain(1..self.body.len().saturating_sub(1))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let admin_room_alias = &self.services.globals.admin_alias;
|
||||
let admin_room_alias = &self.services.admin.admin_alias;
|
||||
|
||||
let mut room_ban_count: usize = 0;
|
||||
let mut room_ids: Vec<OwnedRoomId> = Vec::new();
|
||||
@@ -229,12 +217,12 @@ async fn ban_list_of_rooms(&self) -> Result {
|
||||
for &room in &rooms_s {
|
||||
match <&RoomOrAliasId>::try_from(room) {
|
||||
| Ok(room_alias_or_id) => {
|
||||
if let Ok(admin_room_id) = self.services.admin.get_admin_room().await {
|
||||
if room.to_owned().eq(&admin_room_id) || room.to_owned().eq(admin_room_alias)
|
||||
{
|
||||
warn!("User specified admin room in bulk ban list, ignoring");
|
||||
continue;
|
||||
}
|
||||
if let Ok(admin_room_id) = self.services.admin.get_admin_room().await
|
||||
&& (room.to_owned().eq(&admin_room_id)
|
||||
|| room.to_owned().eq(admin_room_alias))
|
||||
{
|
||||
warn!("User specified admin room in bulk ban list, ignoring");
|
||||
continue;
|
||||
}
|
||||
|
||||
if room_alias_or_id.is_room_id() {
|
||||
@@ -258,7 +246,6 @@ async fn ban_list_of_rooms(&self) -> Result {
|
||||
| Ok(room_alias) => {
|
||||
let room_id = match self
|
||||
.services
|
||||
.rooms
|
||||
.alias
|
||||
.resolve_local_alias(room_alias)
|
||||
.await
|
||||
@@ -272,9 +259,8 @@ async fn ban_list_of_rooms(&self) -> Result {
|
||||
|
||||
match self
|
||||
.services
|
||||
.rooms
|
||||
.alias
|
||||
.resolve_alias(room_alias, None)
|
||||
.resolve_alias(room_alias)
|
||||
.await
|
||||
{
|
||||
| Ok((room_id, servers)) => {
|
||||
@@ -320,10 +306,7 @@ async fn ban_list_of_rooms(&self) -> Result {
|
||||
}
|
||||
|
||||
for room_id in room_ids {
|
||||
self.services
|
||||
.rooms
|
||||
.metadata
|
||||
.ban_room(&room_id, true);
|
||||
self.services.metadata.ban_room(&room_id);
|
||||
|
||||
debug!("Banned {room_id} successfully");
|
||||
room_ban_count = room_ban_count.saturating_add(1);
|
||||
@@ -331,7 +314,6 @@ async fn ban_list_of_rooms(&self) -> Result {
|
||||
debug!("Making all users leave the room {room_id} and forgetting it");
|
||||
let mut users = self
|
||||
.services
|
||||
.rooms
|
||||
.state_cache
|
||||
.room_members(&room_id)
|
||||
.map(ToOwned::to_owned)
|
||||
@@ -344,28 +326,32 @@ async fn ban_list_of_rooms(&self) -> Result {
|
||||
evicting admins too)",
|
||||
);
|
||||
|
||||
if let Err(e) = leave_room(self.services, user_id, &room_id, None)
|
||||
let state_lock = self.services.state.mutex.lock(&room_id).await;
|
||||
|
||||
if let Err(e) = self
|
||||
.services
|
||||
.membership
|
||||
.leave(user_id, &room_id, None, false, &state_lock)
|
||||
.boxed()
|
||||
.await
|
||||
{
|
||||
warn!("Failed to leave room: {e}");
|
||||
}
|
||||
|
||||
drop(state_lock);
|
||||
|
||||
self.services
|
||||
.rooms
|
||||
.state_cache
|
||||
.forget(&room_id, user_id);
|
||||
}
|
||||
|
||||
// remove any local aliases, ignore errors
|
||||
self.services
|
||||
.rooms
|
||||
.alias
|
||||
.local_aliases_for_room(&room_id)
|
||||
.map(ToOwned::to_owned)
|
||||
.for_each(|local_alias| async move {
|
||||
.for_each(async |local_alias| {
|
||||
self.services
|
||||
.rooms
|
||||
.alias
|
||||
.remove_alias(&local_alias, &self.services.globals.server_user)
|
||||
.await
|
||||
@@ -374,15 +360,9 @@ async fn ban_list_of_rooms(&self) -> Result {
|
||||
.await;
|
||||
|
||||
// unpublish from room directory, ignore errors
|
||||
self.services
|
||||
.rooms
|
||||
.directory
|
||||
.set_not_public(&room_id);
|
||||
self.services.directory.set_not_public(&room_id);
|
||||
|
||||
self.services
|
||||
.rooms
|
||||
.metadata
|
||||
.disable_room(&room_id, true);
|
||||
self.services.metadata.disable_room(&room_id);
|
||||
}
|
||||
|
||||
self.write_str(&format!(
|
||||
@@ -407,10 +387,7 @@ async fn unban_room(&self, room: OwnedRoomOrAliasId) -> Result {
|
||||
};
|
||||
|
||||
debug!("Room specified is a room ID, unbanning room ID");
|
||||
self.services
|
||||
.rooms
|
||||
.metadata
|
||||
.ban_room(room_id, false);
|
||||
self.services.metadata.unban_room(room_id);
|
||||
|
||||
room_id.to_owned()
|
||||
} else if room.is_room_alias_id() {
|
||||
@@ -432,7 +409,6 @@ async fn unban_room(&self, room: OwnedRoomOrAliasId) -> Result {
|
||||
|
||||
let room_id = match self
|
||||
.services
|
||||
.rooms
|
||||
.alias
|
||||
.resolve_local_alias(room_alias)
|
||||
.await
|
||||
@@ -446,9 +422,8 @@ async fn unban_room(&self, room: OwnedRoomOrAliasId) -> Result {
|
||||
|
||||
match self
|
||||
.services
|
||||
.rooms
|
||||
.alias
|
||||
.resolve_alias(room_alias, None)
|
||||
.resolve_alias(room_alias)
|
||||
.await
|
||||
{
|
||||
| Ok((room_id, servers)) => {
|
||||
@@ -466,10 +441,7 @@ async fn unban_room(&self, room: OwnedRoomOrAliasId) -> Result {
|
||||
},
|
||||
};
|
||||
|
||||
self.services
|
||||
.rooms
|
||||
.metadata
|
||||
.ban_room(&room_id, false);
|
||||
self.services.metadata.unban_room(&room_id);
|
||||
|
||||
room_id
|
||||
} else {
|
||||
@@ -480,10 +452,7 @@ async fn unban_room(&self, room: OwnedRoomOrAliasId) -> Result {
|
||||
);
|
||||
};
|
||||
|
||||
self.services
|
||||
.rooms
|
||||
.metadata
|
||||
.disable_room(&room_id, false);
|
||||
self.services.metadata.enable_room(&room_id);
|
||||
self.write_str("Room unbanned and federation re-enabled.")
|
||||
.await
|
||||
}
|
||||
@@ -492,7 +461,6 @@ async fn unban_room(&self, room: OwnedRoomOrAliasId) -> Result {
|
||||
async fn list_banned_rooms(&self, no_details: bool) -> Result {
|
||||
let room_ids: Vec<OwnedRoomId> = self
|
||||
.services
|
||||
.rooms
|
||||
.metadata
|
||||
.list_banned_rooms()
|
||||
.map(Into::into)
|
||||
|
||||
@@ -67,7 +67,7 @@ pub(super) async fn list_features(&self, available: bool, enabled: bool, comma:
|
||||
#[admin_command]
|
||||
pub(super) async fn memory_usage(&self) -> Result {
|
||||
let services_usage = self.services.memory_usage().await?;
|
||||
let database_usage = self.services.db.db.memory_usage()?;
|
||||
let database_usage = self.services.db.engine.memory_usage()?;
|
||||
let allocator_usage = tuwunel_core::alloc::memory_usage()
|
||||
.map_or(String::new(), |s| format!("\nAllocator:\n{s}"));
|
||||
|
||||
@@ -88,7 +88,7 @@ pub(super) async fn clear_caches(&self) -> Result {
|
||||
pub(super) async fn list_backups(&self) -> Result {
|
||||
self.services
|
||||
.db
|
||||
.db
|
||||
.engine
|
||||
.backup_list()?
|
||||
.try_stream()
|
||||
.try_for_each(|result| write!(self, "{result}"))
|
||||
@@ -102,13 +102,13 @@ pub(super) async fn backup_database(&self) -> Result {
|
||||
.services
|
||||
.server
|
||||
.runtime()
|
||||
.spawn_blocking(move || match db.db.backup() {
|
||||
.spawn_blocking(move || match db.engine.backup() {
|
||||
| Ok(()) => "Done".to_owned(),
|
||||
| Err(e) => format!("Failed: {e}"),
|
||||
})
|
||||
.await?;
|
||||
|
||||
let count = self.services.db.db.backup_count()?;
|
||||
let count = self.services.db.engine.backup_count()?;
|
||||
self.write_str(&format!("{result}. Currently have {count} backups."))
|
||||
.await
|
||||
}
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
use futures::StreamExt;
|
||||
use tuwunel_core::{Result, utils};
|
||||
use tuwunel_macros::admin_command;
|
||||
use tuwunel_service::registration_tokens::TokenExpires;
|
||||
|
||||
#[admin_command]
|
||||
pub(super) async fn issue(
|
||||
&self,
|
||||
max_uses: Option<u64>,
|
||||
max_age: Option<String>,
|
||||
once: bool,
|
||||
) -> Result {
|
||||
let expires = TokenExpires {
|
||||
max_uses: max_uses.or_else(|| once.then_some(1)),
|
||||
max_age: max_age
|
||||
.map(|max_age| {
|
||||
let duration = utils::time::parse_duration(&max_age)?;
|
||||
utils::time::timepoint_from_now(duration)
|
||||
})
|
||||
.transpose()?,
|
||||
};
|
||||
|
||||
let (token, info) = self
|
||||
.services
|
||||
.registration_tokens
|
||||
.issue_token(expires)
|
||||
.await?;
|
||||
|
||||
self.write_str(&format!("New registration token issued: `{token}` - {info}",))
|
||||
.await
|
||||
}
|
||||
|
||||
#[admin_command]
|
||||
pub(super) async fn revoke(&self, token: String) -> Result {
|
||||
self.services
|
||||
.registration_tokens
|
||||
.revoke_token(&token)
|
||||
.await?;
|
||||
|
||||
self.write_str("Token revoked successfully.")
|
||||
.await
|
||||
}
|
||||
|
||||
#[admin_command]
|
||||
pub(super) async fn list(&self) -> Result {
|
||||
let tokens: Vec<_> = self
|
||||
.services
|
||||
.registration_tokens
|
||||
.iterate_tokens()
|
||||
.collect()
|
||||
.await;
|
||||
|
||||
self.write_str(&format!("Found {} registration tokens:\n", tokens.len()))
|
||||
.await?;
|
||||
|
||||
for token in tokens {
|
||||
self.write_str(&format!("- {token}\n")).await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user