88 lines
3.1 KiB
Nix
Executable file
88 lines
3.1 KiB
Nix
Executable file
# Based on https://github.com/NixOS/nixpkgs/blob/nixos-23.05/nixos/modules/services/networking/shadowsocks.nix
|
|
|
|
{ lib, pkgs, ... }:
|
|
|
|
with lib;
|
|
{
|
|
# Local addresses to which the server binds.
|
|
localAddress ? "0.0.0.0"
|
|
, # Port which the server uses.
|
|
# If `client = true`, port of the remote server to connect to.
|
|
port ? 8388
|
|
, # Password for connecting clients
|
|
password ? null
|
|
, # Password file with a password for connecting clients
|
|
passwordFile ? null
|
|
, # Relay protocols (one of "tcp_only" "tcp_and_udp" "udp_only")
|
|
mode ? "tcp_and_udp"
|
|
, # use TCP fast-open
|
|
fastOpen ? true
|
|
, # Encryption method
|
|
encryptionMethod ? "chacha20-ietf-poly1305"
|
|
, # SIP003 plugin for shadowsocks
|
|
plugin ? null
|
|
, # Options to pass to the plugin if one was specified (e.g. "server;host=example.com")
|
|
pluginOpts ? ""
|
|
, # Whether to set up a Shadowsocks client instead of a server
|
|
client ? false
|
|
, # Address of the remote Shadowsocks server
|
|
server ? null
|
|
, # File containing address of the remote Shadowsocks server
|
|
serverFile ? null
|
|
, # Local port for the client to bind
|
|
localPort ? 8388
|
|
, # Additional configuration for shadowsocks that is not covered by the
|
|
# provided options. The provided attrset will be serialized to JSON config as-is
|
|
extraConfig ? { }
|
|
, # Name of the systemd service
|
|
serviceName ? "shadowsocks-rust"
|
|
, # Shadowsocks-rust package
|
|
package ? pkgs.shadowsocks-rust
|
|
}:
|
|
assert assertOneOf "mode" mode [ "tcp_only" "tcp_and_udp" "udp_only" ];
|
|
assert assertMsg (password == null || passwordFile == null) "Cannot use both password and passwordFile for shadowsocks-rust";
|
|
assert assertMsg (server == null || serverFile == null) "Cannot use both server and serverFile for shadowsocks-rust";
|
|
|
|
let
|
|
opts = {
|
|
server = localAddress;
|
|
server_port = port;
|
|
method = encryptionMethod;
|
|
mode = mode;
|
|
user = "nobody";
|
|
fast_open = fastOpen;
|
|
} // optionalAttrs (plugin != null) {
|
|
plugin = plugin;
|
|
plugin_opts = pluginOpts;
|
|
} // optionalAttrs (password != null) {
|
|
password = password;
|
|
} // optionalAttrs (client == true) {
|
|
server = server;
|
|
local_address = localAddress;
|
|
local_port = localPort;
|
|
} // extraConfig;
|
|
|
|
configFile = pkgs.writeText "shadowsocks.json" (builtins.toJSON opts);
|
|
in
|
|
{
|
|
systemd.services.${serviceName} = {
|
|
description = "${serviceName} Daemon";
|
|
after = [ "network.target" ];
|
|
wantedBy = [ "multi-user.target" ];
|
|
path = [ package ] ++ optional (plugin != null) plugin ++ optional (passwordFile != null) pkgs.jq;
|
|
serviceConfig = {
|
|
PrivateTmp = true;
|
|
Restart = "on-failure";
|
|
};
|
|
script = ''
|
|
cp ${configFile} /tmp/shadowsocks.json
|
|
${optionalString (passwordFile != null) ''
|
|
cat /tmp/shadowsocks.json | jq --arg password "$(cat "${passwordFile}")" '. + { password: $password }' > /tmp/shadowsocks.json
|
|
''}
|
|
${optionalString (serverFile != null) ''
|
|
cat /tmp/shadowsocks.json | jq --arg server "$(cat "${serverFile}")" '. + { server: $server }' > /tmp/shadowsocks.json
|
|
''}
|
|
exec ${if client == true then "sslocal" else "ssserver"} -c /tmp/shadowsocks.json
|
|
'';
|
|
};
|
|
}
|