1 { config, lib, pkgs, ... }:
7 cfg = config.services.nylon;
9 homeDir = "/var/lib/nylon";
11 configFile = cfg: pkgs.writeText "nylon-${cfg.name}.conf" ''
13 No-Simultaneous-Conn=${toString cfg.nrConnections}
14 Log=${if cfg.logging then "1" else "0"}
15 Verbose=${if cfg.verbosity then "1" else "0"}
18 Binding-Interface=${cfg.acceptInterface}
19 Connecting-Interface=${cfg.bindInterface}
20 Port=${toString cfg.port}
21 Allow-IP=${concatStringsSep " " cfg.allowedIPRanges}
22 Deny-IP=${concatStringsSep " " cfg.deniedIPRanges}
25 nylonOpts = { name, ... }: {
32 description = lib.mdDoc ''
33 Enables nylon as a running service upon activation.
40 description = lib.mdDoc "The name of this nylon instance.";
43 nrConnections = mkOption {
46 description = lib.mdDoc ''
47 The number of allowed simultaneous connections to the daemon, default 10.
54 description = lib.mdDoc ''
55 Enable logging, default is no logging.
59 verbosity = mkOption {
62 description = lib.mdDoc ''
63 Enable verbose output, default is to not be verbose.
67 acceptInterface = mkOption {
70 description = lib.mdDoc ''
71 Tell nylon which interface to listen for client requests on, default is "lo".
75 bindInterface = mkOption {
78 description = lib.mdDoc ''
79 Tell nylon which interface to use as an uplink, default is "enp3s0f0".
86 description = lib.mdDoc ''
87 What port to listen for client requests, default is 1080.
91 allowedIPRanges = mkOption {
92 type = with types; listOf str;
93 default = [ "192.168.0.0/16" "127.0.0.1/8" "172.16.0.1/12" "10.0.0.0/8" ];
94 description = lib.mdDoc ''
95 Allowed client IP ranges are evaluated first, defaults to ARIN IPv4 private ranges:
96 [ "192.168.0.0/16" "127.0.0.0/8" "172.16.0.0/12" "10.0.0.0/8" ]
100 deniedIPRanges = mkOption {
101 type = with types; listOf str;
102 default = [ "0.0.0.0/0" ];
103 description = lib.mdDoc ''
104 Denied client IP ranges, these gets evaluated after the allowed IP ranges, defaults to all IPv4 addresses:
106 To block all other access than the allowed.
110 config = { name = mkDefault name; };
113 mkNamedNylon = cfg: {
114 "nylon-${cfg.name}" = {
115 description = "Nylon, a lightweight SOCKS proxy server";
116 after = [ "network.target" ];
117 wantedBy = [ "multi-user.target" ];
122 WorkingDirectory = homeDir;
123 ExecStart = "${pkgs.nylon}/bin/nylon -f -c ${configFile cfg}";
128 anyNylons = collect (p: p ? enable) cfg;
129 enabledNylons = filter (p: p.enable == true) anyNylons;
130 nylonUnits = map (nylon: mkNamedNylon nylon) enabledNylons;
140 services.nylon = mkOption {
142 description = lib.mdDoc "Collection of named nylon instances";
143 type = with types; attrsOf (submodule nylonOpts);
149 ###### implementation
151 config = mkIf (length(enabledNylons) > 0) {
153 users.users.nylon = {
155 description = "Nylon SOCKS Proxy";
158 uid = config.ids.uids.nylon;
161 users.groups.nylon.gid = config.ids.gids.nylon;
163 systemd.services = foldr (a: b: a // b) {} nylonUnits;