Compare commits

...

8 commits

15 changed files with 99229 additions and 40 deletions

92435
china-domain.txt Normal file

File diff suppressed because it is too large Load diff

6467
gfw.txt Normal file

File diff suppressed because it is too large Load diff

View file

@ -317,6 +317,12 @@ in
gthumb
oculante
(epsonscan2.overrideAttrs (
finalAttrs: prevAttrs: {
patches = prevAttrs.patches ++ [ ./fix-crash.patch ];
}
))
# Multimedia
vlc
obs-studio
@ -365,6 +371,26 @@ in
owner = "root";
sopsFile = ./secrets.yaml;
};
"davfs2/photosync_password" = {
sopsFile = ./secrets.yaml;
mode = "0600";
};
};
sops.templates."davfs2.conf" = {
owner = config.services.davfs2.davUser;
content = ''
https://weilite.coho-tet.ts.net:6065/photosync photosync ${
config.sops.placeholder."davfs2/photosync_password"
}
'';
};
environment.etc = {
"davfs2/secrets" = {
source = config.sops.templates."davfs2.conf".path;
mode = "0600";
};
};
custom.restic = {
@ -399,6 +425,32 @@ in
services.flatpak.enable = true;
services.davfs2 = {
enable = true;
settings = {
globalSection = {
use_locks = 1;
gui_optimize = 1;
table_size = 4096;
cache_size = 10240;
};
};
};
fileSystems = {
"/media/photosync" = {
device = "https://weilite.coho-tet.ts.net:6065/photosync";
fsType = "davfs";
options = [
"rw"
"uid=1000"
"nodev"
"nosuid"
"nofail"
];
};
};
# Fonts
fonts = {
packages = with pkgs; [

View file

@ -0,0 +1,36 @@
diff -uNr a/src/Controller/Src/Finder/UsbFinder.cpp b/src/Controller/Src/Finder/UsbFinder.cpp
--- a/src/Controller/Src/Finder/UsbFinder.cpp 2024-10-05 01:47:57.530027467 +0800
+++ b/src/Controller/Src/Finder/UsbFinder.cpp 2024-10-07 01:58:36.293405252 +0800
@@ -119,14 +119,26 @@
sprintf(const_cast<char*>(devInfo.displayName), "%s", "DS-5500/DS-6500/DS-7500");
isValidDeviceInfo = true;
}
+ else if (dd.idProduct == 0x14A)
+ {
+ sprintf(const_cast<char*>(devInfo.displayName), "%s", "Perfection V37/V370");
+ isValidDeviceInfo = true;
+ }
else
{
- sprintf((char*)strDescWithAddress, "%s:%s", strDesc, serialNumber);
- strncpy(const_cast<char*>(devInfo.displayName),(const char*)strDescWithAddress, MAX_DISPLAYNAME - 1);
- if (strlen(devInfo.displayName) != 0 || searchSecondDevice)
- {
- isValidDeviceInfo = true;
- }
+ if (dd.iSerialNumber == 0)
+ {
+ sprintf((char*)strDescWithAddress, "%s", strDesc);
+ }
+ else
+ {
+ sprintf((char*)strDescWithAddress, "%s:%s", strDesc, serialNumber);
+ }
+ strncpy(const_cast<char*>(devInfo.displayName),(const char*)strDescWithAddress, MAX_DISPLAYNAME - 1);
+ if (strlen(devInfo.displayName) != 0 || searchSecondDevice)
+ {
+ isValidDeviceInfo = true;
+ }
}
libusb_close (devHandle);
devHandle = nullptr;

View file

@ -31,12 +31,12 @@ in
};
# services.tailscale.useRoutingFeatures = "both";
services.dae.enable = true;
services.dae.configFile = "/var/lib/dae/config.dae";
systemd.services.dae.after = lib.mkIf (config.networking.networkmanager.enable) [
"NetworkManager-wait-online.service"
];
# services.dae.enable = true;
# services.dae.configFile = "/var/lib/dae/config.dae";
# systemd.services.dae.after = lib.mkIf (config.networking.networkmanager.enable) [
# "NetworkManager-wait-online.service"
# ];
#
# Open ports in the firewall.
networking.firewall.enable = true;
networking.firewall.allowedTCPPorts = [ 3389 ];

View file

@ -3,6 +3,8 @@ restic:
repo_password: ENC[AES256_GCM,data:jqsIP1R5/yX8F0oYaSXACx6C,iv:KckzqctKLnmay+d30/Y4IttiASxYnMw6IHQrtwP2YdQ=,tag:L/Ij51UU1om48I8fd4iuwA==,type:str]
gitea:
envfile: ENC[AES256_GCM,data:CK+JNELuzjKgWnImuV4Euif3f3nNOACOrvc4NiIXs+q/F7QWrtpb3TK8/FrLNQk=,iv:QSDrlKJCBld2gDx/y1sT8anh37GhqSS2QZd2JJi5Yis=,tag:x5T6h59LBXhEyVwSr2dnuQ==,type:str]
davfs2:
photosync_password: ENC[AES256_GCM,data:J3+pJCjjV+hlPC2il5f7Vn+9k+Aatolgut1DX1G+JF4=,iv:OgZn6Glho3Cfrl0GJhGSbmcYjSe6sjM9PjvEZnM/c4w=,tag:i5AVG139nK3ecK3VwWpQuQ==,type:str]
sops:
kms: []
gcp_kms: []
@ -27,8 +29,8 @@ sops:
WGlLdXVoZlp3bEFXZjlMdG1VOUZDNUkKQ2NNTE3OsNUr2pOI7qeNFSCVkUIVRS+g
FG5FbJJcFihXqr+Qo0nZkq+xq07vIia7mKoqyoIfkKwweiVzDKyrkQ==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2024-11-28T03:55:19Z"
mac: ENC[AES256_GCM,data:VH7RnRT33ltsxycuSsUsM+64onQeClwQ3fIHUVQUyRJ6t7aJkBiGMQ80QtmwGE5CJTbq7LV4cis5Pq/f9vTb0SsY4tCSIgXNAE2zW2rjjQKjdHr+rnnKSJExJA+k2tL06Q/FUu+3SP7pVSaYBGQKb53UAbHsdJYbx00Ko6MzZ7U=,iv:EiYhbr6o4n3kGEEWKXeWmDPSb5hOvUhRH7N2ZLPRHmQ=,tag:BdI140bhvBW0bwQPpRYiRw==,type:str]
lastmodified: "2025-04-07T08:57:13Z"
mac: ENC[AES256_GCM,data:UvMXEu2UFapYNHa7kxvFhDzvJZvuV6mwRqmxFISDpp0VhRhY1+Mj2GFxrS5RgTW1ozUnCB0DSBUwWcmsPZeOUveMkHqqRFGZIjinh6blwseZjJMOR30KG3atY6L2adOOZaBERi+HJXqXfdqymeSCmkMC5iJ2jt2KGuMx5NqSfbE=,iv:pueL1hT/tvug65KPYxqY3RwNYeBOlGpIFf70+26VOYQ=,tag:VLwuipBxchMBSSuOMXYKJQ==,type:str]
pgp: []
unencrypted_suffix: _unencrypted
version: 3.9.1
version: 3.9.4

View file

@ -1,6 +1,8 @@
prometheus:
metrics_username: ENC[AES256_GCM,data:/CQfOA==,iv:BjhB+uLfjmYHdgpc/+tDJXJ8C1EK9kngQWbo4NleOmE=,tag:JCdqyqGLRh09T25vmufiZw==,type:str]
metrics_password: ENC[AES256_GCM,data:q/xMPuNtlcUFewMdVu6w2Q==,iv:xLohdb5tdxevYFckZoacjSJp2rZ53QKLxK6u3mc3mDw=,tag:B4LrObH1DsnnD5CcuOPOyg==,type:str]
dae:
sub: ENC[AES256_GCM,data:kruAGgIBwiN508hwczGeVmh6Jr4Mg9BNEWSBNfYnBCCOrkSM1I5GRuG8EZqTq1+Ib+TRN8cgaqCEk2mpZ+7po1FjW1K8M0EBj9QvQCs7a+QVSmP6qS14WY1B,iv:iMhxWb0IR+3jOP2+7GmQTe0Ia1yhycji4hcTTMK57GI=,tag:V/nZgi7AWHU2Kp5WGhaGAw==,type:str]
sops:
kms: []
gcp_kms: []
@ -88,8 +90,8 @@ sops:
am04NVRtU2N6SThYZWdXVE5RZ1B2aE0KVcHvB5k2Gcu/St0P8WPFzlCtuZthZTKo
hwVc0lC6Xxt25hriaUFinwnyvcjxrLCx0Nq7f9Zn16nJcza5kev1nQ==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2024-11-30T06:31:42Z"
mac: ENC[AES256_GCM,data:xh8x9IrQ01ZzdcCTIfBrifIGduMYVmSSP52BkTyr/bx7AgQAz2WeA7LFrccxIayCGHrQKfMQDLUKJ/EBamG/6p8AX6QqZBTfqFD688ZhmRfxgpj7fYR9jPYnhb/9XHI9R2jTaJWwrorXvu3pa+Gy/hWB3Kb+WZc3fslmIuKuLH0=,iv:GDrHSFZxPbpACdusVDPHXEjeEusYfk53N/KGHtdvrYo=,tag:ap38sCSTZVDQ0ZazXM3vlg==,type:str]
lastmodified: "2025-04-10T03:53:49Z"
mac: ENC[AES256_GCM,data:ioiGVfCWOn8Hc5EpCtcDTF4YoKtsMAchBlRM0C00WQbM9Ss3571Oly4jtymshDVbDFbH+y0gYcEXn8Fs5XYjd0rIa6mbaISLvPlG+P34SqHcVsh6eDU15z0vTAncbOHrok+/xAmg64WtiBxteMaWPsTVngCrmPYS247eCav+Jpo=,iv:K7PiHNn2IS0pGUh1F75TjliHMk8l6PaHmDshSPPA4BE=,tag:Jd/lHdeWUDQa5AwSwFCeSw==,type:str]
pgp: []
unencrypted_suffix: _unencrypted
version: 3.9.1
version: 3.9.4

View file

@ -39,6 +39,7 @@
enable = true;
};
comin.enable = true;
network.localdns.enable = true;
};
node = {
mediaDir = "/mnt/nixos/media";
@ -102,6 +103,13 @@
type = "virtiofs";
options = "rw,nodev,nosuid";
}
{
what = "originals";
where = "/mnt/photos/xin/originals";
type = "virtiofs";
options = "rw,nodev,nosuid";
wantedBy = [ "immich-server.service" ];
}
{
what = "/mnt/nixos/ocis";
where = "/var/lib/ocis";
@ -141,11 +149,6 @@
2222
];
services.dae = {
enable = true;
configFile = "/var/lib/dae/config.dae";
};
services.tailscale = {
enable = true;
openFirewall = true;

View file

@ -3,6 +3,7 @@ caddy:
dnspod_dns_token: ENC[AES256_GCM,data:ATed7RqLu1u06B61Irhd4SCzjK/Z823ygAgzROsNixZ2rExpB/Xo,iv:L121CGA+iZhn9V6mG2qEu3FI91/s7JO3cVTAwmAeqGw=,tag:l/7MXMZNqgFBwgCCMeZR2A==,type:str]
immich:
oauth_client_secret: ENC[AES256_GCM,data:EFs2hPjGMj0idwY3oQVIDTOIWkdwoAoAVjDQE9Z2eAKzUDH3grmYpYE+33V8d/Ux,iv:A9cjwFr/ZqltG62/N8MQ1LhdDbSIVVAqIPVB492zYJw=,tag:VTTtE697BZTVsI32UF53/w==,type:str]
auto_stack_apikey: ENC[AES256_GCM,data:pormMdxkevrw1sJrmVtD+jEbfQFTOHeyZRepZt2roftjDYAdbzpppg==,iv:wumPYaTAfU+J0MD6yOFKmxY8eDMzwqVsd3IUXyTfk0A=,tag:54HlWH3iKyWG2Gv9QS/wLA==,type:str]
restic:
localpass: ENC[AES256_GCM,data:GIQAmkpDmGu4+sSG5/b5yQ==,iv:dcu6F8NnVjeQzEG2vM3fOV5owI0PWc86ts20UP3vN18=,tag:vsG8x062FG1pH5YNcAajeg==,type:str]
transmission:
@ -11,6 +12,9 @@ sonarr:
api-key: ENC[AES256_GCM,data:/CkApTCLQy8TLHGKSM1saacNi9uQDswAjshRSLJk1hg=,iv:PNX4BZLx7krs12lxgORMSarnt0c/ga8yPtoLSzbQ+sY=,tag:V1pp9OCtX5/5fbwLBMGlOQ==,type:str]
radarr:
api-key: ENC[AES256_GCM,data:AeJArngvgmqnxk2g13QjMa6XS893B+3ZdX2K8OqXRQg=,iv:NrQf3yyqRpHMeWQ3bpPH4fUDdo/x2uB6pQCq0ZrFP5c=,tag:Yj2PSy6zRfe8anW0RGuZAQ==,type:str]
webdav:
photosync:
password: ENC[AES256_GCM,data:s+omleBtVALG5bpbTnlzbwBj0oCZX8Dm8IbcUV6COnI=,iv:vwCs3ujmCcE87rl91ZtOEAgSQF1/0t17/7/0UM4x8fE=,tag:ylw76CX9SCylWoJt86rmjg==,type:str]
sops:
kms: []
gcp_kms: []
@ -35,8 +39,8 @@ sops:
V0thRjU4WGpQRGFpcnoxSjZTZHhTTkUKzNMHh9p7GUY3hL5XZ9S4x20CwaItsXFV
RKujsFVVBd8Kuq/jyOCBTRCscuHI4LW/wYeZYHFEZFSTK2liAqspgw==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2025-02-11T08:45:49Z"
mac: ENC[AES256_GCM,data:iObzkfSxKET1kE8yQbSxffG1qDO95SWfIRSdwbYcwP4mHOrl5sOtlGEjexVaLl7uKa0SMCK6BghbMr4EdLatiOmngsAzr8bxe/GsPZiCze04nr0VbKBgHxKr74gT8d14dwV+Y+np/5fgRZea7zxzJ4YaVfeUOG9PBsa7L6RWbx0=,iv:LMM096xLa5cOiLVTiFO20jBUaK1Uw4aOqsz7eH9u9vc=,tag:C1fPHN9KFbydcy1lRAhGvQ==,type:str]
lastmodified: "2025-04-06T14:28:44Z"
mac: ENC[AES256_GCM,data:tYAhkwRs2CFOUCw3Iuq6T5C+QkbpSz80fI6CP65VyFrNiej9hshmjngPnf8bFElF+bHI64a/zpo2y4CqV213011tOX2YYvLD5zrAQb18rBFUdJblY5wQyx/DXiPaIf5jK6WGHIRaOmqZJuqXKrQKnf99N12JydXjt6usBGGZr8M=,iv:wySf7lctw14iUbKo5fDu+p6TMY5QXGYYmBukh2qb19I=,tag:pZrnFiNZEK01pnDN0+1Rcw==,type:str]
pgp: []
unencrypted_suffix: _unencrypted
version: 3.9.2
version: 3.9.4

View file

@ -7,5 +7,6 @@
./immich.nix
./jellyfin.nix
./transmission.nix
./webdav.nix
];
}

