1{
2 config,
3 lib,
4 pkgs,
5 utils,
6 ...
7}:
8let
9 cfg = config.services.sing-box;
10 settingsFormat = pkgs.formats.json { };
11in
12{
13
14 meta = {
15 maintainers = with lib.maintainers; [ nickcao ];
16 };
17
18 options = {
19 services.sing-box = {
20 enable = lib.mkEnableOption "sing-box universal proxy platform";
21
22 package = lib.mkPackageOption pkgs "sing-box" { };
23
24 settings = lib.mkOption {
25 type = lib.types.submodule {
26 freeformType = settingsFormat.type;
27 };
28 default = { };
29 description = ''
30 The sing-box configuration, see https://sing-box.sagernet.org/configuration/ for documentation.
31
32 Options containing secret data should be set to an attribute set
33 containing the attribute `_secret` - a string pointing to a file
34 containing the value the option should be set to.
35 '';
36 };
37 };
38 };
39
40 config = lib.mkIf cfg.enable {
41 assertions =
42 let
43 rules = cfg.settings.route.rules or [ ];
44 in
45 [
46 {
47 assertion = !lib.any (r: r ? source_geoip || r ? geoip) rules;
48 message = ''
49 Deprecated option `services.sing-box.settings.route.rules.*.{source_geoip,geoip}` is set.
50 See https://sing-box.sagernet.org/migration/#migrate-geoip-to-rule-sets for migration instructions.
51 '';
52 }
53 {
54 assertion = !lib.any (r: r ? geosite) rules;
55 message = ''
56 Deprecated option `services.sing-box.settings.route.rules.*.geosite` is set.
57 See https://sing-box.sagernet.org/migration/#migrate-geosite-to-rule-sets for migration instructions.
58 '';
59 }
60 ];
61
62 systemd.packages = [ cfg.package ];
63
64 systemd.services.sing-box = {
65 preStart = utils.genJqSecretsReplacementSnippet cfg.settings "/run/sing-box/config.json";
66 serviceConfig = {
67 StateDirectory = "sing-box";
68 StateDirectoryMode = "0700";
69 RuntimeDirectory = "sing-box";
70 RuntimeDirectoryMode = "0700";
71 ExecStart = [
72 ""
73 "${lib.getExe cfg.package} -D \${STATE_DIRECTORY} -C \${RUNTIME_DIRECTORY} run"
74 ];
75 };
76 wantedBy = [ "multi-user.target" ];
77 };
78 };
79
80}