feat: init hectic-lab merge

This commit is contained in:
2026-02-27 19:57:44 +00:00
parent 4e2264dc03
commit cfcd6647ae
13 changed files with 948 additions and 10 deletions

View File

@@ -11,7 +11,7 @@ let
hectic.imports = attrValues (
readModulesRecursive' ./hectic { inherit flake self inputs; }
);
# Read generic modules seperately
# Read generic modules separately
generic = readModulesRecursive'
./generic
{ inherit flake self inputs; };

View File

@@ -0,0 +1,169 @@
# INFO(nrv): This is standalone shadowsocks module. Instance-specific is at ./shadowsocks.nix
{
...
}:
{
config,
lib,
pkgs,
...
}:
with lib;
let
cfg = config.services.shadowsocks-rust;
opts = {
server = cfg.localAddress;
server_port = cfg.port;
method = cfg.encryptionMethod;
mode = cfg.mode;
user = "nobody";
fast_open = cfg.fastOpen;
} // optionalAttrs (cfg.plugin != null) {
plugin = cfg.plugin;
plugin_opts = cfg.pluginOpts;
} // optionalAttrs (cfg.password != null) {
password = cfg.password;
} // cfg.extraConfig;
configFile = pkgs.writeText "shadowsocks.json" (builtins.toJSON opts);
in
{
###### interface
options = {
services.shadowsocks-rust = {
enable = mkOption {
type = types.bool;
default = false;
description = lib.mdDoc ''
Whether to run shadowsocks-rust shadowsocks server.
'';
};
localAddress = mkOption {
type = types.str;
default = "0.0.0.0";
description = lib.mdDoc ''
Local addresses to which the server binds.
'';
};
port = mkOption {
type = types.port;
default = 8388;
description = lib.mdDoc ''
Port which the server uses.
'';
};
password = mkOption {
type = types.nullOr types.str;
default = null;
description = lib.mdDoc ''
Password for connecting clients.
'';
};
passwordFile = mkOption {
type = types.nullOr types.path;
default = null;
description = lib.mdDoc ''
Password file with a password for connecting clients.
'';
};
mode = mkOption {
type = types.enum [ "tcp_only" "tcp_and_udp" "udp_only" ];
default = "tcp_and_udp";
description = lib.mdDoc ''
Relay protocols.
'';
};
fastOpen = mkOption {
type = types.bool;
default = true;
description = lib.mdDoc ''
use TCP fast-open
'';
};
encryptionMethod = mkOption {
type = types.str;
default = "chacha20-ietf-poly1305";
description = lib.mdDoc ''
Encryption method. See <https://github.com/shadowsocks/shadowsocks-org/wiki/AEAD-Ciphers>.
'';
};
plugin = mkOption {
type = types.nullOr types.str;
default = null;
example = literalExpression ''"''${pkgs.shadowsocks-v2ray-plugin}/bin/v2ray-plugin"'';
description = lib.mdDoc ''
SIP003 plugin for shadowsocks
'';
};
pluginOpts = mkOption {
type = types.str;
default = "";
example = "server;host=example.com";
description = lib.mdDoc ''
Options to pass to the plugin if one was specified
'';
};
extraConfig = mkOption {
type = types.attrs;
default = {};
example = {
nameserver = "8.8.8.8";
};
description = lib.mdDoc ''
Additional configuration for shadowsocks that is not covered by the
provided options. The provided attrset will be serialized to JSON and
has to contain valid shadowsocks options. Unfortunately most
additional options are undocumented but it's easy to find out what is
available by looking into the source code of
<https://github.com/shadowsocks/shadowsocks-rust/blob/master/src/jconf.c>
'';
};
};
};
###### implementation
config = mkIf cfg.enable {
assertions = singleton
{ assertion = cfg.password == null || cfg.passwordFile == null;
message = "Cannot use both password and passwordFile for shadowsocks-rust";
};
systemd.services.shadowsocks-rust = {
description = "shadowsocks-rust Daemon";
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
path = [ pkgs.shadowsocks-rust ]
++ optional (cfg.plugin != null) cfg.plugin
++ optional (cfg.passwordFile != null) pkgs.jq;
serviceConfig.PrivateTmp = true;
script = ''
${optionalString (cfg.passwordFile != null) ''
cat ${configFile} | jq --arg password "$(cat "${cfg.passwordFile}")" '. + { password: $password }' > /run/shadowsocks.json
''}
exec ssserver --config ${if cfg.passwordFile != null then "/run/shadowsocks.json" else configFile}
'';
};
};
}

View File

@@ -0,0 +1,28 @@
{
...
}:
{
pkgs,
config,
...
}:
{
sops.secrets."ss-bfs/password" = {};
services.shadowsocks-rust = {
enable = true;
plugin = "${pkgs.shadowsocks-v2ray-plugin}/bin/v2ray-plugin";
# TODO: setup dnscrypt or a private DNS server for this
# extraConfig = {
# nameserver = "185.12.64.1"; # FIXME: this can vary across instances.
# };
port = 55228;
pluginOpts = "server";
# TODO: setup a TLS certs for this (look: (README.md) https://github.com/shadowsocks/v2ray-plugin/)
#pluginOpts = "server;tls;host=ss.bfs.band";
passwordFile = config.sops.secrets."ss-bfs/password".path;
mode = "tcp_and_udp"; # default
localAddress = "0.0.0.0";
fastOpen = true; # default
encryptionMethod = "chacha20-ietf-poly1305"; # default
};
}