View file

@ -52,6 +52,10 @@ let
};
machineLearning = {
enabled = true;
urls = [
"http://calcite.coho-tet.ts.net:3003"
"http://127.0.0.1:3003"
];
clip = {
enabled = true;
modelName = "XLM-Roberta-Large-ViT-H-14__frozen_laion5b_s13b_b90k";
@ -78,20 +82,10 @@ in
sops.templates."immich/auto_stack.env" = {
owner = "immich_auto_stack";
content = ''
API_KEY=${config.sops.placeholder."immich/auto_stack_apikey"};
API_KEY=${config.sops.placeholder."immich/auto_stack_apikey"}
'';
};
systemd.mounts = [
{
what = "originals";
where = "/mnt/immich/external-library/xin";
type = "virtiofs";
options = "ro,nodev,nosuid";
wantedBy = [ "immich-server.service" ];
}
];
systemd.timers.immich-auto-stack = {
enable = true;
wantedBy = [ "immich-server.service" ];
@ -109,8 +103,8 @@ in
]
);
immich_auto_stack = pkgs.fetchurl {
url = "https://gist.github.com/xinyangli/39de5979e72d81af6fe9ddb7d1805df4";
hash = "sha256-izbzP+330tZUGPTfS3SdJnGS5uSn5uf8WmXd6ep8SQg=";
url = "https://gist.githubusercontent.com/xinyangli/39de5979e72d81af6fe9ddb7d1805df4/raw/7798ed8cef7bcd3d06ed005feb0dd01b4b603684/immich_auto_stack.py";
hash = "sha256-qE7TRJ+TLFdSJanBiuKP6fgijdE1NqAeSXWSzsfyEO0=";
};
in
{
@ -118,10 +112,13 @@ in
SKIP_MATCH_MISS = "true";
DRY_RUN = "false";
API_URL = "http://127.0.0.1:${toString config.services.immich.port}/api";
PARENT_PROMOTE = "hdr,edit,export,selects,output";
};
serviceConfig = {
ExecStart = "${lib.getExe python} ${immich_auto_stack}";
EnvironmentFile = config.sops.templates."immich/auto_stack.env".path;
WorkingDirectory = "%t/immich-auto-stack";
RuntimeDirectory = "immich-auto-stack";
User = "immich_auto_stack";
Group = "immich_auto_stack";
};
@ -129,8 +126,8 @@ in
systemd.services.immich-server = {
serviceConfig = {
ReadWritePaths = [
"/mnt/immich/external-library/xin"
BindReadOnlyPaths = [
"/mnt/photos/xin/originals:/mnt/immich/external-library/xin"
];
Environment = "IMMICH_CONFIG_FILE=${config.sops.templates."immich/config.json".path}";
};
@ -155,8 +152,11 @@ in
users.users.immich.extraGroups = [
"video"
"render"
"privimg"
];
users.groups.privimg = { };
users.groups.immich_auto_stack = { };
users.users.immich_auto_stack = {
isSystemUser = true;

View file

@ -0,0 +1,47 @@
{ config, ... }:
{
sops.secrets = {
"webdav/photosync/password" = { };
};
sops.templates."webdav.env" = {
content = ''
PHOTOSYNC_PASSWORD=${config.sops.placeholder."webdav/photosync/password"}
'';
};
services.webdav = {
enable = true;
settings = {
address = "127.0.0.1";
port = "16065";
permissions = "CRUD";
behindProxy = true;
users = [
{
username = "photosync";
password = "{env}PHOTOSYNC_PASSWORD";
}
];
};
group = "privimg";
environmentFile = config.sops.templates."webdav.env".path;
};
systemd.services.webdav.serviceConfig = {
BindPaths = [
"/mnt/photos/xin/originals:%t/webdav/photosync"
];
RuntimeDirectory = "webdav";
WorkingDirectory = "%t/webdav";
};
users.users."${config.services.webdav.user}".extraGroups = [
"privimg"
];
services.caddy.virtualHosts."https://weilite.coho-tet.ts.net:6065".extraConfig = ''
reverse_proxy 127.0.0.1:16065
'';
}

View file

@ -16,9 +16,15 @@ let
cfg = config.inMainland;
in
{
options.inMainland = mkOption {
type = types.bool;
default = config.time.timeZone == "Asia/Shanghai";
options = {
inMainland = mkOption {
type = types.bool;
default = config.time.timeZone == "Asia/Shanghai";
};
commonSettings.network.enableProxy = mkOption {
type = types.bool;
default = config.inMainland;
};
};
config = mkIf cfg {
@ -31,9 +37,136 @@ in
"ntp.ntsc.ac.cn"
];
services.dae = {
sops = mkIf config.commonSettings.network.enableProxy {
secrets = {
"dae/sub" = {
sopsFile = ../../../machines/secrets.yaml;
};
};
templates."dae/sub.dae".content = ''
subscription {
my_sub: '${config.sops.placeholder."dae/sub"}'
}
'';
};
systemd.services.dae.serviceConfig.LoadCredential = mkIf config.commonSettings.network.enableProxy [
"sub.dae:${config.sops.templates."dae/sub.dae".path}"
];
services.dae = mkIf config.commonSettings.network.enableProxy {
enable = mkDefault true;
configFile = mkDefault "/var/lib/dae/config.dae";
config = ''
include {
./sub.dae
}
global {
tproxy_port: 12345
tproxy_port_protect: true
so_mark_from_dae: 0
log_level: info
disable_waiting_network: false
##### Interface and kernel options.
# lan_interface: docker0
wan_interface: auto
auto_config_kernel_parameter: true
##### Node connectivity check.
tcp_check_url: 'http://cp.cloudflare.com,1.1.1.1,2606:4700:4700::1111'
tcp_check_http_method: HEAD
udp_check_dns: 'dns.quad9.net:53,9.9.9.9,2620:fe::fe'
check_interval: 30s
# Group will switch node only when new_latency <= old_latency - tolerance.
check_tolerance: 100ms
##### Connecting options.
dial_mode: ${if config.commonSettings.network.localdns.enable then "domain+" else "domain"}
allow_insecure: false
sniffing_timeout: 100ms
tls_implementation: tls
# utls_imitate: firefox_auto
mptcp: true
}
# See https://github.com/daeuniverse/dae/blob/main/docs/en/configuration/dns.md for full examples.
dns {
ipversion_prefer: 4
upstream {
globaldns: 'tls://dns.quad9.net'
cndns: 'h3://dns.alidns.com:443'
tsdns: 'udp://100.100.100.100'
localdns: 'udp://127.0.0.1:53'
}
routing {
request {
${
if config.commonSettings.network.localdns.enable then
''
fallback: localdns
''
else
''
qname(suffix:ts.net) -> tsdns
qname(geosite:cn) -> cndns
fallback: globaldns
''
}
}
}
}
# Node group (outbound).
group {
default_group {
filter: name(regex: '^(hk)[0-9]+') [add_latency: -30ms]
filter: name(regex: '^(la)[0-9]+') [add_latency: -140ms]
filter: name(regex: '^(fra)[0-9]+') [add_latency: -150ms]
policy: min_moving_avg
}
}
# See https://github.com/daeuniverse/dae/blob/main/docs/en/configuration/routing.md for full examples.
routing {
# pname(kresd) && dport(53) && l4proto(udp)-> must_direct
# Disable h3 because it usually consumes too much cpu/mem resources.
l4proto(udp) && dport(443) -> block
pname(blackbox_exporter) -> direct
pname(tailscaled) -> direct
dip(224.0.0.0/3, 'ff00::/8') -> direct
dip(geoip:private) -> direct
# Direct traffic to dns server
dip(1.12.12.12) -> direct
dip(223.5.5.5) -> direct
dip(223.6.6.6) -> direct
# === Force Proxy ===
domain(geosite:linkedin) -> default_group
# === Custom direct rules ===
domain(geosite:cn) -> direct
domain(suffix:ipify.org) -> direct
domain(geosite:steam@cn) -> direct
dip(geoip:cn) -> direct
fallback: default_group
}
'';
};
};
}

View file

@ -25,6 +25,12 @@ in
useLocalResolver = true;
};
services.resolved.enable = mkIf cfg.localdns.enable false;
services.tailscale = mkIf cfg.localdns.enable {
extraUpFlags = [ "--accept-dns=false" ];
};
services.kresd = mkIf cfg.localdns.enable {
enable = true;
listenPlain = [ "127.0.0.1:53" ];

View file

@ -8,3 +8,4 @@ Demonstrate disk usage by nix-store path.
- [x] synapse jmalloc
- [ ] backup all directories under /var/lib/forgejo
- [ ] collect caddy access logs with promtail (waiting for caddy v2.9.0 release after which log file mode can be set)
- [ ] update "https" to "https-file" with dae 1.0.0