1{ pkgs, ... }:
2{
3 name = "invidious";
4
5 meta = with pkgs.lib.maintainers; {
6 maintainers = [ sbruder ];
7 };
8
9 nodes = {
10 postgres-tcp =
11 { config, pkgs, ... }:
12 {
13 services.postgresql = {
14 enable = true;
15 initialScript = pkgs.writeText "init-postgres-with-password" ''
16 CREATE USER invidious WITH PASSWORD 'correct horse battery staple';
17 CREATE DATABASE invidious WITH OWNER invidious;
18 '';
19 enableTCPIP = true;
20 authentication = ''
21 host invidious invidious samenet scram-sha-256
22 '';
23 };
24 networking.firewall.allowedTCPPorts = [ config.services.postgresql.settings.port ];
25 };
26 machine =
27 { lib, pkgs, ... }:
28 {
29 services.invidious = {
30 enable = true;
31 };
32
33 specialisation = {
34 nginx.configuration = {
35 services.invidious = {
36 nginx.enable = true;
37 domain = "invidious.example.com";
38 };
39 services.nginx.virtualHosts."invidious.example.com" = {
40 forceSSL = false;
41 enableACME = false;
42 };
43 networking.hosts."127.0.0.1" = [ "invidious.example.com" ];
44 };
45 nginx-sig-helper.configuration = {
46 services.invidious = {
47 nginx.enable = true;
48 domain = "invidious.example.com";
49 sig-helper.enable = true;
50 settings.log_level = "Trace";
51 };
52 services.nginx.virtualHosts."invidious.example.com" = {
53 forceSSL = false;
54 enableACME = false;
55 };
56 networking.hosts."127.0.0.1" = [ "invidious.example.com" ];
57 };
58 nginx-scale.configuration = {
59 services.invidious = {
60 nginx.enable = true;
61 domain = "invidious.example.com";
62 serviceScale = 3;
63 };
64 services.nginx.virtualHosts."invidious.example.com" = {
65 forceSSL = false;
66 enableACME = false;
67 };
68 networking.hosts."127.0.0.1" = [ "invidious.example.com" ];
69 };
70 nginx-scale-ytproxy.configuration = {
71 services.invidious = {
72 nginx.enable = true;
73 http3-ytproxy.enable = true;
74 domain = "invidious.example.com";
75 serviceScale = 3;
76 };
77 services.nginx.virtualHosts."invidious.example.com" = {
78 forceSSL = false;
79 enableACME = false;
80 };
81 networking.hosts."127.0.0.1" = [ "invidious.example.com" ];
82 };
83 postgres-tcp.configuration = {
84 services.invidious = {
85 database = {
86 createLocally = false;
87 host = "postgres-tcp";
88 passwordFile = toString (pkgs.writeText "database-password" "correct horse battery staple");
89 };
90 };
91 };
92 };
93 };
94 };
95
96 testScript =
97 { nodes, ... }:
98 ''
99 def curl_assert_status_code(url, code, form=None):
100 assert int(machine.succeed(f"curl -s -o /dev/null -w %{{http_code}} {'-F ' + form + ' ' if form else '''}{url}")) == code
101
102
103 def activate_specialisation(name: str):
104 machine.succeed(f"${nodes.machine.system.build.toplevel}/specialisation/{name}/bin/switch-to-configuration test >&2")
105
106
107 url = "http://localhost:${toString nodes.machine.services.invidious.port}"
108 port = ${toString nodes.machine.services.invidious.port}
109
110 # start postgres vm now
111 postgres_tcp.start()
112
113 machine.wait_for_open_port(port)
114 curl_assert_status_code(f"{url}/search", 200)
115
116 activate_specialisation("nginx")
117 machine.wait_for_open_port(80)
118 curl_assert_status_code("http://invidious.example.com/search", 200)
119
120 activate_specialisation("nginx-scale")
121 machine.wait_for_open_port(80)
122 # this depends on nginx round-robin behaviour for the upstream servers
123 curl_assert_status_code("http://invidious.example.com/search", 200)
124 curl_assert_status_code("http://invidious.example.com/search", 200)
125 curl_assert_status_code("http://invidious.example.com/search", 200)
126 machine.succeed("journalctl -eu invidious.service | grep -o '200 GET /search'")
127 machine.succeed("journalctl -eu invidious-1.service | grep -o '200 GET /search'")
128 machine.succeed("journalctl -eu invidious-2.service | grep -o '200 GET /search'")
129
130 activate_specialisation("nginx-scale-ytproxy")
131 machine.wait_for_unit("http3-ytproxy.service")
132 machine.wait_for_open_port(80)
133 machine.wait_until_succeeds("ls /run/http3-ytproxy/socket/http-proxy.sock")
134 curl_assert_status_code("http://invidious.example.com/search", 200)
135 # this should error out as no internet connectivity is available in the test
136 curl_assert_status_code("http://invidious.example.com/vi/dQw4w9WgXcQ/mqdefault.jpg", 502)
137 machine.succeed("journalctl -eu http3-ytproxy.service | grep -o 'dQw4w9WgXcQ'")
138
139 activate_specialisation("nginx-sig-helper")
140 machine.wait_for_unit("invidious-sig-helper.service")
141 # we can't really test the sig helper that well without internet connection...
142 # invidious does connect to the sig helper though and crashes when the sig helper is not available
143 machine.wait_for_open_port(80)
144 curl_assert_status_code("http://invidious.example.com/search", 200)
145 machine.succeed("journalctl -eu invidious.service | grep -o \"SigHelper: Using helper at 'tcp://127.0.0.1:2999'\"")
146
147 postgres_tcp.wait_for_unit("postgresql.target")
148 activate_specialisation("postgres-tcp")
149 machine.wait_for_open_port(port)
150 curl_assert_status_code(f"{url}/search", 200)
151 '';
152}