at 18.09-beta 2.8 kB view raw
1{ config, lib, pkgs, ... }: 2 3with lib; 4 5let 6 cfg = config.services.shadowsocks; 7 8 opts = { 9 server = cfg.localAddress; 10 server_port = cfg.port; 11 method = cfg.encryptionMethod; 12 mode = cfg.mode; 13 user = "nobody"; 14 fast_open = true; 15 } // optionalAttrs (cfg.password != null) { password = cfg.password; }; 16 17 configFile = pkgs.writeText "shadowsocks.json" (builtins.toJSON opts); 18 19in 20 21{ 22 23 ###### interface 24 25 options = { 26 27 services.shadowsocks = { 28 29 enable = mkOption { 30 type = types.bool; 31 default = false; 32 description = '' 33 Whether to run shadowsocks-libev shadowsocks server. 34 ''; 35 }; 36 37 localAddress = mkOption { 38 type = types.str; 39 default = "0.0.0.0"; 40 description = '' 41 Local address to which the server binds. 42 ''; 43 }; 44 45 port = mkOption { 46 type = types.int; 47 default = 8388; 48 description = '' 49 Port which the server uses. 50 ''; 51 }; 52 53 password = mkOption { 54 type = types.nullOr types.str; 55 default = null; 56 description = '' 57 Password for connecting clients. 58 ''; 59 }; 60 61 passwordFile = mkOption { 62 type = types.nullOr types.path; 63 default = null; 64 description = '' 65 Password file with a password for connecting clients. 66 ''; 67 }; 68 69 mode = mkOption { 70 type = types.enum [ "tcp_only" "tcp_and_udp" "udp_only" ]; 71 default = "tcp_and_udp"; 72 description = '' 73 Relay protocols. 74 ''; 75 }; 76 77 encryptionMethod = mkOption { 78 type = types.str; 79 default = "chacha20-ietf-poly1305"; 80 description = '' 81 Encryption method. See <link xlink:href="https://github.com/shadowsocks/shadowsocks-org/wiki/AEAD-Ciphers"/>. 82 ''; 83 }; 84 85 }; 86 87 }; 88 89 90 ###### implementation 91 92 config = mkIf cfg.enable { 93 assertions = singleton 94 { assertion = cfg.password == null || cfg.passwordFile == null; 95 message = "Cannot use both password and passwordFile for shadowsocks-libev"; 96 }; 97 98 systemd.services.shadowsocks-libev = { 99 description = "shadowsocks-libev Daemon"; 100 after = [ "network.target" ]; 101 wantedBy = [ "multi-user.target" ]; 102 path = [ pkgs.shadowsocks-libev ] ++ optional (cfg.passwordFile != null) pkgs.jq; 103 serviceConfig.PrivateTmp = true; 104 script = '' 105 ${optionalString (cfg.passwordFile != null) '' 106 cat ${configFile} | jq --arg password "$(cat "${cfg.passwordFile}")" '. + { password: $password }' > /tmp/shadowsocks.json 107 ''} 108 exec ss-server -c ${if cfg.passwordFile != null then "/tmp/shadowsocks.json" else configFile} 109 ''; 110 }; 111 }; 112}