1{ lib, pkgs, ... }:
2let
3
4 v2rayUser = {
5 # A random UUID.
6 id = "a6a46834-2150-45f8-8364-0f6f6ab32384";
7 alterId = 0; # Non-zero support will be disabled in the future.
8 };
9
10 # 1080 [http proxy] -> 1081 [vmess] -> direct
11 v2rayConfig = {
12 inbounds = [
13 {
14 tag = "http_in";
15 port = 1080;
16 listen = "127.0.0.1";
17 protocol = "http";
18 }
19 {
20 tag = "vmess_in";
21 port = 1081;
22 listen = "127.0.0.1";
23 protocol = "vmess";
24 settings.clients = [ v2rayUser ];
25 }
26 ];
27 outbounds = [
28 {
29 tag = "vmess_out";
30 protocol = "vmess";
31 settings.vnext = [
32 {
33 address = "127.0.0.1";
34 port = 1081;
35 users = [ v2rayUser ];
36 }
37 ];
38 }
39 {
40 tag = "direct";
41 protocol = "freedom";
42 }
43 ];
44 routing.rules = [
45 {
46 type = "field";
47 inboundTag = "http_in";
48 outboundTag = "vmess_out";
49 }
50 {
51 type = "field";
52 inboundTag = "vmess_in";
53 outboundTag = "direct";
54 }
55
56 # Assert assets "geoip" and "geosite" are accessible.
57 {
58 type = "field";
59 ip = [ "geoip:private" ];
60 domain = [ "geosite:category-ads" ];
61 outboundTag = "direct";
62 }
63 ];
64 };
65
66in
67{
68 name = "v2ray";
69 meta = with lib.maintainers; {
70 maintainers = [ servalcatty ];
71 };
72 nodes.machine =
73 { pkgs, ... }:
74 {
75 environment.systemPackages = [ pkgs.curl ];
76 services.v2ray = {
77 enable = true;
78 config = v2rayConfig;
79 };
80 services.httpd = {
81 enable = true;
82 adminAddr = "foo@example.org";
83 };
84 };
85
86 testScript = ''
87 start_all()
88
89 machine.wait_for_unit("httpd.service")
90 machine.wait_for_unit("v2ray.service")
91 machine.wait_for_open_port(80)
92 machine.wait_for_open_port(1080)
93 machine.succeed(
94 "curl --fail --max-time 10 --proxy http://localhost:1080 http://localhost"
95 )
96 '';
97}