1{ pkgs, ... }:
2
3let
4 backend =
5 { pkgs, ... }:
6 {
7 services.httpd = {
8 enable = true;
9 adminAddr = "foo@example.org";
10 virtualHosts.localhost.documentRoot = "${pkgs.valgrind.doc}/share/doc/valgrind/html";
11 };
12 networking.firewall.allowedTCPPorts = [ 80 ];
13 };
14in
15{
16 name = "proxy";
17 meta = with pkgs.lib.maintainers; {
18 maintainers = [ ];
19 };
20
21 nodes = {
22 proxy =
23 { nodes, ... }:
24 {
25 services.httpd = {
26 enable = true;
27 adminAddr = "bar@example.org";
28 extraModules = [
29 "proxy_balancer"
30 "lbmethod_byrequests"
31 ];
32 extraConfig = ''
33 ExtendedStatus on
34 '';
35 virtualHosts.localhost = {
36 extraConfig = ''
37 <Location /server-status>
38 Require all granted
39 SetHandler server-status
40 </Location>
41
42 <Proxy balancer://cluster>
43 Require all granted
44 BalancerMember http://${nodes.backend1.config.networking.hostName} retry=0
45 BalancerMember http://${nodes.backend2.config.networking.hostName} retry=0
46 </Proxy>
47
48 ProxyStatus full
49 ProxyPass /server-status !
50 ProxyPass / balancer://cluster/
51 ProxyPassReverse / balancer://cluster/
52
53 # For testing; don't want to wait forever for dead backend servers.
54 ProxyTimeout 5
55 '';
56 };
57 };
58 networking.firewall.allowedTCPPorts = [ 80 ];
59 };
60
61 backend1 = backend;
62 backend2 = backend;
63
64 client = { ... }: { };
65 };
66
67 testScript = ''
68 start_all()
69
70 proxy.wait_for_unit("httpd")
71 backend1.wait_for_unit("httpd")
72 backend2.wait_for_unit("httpd")
73 client.wait_for_unit("network.target")
74
75 # With the back-ends up, the proxy should work.
76 client.succeed("curl --fail http://proxy/")
77
78 client.succeed("curl --fail http://proxy/server-status")
79
80 # Block the first back-end.
81 backend1.block()
82
83 # The proxy should still work.
84 client.succeed("curl --fail http://proxy/")
85 client.succeed("curl --fail http://proxy/")
86
87 # Block the second back-end.
88 backend2.block()
89
90 # Now the proxy should fail as well.
91 client.fail("curl --fail http://proxy/")
92
93 # But if the second back-end comes back, the proxy should start
94 # working again.
95 backend2.unblock()
96 client.succeed("curl --fail http://proxy/")
97 '';
98}