add juicity service module and juicity nixos module
This commit is contained in:
parent
63a8871eaa
commit
1a6d282046
9 changed files with 447 additions and 104 deletions
|
|
@ -31,6 +31,7 @@
|
|||
enable = true;
|
||||
baseDomain = "youthlic.fun";
|
||||
};
|
||||
juicity.server.enable = true;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@
|
|||
open-webui.enable = true;
|
||||
transmission.enable = true;
|
||||
nix-ld.enable = true;
|
||||
juicity.client.enable = true;
|
||||
};
|
||||
gui.enabled = "niri";
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
include {
|
||||
proxy.d/*.dae
|
||||
local.d/*.dae
|
||||
}
|
||||
|
||||
global {
|
||||
|
|
@ -43,10 +44,12 @@ dns {
|
|||
group {
|
||||
proxy {
|
||||
filter: subtag(wget)
|
||||
filter: name(local)
|
||||
policy: min_moving_avg
|
||||
}
|
||||
us {
|
||||
filter: subtag(wget) && name(keyword: "美国")
|
||||
filter: name(local)
|
||||
policy: min_moving_avg
|
||||
}
|
||||
hk {
|
||||
|
|
@ -59,6 +62,7 @@ group {
|
|||
routing {
|
||||
pname(hickory-dns) && dport(53) -> must_direct
|
||||
pname(mihomo) -> must_direct
|
||||
pname(juicity-client) -> must_direct
|
||||
# pname(systemd-resolve) -> must_direct
|
||||
|
||||
dip(107.174.145.140) -> must_direct
|
||||
|
|
|
|||
|
|
@ -14,114 +14,126 @@ in
|
|||
enable = lib.mkEnableOption "dae";
|
||||
};
|
||||
};
|
||||
config = lib.mkIf cfg.enable {
|
||||
services.dae = {
|
||||
enable = true;
|
||||
openFirewall = {
|
||||
config = lib.mkMerge [
|
||||
(lib.mkIf cfg.enable {
|
||||
services.dae = {
|
||||
enable = true;
|
||||
port = 12345;
|
||||
openFirewall = {
|
||||
enable = true;
|
||||
port = 12345;
|
||||
};
|
||||
disableTxChecksumIpGeneric = false;
|
||||
config = builtins.readFile ./config.dae;
|
||||
};
|
||||
disableTxChecksumIpGeneric = false;
|
||||
config = builtins.readFile ./config.dae;
|
||||
};
|
||||
sops.secrets.url = {
|
||||
mode = "0444";
|
||||
sopsFile = rootPath + "/secrets/general.yaml";
|
||||
};
|
||||
systemd.services =
|
||||
let
|
||||
update = ''
|
||||
head="user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.182 Safari/537.36"
|
||||
new_proxy=/etc/dae/proxy.d.new
|
||||
num=0
|
||||
check=1
|
||||
urls="$(cat ${config.sops.secrets.url.path})"
|
||||
mkdir -p ''${new_proxy}
|
||||
for url in ''${urls}; do
|
||||
txt=''${new_proxy}/''${num}.txt
|
||||
config="''${new_proxy}/''${num}.dae"
|
||||
echo \'curl -LH \""''${head}"\" \""''${url}"\" -o \""''${txt}"\"\'
|
||||
curl -LH "''${head}" "''${url}" -o "''${txt}"
|
||||
echo End curl
|
||||
echo "" > ''${config}
|
||||
{
|
||||
echo 'subscription {'
|
||||
echo \ \ wget:\ \"file://proxy.d/''${num}.txt\"
|
||||
echo "}"
|
||||
} >> ''${config}
|
||||
if [[ ! -s ''${txt} ]]; then
|
||||
check=0
|
||||
fi
|
||||
chmod 0640 ''${txt}
|
||||
chmod 0640 ''${config}
|
||||
num=$((num+1))
|
||||
sops.secrets.url = {
|
||||
mode = "0444";
|
||||
sopsFile = rootPath + "/secrets/general.yaml";
|
||||
};
|
||||
systemd.services =
|
||||
let
|
||||
update = ''
|
||||
head="user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.182 Safari/537.36"
|
||||
new_proxy=/etc/dae/proxy.d.new
|
||||
num=0
|
||||
check=1
|
||||
urls="$(cat ${config.sops.secrets.url.path})"
|
||||
mkdir -p ''${new_proxy}
|
||||
for url in ''${urls}; do
|
||||
txt=''${new_proxy}/''${num}.txt
|
||||
config="''${new_proxy}/''${num}.dae"
|
||||
echo \'curl -LH \""''${head}"\" \""''${url}"\" -o \""''${txt}"\"\'
|
||||
curl -LH "''${head}" "''${url}" -o "''${txt}"
|
||||
echo End curl
|
||||
echo "" > ''${config}
|
||||
{
|
||||
echo 'subscription {'
|
||||
echo \ \ wget:\ \"file://proxy.d/''${num}.txt\"
|
||||
echo "}"
|
||||
} >> ''${config}
|
||||
if [[ ! -s ''${txt} ]]; then
|
||||
check=0
|
||||
fi
|
||||
chmod 0640 ''${txt}
|
||||
chmod 0640 ''${config}
|
||||
num=$((num+1))
|
||||
|
||||
if [[ ''${check} -eq 0 ]]; then
|
||||
echo "''${txt}" is empty
|
||||
exit 103
|
||||
if [[ ''${check} -eq 0 ]]; then
|
||||
echo "''${txt}" is empty
|
||||
exit 103
|
||||
fi
|
||||
done
|
||||
if [[ -d /etc/dae/proxy.d ]]; then
|
||||
mv /etc/dae/proxy.d /etc/dae/proxy.d.old
|
||||
fi
|
||||
done
|
||||
if [[ -d /etc/dae/proxy.d ]]; then
|
||||
mv /etc/dae/proxy.d /etc/dae/proxy.d.old
|
||||
fi
|
||||
mv ''${new_proxy} /etc/dae/proxy.d
|
||||
'';
|
||||
updateScript = pkgs.writeShellApplication {
|
||||
name = "update.sh";
|
||||
runtimeInputs = with pkgs; [
|
||||
coreutils
|
||||
curl
|
||||
];
|
||||
text = ''
|
||||
mkdir -p /etc/proxy.d
|
||||
if [ -z "$(ls -A /etc/dae/proxy.d 2>/dev/null)" ]; then
|
||||
echo "No subscription file found in /etc/dae/proxy.d. Update now..."
|
||||
mv ''${new_proxy} /etc/dae/proxy.d
|
||||
'';
|
||||
updateScript = pkgs.writeShellApplication {
|
||||
name = "update.sh";
|
||||
runtimeInputs = with pkgs; [
|
||||
coreutils
|
||||
curl
|
||||
];
|
||||
text = ''
|
||||
mkdir -p /etc/proxy.d
|
||||
if [ -z "$(ls -A /etc/dae/proxy.d 2>/dev/null)" ]; then
|
||||
echo "No subscription file found in /etc/dae/proxy.d. Update now..."
|
||||
${update}
|
||||
else
|
||||
echo "Found existing subscription files. Skipping immediate update."
|
||||
fi
|
||||
'';
|
||||
};
|
||||
updateForceScript = pkgs.writeShellApplication {
|
||||
name = "update-force.sh";
|
||||
runtimeInputs = with pkgs; [
|
||||
coreutils
|
||||
curl
|
||||
];
|
||||
text = ''
|
||||
${update}
|
||||
else
|
||||
echo "Found existing subscription files. Skipping immediate update."
|
||||
fi
|
||||
'';
|
||||
};
|
||||
updateForceScript = pkgs.writeShellApplication {
|
||||
name = "update-force.sh";
|
||||
runtimeInputs = with pkgs; [
|
||||
coreutils
|
||||
curl
|
||||
];
|
||||
text = ''
|
||||
${update}
|
||||
'';
|
||||
};
|
||||
in
|
||||
{
|
||||
"update-dae-subscription-immediate" = {
|
||||
after = [ "network-online.target" ];
|
||||
wants = [ "network-online.target" ];
|
||||
before = [ "dae.service" ];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
User = "root";
|
||||
ExecStart = [
|
||||
"${updateScript}/bin/update.sh"
|
||||
];
|
||||
'';
|
||||
};
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
};
|
||||
"update-dae-subscription-force" = {
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
User = "root";
|
||||
ExecStartPre = [
|
||||
"-${pkgs.systemd}/bin/systemctl stop dae.service"
|
||||
];
|
||||
ExecStartPost = [
|
||||
"-${pkgs.systemd}/bin/systemctl start dae.service"
|
||||
];
|
||||
ExecStart = [
|
||||
"${updateForceScript}/bin/update-force.sh"
|
||||
];
|
||||
in
|
||||
{
|
||||
"update-dae-subscription-immediate" = {
|
||||
after = [ "network-online.target" ];
|
||||
wants = [ "network-online.target" ];
|
||||
before = [ "dae.service" ];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
User = "root";
|
||||
ExecStart = [
|
||||
"${updateScript}/bin/update.sh"
|
||||
];
|
||||
};
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
};
|
||||
"update-dae-subscription-force" = {
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
User = "root";
|
||||
ExecStartPre = [
|
||||
"-${pkgs.systemd}/bin/systemctl stop dae.service"
|
||||
];
|
||||
ExecStartPost = [
|
||||
"-${pkgs.systemd}/bin/systemctl start dae.service"
|
||||
];
|
||||
ExecStart = [
|
||||
"${updateForceScript}/bin/update-force.sh"
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
})
|
||||
(lib.mkIf (cfg.enable && config.youthlic.programs.juicity.client.enable) {
|
||||
environment.etc."dae/local.d/0.dae" = {
|
||||
text = ''
|
||||
node {
|
||||
local: 'socks5://127.0.0.1:7890/'
|
||||
}
|
||||
'';
|
||||
mode = "0440";
|
||||
};
|
||||
};
|
||||
})
|
||||
];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,5 +16,6 @@
|
|||
./transmission.nix
|
||||
./conduwuit.nix
|
||||
./nix-ld.nix
|
||||
./juicity
|
||||
];
|
||||
}
|
||||
|
|
|
|||
106
nixos/modules/programs/juicity/default.nix
Normal file
106
nixos/modules/programs/juicity/default.nix
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
{
|
||||
pkgs,
|
||||
lib,
|
||||
config,
|
||||
...
|
||||
}:
|
||||
let
|
||||
cfg = config.youthlic.programs.juicity;
|
||||
in
|
||||
{
|
||||
imports = [
|
||||
./template.nix
|
||||
];
|
||||
options = {
|
||||
youthlic.programs.juicity = {
|
||||
client = {
|
||||
enable = lib.mkEnableOption "juicity-client";
|
||||
};
|
||||
server = {
|
||||
enable = lib.mkEnableOption "juicity-server";
|
||||
};
|
||||
};
|
||||
};
|
||||
config = lib.mkMerge [
|
||||
(lib.mkIf cfg.client.enable {
|
||||
users.groups.juicity.members = [ "root" ];
|
||||
sops = {
|
||||
secrets = {
|
||||
"juicity/serverIp" = { };
|
||||
"juicity/sni" = { };
|
||||
"juicity/certchainSha256" = { };
|
||||
};
|
||||
templates."juicity-client-config.json" = {
|
||||
group = "juicity";
|
||||
mode = "0440";
|
||||
content = ''
|
||||
{
|
||||
"listen": ":7890",
|
||||
"server": "${config.sops.placeholder."juicity/serverIp"}:23182",
|
||||
"uuid": "${config.sops.placeholder."juicity/uuid"}",
|
||||
"password": "${config.sops.placeholder."juicity/password"}",
|
||||
"sni": "${config.sops.placeholder."juicity/sni"}",
|
||||
"allow_insecure": false,
|
||||
"pinned_certchain_sha256": "${config.sops.placeholder."juicity/certchainSha256"}",
|
||||
"log_level": "info"
|
||||
}
|
||||
'';
|
||||
};
|
||||
};
|
||||
services.juicity.client = {
|
||||
enable = true;
|
||||
package = pkgs.juicity;
|
||||
configFile = "${config.sops.templates."juicity-client-config.json".path}";
|
||||
allowedOpenFirewallPorts = [
|
||||
7890
|
||||
];
|
||||
group = "juicity";
|
||||
};
|
||||
})
|
||||
(lib.mkIf cfg.server.enable {
|
||||
users.groups.juicity.members = [ "root" ];
|
||||
sops = {
|
||||
secrets = {
|
||||
"juicity/certificate" = {
|
||||
group = "juicity";
|
||||
mode = "0440";
|
||||
};
|
||||
"juicity/private_key" = {
|
||||
group = "juicity";
|
||||
mode = "0440";
|
||||
};
|
||||
};
|
||||
templates."juicity-server-config.json" = {
|
||||
group = "juicity";
|
||||
mode = "0440";
|
||||
content = ''
|
||||
{
|
||||
"listen": ":23182",
|
||||
"users": {
|
||||
"${config.sops.placeholder."juicity/uuid"}": "${config.sops.placeholder."juicity/password"}"
|
||||
},
|
||||
"certificate": "${config.sops.secrets."juicity/certificate".path}",
|
||||
"private_key": "${config.sops.secrets."juicity/private_key".path}",
|
||||
"log_level": "info"
|
||||
}
|
||||
'';
|
||||
};
|
||||
};
|
||||
services.juicity.server = {
|
||||
enable = true;
|
||||
package = pkgs.juicity;
|
||||
configFile = "${config.sops.templates."juicity-server-config.json".path}";
|
||||
allowedOpenFirewallPorts = [
|
||||
23182
|
||||
];
|
||||
group = "juicity";
|
||||
};
|
||||
})
|
||||
(lib.mkIf (cfg.server.enable || cfg.client.enable) {
|
||||
sops.secrets = {
|
||||
"juicity/uuid" = { };
|
||||
"juicity/password" = { };
|
||||
};
|
||||
})
|
||||
];
|
||||
}
|
||||
206
nixos/modules/programs/juicity/template.nix
Normal file
206
nixos/modules/programs/juicity/template.nix
Normal file
|
|
@ -0,0 +1,206 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
let
|
||||
cfg = config.services.juicity;
|
||||
settingsFormat = pkgs.formats.json { };
|
||||
clientConfigFile =
|
||||
if (cfg.client.configFile != null) then
|
||||
cfg.client.configFile
|
||||
else
|
||||
settingsFormat cfg.client.settings;
|
||||
serverConfigFile =
|
||||
if (cfg.server.configFile != null) then
|
||||
cfg.server.configFile
|
||||
else
|
||||
settingsFormat cfg.server.settings;
|
||||
in
|
||||
{
|
||||
options = {
|
||||
services.juicity = {
|
||||
client = {
|
||||
enable = lib.mkEnableOption "juicity-client";
|
||||
package = lib.mkPackageOption pkgs "juicity" { };
|
||||
group = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
example = "juicity";
|
||||
default = null;
|
||||
};
|
||||
settings = lib.mkOption {
|
||||
type = settingsFormat.type;
|
||||
default = { };
|
||||
example = {
|
||||
listen = ":1000";
|
||||
server = "112.32.62.11:23182";
|
||||
uuid = "00000000-0000-0000-0000-000000000000";
|
||||
password = "my_password";
|
||||
sni = "www.example.com";
|
||||
allow_insecure = false;
|
||||
congestion_control = "bbr";
|
||||
log_level = "info";
|
||||
};
|
||||
description = ''
|
||||
Juicity client configuration, for configuration options
|
||||
see example of [client](https://github.com/juicity/juicity/blob/main/install/example-client.json) on github.
|
||||
'';
|
||||
};
|
||||
configFile = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.path;
|
||||
example = "/run/juicity/config.json";
|
||||
default = null;
|
||||
description = ''
|
||||
A file which JSON configurations for juicity client. See the {option}`settings` option for more information.
|
||||
|
||||
Note: this file will override {options}`settings` option, which is recommanded.
|
||||
'';
|
||||
};
|
||||
allowedOpenFirewallPorts = lib.mkOption {
|
||||
type = lib.types.nullOr (lib.types.listOf lib.types.port);
|
||||
example = [ 23182 ];
|
||||
default = null;
|
||||
description = ''
|
||||
the ports should be open
|
||||
'';
|
||||
};
|
||||
};
|
||||
server = {
|
||||
enable = lib.mkEnableOption "juicity-server";
|
||||
package = lib.mkPackageOption pkgs "juicity" { };
|
||||
group = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
example = "juicity";
|
||||
default = null;
|
||||
};
|
||||
settings = lib.mkOption {
|
||||
type = settingsFormat.type;
|
||||
default = { };
|
||||
description = ''
|
||||
Juicity server configuration, for configuration options
|
||||
see example of [server](https://github.com/juicity/juicity/blob/main/install/example-server.json) on github.
|
||||
'';
|
||||
example = {
|
||||
listen = ":23182";
|
||||
users = {
|
||||
"00000000-0000-0000-0000-000000000000" = "my_password";
|
||||
};
|
||||
certificate = "/path/to/fullchain.cer";
|
||||
private_key = "/path/to/private.key";
|
||||
congestion_control = "bbr";
|
||||
log_level = "info";
|
||||
};
|
||||
};
|
||||
configFile = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.path;
|
||||
example = "/run/juicity/config.json";
|
||||
default = null;
|
||||
description = ''
|
||||
A file which JSON configurations for juicity server. See the {option}`settings` option for more information.
|
||||
|
||||
Note: this file will override {options}`settings` option, which is recommanded.
|
||||
'';
|
||||
};
|
||||
allowedOpenFirewallPorts = lib.mkOption {
|
||||
type = lib.types.nullOr (lib.types.listOf lib.types.port);
|
||||
example = [ 23182 ];
|
||||
default = null;
|
||||
description = ''
|
||||
the ports should be open
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
config = lib.mkMerge [
|
||||
(lib.mkIf (cfg.client.enable && (cfg.client.allowedOpenFirewallPorts != null)) {
|
||||
networking.firewall.allowedTCPPorts = cfg.client.allowedOpenFirewallPorts;
|
||||
networking.firewall.allowedUDPPorts = cfg.client.allowedOpenFirewallPorts;
|
||||
})
|
||||
(lib.mkIf (cfg.server.enable && (cfg.server.allowedOpenFirewallPorts != null)) {
|
||||
networking.firewall.allowedTCPPorts = cfg.server.allowedOpenFirewallPorts;
|
||||
networking.firewall.allowedUDPPorts = cfg.server.allowedOpenFirewallPorts;
|
||||
})
|
||||
(lib.mkIf (cfg.server.enable && (cfg.server.group != null)) {
|
||||
systemd.services."juicity-server".serviceConfig = {
|
||||
Group = cfg.server.group;
|
||||
};
|
||||
})
|
||||
(lib.mkIf (cfg.client.enable && (cfg.client.group != null)) {
|
||||
systemd.services."juicity-client".serviceConfig = {
|
||||
Group = cfg.client.group;
|
||||
};
|
||||
})
|
||||
(lib.mkIf cfg.client.enable {
|
||||
environment.systemPackages = [
|
||||
cfg.client.package
|
||||
];
|
||||
systemd.services.juicity-client = {
|
||||
description = ''
|
||||
juicity-client Service
|
||||
'';
|
||||
documentation = [
|
||||
"https://github.com/juicity/juicity"
|
||||
];
|
||||
after = [
|
||||
"network.target"
|
||||
"nss-lookup.target"
|
||||
];
|
||||
wantedBy = [
|
||||
"multi-user.target"
|
||||
];
|
||||
serviceConfig = {
|
||||
Type = "simple";
|
||||
DynamicUser = true;
|
||||
CapabilityBoundingSet = [
|
||||
"CAP_NET_ADMIN"
|
||||
"CAP_NET_BIND_SERVICE"
|
||||
"CAP_NET_RAW"
|
||||
];
|
||||
AmbientCapabilities = [
|
||||
"CAP_NET_ADMIN"
|
||||
"CAP_NET_BIND_SERVICE"
|
||||
"CAP_NET_RAW"
|
||||
];
|
||||
ExecStart = ''
|
||||
${lib.getExe' cfg.client.package "juicity-client"} run --disable-timestamp --config ${clientConfigFile}
|
||||
'';
|
||||
Restart = "on-failure";
|
||||
LimitNPROC = 512;
|
||||
LimitNOFILE = "infinity";
|
||||
};
|
||||
};
|
||||
})
|
||||
(lib.mkIf cfg.server.enable {
|
||||
environment.systemPackages = [
|
||||
cfg.server.package
|
||||
];
|
||||
systemd.services.juicity-server = {
|
||||
description = ''
|
||||
juicity-server Service
|
||||
'';
|
||||
documentation = [
|
||||
"https://github.com/juicity/juicity"
|
||||
];
|
||||
after = [
|
||||
"network.target"
|
||||
"nss-lookup.target"
|
||||
];
|
||||
wantedBy = [
|
||||
"multi-user.target"
|
||||
];
|
||||
serviceConfig = {
|
||||
Type = "simple";
|
||||
DynamicUser = true;
|
||||
ExecStart = ''
|
||||
${lib.getExe' cfg.server.package "juicity-server"} run --disable-timestamp --config ${serverConfigFile}
|
||||
'';
|
||||
Restart = "on-failure";
|
||||
LimitNPROC = 512;
|
||||
LimitNOFILE = "infinity";
|
||||
};
|
||||
};
|
||||
})
|
||||
];
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue