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 `configFile` or `config` must be specified.
16 '';
17 };
18
19 package = mkPackageOption pkgs "v2ray" { };
20
21 configFile = mkOption {
22 type = types.nullOr types.str;
23 default = null;
24 example = "/etc/v2ray/config.json";
25 description = ''
26 The absolute path to the configuration file.
27
28 Either `configFile` or `config` must be specified.
29
30 See <https://www.v2fly.org/en_US/v5/config/overview.html>.
31 '';
32 };
33
34 config = mkOption {
35 type = types.nullOr (types.attrsOf types.unspecified);
36 default = null;
37 example = {
38 inbounds = [{
39 port = 1080;
40 listen = "127.0.0.1";
41 protocol = "http";
42 }];
43 outbounds = [{
44 protocol = "freedom";
45 }];
46 };
47 description = ''
48 The configuration object.
49
50 Either `configFile` or `config` must be specified.
51
52 See <https://www.v2fly.org/en_US/v5/config/overview.html>.
53 '';
54 };
55 };
56
57 };
58
59 config = let
60 cfg = config.services.v2ray;
61 configFile = if cfg.configFile != null
62 then cfg.configFile
63 else pkgs.writeTextFile {
64 name = "v2ray.json";
65 text = builtins.toJSON cfg.config;
66 checkPhase = ''
67 ${cfg.package}/bin/v2ray test -c $out
68 '';
69 };
70
71 in mkIf cfg.enable {
72 assertions = [
73 {
74 assertion = (cfg.configFile == null) != (cfg.config == null);
75 message = "Either but not both `configFile` and `config` should be specified for v2ray.";
76 }
77 ];
78
79 environment.etc."v2ray/config.json".source = configFile;
80
81 systemd.packages = [ cfg.package ];
82
83 systemd.services.v2ray = {
84 restartTriggers = [ config.environment.etc."v2ray/config.json".source ];
85
86 # Workaround: https://github.com/NixOS/nixpkgs/issues/81138
87 wantedBy = [ "multi-user.target" ];
88 };
89 };
90}