commit 09a33d8c71ab3d9ac0119a565b9d3a7a8247e7ec
parent da24facdbffb734afcc07a43c2f15d188ecc822a
Author: Toni Brown <me@tb148.net>
Date: Thu, 29 Jan 2026 05:05:55 +0800
use sops-nix
Diffstat:
6 files changed, 338 insertions(+), 12 deletions(-)
diff --git a/.sops.yaml b/.sops.yaml
@@ -0,0 +1,10 @@
+keys:
+ - &admin_tb148 19FE8C3696B760FE647D7FF84E512749E5D2792E
+ - &server_nixosion age17ag74r0avel6vfxd55r5n3tmj6ugtxegvlshv49uzdcd2carcp4shwtce8
+creation_rules:
+ - path_regex: secrets.(yaml|json|env|ini)$
+ key_groups:
+ - pgp:
+ - *admin_tb148
+ age:
+ - *server_nixosion
diff --git a/configuration.nix b/configuration.nix
@@ -10,6 +10,7 @@
}: {
imports = [
./hardware-configuration.nix
+ ./mihomo.nix
];
fileSystems."/".options = [
@@ -49,10 +50,9 @@
hardware.bluetooth.enable = true;
- nix.settings.experimental-features = [
- "nix-command"
- "flakes"
- ];
+ sops.defaultSopsFile = ./secrets.yaml;
+ sops.age.sshKeyPaths = ["/etc/ssh/ssh_host_ed25519_key"];
+ sops.secrets.doggygo = {};
environment.systemPackages = with pkgs; [
catppuccin-cursors.mochaMauve
@@ -87,11 +87,13 @@
networking.nftables.enable = true;
networking.firewall.enable = false;
+ services.openssh.enable = true;
+
services.mihomo = {
enable = true;
tunMode = true;
webui = pkgs.metacubexd;
- configFile = "${config.users.users.tb148.home}/mihomo.yaml";
+ configFile = "${config.sops.templates."mihomo.yaml".path}";
};
# programs.clash-verge = {
# enable = true;
@@ -100,9 +102,13 @@
# };
nix.package = pkgs.lixPackageSets.latest.lix;
+ nix.settings.experimental-features = [
+ "nix-command"
+ "flakes"
+ ];
nix.settings.substituters = ["https://mirrors.tuna.tsinghua.edu.cn/nix-channels/store"];
nix.extraOptions =
- lib.concatStringsSep "\n" [
+ builtins.concatStringsSep "\n" [
"extra-substituters = https://devenv.cachix.org"
"extra-trusted-public-keys = devenv.cachix.org-1:w1cLUi8dv3hnoSPGAuibQv+f9TZLr6cv/Hm9XgU50cw="
];
diff --git a/flake.lock b/flake.lock
@@ -62,7 +62,28 @@
"inputs": {
"catppuccin": "catppuccin",
"home-manager": "home-manager",
- "nixpkgs": "nixpkgs"
+ "nixpkgs": "nixpkgs",
+ "sops-nix": "sops-nix"
+ }
+ },
+ "sops-nix": {
+ "inputs": {
+ "nixpkgs": [
+ "nixpkgs"
+ ]
+ },
+ "locked": {
+ "lastModified": 1769469829,
+ "narHash": "sha256-wFcr32ZqspCxk4+FvIxIL0AZktRs6DuF8oOsLt59YBU=",
+ "ref": "refs/heads/master",
+ "rev": "c5eebd4eb2e3372fe12a8d70a248a6ee9dd02eff",
+ "revCount": 1128,
+ "type": "git",
+ "url": "ssh://git@github.com/Mic92/sops-nix"
+ },
+ "original": {
+ "type": "git",
+ "url": "ssh://git@github.com/Mic92/sops-nix"
}
}
},
diff --git a/flake.nix b/flake.nix
@@ -3,10 +3,18 @@
inputs = {
nixpkgs.url = "git+https://mirrors.tuna.tsinghua.edu.cn/git/nixpkgs.git?ref=nixos-unstable";
- home-manager.url = "git+ssh://git@github.com/nix-community/home-manager.git?ref=master";
- home-manager.inputs.nixpkgs.follows = "nixpkgs";
- catppuccin.url = "git+ssh://git@github.com/catppuccin/nix.git?ref=main";
- catppuccin.inputs.nixpkgs.follows = "nixpkgs";
+ home-manager = {
+ url = "git+ssh://git@github.com/nix-community/home-manager.git?ref=master";
+ inputs.nixpkgs.follows = "nixpkgs";
+ };
+ catppuccin = {
+ url = "git+ssh://git@github.com/catppuccin/nix.git?ref=main";
+ inputs.nixpkgs.follows = "nixpkgs";
+ };
+ sops-nix = {
+ url = "git+ssh://git@github.com/Mic92/sops-nix";
+ inputs.nixpkgs.follows = "nixpkgs";
+ };
};
outputs = {
@@ -14,6 +22,7 @@
nixpkgs,
home-manager,
catppuccin,
+ sops-nix,
...
} @ inputs: {
nixosConfigurations.nixosion =
@@ -22,8 +31,9 @@
specialArgs = {inherit inputs;};
modules = [
./configuration.nix
- catppuccin.nixosModules.catppuccin
home-manager.nixosModules.home-manager
+ catppuccin.nixosModules.catppuccin
+ sops-nix.nixosModules.sops
{
home-manager.useGlobalPkgs = true;
home-manager.useUserPackages = true;
diff --git a/mihomo.nix b/mihomo.nix
@@ -0,0 +1,251 @@
+{
+ config,
+ lib,
+ pkgs,
+ inputs,
+ ...
+}: {
+ sops.templates."mihomo.yaml".content =
+ builtins.toJSON {
+ allow-lan = false;
+ dns = {
+ default-nameserver = [
+ "tls://223.5.5.5"
+ "tls://223.6.6.6"
+ ];
+ enable = true;
+ enhanced-mode = "fake-ip";
+ fake-ip-filter = [
+ "*"
+ "+.lan"
+ "+.local"
+ ];
+ ipv6 = true;
+ nameserver = [
+ "https://doh.pub/dns-query"
+ "https://dns.alidns.com/dns-query"
+ ];
+ };
+ external-controller = "127.0.0.1:32805";
+ external-controller-cors = {
+ allow-origins = ["*"];
+ allow-private-network = true;
+ };
+ find-process-mode = "strict";
+ geodata-mode = true;
+ geox-url = {
+ geoip = "https://cdn.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@release/geoip.dat";
+ geosite = "https://cdn.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@release/geosite.dat";
+ };
+ global-client-fingerprint = "random";
+ ipv6 = true;
+ log-level = "info";
+ mixed-port = 7776;
+ profile = {
+ store-fake-ip = true;
+ store-selected = true;
+ };
+ proxies = [
+ {
+ name = "直连";
+ type = "direct";
+ udp = true;
+ }
+ {
+ name = "拒绝";
+ type = "reject";
+ udp = true;
+ }
+ ];
+ proxy-groups = [
+ {
+ name = "代理";
+ proxies = [
+ "直连"
+ "拒绝"
+ "手动选择"
+ "自动选择"
+ "故障转移"
+ "负载均衡"
+ ];
+ type = "select";
+ }
+ {
+ name = "国外";
+ proxies = [
+ "默认"
+ "代理"
+ "手动选择"
+ "自动选择"
+ "故障转移"
+ "负载均衡"
+ ];
+ type = "select";
+ }
+ {
+ name = "默认";
+ proxies = [
+ "直连"
+ "代理"
+ "手动选择"
+ "自动选择"
+ "故障转移"
+ "负载均衡"
+ ];
+ type = "select";
+ }
+ {
+ name = "国内";
+ proxies = [
+ "直连"
+ "默认"
+ "手动选择"
+ "自动选择"
+ "故障转移"
+ "负载均衡"
+ ];
+ type = "select";
+ }
+ {
+ name = "手动选择";
+ type = "select";
+ use = ["doggygo"];
+ }
+ {
+ interval = 300;
+ name = "自动选择";
+ type = "url-test";
+ url = "https://www.google.com";
+ use = ["doggygo"];
+ }
+ {
+ interval = 300;
+ name = "故障转移";
+ type = "fallback";
+ url = "https://www.google.com";
+ use = ["doggygo"];
+ }
+ {
+ interval = 300;
+ name = "负载均衡";
+ type = "load-balance";
+ url = "https://www.google.com";
+ use = ["doggygo"];
+ }
+ {
+ hidden = true;
+ name = "GLOBAL";
+ proxies = [
+ "代理"
+ "国外"
+ "默认"
+ "国内"
+ "手动选择"
+ "自动选择"
+ "故障转移"
+ "负载均衡"
+ ];
+ type = "select";
+ }
+ ];
+ proxy-providers = {
+ doggygo = {
+ interval = 86400;
+ type = "http";
+ url = "${config.sops.placeholder.doggygo}";
+ };
+ };
+ rule-providers = {
+ cn_domain = {
+ behavior = "domain";
+ format = "mrs";
+ interval = 86400;
+ type = "http";
+ url = "https://cdn.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@meta/geo/geosite/cn.mrs";
+ };
+ cn_ip = {
+ behavior = "ipcidr";
+ format = "mrs";
+ interval = 86400;
+ type = "http";
+ url = "https://cdn.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@meta/geo/geoip/cn.mrs";
+ };
+ "geolocation-!cn" = {
+ behavior = "domain";
+ format = "mrs";
+ interval = 86400;
+ type = "http";
+ url = "https://cdn.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@meta/geo/geosite/geolocation-!cn.mrs";
+ };
+ gfw = {
+ behavior = "domain";
+ format = "mrs";
+ interval = 86400;
+ type = "http";
+ url = "https://cdn.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@meta/geo/geosite/gfw.mrs";
+ };
+ private_domain = {
+ behavior = "domain";
+ format = "mrs";
+ interval = 86400;
+ type = "http";
+ url = "https://cdn.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@meta/geo/geosite/private.mrs";
+ };
+ private_ip = {
+ behavior = "ipcidr";
+ format = "mrs";
+ interval = 86400;
+ type = "http";
+ url = "https://cdn.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@meta/geo/geoip/private.mrs";
+ };
+ };
+ rules = [
+ "RULE-SET,private_domain,直连,no-resolve"
+ "RULE-SET,private_ip,直连,no-resolve"
+ "DST-PORT,22,直连"
+ "RULE-SET,cn_domain,国内"
+ "RULE-SET,cn_ip,国内"
+ "RULE-SET,gfw,代理"
+ "RULE-SET,geolocation-!cn,国外"
+ "MATCH,默认"
+ ];
+ secret = "Scene-Effect-Mixture-Explosive";
+ sniffer = {
+ enable = true;
+ sniff = {
+ HTTP = {
+ override-destination = true;
+ ports = [
+ 80
+ "8080-8880"
+ ];
+ };
+ QUIC = {
+ ports = [
+ 443
+ 8443
+ ];
+ };
+ TLS = {
+ ports = [
+ 443
+ 8443
+ ];
+ };
+ };
+ };
+ tcp-concurrent = true;
+ tun = {
+ auto-detect-interface = true;
+ auto-redirect = true;
+ auto-route = true;
+ dns-hijack = [
+ "any:53"
+ "tcp://any:53"
+ ];
+ enable = true;
+ stack = "mixed";
+ };
+ unified-delay = true;
+ };
+}
diff --git a/secrets.yaml b/secrets.yaml
@@ -0,0 +1,28 @@
+doggygo: ENC[AES256_GCM,data:+Aqq7vlT4dbVCYBImZ/kU/JaW7QfqukCak6BM4EBcvpcUbLqnwfq0kvPCCxgU6s2PAQzch3OBlgua+CVjrUMzxmaoWKh4zgBBmBNm/d1CODEtFNh,iv:HiZQFp2mQquozNzm3YxnXKQXtmclbAR44GbUG4ut0Yo=,tag:6IMMRTRL9X99ol2bxluwRQ==,type:str]
+sops:
+ age:
+ - recipient: age17ag74r0avel6vfxd55r5n3tmj6ugtxegvlshv49uzdcd2carcp4shwtce8
+ enc: |
+ -----BEGIN AGE ENCRYPTED FILE-----
+ YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB4QXJYWTIxekxvTmVRdWdS
+ b3lRTzBFbUZ4TGJyT29RdzdheTZrWlRPSkhVCk1HSVJ4VjZDL1YvaDRPeERWZFdl
+ TU1QSldVQUtjQXR0OGt3WEd1bmxOZnMKLS0tIEYrclY1TU9GaHlKcmVNOHk5RU1J
+ Y0FXNjI1YkRBc3IyWTc5enZ3c25lZW8Kx7k8+VpKHXtQqAXJU1Sz7QKOm0csecMg
+ S4QclisKM4XU1zAkFDFLJVvJ3a8qg0rXb2Q5W19CZW+X27YXKhXU0g==
+ -----END AGE ENCRYPTED FILE-----
+ lastmodified: "2026-01-28T21:02:45Z"
+ mac: ENC[AES256_GCM,data:Xi2R2gAGlidGGe7KD6mXTVYpHaFOwTg53SVAbv7Ntx1Emu9I46YdG7tn2zSqpnu7Cr1y6/GVZOsVaANTK5JH66KBqAoMCp6WInTeJIz92LYpEWMDLQEPbuvyw64NV2tnv9frTDyfLagbiIRu9SqMtOciMC+F3DN8EdvyZlaTlw8=,iv:ag1XM3KOZhClHbkLpDFg1QFxT7gky8TnSrV2Q6oN/2E=,tag:+RBrF5hhzO3d48bbrHBsgA==,type:str]
+ pgp:
+ - created_at: "2026-01-28T20:51:25Z"
+ enc: |-
+ -----BEGIN PGP MESSAGE-----
+
+ wV4DoAJ7X5x4kXQSAQdA35MhWxd/S6FjdG1RNkOWPBqKdRhj17M7TK/sp+rsA3Mw
+ GkhSHk19hi+9lylnXoJmuRBPeQ4H1nFB+eLNJYQ5w1Mu6SEETgiJharj2LwlBNBy
+ 0lEBmE+jKRHj8+GP6qUd2xdElwhJ7sDP+z9jww5VEpwqFByp0zCVWJCKyjbrtkCl
+ s1DYuj+LTAUCCpJ57LAzsZ7Imzec8zPEIHZv9mMieagRJog=
+ =aRrp
+ -----END PGP MESSAGE-----
+ fp: 19FE8C3696B760FE647D7FF84E512749E5D2792E
+ unencrypted_suffix: _unencrypted
+ version: 3.11.0