1{ config, lib, pkgs, ... }:
2
3with lib;
4
5{
6 options = {
7
8 services.v2ray = {
9 enable = mkOption {
10 type = types.bool;
11 default = false;
12 description = ''
13 Whether to run v2ray server.
14
15 Either <literal>configFile</literal> or <literal>config</literal> must be specified.
16 '';
17 };
18
19 configFile = mkOption {
20 type = types.nullOr types.str;
21 default = null;
22 example = "/etc/v2ray/config.json";
23 description = ''
24 The absolute path to the configuration file.
25
26 Either <literal>configFile</literal> or <literal>config</literal> must be specified.
27
28 See <link xlink:href="https://v2ray.com/en/configuration/overview.html"/>.
29 '';
30 };
31
32 config = mkOption {
33 type = types.nullOr (types.attrsOf types.unspecified);
34 default = null;
35 example = {
36 inbounds = [{
37 port = 1080;
38 listen = "127.0.0.1";
39 protocol = "http";
40 }];
41 outbounds = [{
42 protocol = "freedom";
43 }];
44 };
45 description = ''
46 The configuration object.
47
48 Either `configFile` or `config` must be specified.
49
50 See <link xlink:href="https://v2ray.com/en/configuration/overview.html"/>.
51 '';
52 };
53 };
54
55 };
56
57 config = let
58 cfg = config.services.v2ray;
59 configFile = if cfg.configFile != null
60 then cfg.configFile
61 else pkgs.writeTextFile {
62 name = "v2ray.json";
63 text = builtins.toJSON cfg.config;
64 checkPhase = ''
65 ${pkgs.v2ray}/bin/v2ray -test -config $out
66 '';
67 };
68
69 in mkIf cfg.enable {
70 assertions = [
71 {
72 assertion = (cfg.configFile == null) != (cfg.config == null);
73 message = "Either but not both `configFile` and `config` should be specified for v2ray.";
74 }
75 ];
76
77 systemd.services.v2ray = {
78 description = "v2ray Daemon";
79 after = [ "network.target" ];
80 wantedBy = [ "multi-user.target" ];
81 path = [ pkgs.v2ray ];
82 script = ''
83 exec v2ray -config ${configFile}
84 '';
85 };
86 };
87}