Compare commits

..

No commits in common. "6fe7504460c6bd50e2f422ba3da118c7dbb7c3da" and "4b5b41b05ae779a0409e354b0ede77be9b4fb46f" have entirely different histories.

57 changed files with 1359 additions and 1674 deletions

View file

@ -1,51 +0,0 @@
name: Eval NixOS Configurations
on:
push:
branches:
- deploy
workflow_dispatch:
permissions:
contents: write
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
ref: deploy
- name: Install Nix
uses: cachix/install-nix-action@v25
- name: Configure Git
run: |
git config --global user.name "GitHub Actions Bot"
git config --global user.email "actions@github.com"
- name: Process Configurations
run: |
git checkout -b deploy-comin-eval
mkdir -p eval
hosts=$(nix flake show --json | jq -r '.nixosConfigurations | keys[]')
echo "Found hosts: $hosts"
for host in $hosts; do
echo "Eval derivation for $host"
if ! nix show-derivation -L ".#nixosConfigurations.$host.config.system.build.toplevel" > "eval/$host.json"; then
echo "❌ Failed to evaluate $host"
else
echo "✅ Successfully evaluated $host"
fi
done
echo "Total hosts: $(echo "$hosts" | wc -w)"
echo "Failed hosts: $failed_hosts"
git add eval/
git commit -m "Update deployment configurations for all hosts"
git push origin deploy-comin-eval

View file

@ -15,7 +15,6 @@ creation_rules:
- age: - age:
- *xin - *xin
- *host-calcite - *host-calcite
- *host-weilite
- *host-massicot - *host-massicot
- *host-thorite - *host-thorite
- *host-biotite - *host-biotite

198
flake.lock generated
View file

@ -2,11 +2,11 @@
"nodes": { "nodes": {
"catppuccin": { "catppuccin": {
"locked": { "locked": {
"lastModified": 1733001911, "lastModified": 1731232837,
"narHash": "sha256-uX/9m0TbdhEzuWA0muM5mI/AaWcLiDLjCCyu5Qr9MRk=", "narHash": "sha256-0aIwr/RC/oe7rYkfJb47xjdEQDSNcqpFGsEa+EPlDEs=",
"owner": "catppuccin", "owner": "catppuccin",
"repo": "nix", "repo": "nix",
"rev": "a817009ebfd2cca7f70a77884e5098d0a8c83f8e", "rev": "32359bf226fe874d3b7a0a5753d291a4da9616fe",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -68,11 +68,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1733168902, "lastModified": 1732645828,
"narHash": "sha256-8dupm9GfK+BowGdQd7EHK5V61nneLfr9xR6sc5vtDi0=", "narHash": "sha256-+4U2I2653JvPFxcux837ulwYS864QvEueIljUkwytsk=",
"owner": "nix-community", "owner": "nix-community",
"repo": "disko", "repo": "disko",
"rev": "785c1e02c7e465375df971949b8dcbde9ec362e5", "rev": "869ba3a87486289a4197b52a6c9e7222edf00b3e",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -167,27 +167,6 @@
"type": "github" "type": "github"
} }
}, },
"flake-parts_3": {
"inputs": {
"nixpkgs-lib": [
"nur",
"nixpkgs"
]
},
"locked": {
"lastModified": 1733312601,
"narHash": "sha256-4pDvzqnegAfRkPwO3wmwBhVi/Sye1mzps0zHWYnP88c=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "205b12d8b7cd4802fbcb8e8ef6a0f1408781a4f9",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "flake-parts",
"type": "github"
}
},
"flake-utils": { "flake-utils": {
"locked": { "locked": {
"lastModified": 1659877975, "lastModified": 1659877975,
@ -259,11 +238,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1730814269, "lastModified": 1730302582,
"narHash": "sha256-fWPHyhYE6xvMI1eGY3pwBTq85wcy1YXqdzTZF+06nOg=", "narHash": "sha256-W1MIJpADXQCgosJZT8qBYLRuZls2KSiKdpnTVdKBuvU=",
"owner": "cachix", "owner": "cachix",
"repo": "git-hooks.nix", "repo": "git-hooks.nix",
"rev": "d70155fdc00df4628446352fc58adc640cd705c2", "rev": "af8a16fe5c264f5e9e18bcee2859b40a656876cf",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -302,11 +281,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1733754861, "lastModified": 1731786860,
"narHash": "sha256-3JKzIou54yjiMVmvgdJwopekEvZxX3JDT8DpKZs4oXY=", "narHash": "sha256-130gQ5k8kZlxjBEeLpE+SvWFgSOFgQFeZlqIik7KgtQ=",
"owner": "nix-community", "owner": "nix-community",
"repo": "home-manager", "repo": "home-manager",
"rev": "9ebaa80a227eaca9c87c53ed515ade013bc2bca9", "rev": "1bd5616e33c0c54d7a5b37db94160635a9b27aeb",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -324,11 +303,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1731235328, "lastModified": 1730490306,
"narHash": "sha256-NjavpgE9/bMe/ABvZpyHIUeYF1mqR5lhaep3wB79ucs=", "narHash": "sha256-AvCVDswOUM9D368HxYD25RsSKp+5o0L0/JHADjLoD38=",
"owner": "nix-community", "owner": "nix-community",
"repo": "home-manager", "repo": "home-manager",
"rev": "60bb110917844d354f3c18e05450606a435d2d10", "rev": "1743615b61c7285976f85b303a36cdf88a556503",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -353,16 +332,16 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1729958008, "lastModified": 1729544999,
"narHash": "sha256-EiOq8jF4Z/zQe0QYVc3+qSKxRK//CFHMB84aYrYGwEs=", "narHash": "sha256-YcyJLvTmN6uLEBGCvYoMLwsinblXMkoYkNLEO4WnKus=",
"owner": "NuschtOS", "owner": "NuschtOS",
"repo": "ixx", "repo": "ixx",
"rev": "9fd01aad037f345350eab2cd45e1946cc66da4eb", "rev": "65c207c92befec93e22086da9456d3906a4e999c",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "NuschtOS", "owner": "NuschtOS",
"ref": "v0.0.6", "ref": "v0.0.5",
"repo": "ixx", "repo": "ixx",
"type": "github" "type": "github"
} }
@ -376,17 +355,17 @@
"nixvim": "nixvim" "nixvim": "nixvim"
}, },
"locked": { "locked": {
"lastModified": 1732936640, "lastModified": 1730642581,
"narHash": "sha256-NcluA0L+ZV5MUj3UuQhlkGCj8KoEhX/ObWlMHZ/F/ac=", "narHash": "sha256-Tcq+RnctJTm+TUr1fN3ivqYNcd1pJnHYzLDQdgUCX70=",
"ref": "refs/heads/master", "ref": "refs/heads/master",
"rev": "a3709a89797ea094f82d38edeb4a538c07c8c3fa", "rev": "a09d2b94efb5e2d801275a244eedaab0816f3702",
"revCount": 20, "revCount": 18,
"type": "git", "type": "git",
"url": "https://git.xiny.li/xin/nixvim" "url": "https://git.xinyang.life/xin/nixvim"
}, },
"original": { "original": {
"type": "git", "type": "git",
"url": "https://git.xiny.li/xin/nixvim" "url": "https://git.xinyang.life/xin/nixvim"
} }
}, },
"nix-darwin": { "nix-darwin": {
@ -398,11 +377,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1731153869, "lastModified": 1730448474,
"narHash": "sha256-3Ftf9oqOypcEyyrWJ0baVkRpvQqroK/SVBFLvU3nPuc=", "narHash": "sha256-qE/cYKBhzxHMtKtLK3hlSR3uzO1pWPGLrBuQK7r0CHc=",
"owner": "lnl7", "owner": "lnl7",
"repo": "nix-darwin", "repo": "nix-darwin",
"rev": "5c74ab862c8070cbf6400128a1b56abb213656da", "rev": "683d0c4cd1102dcccfa3f835565378c7f3cbe05e",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -439,11 +418,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1733629314, "lastModified": 1731814505,
"narHash": "sha256-U0vivjQFAwjNDYt49Krevs1murX9hKBFe2Ye0cHpgbU=", "narHash": "sha256-l9ryrx1Twh08a+gxrMGM9O/aZKEimZfa6sZVyPCImgI=",
"owner": "Mic92", "owner": "Mic92",
"repo": "nix-index-database", "repo": "nix-index-database",
"rev": "f1e477a7dd11e27e7f98b646349cd66bbabf2fb8", "rev": "bdba246946fb079b87b4cada4df9b1cdf1c06132",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -463,11 +442,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1733795858, "lastModified": 1731808759,
"narHash": "sha256-K595Q2PrZv2iiumdBkwM2G456T2lKsLD71bn/fbJiQ0=", "narHash": "sha256-WwJqguc/5Q7HEwHlgDzDT8mtd8ZxInxZM2neJKC1oh8=",
"owner": "nix-community", "owner": "nix-community",
"repo": "nix-vscode-extensions", "repo": "nix-vscode-extensions",
"rev": "66ced222ef9235f90dbdd754ede3d6476722aaa9", "rev": "5cf92678e6799ce45442dee4c9cb8094843c7cfa",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -478,11 +457,11 @@
}, },
"nixos-hardware": { "nixos-hardware": {
"locked": { "locked": {
"lastModified": 1733481457, "lastModified": 1731797098,
"narHash": "sha256-IS3bxa4N1VMSh3/P6vhEAHQZecQ3oAlKCDvzCQSO5Is=", "narHash": "sha256-UhWmEZhwJZmVZ1jfHZFzCg+ZLO9Tb/v3Y6LC0UNyeTo=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixos-hardware", "repo": "nixos-hardware",
"rev": "e563803af3526852b6b1d77107a81908c66a9fcf", "rev": "672ac2ac86f7dff2f6f3406405bddecf960e0db6",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -494,11 +473,11 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1731139594, "lastModified": 1730200266,
"narHash": "sha256-IigrKK3vYRpUu+HEjPL/phrfh7Ox881er1UEsZvw9Q4=", "narHash": "sha256-l253w0XMT8nWHGXuXqyiIC/bMvh1VRszGXgdpQlfhvU=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "76612b17c0ce71689921ca12d9ffdc9c23ce40b2", "rev": "807e9154dcb16384b1b765ebe9cd2bba2ac287fd",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -522,11 +501,11 @@
}, },
"nixpkgs-stable": { "nixpkgs-stable": {
"locked": { "locked": {
"lastModified": 1733730953, "lastModified": 1731652201,
"narHash": "sha256-dlK7n82FEyZlHH7BFHQAM5tua+lQO1Iv7aAtglc1O5s=", "narHash": "sha256-XUO0JKP1hlww0d7mm3kpmIr4hhtR4zicg5Wwes9cPMg=",
"owner": "nixos", "owner": "nixos",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "7109b680d161993918b0a126f38bc39763e5a709", "rev": "c21b77913ea840f8bcf9adf4c41cecc2abffd38d",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -536,13 +515,29 @@
"type": "github" "type": "github"
} }
}, },
"nixpkgs-stable_2": {
"locked": {
"lastModified": 1731797254,
"narHash": "sha256-df3dJApLPhd11AlueuoN0Q4fHo/hagP75LlM5K1sz9g=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "e8c38b73aeb218e27163376a2d617e61a2ad9b59",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "release-24.05",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_2": { "nixpkgs_2": {
"locked": { "locked": {
"lastModified": 1733805440, "lastModified": 1731819057,
"narHash": "sha256-AQdCeGt3dMV9/cchlWGMcP0Z8qM47V+B0p7cSRr+HhA=", "narHash": "sha256-nfqKsQhFCakM+eIKGf/JWu/g56rOPoGny10EZN8q7R0=",
"owner": "xinyangli", "owner": "xinyangli",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "61b1078fca3a097ce06ada68a6f2766347eed02c", "rev": "b2644ed7258502987ad4a70cf8959bf5a26ce26d",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -552,22 +547,6 @@
"type": "github" "type": "github"
} }
}, },
"nixpkgs_3": {
"locked": {
"lastModified": 1733581040,
"narHash": "sha256-Qn3nPMSopRQJgmvHzVqPcE3I03zJyl8cSbgnnltfFDY=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "22c3f2cf41a0e70184334a958e6b124fb0ce3e01",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixvim": { "nixvim": {
"inputs": { "inputs": {
"devshell": "devshell", "devshell": "devshell",
@ -581,11 +560,11 @@
"treefmt-nix": "treefmt-nix" "treefmt-nix": "treefmt-nix"
}, },
"locked": { "locked": {
"lastModified": 1731527733, "lastModified": 1730569492,
"narHash": "sha256-12OpSgbLDiKmxvBXwVracIfGI9FpjFyHpa1r0Ho+NFA=", "narHash": "sha256-NByr7l7JetL9kIrdCOcRqBu+lAkruYXETp1DMiDHNQs=",
"owner": "nix-community", "owner": "nix-community",
"repo": "nixvim", "repo": "nixvim",
"rev": "f11a877bcc1d66cc8bd7990c704f91c1e99c7d08", "rev": "6f210158b03b01a1fd44bf3968165e6da80635ce",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -595,17 +574,12 @@
} }
}, },
"nur": { "nur": {
"inputs": {
"flake-parts": "flake-parts_3",
"nixpkgs": "nixpkgs_3",
"treefmt-nix": "treefmt-nix_2"
},
"locked": { "locked": {
"lastModified": 1733805328, "lastModified": 1731819675,
"narHash": "sha256-5F49/mOzFb40uUZh71uNr7kBXjDCw5ZfHMbpZjjUVBQ=", "narHash": "sha256-GGp/rEfxRdi1BD9TlHoXxp2g9IuKDp0Jk7wYh1LacP8=",
"owner": "nix-community", "owner": "nix-community",
"repo": "NUR", "repo": "NUR",
"rev": "b54fa3d8c020e077d88be036a12a711b84fe2031", "rev": "59740d792bea5caa547c9bc7ce366802ecfafb7f",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -625,11 +599,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1731060242, "lastModified": 1730515563,
"narHash": "sha256-43yLsOm/wxBbfYSNDWVJeVv5Ij+23X3BIjFUfsdx/6M=", "narHash": "sha256-8lklUZRV7nwkPLF3roxzi4C2oyLydDXyAzAnDvjkOms=",
"owner": "NuschtOS", "owner": "NuschtOS",
"repo": "search", "repo": "search",
"rev": "ef493352f9e1f051e01a55c062731503a6b36b4e", "rev": "9e22bd742480916ff5d0ab20ca2522eaa3fa061e",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -659,14 +633,15 @@
"inputs": { "inputs": {
"nixpkgs": [ "nixpkgs": [
"nixpkgs" "nixpkgs"
] ],
"nixpkgs-stable": "nixpkgs-stable_2"
}, },
"locked": { "locked": {
"lastModified": 1733785344, "lastModified": 1731814239,
"narHash": "sha256-pm4cfEcPXripE36PYCl0A2Tu5ruwHEvTee+HzNk+SQE=", "narHash": "sha256-TGnMXCeXS924w9W6CvRFtUCUFr8E/RK138lHxU3vcw8=",
"owner": "Mic92", "owner": "Mic92",
"repo": "sops-nix", "repo": "sops-nix",
"rev": "a80af8929781b5fe92ddb8ae52e9027fae780d2a", "rev": "47fc1d8c72dbd69b32ecb2019b5b648da3dd20ce",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -742,27 +717,6 @@
"repo": "treefmt-nix", "repo": "treefmt-nix",
"type": "github" "type": "github"
} }
},
"treefmt-nix_2": {
"inputs": {
"nixpkgs": [
"nur",
"nixpkgs"
]
},
"locked": {
"lastModified": 1733222881,
"narHash": "sha256-JIPcz1PrpXUCbaccEnrcUS8jjEb/1vJbZz5KkobyFdM=",
"owner": "numtide",
"repo": "treefmt-nix",
"rev": "49717b5af6f80172275d47a418c9719a31a78b53",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "treefmt-nix",
"type": "github"
}
} }
}, },
"root": "root", "root": "root",

View file

@ -43,7 +43,7 @@
}; };
my-nixvim = { my-nixvim = {
url = "git+https://git.xiny.li/xin/nixvim"; url = "git+https://git.xinyang.life/xin/nixvim";
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
}; };
@ -84,16 +84,11 @@
overlayModule = overlayModule =
{ ... }: { ... }:
{ {
options.my-lib = nixpkgs.lib.mkOption { _module.args.my-lib = import ./overlays/my-lib;
type = nixpkgs.lib.types.attrs; nixpkgs.overlays = [
default = import ./overlays/my-lib; editorOverlay
}; (import ./overlays/add-pkgs.nix)
config = { ];
nixpkgs.overlays = [
editorOverlay
(import ./overlays/add-pkgs.nix)
];
};
}; };
deploymentModule = { deploymentModule = {
deployment.targetUser = "xin"; deployment.targetUser = "xin";
@ -111,6 +106,7 @@
nodeNixosModules = { nodeNixosModules = {
calcite = [ calcite = [
nixos-hardware.nixosModules.asus-zephyrus-ga401 nixos-hardware.nixosModules.asus-zephyrus-ga401
nur.nixosModules.nur
catppuccin.nixosModules.catppuccin catppuccin.nixosModules.catppuccin
machines/calcite/configuration.nix machines/calcite/configuration.nix
(mkHome "xin" "calcite") (mkHome "xin" "calcite")
@ -146,15 +142,17 @@
user: host: user: host:
{ ... }: { ... }:
{ {
imports = [ home-manager.nixosModules.home-manager ]; imports = [
config = { home-manager.nixosModules.home-manager
home-manager = { {
sharedModules = sharedHmModules; home-manager = {
useGlobalPkgs = true; sharedModules = sharedHmModules;
useUserPackages = true; useGlobalPkgs = true;
}; useUserPackages = true;
home-manager.users.${user} = (import ./home).${user}.${host}; };
}; home-manager.users.${user} = (import ./home).${user}.${host};
}
];
}; };
mkNixos = mkNixos =
{ {
@ -286,22 +284,16 @@
{ {
imports = nodeNixosModules.biotite ++ sharedColmenaModules; imports = nodeNixosModules.biotite ++ sharedColmenaModules;
}; };
osmium =
{ ... }:
{
deployment = {
targetHost = "osmium.coho-tet.ts.net";
buildOnTarget = false;
};
imports = nodeNixosModules.osmium ++ sharedColmenaModules;
};
}; };
nixosConfigurations = { nixosConfigurations = {
calcite = mkNixos { calcite = mkNixos {
hostname = "calcite"; hostname = "calcite";
}; };
osmium = mkNixos {
hostname = "osmium";
};
} // self.colmenaHive.nodes; } // self.colmenaHive.nodes;
} }
@ -311,7 +303,7 @@
pkgs = nixpkgs.legacyPackages.${system}; pkgs = nixpkgs.legacyPackages.${system};
mkHomeConfiguration = user: host: { mkHomeConfiguration = user: host: {
name = "${user}-${host}"; name = user;
value = home-manager.lib.homeManagerConfiguration { value = home-manager.lib.homeManagerConfiguration {
inherit pkgs; inherit pkgs;
modules = [ modules = [

View file

@ -125,8 +125,7 @@ in
profiles.default = { profiles.default = {
isDefault = true; isDefault = true;
userChrome = '' userChrome = ''
#titlebar {
#TabsToolbar {
display: none; display: none;
} }
@ -137,7 +136,7 @@ in
[titlepreface*="."] #sidebar-header { [titlepreface*="."] #sidebar-header {
visibility: collapse !important; visibility: collapse !important;
} }
[titlepreface*="."] #TabsToolbar { [titlepreface*="."] #titlebar {
visibility: collapse; visibility: collapse;
} }
@ -149,7 +148,7 @@ in
min-width: var(--uc-sidebar-width) !important; min-width: var(--uc-sidebar-width) !important;
width: var(--uc-sidebar-width) !important; width: var(--uc-sidebar-width) !important;
max-width: var(--uc-sidebar-width) !important; max-width: var(--uc-sidebar-width) !important;
z-index: calc(var(--browser-area-z-index-tabbox) + 1); z-index:1;
} }
#sidebar-box[positionend]{ direction: rtl } #sidebar-box[positionend]{ direction: rtl }
@ -191,12 +190,12 @@ in
transition-delay: 0ms !important; transition-delay: 0ms !important;
} }
.sidebar-placeTree { .sidebar-panel{
/* background-color: transparent !important; */ background-color: transparent !important;
color: var(--newtab-text-primary-color) !important; color: var(--newtab-text-primary-color) !important;
} }
.sidebar-placeTree #search-box{ .sidebar-panel #search-box{
-moz-appearance: none !important; -moz-appearance: none !important;
background-color: rgba(249,249,250,0.1) !important; background-color: rgba(249,249,250,0.1) !important;
color: inherit !important; color: inherit !important;

View file

@ -5,12 +5,13 @@
... ...
}: }:
{ {
imports = [ imports = [ ];
./modern-unix.nix
];
home.packages = with pkgs; [ home.packages = with pkgs; [
dig dig
du-dust # du + rust
zoxide # autojumper
ripgrep
file file
man-pages man-pages
unar unar
@ -18,6 +19,7 @@
wget wget
tmux tmux
ffmpeg ffmpeg
tealdeer
rclone rclone
wl-clipboard wl-clipboard

View file

@ -1,17 +0,0 @@
{ pkgs, ... }:
{
home.packages = with pkgs; [
httpie
curlie
bat
htop
procs
rust-parallel
jq
fd
du-dust # du + rust
zoxide # autojumper
ripgrep
tealdeer
];
}

View file

@ -1,7 +1,5 @@
{ {
pkgs,
lib, lib,
config,
... ...
}: }:
@ -9,12 +7,6 @@
imports = [ imports = [
./hardware-configurations.nix ./hardware-configurations.nix
./services/gotosocial.nix ./services/gotosocial.nix
./services/synapse.nix
./services/restic.nix
./services/miniflux.nix
./services/hedgedoc.nix
./services/forgejo.nix
./services/vaultwarden.nix
]; ];
networking.hostName = "biotite"; networking.hostName = "biotite";
@ -36,56 +28,20 @@
commonSettings = { commonSettings = {
auth.enable = true; auth.enable = true;
autoupgrade.enable = true;
}; };
custom.monitoring = { custom.monitoring = {
promtail.enable = true; promtail.enable = true;
}; };
custom.prometheus.exporters = {
enable = true;
node.enable = true;
};
services.tailscale.enable = true;
services.caddy.enable = true;
sops = { sops = {
defaultSopsFile = ./secrets.yaml; defaultSopsFile = ./secrets.yaml;
age.sshKeyPaths = [ "/etc/ssh/ssh_host_ed25519_key" ]; age.sshKeyPaths = [ "/etc/ssh/ssh_host_ed25519_key" ];
}; };
services.postgresql = { services.caddy.enable = true;
enable = true; services.tailscale.enable = true;
package = pkgs.postgresql_17;
settings = {
allow_alter_system = false;
# DB Version: 17
# OS Type: linux
# DB Type: mixed
# Total Memory (RAM): 8 GB
# CPUs num: 4
# Data Storage: ssd
max_connections = 100;
shared_buffers = "2GB";
effective_cache_size = "6GB";
maintenance_work_mem = "512MB";
checkpoint_completion_target = 0.9;
wal_buffers = "16MB";
default_statistics_target = 100;
random_page_cost = 1.1;
effective_io_concurrency = 200;
work_mem = "5242kB";
huge_pages = "off";
min_wal_size = "1GB";
max_wal_size = "4GB";
max_worker_processes = 4;
max_parallel_workers_per_gather = 2;
max_parallel_workers = 4;
max_parallel_maintenance_workers = 2;
};
};
users.users.root.hashedPassword = "$y$j9T$NToEZWJBONjSgRnMd9Ur9/$o6n7a9b8eUILQz4d37oiHCCVnDJ8hZTZt.c.37zFfU."; users.users.root.hashedPassword = "$y$j9T$NToEZWJBONjSgRnMd9Ur9/$o6n7a9b8eUILQz4d37oiHCCVnDJ8hZTZt.c.37zFfU.";

View file

@ -1,16 +1,5 @@
gotosocial: gotosocial:
oidc_client_secret: ENC[AES256_GCM,data:KVQxzs67sohax2h0Y/jjhnbY4fetrdVvWhBGbqgDSGgBC7QazrOmTA++BSRzMmVv,iv:HIRMc56aLanqQRTWH9E0wzzXymImi0pxK/ccPEP8Fcc=,tag:PMhOLeE3mKIIQveRdfpgpA==,type:str] oidc_client_secret: ENC[AES256_GCM,data:KVQxzs67sohax2h0Y/jjhnbY4fetrdVvWhBGbqgDSGgBC7QazrOmTA++BSRzMmVv,iv:HIRMc56aLanqQRTWH9E0wzzXymImi0pxK/ccPEP8Fcc=,tag:PMhOLeE3mKIIQveRdfpgpA==,type:str]
synapse:
oidc_client_secret: ENC[AES256_GCM,data:TdZF8Bo+h34fn03sPpt7JEqmP8Cwm8V++q9VDvaapMBc3rlkrVu3iDUhQE2DvJri,iv:/QNX+aYUPpDKIqWZ13TLAznR3ZpUPI8rQHrJuqv7R+g=,tag:lcBIpeWiIXK/NV84uuxNiA==,type:str]
restic:
repo_url: ENC[AES256_GCM,data:ZcBMqwEsyc7zyEftJZj4XkKBzUHwlqd6cjX8xVDn9m26jBL7aP5atpnXDRE9FXY4CuAllFyQZyAOQ2L61Nfx+iplL2ADbSoH,iv:fhNODiyoOlZEqYR2O/GsH2IWTPDr3rXSJgWC/EFDLSA=,tag:nZdKKnpiszSiXxdZI1KQ/A==,type:str]
repo_password: ENC[AES256_GCM,data:9YDOz1tiyykz6zSXboWtIg==,iv:j96mRLXGuD4NZcC0Nv1yXFbtOlr6UborqclefZ7J94w=,tag:MqhSewK2NuckTJBf7xu+lA==,type:str]
miniflux:
oauth2_secret: ENC[AES256_GCM,data:/WtZemrdKU8bQbxzrAn437uqoJSO+yZSUDCnxovXV0HFZYQvAn2rbMrgOdoc1OuP,iv:xENKuGDYS1ctnO/WkGv1TxjtQYZ8p64Ik/lMIIam4Q0=,tag:RbAA0LUmsAQDqEM5+a2quQ==,type:str]
hedgedoc:
client_secret: ENC[AES256_GCM,data:J6lRBM7V6F+gPYVyEbOzsFUQe8+3ggP0r58c655DNt7TGgKGdq95pRvLaghMmBCc,iv:i+eLYwnmG1/bKtad2iM2pwEAC3GZLNaKS5ldbubRvyY=,tag:yxaug6YdYo8RR3YOyHd/iA==,type:str]
forgejo:
client_secret: ENC[AES256_GCM,data:5OXhaGzBCbge2tvTaU4ry6/KoavQeYJ45EuakCQJlxb5gMXjRK/s+feF25YJSr2f,iv:TT8j+ciKeSQCZzu1E7D70hWNFpn0cGiomz7jURXjavc=,tag:JVJR033Pc2vaLudaovkl8w==,type:str]
sops: sops:
kms: [] kms: []
gcp_kms: [] gcp_kms: []
@ -35,8 +24,8 @@ sops:
RzBMVDNjS29SUkdRK3dIV01sU0hYR3cK1SbvKAM6Gpsffv3HIi/WtWnCZUBic0AT RzBMVDNjS29SUkdRK3dIV01sU0hYR3cK1SbvKAM6Gpsffv3HIi/WtWnCZUBic0AT
ZRv4pvJBx1oxWsKIHW0t6VrqWMQ+suup8p6dW+h5HE8Z4ciIMrXLEg== ZRv4pvJBx1oxWsKIHW0t6VrqWMQ+suup8p6dW+h5HE8Z4ciIMrXLEg==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
lastmodified: "2024-12-04T05:07:32Z" lastmodified: "2024-12-02T05:10:32Z"
mac: ENC[AES256_GCM,data:hD7645epMVYHU6K1AZsHu+fp/PMIqqiZpv7K4Vxzo84slzn0CfZSYaVaYxKNGjOIgEGN9D2FFmq9WL6ChMskMfqqafY7qDpSQqFp9TUwb5jN34XcQg9vplfNw+lMqsnDCt1HENWErRnlDxTI2ctSEcx3UKGBOQ3ttLzUIySdnFY=,iv:reOsqvc8E3l8yxb5gVcqF/rU2o2yKmaUyGNRNT+Skx8=,tag:eBoV8G+X0cPs3Q1xAuv55w==,type:str] mac: ENC[AES256_GCM,data:ZAdFsjVuk1Fiv+DKmHrc1yu1XQpRDmRHaQhu5hduSZUa1W1cXdTlChvIW5vADFg5tVCjuYptuLvCMW+ZSQeqqG2ntHHZ+IkuovZzKFuc+BIiL/jF2ZzbyJ7X4Wj1GziCScHVxx98dgbpFoufHe6N3wCaHmngo1RYsY5N1RRbRdU=,iv:5IMQ0kOX9UAOm8bcsQRyu6zu8GJjvnHFufCNjY0s9UI=,tag:zBEPSR9DZDpwbCaIka8mXA==,type:str]
pgp: [] pgp: []
unencrypted_suffix: _unencrypted unencrypted_suffix: _unencrypted
version: 3.9.1 version: 3.9.1

View file

@ -1,115 +0,0 @@
{
config,
pkgs,
lib,
...
}:
let
inherit (lib) getExe;
inherit (config.my-lib.settings) idpUrl forgejoDomain forgejoGitDomain;
settings = {
service.DISABLE_REGISTRATION = true;
server = {
DOMAIN = forgejoDomain;
ROOT_URL = "https://${forgejoDomain}";
HTTP_ADDR = "/var/run/forgejo/forgejo.sock";
START_SSH_SERVER = false;
SSH_USER = config.services.forgejo.user;
SSH_DOMAIN = forgejoGitDomain;
SSH_PORT = 22;
PROTOCOL = "http+unix";
LFS_MAX_FILE_SIZE = 10737418240;
LANDING_PAGE = "/explore/repos";
};
repository = {
ENABLE_PUSH_CREATE_USER = true;
};
service = {
ENABLE_BASIC_AUTHENTICATION = false;
};
oauth2 = {
ENABLED = false; # Disable forgejo as oauth2 provider
};
oauth2_client = {
ACCOUNT_LINKING = "auto";
USERNAME = "email";
ENABLE_AUTO_REGISTRATION = true;
UPDATE_AVATAR = false;
OPENID_CONNECT_SCOPES = "openid profile email groups";
};
metrics = {
# ENABLED = true;
};
other = {
SHOW_FOOTER_VERSION = false;
};
};
in
{
sops.secrets."forgejo/client_secret" = { };
sops.templates."forgejo/env" = {
content = ''
CLIENT_SECRET=${config.sops.placeholder."forgejo/client_secret"}
'';
owner = config.systemd.services.forgejo.serviceConfig.User;
};
services.forgejo = {
enable = true;
inherit settings;
# Use cutting edge instead of lts
package = pkgs.forgejo;
# repositoryRoot = "/mnt/storage/forgejo/repositories";
lfs = {
enable = true;
# contentDir = "/mnt/storage/forgejo/lfs";
};
};
systemd.services.forgejo = {
serviceConfig = {
EnvironmentFile = config.sops.templates."forgejo/env".path;
preStart =
let
providerName = "kanidm";
args = lib.concatStringsSep " " [
"--name ${providerName}"
"--provider openidConnect"
"--key forgejo"
"--secret $CLIENT_SECRET"
"--icon-url ${idpUrl}/pkg/img/favicon.png"
"--group-claim-name forgejo_role --admin-group Admin"
];
exe = getExe config.services.forgejo.package;
in
''
provider_id=$(${exe} admin auth list | ${pkgs.gnugrep}/bin/grep -w '${providerName}' | cut -f1)
if [[ -z "$provider_id" ]]; then
${exe} admin auth add-oauth ${args}
else
${exe} admin auth update-oauth --id "$provider_id" ${args}
fi
'';
};
};
users.users.git = {
isSystemUser = true;
useDefaultShell = true;
group = "git";
extraGroups = [ "forgejo" ];
};
users.groups.git = { };
services.caddy = {
virtualHosts."https://${forgejoDomain}".extraConfig = with settings; ''
${
if server.PROTOCOL == "http+unix" then
"reverse_proxy unix/${server.HTTP_ADDR}"
else
"reverse_proxy http://${server.HTTP_ADDR}:${toString server.HTTP_PORT}"
}
'';
};
users.users.caddy.extraGroups = lib.optional (settings.server.PROTOCOL == "http+unix") "forgejo";
}

View file

@ -1,7 +1,4 @@
{ config, ... }: { config, ... }:
let
inherit (config.my-lib.settings) idpUrl;
in
{ {
sops.secrets."gotosocial/oidc_client_secret" = { sops.secrets."gotosocial/oidc_client_secret" = {
owner = "gotosocial"; owner = "gotosocial";
@ -26,17 +23,17 @@ in
instance-expose-public-timeline = true; instance-expose-public-timeline = true;
oidc-enabled = true; oidc-enabled = true;
oidc-idp-name = "Kanidm"; oidc-idp-name = "Kanidm";
oidc-issuer = "${idpUrl}/oauth2/openid/gotosocial"; oidc-issuer = "https://auth.xinyang.life/oauth2/openid/gotosocial";
oidc-client-id = "gotosocial"; oidc-client-id = "gotosocial";
oidc-link-existing = true; oidc-link-existing = true;
}; };
setupPostgresqlDB = true;
environmentFile = config.sops.templates."gotosocial.env".path; environmentFile = config.sops.templates."gotosocial.env".path;
}; };
services.caddy = { services.caddy = {
virtualHosts."https://gts.xiny.li".extraConfig = '' virtualHosts."https://gts.xiny.li".extraConfig = ''
reverse_proxy http://${config.services.gotosocial.settings.bind-address}:${toString config.services.gotosocial.settings.port} { encode zstd gzip
reverse_proxy * http://${config.services.gotosocial.settings.bind-address}:${toString config.services.gotosocial.settings.port} {
flush_interval -1 flush_interval -1
} }
''; '';

View file

@ -1,45 +0,0 @@
{ config, pkgs, ... }:
let
inherit (config.my-lib.settings) hedgedocDomain idpUrl;
in
{
sops.secrets."hedgedoc/client_secret" = { };
sops.templates."hedgedoc/env" = {
content = ''
CMD_OAUTH2_CLIENT_SECRET=${config.sops.placeholder."hedgedoc/client_secret"}
'';
owner = config.systemd.services.hedgedoc.serviceConfig.User;
};
services.hedgedoc = {
enable = true;
environmentFile = config.sops.templates."hedgedoc/env".path;
settings = {
domain = hedgedocDomain;
protocolUseSSL = true; # use SSL for resources
path = "/run/hedgedoc/hedgedoc.sock";
email = false;
allowEmailRegister = false;
oauth2 = {
baseURL = "${idpUrl}/oauth2/openid/hedgedoc";
authorizationURL = "${idpUrl}/ui/oauth2";
tokenURL = "${idpUrl}/oauth2/token";
userProfileURL = "${idpUrl}/oauth2/openid/hedgedoc/userinfo";
userProfileEmailAttr = "email";
userProfileUsernameAttr = "name";
userProfileDisplayNameAttr = "preferred_name";
scope = "openid email profile";
clientID = "hedgedoc";
};
enableStatsApi = true;
allowAnonymous = false;
defaultPermission = "private";
};
};
services.caddy = {
enable = true;
virtualHosts."https://${hedgedocDomain}".extraConfig = ''
reverse_proxy unix/${config.services.hedgedoc.settings.path}
'';
};
users.users.caddy.extraGroups = [ "hedgedoc" ];
}

View file

@ -1,35 +0,0 @@
{ config, pkgs, ... }:
let
inherit (config.my-lib.settings) idpUrl minifluxUrl;
in
{
sops = {
secrets."miniflux/oauth2_secret" = { };
};
services.miniflux = {
enable = true;
config = {
LOG_LEVEL = "debug";
LISTEN_ADDR = "127.0.0.1:58173";
BASE_URL = "https://rss.xiny.li/";
OAUTH2_PROVIDER = "oidc";
OAUTH2_CLIENT_ID = "miniflux";
OAUTH2_CLIENT_SECRET_FILE = "%d/oauth2_secret";
OAUTH2_REDIRECT_URL = "${minifluxUrl}/oauth2/oidc/callback";
OAUTH2_OIDC_DISCOVERY_ENDPOINT = "${idpUrl}/oauth2/openid/miniflux";
OAUTH2_USER_CREATION = 1;
CREATE_ADMIN = 0;
};
createDatabaseLocally = true;
};
systemd.services.miniflux.serviceConfig.LoadCredential = [
"oauth2_secret:${config.sops.secrets."miniflux/oauth2_secret".path}"
];
services.caddy.virtualHosts.${minifluxUrl}.extraConfig = ''
reverse_proxy ${config.services.miniflux.config.LISTEN_ADDR}
'';
}

View file

@ -1,55 +0,0 @@
{
config,
lib,
pkgs,
...
}:
let
sqliteBackup = fromPath: toPath: file: ''
mkdir -p ${toPath}
${lib.getExe pkgs.sqlite} ${fromPath} ".backup '${toPath}/${file}'"
'';
in
{
sops.secrets = {
"restic/repo_url" = {
sopsFile = ../secrets.yaml;
};
"restic/repo_password" = {
sopsFile = ../secrets.yaml;
};
};
custom.restic = {
enable = true;
paths = [
"/backup/db"
"/backup/var/lib"
];
backupPrepareCommand = [
''
mkdir -p /backup/var
${pkgs.btrfs-progs}/bin/btrfs subvolume snapshot -r /var/lib /backup/var/lib
''
];
backupCleanupCommand = [
''
${pkgs.btrfs-progs}/bin/btrfs subvolume delete /backup/var/lib
''
];
btrfsRoots = [ ];
};
services.postgresqlBackup = {
enable = true;
compression = "zstd";
compressionLevel = 9;
location = "/backup/db/postgresql";
};
services.restic.backups.${config.networking.hostName} = {
extraBackupArgs = [
"--limit-upload=1024"
];
};
}

View file

@ -1,120 +0,0 @@
{
config,
lib,
pkgs,
...
}:
let
inherit (config.my-lib.settings) idpUrl synapseDelegateUrl synapseUrl;
port-synapse = 6823;
in
{
sops.secrets."synapse/oidc_client_secret" = {
owner = "matrix-synapse";
};
nixpkgs.config.permittedInsecurePackages = [
"olm-3.2.16"
];
services.postgresql = {
# Not using ensure here because LC_COLLATE and LC_CTYPE must be provided
# at db creation
initialScript = pkgs.writeText "synapse-init.sql" ''
CREATE ROLE "matrix-synapse" WITH LOGIN PASSWORD 'synapse';
CREATE DATABASE "matrix-synapse" WITH OWNER "matrix-synapse"
TEMPLATE template0
LC_COLLATE = "C"
LC_CTYPE = "C";
'';
};
services.matrix-synapse = {
enable = true;
withJemalloc = true;
settings = {
server_name = "xiny.li";
public_baseurl = synapseDelegateUrl;
database = {
name = "psycopg2";
args = {
user = "matrix-synapse";
};
};
listeners = [
{
bind_addresses = [
"127.0.0.1"
];
port = port-synapse;
resources = [
{
compress = true;
names = [
"client"
"federation"
];
}
];
tls = false;
type = "http";
x_forwarded = true;
}
];
experimental_features = {
# Room summary api
msc3266_enabled = true;
# Removing account data
msc3391_enabled = true;
# Thread notifications
msc3773_enabled = true;
# Remotely toggle push notifications for another client
msc3881_enabled = true;
# Remotely silence local notifications
msc3890_enabled = true;
# Remove legacy mentions
msc4210_enabled = true;
};
oidc_providers = [
{
idp_id = "Kanidm";
idp_name = lib.removePrefix "https://" idpUrl;
issuer = "${idpUrl}/oauth2/openid/synapse";
authorization_endpoint = "${idpUrl}/ui/oauth2";
token_endpoint = "${idpUrl}/oauth2/token";
userinfo_endpoint = "${idpUrl}/oauth2/openid/synapse/userinfo";
client_id = "synapse";
client_secret_path = config.sops.secrets."synapse/oidc_client_secret".path;
scopes = [
"openid"
"profile"
];
allow_existing_users = true;
backchannel_logout_enabled = true;
user_mapping_provider.config = {
confirm_localpart = true;
localpart_template = "{{ user.preferred_username }}";
display_name_template = "{{ user.name }}";
};
}
];
};
};
services.caddy = {
virtualHosts.${synapseUrl}.extraConfig = ''
header /.well-known/matrix/* Content-Type application/json
header /.well-known/matrix/* Access-Control-Allow-Origin *
respond /.well-known/matrix/server `{"m.server":"synapse.xiny.li:443"}`
respond /.well-known/matrix/client `{"m.homeserver":{"base_url":"${synapseDelegateUrl}"}}`
'';
virtualHosts.${synapseDelegateUrl}.extraConfig = ''
reverse_proxy /_matrix/* 127.0.0.1:${toString port-synapse}
reverse_proxy /_synapse/client/* 127.0.0.1:${toString port-synapse}
'';
};
networking.firewall.allowedTCPPorts = [
443
];
}

View file

@ -1,25 +0,0 @@
{ config, pkgs, ... }:
let
inherit (config.my-lib.settings) vaultwardenUrl;
in
{
services.vaultwarden = {
enable = true;
dbBackend = "sqlite";
config = {
DOMAIN = "${vaultwardenUrl}";
SIGNUPS_ALLOWED = false;
ROCKET_ADDRESS = "127.0.0.1";
ROCKET_PORT = 8222;
ROCKET_LOG = "normal";
};
};
services.caddy = {
virtualHosts.${vaultwardenUrl}.extraConfig = with config.services.vaultwarden.config; ''
reverse_proxy ${ROCKET_ADDRESS}:${toString ROCKET_PORT}
'';
};
}

View file

@ -16,7 +16,7 @@ in
]; ];
commonSettings = { commonSettings = {
# auth.enable = true; auth.enable = true;
nix = { nix = {
signing.enable = true; signing.enable = true;
}; };
@ -51,6 +51,7 @@ in
}; };
# services.gnome.gnome-keyring.enable = lib.mkForce false; # services.gnome.gnome-keyring.enable = lib.mkForce false;
security.pam.services.login.enableGnomeKeyring = lib.mkForce false; security.pam.services.login.enableGnomeKeyring = lib.mkForce false;
services.ssh-tpm-agent.enable = true;
programs.ssh.agentPKCS11Whitelist = "${config.security.tpm2.pkcs11.package}/lib/libtpm_pkcs11.so"; programs.ssh.agentPKCS11Whitelist = "${config.security.tpm2.pkcs11.package}/lib/libtpm_pkcs11.so";
@ -65,7 +66,18 @@ in
}; };
}; };
programs.vim.enable = true; programs.oidc-agent.enable = true;
programs.oidc-agent.providers = [
{
issuer = "https://home.xinyang.life:9201";
pubclient = {
client_id = "xdXOt13JKxym1B1QcEncf2XDkLAexMBFwiT9j6EfhhHFJhs2KM9jbjTmf8JBXE69";
client_secret = "UBntmLjC2yYCeHwsyj73Uwo9TAaecAetRwMw0xYcvNL9yRdLSUi0hUAHfvCHFeFh";
scope = "openid offline_access profile email";
};
}
];
programs.vim.defaultEditor = true; programs.vim.defaultEditor = true;
# Keep this even if enabled in home manager # Keep this even if enabled in home manager
@ -295,22 +307,23 @@ in
bitwarden bitwarden
# Browser # Browser
chromium (chromium.override {
commandLineArgs = [
"--ozone-platform-hint=auto"
"--enable-wayland-ime"
];
})
brave
# Writting # Writting
zotero zotero
# onlyoffice-bin # onlyoffice-bin
wemeet config.nur.repos.linyinfeng.wemeet
virt-manager virt-manager
wineWowPackages.waylandFull
winetricks
]; ];
services.esphome.enable = true;
users.groups.dialout.members = [ "xin" ];
system.stateVersion = "22.05"; system.stateVersion = "22.05";
system.switch.enable = false; system.switch.enable = false;
@ -339,16 +352,16 @@ in
]; ];
}; };
# custom.forgejo-actions-runner = { custom.forgejo-actions-runner = {
# enable = false; enable = false;
# tokenFile = config.sops.secrets."gitea/envfile".path; tokenFile = config.sops.secrets."gitea/envfile".path;
# settings = { settings = {
# runner.capacity = 2; runner.capacity = 2;
# runner.fetch_timeout = "120s"; runner.fetch_timeout = "120s";
# runner.fetch_interval = "30s"; runner.fetch_interval = "30s";
# }; };
# }; };
#
custom.prometheus = { custom.prometheus = {
exporters.node.enable = true; exporters.node.enable = true;
}; };
@ -366,12 +379,15 @@ in
# Fonts # Fonts
fonts = { fonts = {
packages = with pkgs; [ packages = with pkgs; [
nerd-fonts.ubuntu-sans (nerdfonts.override {
nerd-fonts.ubuntu fonts = [
nerd-fonts.fira-code "FiraCode"
nerd-fonts.fira-mono "FiraMono"
nerd-fonts.jetbrains-mono "JetBrainsMono"
nerd-fonts.roboto-mono "RobotoMono"
"Ubuntu"
];
})
noto-fonts noto-fonts
noto-fonts-emoji noto-fonts-emoji
liberation_ttf liberation_ttf

View file

@ -1,9 +1,4 @@
{ { config, pkgs, lib, ... }:
config,
pkgs,
lib,
...
}:
{ {
imports = [ ]; imports = [ ];
@ -29,9 +24,16 @@
services.dae.enable = true; services.dae.enable = true;
services.dae.configFile = "/var/lib/dae/config.dae"; services.dae.configFile = "/var/lib/dae/config.dae";
systemd.services.dae.after = lib.mkIf (config.networking.networkmanager.enable) [ systemd.services.dae.after = lib.mkIf (config.networking.networkmanager.enable) [ "NetworkManager-wait-online.service" ];
"NetworkManager-wait-online.service"
]; custom.sing-box = {
enable = false;
configFile = {
urlFile = config.sops.secrets.sing_box_url.path;
hash = "6ca5bc8a16f8c413227690aceeee2c12c02cab09473c216b849af1e854b98588";
};
overrideSettings.experimental.clash_api.external_ui = "${config.nur.repos.linyinfeng.yacd}";
};
# Open ports in the firewall. # Open ports in the firewall.
networking.firewall.enable = true; networking.firewall.enable = true;

View file

@ -3,7 +3,6 @@
config = { config = {
sops = { sops = {
age.sshKeyPaths = [ "/etc/ssh/ssh_host_ed25519_key" ]; age.sshKeyPaths = [ "/etc/ssh/ssh_host_ed25519_key" ];
defaultSopsFile = ./secrets/secrets.yaml;
secrets = { secrets = {
wg_private_key = { wg_private_key = {
owner = "root"; owner = "root";
@ -13,6 +12,14 @@
owner = "root"; owner = "root";
sopsFile = ./secrets + "/${config.networking.hostName}.yaml"; sopsFile = ./secrets + "/${config.networking.hostName}.yaml";
}; };
"sing-box/password" = {
owner = "root";
sopsFile = ./secrets/secrets.yaml;
};
"sing-box/uuid" = {
owner = "root";
sopsFile = ./secrets/secrets.yaml;
};
}; };
}; };
swapDevices = [ swapDevices = [
@ -25,8 +32,6 @@
custom.prometheus.exporters = { custom.prometheus.exporters = {
enable = true; enable = true;
node.enable = true; node.enable = true;
blackbox.enable = true;
v2ray.enable = true;
}; };
custom.monitoring = { custom.monitoring = {
@ -39,11 +44,6 @@
auth.enable = true; auth.enable = true;
proxyServer = { proxyServer = {
enable = true; enable = true;
users = [
"wyj"
"yhb"
"xin"
];
}; };
}; };
}; };

View file

@ -1,14 +1,6 @@
sing-box: sing-box:
users: password: ENC[AES256_GCM,data:qCc1v8nAL0oYisRinMDXGrBQA+r6XNoa,iv:eTxtad4kEdE28XqnrZEek8BtXNY1rNgLvGLxlMzRtl4=,tag:s/shWAkYE4DSnScpTY8ulQ==,type:str]
wyj: uuid: ENC[AES256_GCM,data:lEpz15sLOVrGDzQwTJyS+tFJY0bMeO265bxocWAjB6qrvxYx,iv:lhk5jl/udUH3AZEuk5ffuvin/qhRUaOZ/3nk1Jaw+DI=,tag:4mKFIVKT+D47njfDsxe9iA==,type:str]
password: ENC[AES256_GCM,data:yp+T3eci9RiuZzdmRSq5nTjHaz8e/Rri,iv:hIPc+7YHUnaIdU9O8GGx3r7l3oBA6prQb+KBQV0G+8k=,tag:2GNiBP4PQy+KGHgLupKGSg==,type:str]
uuid: ENC[AES256_GCM,data:Qrgil6G7pjQAQzCCOlstDi27EqqmSuBMhs+RTl9++wrPrIgJ,iv:u+3Z17uX4I6li2qd9UP3y+WaKn7aKfbb3J6H1Pyc1QY=,tag:hSa4AB383/B58XMmZ8LIfQ==,type:str]
yhb:
password: ENC[AES256_GCM,data:TwRct68TePpcZcnpWIQpFaF23WGMre8=,iv:YU4mQNm0rt2u4ItJwQ8nZPEmJi0+lmEIPG2Kxh/nI58=,tag:ukZem38O/b42dEKM3CYa+w==,type:str]
uuid: ENC[AES256_GCM,data:6hVhEqWPLVrn8rCS4x/eapd+iL7JRaXtOGCj9uuPlkGjBTMK,iv:VZ27KWCY6/K5GoNwRNmaRWzqfV7+8iFjtias1vKeGfA=,tag:8mhmZPooxHaGNYdznuFhMQ==,type:str]
xin:
password: ENC[AES256_GCM,data:SRiPFO+Uwy/PT41SIg7eI68wk4AX6so=,iv:aXwP5wa1IrlnvFo/ZL+DYFFHDdWw2Z83de3ApHUTsXo=,tag:sxXoy1FnDxZBQCDeNxphzQ==,type:str]
uuid: ENC[AES256_GCM,data:7xK53SO4x0tOIEIYl6kmmAvnpdsR/tYQoG1t/ytsnO4QqWY3,iv:i694Fnu7g1OA3IGzSaoSGA5/eMPo+I/1TZbYuaQrgNA=,tag:4cUlioJn/IvsvZclgboOSA==,type:str]
sops: sops:
kms: [] kms: []
gcp_kms: [] gcp_kms: []
@ -51,8 +43,8 @@ sops:
K1F1SzI2NFNIKzlreVBXSjAxaUxQd28KFaf1uu7OlqIe0TirJFgS3iPjhXPyfNDE K1F1SzI2NFNIKzlreVBXSjAxaUxQd28KFaf1uu7OlqIe0TirJFgS3iPjhXPyfNDE
m2XUjzdXp+chJCzVOFvpYStqz+e08ADEc+jp3YsTLcxyqvXhQdyL/Q== m2XUjzdXp+chJCzVOFvpYStqz+e08ADEc+jp3YsTLcxyqvXhQdyL/Q==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
lastmodified: "2024-12-06T04:35:52Z" lastmodified: "2024-12-02T05:26:17Z"
mac: ENC[AES256_GCM,data:DAg4UTwNv+rs6hye2z5UUtA1a4yZbFaAWjLoKAXf87tKgBCZzK8C1q6gLyTQOqp07ptYQd5Q951kfE1a/35SFJsubREzJmu6haxznRgq7pO5HDGqgtjYEHsngsWZh3bUSX/aG2dLISdD81VY68nLzTO0r4h/SL6DNG36RzJgL8E=,iv:V0WhENNt/Szi5VWVD2t5AsWP1tOZUGjFjMNYPDq59XI=,tag:ThRstdzVNtSs6E7qlvKPOw==,type:str] mac: ENC[AES256_GCM,data:K94zFWPWGUisLCqDjSLs17QxHXPH4tPU/98Sb4lCnt7IRAIn14x/T+BnInY/DK+DOVLLtzSfuN0kgzzGjSzwJx5Vq1G3MkhngRQQRT9dvODTCMAw6lPt98Ofw1CEEsFQnpYo9zIUlCGKg2YPKFLqE7OjkPxqw7VYvgzr5dDw58s=,iv:3xcJfNX5v/e9HgZt3UrHs2/C5ivaBV1rXKIBs9hKKFg=,tag:RQPQQ1cmZiOpQjUwqnzZQA==,type:str]
pgp: [] pgp: []
unencrypted_suffix: _unencrypted unencrypted_suffix: _unencrypted
version: 3.9.1 version: 3.9.1

View file

@ -15,9 +15,24 @@
defaultSopsFile = ./secrets.yaml; defaultSopsFile = ./secrets.yaml;
age.sshKeyPaths = [ "/etc/ssh/ssh_host_ed25519_key" ]; age.sshKeyPaths = [ "/etc/ssh/ssh_host_ed25519_key" ];
secrets = { secrets = {
storage_box_mount = {
owner = "root";
};
gts_env = { gts_env = {
owner = "gotosocial"; owner = "gotosocial";
}; };
hedgedoc_env = {
owner = "hedgedoc";
};
grafana_oauth_secret = {
owner = "grafana";
};
"miniflux/oauth2_secret" = {
owner = "root";
};
"forgejo/env" = {
owner = "forgejo";
};
}; };
}; };

View file

@ -1,14 +1,4 @@
{ pkgs, config, ... }: { config, lib, ... }:
let
inherit (config.my-lib.settings)
gotosocialUrl
minifluxUrl
hedgedocDomain
forgejoDomain
grafanaUrl
synapseDelegateUrl
;
in
{ {
services.kanidm.provision = { services.kanidm.provision = {
enable = true; enable = true;
@ -55,9 +45,6 @@ in
miniflux-users = { miniflux-users = {
members = [ "xin" ]; members = [ "xin" ];
}; };
synapse-users = {
members = [ "xin" ];
};
idm_people_self_mail_write = { idm_people_self_mail_write = {
members = [ ]; members = [ ];
}; };
@ -86,8 +73,8 @@ in
systems.oauth2 = { systems.oauth2 = {
forgejo = { forgejo = {
displayName = "ForgeJo"; displayName = "ForgeJo";
originUrl = "https://${forgejoDomain}/user/oauth2/kanidm/callback"; originUrl = "https://git.xinyang.life/user/oauth2/kanidm/callback";
originLanding = "https://${forgejoDomain}/user/oauth2/kanidm"; originLanding = "https://git.xinyang.life/user/oauth2/kanidm";
allowInsecureClientDisablePkce = true; allowInsecureClientDisablePkce = true;
scopeMaps = { scopeMaps = {
forgejo-access = [ forgejo-access = [
@ -123,8 +110,8 @@ in
}; };
gotosocial = { gotosocial = {
displayName = "GoToSocial"; displayName = "GoToSocial";
originUrl = "${gotosocialUrl}/auth/callback"; originUrl = "https://gts.xiny.li/auth/callback";
originLanding = "${gotosocialUrl}/auth/callback"; originLanding = "https://gts.xiny.li/auth/callback";
allowInsecureClientDisablePkce = true; allowInsecureClientDisablePkce = true;
scopeMaps = { scopeMaps = {
gts-users = [ gts-users = [
@ -160,8 +147,8 @@ in
hedgedoc = { hedgedoc = {
displayName = "HedgeDoc"; displayName = "HedgeDoc";
originUrl = "https://${hedgedocDomain}/auth/oauth2/callback"; originUrl = "https://docs.xinyang.life/auth/oauth2/callback";
originLanding = "https://${hedgedocDomain}/auth/oauth2"; originLanding = "https://docs.xinyang.life/auth/oauth2";
allowInsecureClientDisablePkce = true; allowInsecureClientDisablePkce = true;
scopeMaps = { scopeMaps = {
hedgedoc-users = [ hedgedoc-users = [
@ -190,8 +177,9 @@ in
}; };
miniflux = { miniflux = {
displayName = "Miniflux"; displayName = "Miniflux";
originUrl = "${minifluxUrl}/oauth2/oidc/callback"; originUrl = "https://rss.xinyang.life/oauth2/oidc/callback";
originLanding = "${minifluxUrl}/oauth2/oidc/redirect";
originLanding = "https://rss.xinyang.life/oauth2/oidc/redirect";
scopeMaps = { scopeMaps = {
miniflux-users = [ miniflux-users = [
"openid" "openid"
@ -202,8 +190,8 @@ in
}; };
grafana = { grafana = {
displayName = "Grafana"; displayName = "Grafana";
originUrl = "${grafanaUrl}/login/generic_oauth"; originUrl = "https://grafana.xinyang.life/login/generic_oauth";
originLanding = "${grafanaUrl}/"; originLanding = "https://grafana.xinyang.life/";
scopeMaps = { scopeMaps = {
grafana-users = [ grafana-users = [
"openid" "openid"
@ -223,17 +211,6 @@ in
}; };
}; };
}; };
synapse = {
displayName = "Synapse";
originUrl = "${synapseDelegateUrl}/_synapse/client/oidc/callback";
originLanding = "${synapseDelegateUrl}/";
scopeMaps = {
synapse-users = [
"openid"
"profile"
];
};
};
}; };
}; };
} }

View file

@ -23,6 +23,26 @@ in
8448 8448
]; ];
custom.vaultwarden = {
enable = true;
domain = "vaultwarden.xinyang.life";
};
custom.hedgedoc = {
enable = true;
caddy = true;
domain = "docs.xinyang.life";
mediaPath = "/mnt/storage/hedgedoc";
oidc = {
enable = true;
baseURL = "https://auth.xinyang.life/oauth2/openid/hedgedoc";
authorizationURL = "https://auth.xinyang.life/ui/oauth2";
tokenURL = "https://auth.xinyang.life/oauth2/token";
userProfileURL = "https://auth.xinyang.life/oauth2/openid/hedgedoc/userinfo";
};
environmentFile = config.sops.secrets.hedgedoc_env.path;
};
custom.monitoring = { custom.monitoring = {
promtail.enable = true; promtail.enable = true;
}; };
@ -46,6 +66,18 @@ in
}; };
}; };
services.ntfy-sh = {
enable = true;
group = "caddy";
settings = {
listen-unix = "/var/run/ntfy-sh/ntfy.sock";
listen-unix-mode = 432; # octal 0660
base-url = "https://ntfy.xinyang.life";
};
};
systemd.services.ntfy-sh.serviceConfig.RuntimeDirectory = "ntfy-sh";
services.kanidm = { services.kanidm = {
package = pkgs.kanidm.withSecretProvisioning; package = pkgs.kanidm.withSecretProvisioning;
enableServer = true; enableServer = true;
@ -60,6 +92,40 @@ in
}; };
}; };
custom.miniflux = {
enable = true;
environment = {
LOG_LEVEL = "debug";
LISTEN_ADDR = "127.0.0.1:58173";
BASE_URL = "https://rss.xinyang.life/";
OAUTH2_PROVIDER = "oidc";
OAUTH2_CLIENT_ID = "miniflux";
OAUTH2_REDIRECT_URL = "https://rss.xinyang.life/oauth2/oidc/callback";
OAUTH2_OIDC_DISCOVERY_ENDPOINT = "https://auth.xinyang.life/oauth2/openid/miniflux";
OAUTH2_USER_CREATION = 1;
};
oauth2SecretFile = config.sops.secrets."miniflux/oauth2_secret".path;
};
services.matrix-conduit = {
enable = true;
package = pkgs.matrix-conduit;
settings.global = {
server_name = "xinyang.life";
port = 6167;
# database_path = "/var/lib/matrix-conduit/";
max_concurrent_requests = 100;
log = "info";
database_backend = "rocksdb";
allow_registration = false;
well_known = {
client = "https://msg.xinyang.life";
server = "msg.xinyang.life:443";
};
};
};
users.users.conduit = { users.users.conduit = {
isSystemUser = true; isSystemUser = true;
group = "conduit"; group = "conduit";
@ -84,8 +150,128 @@ in
environmentFile = config.sops.secrets.gts_env.path; environmentFile = config.sops.secrets.gts_env.path;
}; };
services.forgejo = {
enable = true;
# Use cutting edge instead of lts
package = pkgs.forgejo;
repositoryRoot = "/mnt/storage/forgejo/repositories";
lfs = {
enable = true;
contentDir = "/mnt/storage/forgejo/lfs";
};
settings = {
service.DISABLE_REGISTRATION = true;
server = {
ROOT_URL = "https://git.xinyang.life/";
START_SSH_SERVER = false;
SSH_USER = config.services.forgejo.user;
SSH_DOMAIN = "ssh.xinyang.life";
SSH_PORT = 22;
LFS_MAX_FILE_SIZE = 10737418240;
LANDING_PAGE = "/explore/repos";
};
repository = {
ENABLE_PUSH_CREATE_USER = true;
};
service = {
ENABLE_BASIC_AUTHENTICATION = false;
};
oauth2 = {
ENABLED = false; # Disable forgejo as oauth2 provider
};
oauth2_client = {
ACCOUNT_LINKING = "auto";
USERNAME = "email";
ENABLE_AUTO_REGISTRATION = true;
UPDATE_AVATAR = false;
OPENID_CONNECT_SCOPES = "openid profile email groups";
};
other = {
SHOW_FOOTER_VERSION = false;
};
};
};
systemd.services.forgejo = {
serviceConfig = {
EnvironmentFile = config.sops.secrets."forgejo/env".path;
ExecStartPost = ''
${lib.getExe config.services.forgejo.package} admin auth update-oauth \
--id 1 \
--name kanidm \
--provider openidConnect \
--key forgejo \
--secret $CLIENT_SECRET \
--icon-url https://auth.xinyang.life/pkg/img/favicon.png \
--group-claim-name forgejo_role --admin-group Admin
'';
};
};
services.grafana = {
enable = true;
settings = {
server = {
http_addr = "127.0.0.1";
http_port = 3003;
root_url = "https://grafana.xinyang.life";
domain = "grafana.xinyang.life";
};
"auth.generic_oauth" = {
enabled = true;
name = "Kanidm";
client_id = "grafana";
scopes = "openid,profile,email,groups";
auth_url = "https://auth.xinyang.life/ui/oauth2";
token_url = "https://auth.xinyang.life/oauth2/token";
api_url = "https://auth.xinyang.life/oauth2/openid/grafana/userinfo";
use_pkce = true;
use_refresh_token = true;
allow_sign_up = true;
login_attribute_path = "preferred_username";
groups_attribute_path = "groups";
role_attribute_path = "contains(grafana_role[*], 'GrafanaAdmin') && 'GrafanaAdmin' || contains(grafana_role[*], 'Admin') && 'Admin' || contains(grafana_role[*], 'Editor') && 'Editor' || 'Viewer'";
allow_assign_grafana_admin = true;
auto_login = true;
};
"auth" = {
disable_login_form = true;
};
};
};
systemd.services.grafana.serviceConfig.EnvironmentFile =
config.sops.secrets.grafana_oauth_secret.path;
users.users.git = {
isSystemUser = true;
useDefaultShell = true;
group = "git";
extraGroups = [ "forgejo" ];
};
users.groups.git = { };
users.users = {
${config.services.caddy.user}.extraGroups = [ config.services.ntfy-sh.group ];
};
services.caddy = { services.caddy = {
enable = true; enable = true;
virtualHosts."xinyang.life:443".extraConfig = ''
tls internal
encode zstd gzip
reverse_proxy /.well-known/matrix/* localhost:6167
reverse_proxy * http://localhost:8080 {
flush_interval -1
}
'';
virtualHosts."https://msg.xinyang.life:443".extraConfig = ''
reverse_proxy /_matrix/* localhost:6167
'';
virtualHosts."https://git.xinyang.life:443".extraConfig = ''
reverse_proxy http://${config.services.gitea.settings.server.DOMAIN}:${toString config.services.gitea.settings.server.HTTP_PORT}
'';
virtualHosts."http://auth.xinyang.life:80".extraConfig = '' virtualHosts."http://auth.xinyang.life:80".extraConfig = ''
reverse_proxy ${config.security.acme.certs."auth.xinyang.life".listenHTTP} reverse_proxy ${config.security.acme.certs."auth.xinyang.life".listenHTTP}
''; '';
@ -98,5 +284,27 @@ in
} }
} }
''; '';
virtualHosts."https://rss.xinyang.life".extraConfig = ''
reverse_proxy ${config.custom.miniflux.environment.LISTEN_ADDR}
'';
virtualHosts."https://ntfy.xinyang.life".extraConfig = ''
reverse_proxy unix/${config.services.ntfy-sh.settings.listen-unix}
@httpget {
protocol http
method GET
path_regexp ^/([-_a-z0-9]{0,64}$|docs/|static/)
}
redir @httpget https://{host}{uri}
'';
virtualHosts."https://grafana.xinyang.life".extraConfig =
let
grafanaSettings = config.services.grafana.settings.server;
in
''
reverse_proxy http://${grafanaSettings.http_addr}:${toString grafanaSettings.http_port}
'';
}; };
} }

View file

@ -34,6 +34,13 @@ in
]; ];
}; };
services.postgresqlBackup = {
enable = true;
compression = "zstd";
compressionLevel = 9;
location = "/backup/postgresql";
};
services.restic.backups.${config.networking.hostName} = { services.restic.backups.${config.networking.hostName} = {
extraBackupArgs = [ extraBackupArgs = [
"--limit-upload=1024" "--limit-upload=1024"

View file

@ -10,83 +10,74 @@ sops:
- recipient: age1uw059wcwfvd9xuj0hpqzqpeg7qemecspjrsatg37wc7rs2pumfdsgken0c - recipient: age1uw059wcwfvd9xuj0hpqzqpeg7qemecspjrsatg37wc7rs2pumfdsgken0c
enc: | enc: |
-----BEGIN AGE ENCRYPTED FILE----- -----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA5SjAzOEozUzh1bzVvaHgr YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAwMHB1bFQ3dWJIU3NiOVVP
T2xsVUszTHVSdWIyM3B5TFhtUEFMeVZlYzNrCk5IOWFNbTErbTVkQnNlVllMZWlV Yi9LZE1PTVdMY1BqS1JHV3VPLzZIY0hGK0NZClNlclVXKzBvNTBrTlhiR0VsaVoz
Q2lHZXRIdzBiRFRSZnNUVWd2NXVXVGcKLS0tIERhcjh3VVlqSGxHUHpnc1JzVksv RlVLNVBEVDgzSXB5ZGxDd3hqNDh2V2MKLS0tIEhBZHFUY3c2VXJBVEVKamZ6TzBa
VXpQVVVCUC9xR3crWm9rTk13LzVhK1EKwiuvwx3ZhcDE+9w7/dR4PrZSSoJMvklT MlFsNnVEV0xCdlJoRnBhUHF2MmswUEUKNYD9zssGBy9SaKeOMvTz71B6KMPW87cM
m7I32dMRk0o9zcl5KYU5L9Hwb+z+EBE34raoGKBF5K4aQcbZQUX3Cw== tFJzgnQceEQF658lVa5cCzG1gzraCgBtQU15XzC7e8zWI9CHquRRlQ==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
- recipient: age1ytwfqfeez3dqtazyjltn7mznccwx3ua8djhned7n8mxqhw4p6e5s97skfa - recipient: age1ytwfqfeez3dqtazyjltn7mznccwx3ua8djhned7n8mxqhw4p6e5s97skfa
enc: | enc: |
-----BEGIN AGE ENCRYPTED FILE----- -----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA5R1ZIRlN2b3M2OUQ0T2cw YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBTTnZLTlZQRzc1enVEa1BN
eE5DTm9KY1NUY1p5eDhLNG4xMDVkVjRyWDNRClp3MTRWeGJMYTczcC9YQTNZdkxx SHdoSi9oOXk4UTV0SlRZS2tLS2FFL3VjNzNNClVWTTNKekF6T0RTUzdEeWhLbHoz
ejJ3QnhjcUcyUldUNEVqVUh6Z2grd00KLS0tIDVvbDZWbmZPZVhDNHM1K1kzaE95 WFZKaHJEaVBWa04zRWRiVnJZRjU0YVEKLS0tIFJVL0FEemowS3V6MmsxbWJMU2I1
aHJqSU16dlJiRGl0VWNMVXVYMmhPb2MKMboq9ShGIJMFVENgLPlQdwdtTOjVb0CC U2NnUnVKdFlRSGVzUFQ4ZFcwL0lWTlkKz1t3yqjgIdMWS/Nsy2nq3oCjOhGDP+UT
4ttM3xWnYkf8416a0OYFrda5l1kfJJzQakbk/tbGcTu1yTcd+6lOtA== L+LAuFExJPV0qlsOG/kCGB/WtCJfnBvcp6vPDBLqjK8NllIX/iPI5g==
-----END AGE ENCRYPTED FILE-----
- recipient: age17r3fxfmt6hgwe984w4lds9u0cnkf5ttq8hnqt800ayfmx7t8t5gqjddyml
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBVby8wYS9pa0szTlVUS3FI
VWhjaCtyUzNLbkw2VXRlWkVMZlRkeXJMZGlRCnBTWklnZ0Uzd2lTMGt1M2wxZ0px
NFl2RW5hSUZVdHI0aVFRMHJtMFQ3ODAKLS0tIFlYOHVRYVFGbkcvUWRmQitQQnI5
bG5vemMvcWdpOEtxNGRpS0doQmtuUFkK8Hxl//kOtbEw3jf96ZZ4G1Yb94f4Jeb4
TfPs7O/ESJY8ovNsoXRQEt99vOR5D1wBzyZBY9E3f2ZzY/uBmup0cw==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
- recipient: age1jle2auermhswqtehww9gqada8car5aczrx43ztzqf9wtcld0sfmqzaecta - recipient: age1jle2auermhswqtehww9gqada8car5aczrx43ztzqf9wtcld0sfmqzaecta
enc: | enc: |
-----BEGIN AGE ENCRYPTED FILE----- -----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBPSmRYMkNIdERJZVBxV1p1 YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBETWpkcjhINktqeGxjdWxz
emlqOTBpN3l2WXkzNjRRcFI5NUZDZnQ1WXdnCkRVbm8xais5aGVCTmtSTGxaTXlT UTVVNC9kalorcVJOdHpJSkZJNXlGUHZ2VUdrCjRCclBTZnJEZ3JGOVpqS1Y0b0dt
L2ZWQ0p5WFZNRWl5SWVkRUYwc2R3b1UKLS0tIEZEck4yMmJUQWVvNHRJQnpCQTBo eldFMS91WUc2Y1FnWWZoN0grc01pT0UKLS0tIC96TjlEaVBGRkZhZ0hac2lmbEdI
cDJsaG83MTdXWVd2NUpLczhjWTBBZVUK5BxBIYVqkqVLw9LTbnJ8SQWN2i4USdI8 eHMzTFhsQ0FqY05uUEZSbExCcmdscEkKdxITlc0V5ayq+9fmj77SnEMFxKJhOOta
8m/hZFXTJ4GI0f795DEmbcZq9xET14aQqta0wSASqwP/5Ld1mo0a0w== RfJhOQUv8g3nCN+SsuaOy0TitUCiDWh5XoB0DufEQPcS/kzGZN1Inw==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
- recipient: age12ng08vjx5jde5ncqutwkd5vm4ygfwy33mzhzwe0lkxzglulgpqusc89r96 - recipient: age12ng08vjx5jde5ncqutwkd5vm4ygfwy33mzhzwe0lkxzglulgpqusc89r96
enc: | enc: |
-----BEGIN AGE ENCRYPTED FILE----- -----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAwSkhjRTdBWklZUEpUanM0 YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBydlQ4S1duQU53Wk1nd21K
Wjl4b2c3K0g0ZUxxMlRrUFhhZzhNRXhPVnpvCmpNWVBNTXNYczV3aWhCd05FOGJ0 d2RqM1F0VDFJVXB2aGRTZ2hxczI2V1lndVdrCjArVlE2N0RGZ0htUEZYdVlQMlU5
YlNobFhWdStGbDRZV2NlUWV6ZFRVNEkKLS0tIGd1RUR4K21GOEQ0aWtqRi9RREpE SWIwWHVCaWxaQTJMNzg3WC8xRS9IYzgKLS0tIDRvSS8ybVlrSy9zYjQ2NXBaMlZk
RXBXcXFYUDVXVzN4Q25zSklFU21wbFkKQuTHkgFC5HRPO7/PuVhJzbbHOTPaFXvN Ulg4cUFBejRoS3VEWkRaZEUxMExUeWMKNeq6TN1gaBNU9vAitGttcU+8HmFQipdm
+Y31AK3OAVdUETMEuJ2mk50Bi5BiiUeOnnv1bZ6O+iX0o20ysUseTg== LPwo4/toyf27emb4KGs0AV0Dm4Sxj9S3Xvrv1B+qvhfT638/RIUm2w==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
- recipient: age1v5h946jfke6ae8pcgz52mhj26cacqcpl9dmmrrkf37x55rnq2v3szqctvv - recipient: age1v5h946jfke6ae8pcgz52mhj26cacqcpl9dmmrrkf37x55rnq2v3szqctvv
enc: | enc: |
-----BEGIN AGE ENCRYPTED FILE----- -----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBnc3NOZFRYT1VnaVZSaTRi YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB4YXpyOXE3MFovWEQvMVRr
WnluSEk4d1U5TWx2REZRZ3VCRVp2ZzlKY0NvCjNlUnIwdWVqSnlQOWp1dlJ5THlW TGVST3U0N2dCVDJGT1A3eUtlRis3bFEvTHlFClZHQ2xRWklMMCtER01QNEVHaVYr
c2xTNHhnaE94a2ZTeXJjQTVxeGRLTmsKLS0tIFV4c2NZK1ZnL2xtUlVvSksxNi9o MC94V3R4MVdNdUU3eXQ2RGFFVGo4VFEKLS0tIDQ4b2ZuMy9URUswWUZqNHlxandU
L3dodkJXVjZrekVldTVsRFRxSFlrTmMKiokjgIRIsI8D2aFP/Qem4iGzC4yr5lm2 OFducVVzdGZGY0tnbFFBZDdjVzVkaUEKN8qAbbrd4pAHRGIN8O64fl7bQ6hx6Isr
ZwggC/UfD56ysTEqrVaDnR7f5fSqZLWdstPJn7I/vr5CwKRMbMPYSA== Qx0xKeuhJCVXgtE8xc7xmnEhqrcONlflJ/XUnYV9jOkB71zSBJxruA==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
- recipient: age1p2dlc8gfgyrvtta6mty2pezjycn244gmvh456qd3wvkfwesp253qnwyta9 - recipient: age1p2dlc8gfgyrvtta6mty2pezjycn244gmvh456qd3wvkfwesp253qnwyta9
enc: | enc: |
-----BEGIN AGE ENCRYPTED FILE----- -----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBpN0llOTBJU1pNNVFxVWxt YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAzczdPMDdWU1ZtckJRQm5j
aFdKdStKL1ZlZ0p6WFRQbHpGNnpmdlJXdG1FCkx5eDhZWWJvQ2xSWEJqWnZ6NmNt UWJub0Yzd3NzOEh4YWdId01nYWI1YVY3dng0ClpEYXBJV2cvWEdjdXcwUFI3Y0NG
Y0MzNDg5QzVSbEZteW1LNlFyRFg5Q0EKLS0tIDBrT0dEZlBoTExYcGRNZjZ5Znpz MDgvTmNZOXRQQndyVmRHamNRbzVaVU0KLS0tIGFKVTI4TkE2UjhDUSsxQTlNQ0Vk
cnE4YWRTMmRsTENhOTl5R2dYSzQwazAKvnTvZz842Mg5AVlIoYHI2BG+0/hO5zIv QmFMNnlqbnhScC90T012K1QxRnRUOHcKAV7NxUn0CMcjKwK8zrocoLO1P9jc22uG
jRVJri98fgGterXADTPmeoY3p+fFQggTPhs/5s5GSQxd5aiX8vvvrA== eG+vdJ6xzA99UX51aPxQOeEJgdFPEd3y1QJszQmRzThvid7y4lv0Cw==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
- recipient: age18u4mqrhqkrpcytxfxfex6aeap04u38emhy6u4wrp5k62sz2vae4qm5jj7s - recipient: age18u4mqrhqkrpcytxfxfex6aeap04u38emhy6u4wrp5k62sz2vae4qm5jj7s
enc: | enc: |
-----BEGIN AGE ENCRYPTED FILE----- -----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBPQWljdGg4VTlDdGhoblpk YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBsVmpzenRvWE5EK2wzRFkx
LytxK2FnQVI1dzB2bnFaWUtoUVNGS3lpU3prCnRwUTNnZVVXTnZ6eCtScTk5YzI3 SERZV0s1Rkt0ZnZ1U3JQSFNhdGVvaWhWcTA4CjVxK0Z0MHI0ZnMrUS9YYWhTTG1z
TGM2MmNhaHQ3NXAzMk0rcnJoTlp5STQKLS0tIEp2U3YvUUhXTkt3VFczY3J1LzMv L2lVS1Q2UkVQd2x5b1E1eWpQVGp2ZHMKLS0tIHNLOGhTYjkzWkFEM05wYkRZeXFQ
ZzM0VHpqamRIZVROS2lQdXFhQTNBekEKEySldC+VvZvPY398ZVkB5s73bT3QbuLh SXNTSGZZSFE2bFhybXdIc1FUb1ZBd0kKkYzflPRk6GrE6t9oVGOzc8xcyZDxiIw8
IqTv+wbkbjlvZJUavVyycY5SwMXkSX3ge9W/64mt/RDs88gSXFS+Sw== 9SVXIgV0WVpY4lnFKYKH2i4+1sIm6tKOpizlQxTg5VgmmrTtfazWAA==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
- recipient: age1fw2sqaa5s9c8ml6ncsexkj8ar4288387ju92ytjys4awf9aw6smqqz94dh - recipient: age1fw2sqaa5s9c8ml6ncsexkj8ar4288387ju92ytjys4awf9aw6smqqz94dh
enc: | enc: |
-----BEGIN AGE ENCRYPTED FILE----- -----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA4bGppem15NlVod2hCRkM5 YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB0NHpkOTFHaXRhVGNua0dV
MzY1aUZOdEVzRzdEYTRNakdMQWJlRkk0eEZzClRLSnRrQUoreU5MVG40KzRKSGcw alRieWJ6WG5ZNzlvcTR2aTVUeWFBVGVVUUNZCnY2VUZUOWVlNGY1ZldyVGE2bkpi
bUU4ZnpLU0VtOWxXVllrSW5lN0NWb0kKLS0tIE1iemRlVVpieEhxRnlIb2dFUHZr VXVtQ3IyK0kyV1cyMU5nN1lYaW1oOUkKLS0tIFRVRGFCNWlGendSVEhHY0w0QTl6
am04NVRtU2N6SThYZWdXVE5RZ1B2aE0KVcHvB5k2Gcu/St0P8WPFzlCtuZthZTKo emJEQkQ3QlU0TFVWaW1uQytaUndmQlEKKahqJpX8vI+PASOzzod/sFvXSkQFnJ9O
hwVc0lC6Xxt25hriaUFinwnyvcjxrLCx0Nq7f9Zn16nJcza5kev1nQ== YmnmiFxm5WZDPLHwkgVx8FgCq9RfAad4HybhsMjYPKXJ/fNa/WVZRA==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
lastmodified: "2024-11-30T06:31:42Z" 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] mac: ENC[AES256_GCM,data:xh8x9IrQ01ZzdcCTIfBrifIGduMYVmSSP52BkTyr/bx7AgQAz2WeA7LFrccxIayCGHrQKfMQDLUKJ/EBamG/6p8AX6QqZBTfqFD688ZhmRfxgpj7fYR9jPYnhb/9XHI9R2jTaJWwrorXvu3pa+Gy/hWB3Kb+WZc3fslmIuKuLH0=,iv:GDrHSFZxPbpACdusVDPHXEjeEusYfk53N/KGHtdvrYo=,tag:ap38sCSTZVDQ0ZazXM3vlg==,type:str]

View file

@ -1,10 +1,7 @@
{ config, ... }:
{ {
imports = [ imports = [
./hardware-configurations.nix ./hardware-configurations.nix
./monitoring.nix ./monitoring.nix
./restic.nix
./ntfy.nix
]; ];
config = { config = {
@ -31,10 +28,6 @@
443 443
]; ];
services.tailscale.enable = true;
services.caddy.enable = true;
commonSettings = { commonSettings = {
auth.enable = true; auth.enable = true;
}; };

View file

@ -1,20 +1,5 @@
{ { config, my-lib, ... }:
config, with my-lib;
lib,
pkgs,
...
}:
with config.my-lib;
let
inherit (config.my-lib.settings)
minifluxUrl
gotosocialUrl
hedgedocDomain
grafanaUrl
ntfyUrl
;
removeHttps = s: lib.removePrefix "https://" s;
in
{ {
config = { config = {
sops = { sops = {
@ -29,23 +14,11 @@ in
custom.monitoring = { custom.monitoring = {
grafana.enable = true; grafana.enable = true;
loki = { loki.enable = true;
enable = true;
rules = {
sshd_closed = {
expr = ''count_over_time({unit="sshd.service"} |~ "Connection closed by authenticating user" [15m]) > 25'';
description = "More then 25 login attemps in last 15 min without success";
};
unusual_log_volume = {
expr = ''sum by (unit) (rate({unit=~".+"}[5m])) > 80'';
description = "Unit {{ $labels.unit }} is logging at an unusually high rate";
};
};
};
promtail.enable = true; promtail.enable = true;
}; };
services.caddy.virtualHosts.${grafanaUrl}.extraConfig = services.caddy.virtualHosts."https://grafana.xinyang.life".extraConfig =
with config.services.grafana.settings.server; '' with config.services.grafana.settings.server; ''
reverse_proxy http://${http_addr}:${toString http_port} reverse_proxy http://${http_addr}:${toString http_port}
''; '';
@ -57,28 +30,19 @@ in
blackbox.enable = true; blackbox.enable = true;
node.enable = true; node.enable = true;
}; };
ruleModules = ruleModules = (mkCaddyRules [ { host = "thorite"; } ]) ++ (mkNodeRules [ { host = "thorite"; } ]);
(mkCaddyRules [ { host = "thorite"; } ])
++ (mkNodeRules [ { host = "thorite"; } ])
++ (mkBlackboxRules [ { host = "thorite"; } ]);
}; };
services.prometheus.scrapeConfigs = services.prometheus.scrapeConfigs =
let let
probeList = [ probeList = [
"la-00.video.namely.icu:8080" "la-00.video.namely.icu:8080"
"fra-00.video.namely.icu:8080" "fre-00.video.namely.icu:8080"
"hk-00.video.namely.icu:8080" "hk-00.video.namely.icu:8080"
"49.13.13.122:443"
"45.142.178.32:22"
"home.xinyang.life:8000" "home.xinyang.life:8000"
]; ];
chinaTargets = [
"bj-cu-v4.ip.zstaticcdn.com:80"
"bj-cm-v4.ip.zstaticcdn.com:80"
"bj-ct-v4.ip.zstaticcdn.com:80"
"sh-cu-v4.ip.zstaticcdn.com:80"
"sh-cm-v4.ip.zstaticcdn.com:80"
"sh-ct-v4.ip.zstaticcdn.com:80"
];
passwordFile = config.sops.secrets."prometheus/metrics_password".path; passwordFile = config.sops.secrets."prometheus/metrics_password".path;
in in
(mkScrapes [ (mkScrapes [
@ -88,50 +52,32 @@ in
address = "weilite.coho-tet.ts.net"; address = "weilite.coho-tet.ts.net";
port = 8082; port = 8082;
} }
{
name = "restic_rest_server";
address = "backup.xinyang.life";
port = 8443;
}
{ {
inherit passwordFile; inherit passwordFile;
name = "gotosocial"; name = "gotosocial";
address = removeHttps gotosocialUrl; address = "xinyang.life";
} }
{ {
inherit passwordFile; inherit passwordFile;
name = "miniflux"; name = "miniflux";
address = removeHttps minifluxUrl; address = "rss.xinyang.life";
}
{
name = "hedgedoc";
address = hedgedocDomain;
} }
{ {
name = "ntfy"; name = "ntfy";
address = removeHttps ntfyUrl; address = "ntfy.xinyang.life";
} }
{ {
name = "grafana-eu"; name = "grafana-eu";
address = removeHttps grafanaUrl; address = "grafana.xinyang.life";
}
{
name = "loki";
scheme = "http";
address = "thorite.coho-tet.ts.net";
port = 3100;
} }
]) ])
++ (mkCaddyScrapes [ ++ (mkCaddyScrapes [
{ address = "thorite.coho-tet.ts.net"; } { address = "thorite.coho-tet.ts.net"; }
{ address = "biotite.coho-tet.ts.net"; }
{ address = "weilite.coho-tet.ts.net"; }
]) ])
++ (mkNodeScrapes [ ++ (mkNodeScrapes [
{ address = "thorite.coho-tet.ts.net"; } { address = "thorite.coho-tet.ts.net"; }
{ address = "massicot.coho-tet.ts.net"; } { address = "massicot.coho-tet.ts.net"; }
{ address = "weilite.coho-tet.ts.net"; } { address = "weilite.coho-tet.ts.net"; }
{ address = "biotite.coho-tet.ts.net"; }
{ address = "hk-00.coho-tet.ts.net"; } { address = "hk-00.coho-tet.ts.net"; }
{ address = "la-00.coho-tet.ts.net"; } { address = "la-00.coho-tet.ts.net"; }
{ address = "fra-00.coho-tet.ts.net"; } { address = "fra-00.coho-tet.ts.net"; }
@ -139,37 +85,20 @@ in
++ (mkBlackboxScrapes [ ++ (mkBlackboxScrapes [
{ {
hostAddress = "thorite.coho-tet.ts.net"; hostAddress = "thorite.coho-tet.ts.net";
targetAddresses = probeList ++ [ "49.13.13.122:443" ]; targetAddresses = probeList;
} }
{ {
hostAddress = "massicot.coho-tet.ts.net"; hostAddress = "massicot.coho-tet.ts.net";
targetAddresses = probeList ++ [ "45.142.178.32:443" ]; targetAddresses = probeList;
} }
{ {
hostAddress = "weilite.coho-tet.ts.net"; hostAddress = "weilite.coho-tet.ts.net";
targetAddresses = [ targetAddresses = [
"la-00.video.namely.icu:8080" "la-00.video.namely.icu:8080"
"fra-00.video.namely.icu:8080" "fre-00.video.namely.icu:8080"
"hk-00.video.namely.icu:8080" "hk-00.video.namely.icu:8080"
]; ];
} }
{
hostAddress = "la-00.coho-tet.ts.net";
targetAddresses = chinaTargets;
}
{
hostAddress = "hk-00.coho-tet.ts.net";
targetAddresses = chinaTargets;
}
{
hostAddress = "fra-00.coho-tet.ts.net";
targetAddresses = chinaTargets;
}
])
++ (mkV2rayScrapes [
{ address = "la-00.coho-tet.ts.net"; }
{ address = "hk-00.coho-tet.ts.net"; }
{ address = "fra-00.coho-tet.ts.net"; }
]); ]);
}; };

View file

@ -1,29 +0,0 @@
{ config, ... }:
let
inherit (config.my-lib.settings) ntfyUrl;
in
{
services.ntfy-sh = {
enable = true;
group = "caddy";
settings = {
listen-unix = "/var/run/ntfy-sh/ntfy.sock";
listen-unix-mode = 432; # octal 0660
base-url = ntfyUrl;
};
};
systemd.services.ntfy-sh.serviceConfig.RuntimeDirectory = "ntfy-sh";
services.caddy.virtualHosts.${ntfyUrl}.extraConfig = ''
reverse_proxy unix/${config.services.ntfy-sh.settings.listen-unix}
@httpget {
protocol http
method GET
path_regexp ^/([-_a-z0-9]{0,64}$|docs/|static/)
}
redir @httpget https://{host}{uri}
'';
}

View file

@ -1,51 +0,0 @@
{
config,
lib,
pkgs,
...
}:
let
sqliteBackup = fromPath: toPath: file: ''
mkdir -p ${toPath}
${lib.getExe pkgs.sqlite} ${fromPath} ".backup '${toPath}/${file}'"
'';
in
{
sops.secrets = {
"restic/repo_url" = { };
"restic/repo_password" = { };
};
custom.restic = {
enable = true;
paths = [
"/backup/db"
"/backup/var/lib"
];
backupPrepareCommand = [
''
mkdir -p /backup/var
${pkgs.btrfs-progs}/bin/btrfs subvolume snapshot -r /var/lib /backup/var/lib
''
];
backupCleanupCommand = [
''
${pkgs.btrfs-progs}/bin/btrfs subvolume delete /backup/var/lib
''
];
btrfsRoots = [ ];
};
services.postgresqlBackup = lib.mkIf config.services.postgresql.enable {
enable = true;
compression = "zstd";
compressionLevel = 9;
location = "/backup/db/postgresql";
};
services.restic.backups.${config.networking.hostName} = {
extraBackupArgs = [
"--limit-upload=1024"
];
};
}

View file

@ -1,8 +1,5 @@
grafana: grafana:
oauth_secret: ENC[AES256_GCM,data:angZR3sl8vGcbAXyKFBvCSm+YhF5OooCcxRiSxR2zBoXMz5wv5/uMJFynwOTRVI6,iv:hVpOlM89lNbK6AsGf4Is/tLv3xPfg/XdtA8vuEK52L8=,tag:zCER+IdRnTcG2WHQ/AhxZA==,type:str] oauth_secret: ENC[AES256_GCM,data:angZR3sl8vGcbAXyKFBvCSm+YhF5OooCcxRiSxR2zBoXMz5wv5/uMJFynwOTRVI6,iv:hVpOlM89lNbK6AsGf4Is/tLv3xPfg/XdtA8vuEK52L8=,tag:zCER+IdRnTcG2WHQ/AhxZA==,type:str]
restic:
repo_url: ENC[AES256_GCM,data:tc7wYRN20sHxATTZYEBpf6tNafzq9vcvqdUHYJDmJIArxprNd6WiyqPXowzbksZcEi5JwSwwJH/MYminnPGtrR8erWZg8OB3,iv:/z7mF58tMAviscFWHd4NJw7UZlq7Bzz+LU88J+kE9qg=,tag:i97FP4SmmNXOuxylkHhYCA==,type:str]
repo_password: ENC[AES256_GCM,data:o3MbXJRwR5UE9uCELN2ejQ==,iv:cYPNjJAV7H2BNCuFLDJoJvPk+CFvagXJwW9LRAGc0G0=,tag:qF6Di2W+8kESCRAphC/c0g==,type:str]
sops: sops:
kms: [] kms: []
gcp_kms: [] gcp_kms: []
@ -27,8 +24,8 @@ sops:
M2pqMUJoMGlBZnpBaVBUTFFRZUMzb2sKrlWy26Cv55/8XQEl9hee8P29uj582sIx M2pqMUJoMGlBZnpBaVBUTFFRZUMzb2sKrlWy26Cv55/8XQEl9hee8P29uj582sIx
mUjaYE0U2qOP9bklXUQyyzQjfkBLWTLc1PTX9BjqOOsqXwkRQIYppA== mUjaYE0U2qOP9bklXUQyyzQjfkBLWTLc1PTX9BjqOOsqXwkRQIYppA==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
lastmodified: "2024-12-03T08:18:54Z" lastmodified: "2024-11-28T17:02:03Z"
mac: ENC[AES256_GCM,data:jqSt34avoMfL9g3LmvjrPTzW4xGLgX70CXI8qk4isaLbZ8FkxjVU8QY1ot9GZnFEQWUkReSuGD4gFxi8TjetlNdx0zDPcv6zGJUSfcYpyKDCqGdyL/2x8xnYtI2pWINBZxR/2XxT3cus39FJdXVcz3l7KX4DvYvm8t/D9+r4ef0=,iv:KY/OTbDOOD/bBDTIuIk1ck7wDxLogo2EKeSOfOe4j5o=,tag:B17iF5O32KDZfctubpXCng==,type:str] mac: ENC[AES256_GCM,data:14FOUXuKP+8+sad1UlhBW37fWzmutpyn6d4q2qKtBiOyT5ivHunFHJfHrtX83X2fLDmUfiD42bXf+rYfdtKzVUmQ6vutCUQk+Hal8NElhjcq5Ns5kT4VZRKG7/ya9+eNEEkajtq/7OFEM5KOQKTKjyOBqBq/AdYQ+ni9r45c1sM=,iv:WrdWSfrZrGalZO4WGk3JpgACY7W0odt3vP+pRkMXHfA=,tag:jeRBfR2QYjLBylOLHxU3hQ==,type:str]
pgp: [] pgp: []
unencrypted_suffix: _unencrypted unencrypted_suffix: _unencrypted
version: 3.9.1 version: 3.9.1

View file

@ -52,8 +52,9 @@
owner = "caddy"; owner = "caddy";
mode = "400"; mode = "400";
}; };
"restic/localpass" = { "immich/oauth_client_secret" = {
owner = "restic"; owner = "immich";
mode = "400";
}; };
}; };
}; };
@ -68,10 +69,6 @@
}; };
}; };
custom.monitoring = {
promtail.enable = true;
};
systemd.mounts = [ systemd.mounts = [
{ {
what = "immich"; what = "immich";
@ -108,6 +105,43 @@
2222 2222
]; ];
services.immich = {
enable = true;
mediaLocation = "/mnt/XinPhotos/immich";
host = "127.0.0.1";
port = 3001;
openFirewall = true;
machine-learning.enable = true;
environment = {
IMMICH_MACHINE_LEARNING_ENABLED = "true";
};
database.enable = true;
};
custom.immich.jsonSettings = {
oauth = {
enabled = true;
issuerUrl = "https://auth.xinyang.life/oauth2/openid/immich/";
clientId = "immich";
clientSecret = {
_secret = config.sops.secrets."immich/oauth_client_secret".path;
};
scope = "openid email profile";
signingAlgorithm = "ES256";
storageLabelClaim = "email";
buttonText = "Login with Kanidm";
autoLaunch = true;
mobileOverrideEnabled = true;
mobileRedirectUri = "https://immich.xinyang.life:8000/api/oauth/mobile-redirect/";
};
passwordLogin = {
enabled = false;
};
newVersionCheck = {
enabled = false;
};
};
services.dae = { services.dae = {
enable = true; enable = true;
configFile = "/var/lib/dae/config.dae"; configFile = "/var/lib/dae/config.dae";

View file

@ -2,8 +2,6 @@ cloudflare_dns_token: ENC[AES256_GCM,data:m4euSkxxJmiMk9UPyeni/hwpl1W9A4MM0ssg71
dnspod_dns_token: ENC[AES256_GCM,data:uZfr3g103amywxh3NMU+AkwuYb61svzyavvQ4rxJijIMIbfPvERrVNcyivoOrFWYXHpPWkhZFdU=,iv:mArVAcebW9i+u26GmQmfmJTsFkR4ZRMIisTqjpMYan8=,tag:Zsmv1Wzfi3+PHigjReToHQ==,type:str] dnspod_dns_token: ENC[AES256_GCM,data:uZfr3g103amywxh3NMU+AkwuYb61svzyavvQ4rxJijIMIbfPvERrVNcyivoOrFWYXHpPWkhZFdU=,iv:mArVAcebW9i+u26GmQmfmJTsFkR4ZRMIisTqjpMYan8=,tag:Zsmv1Wzfi3+PHigjReToHQ==,type:str]
immich: immich:
oauth_client_secret: ENC[AES256_GCM,data:EFs2hPjGMj0idwY3oQVIDTOIWkdwoAoAVjDQE9Z2eAKzUDH3grmYpYE+33V8d/Ux,iv:A9cjwFr/ZqltG62/N8MQ1LhdDbSIVVAqIPVB492zYJw=,tag:VTTtE697BZTVsI32UF53/w==,type:str] oauth_client_secret: ENC[AES256_GCM,data:EFs2hPjGMj0idwY3oQVIDTOIWkdwoAoAVjDQE9Z2eAKzUDH3grmYpYE+33V8d/Ux,iv:A9cjwFr/ZqltG62/N8MQ1LhdDbSIVVAqIPVB492zYJw=,tag:VTTtE697BZTVsI32UF53/w==,type:str]
restic:
localpass: ENC[AES256_GCM,data:GIQAmkpDmGu4+sSG5/b5yQ==,iv:dcu6F8NnVjeQzEG2vM3fOV5owI0PWc86ts20UP3vN18=,tag:vsG8x062FG1pH5YNcAajeg==,type:str]
sops: sops:
kms: [] kms: []
gcp_kms: [] gcp_kms: []
@ -28,8 +26,8 @@ sops:
V0thRjU4WGpQRGFpcnoxSjZTZHhTTkUKzNMHh9p7GUY3hL5XZ9S4x20CwaItsXFV V0thRjU4WGpQRGFpcnoxSjZTZHhTTkUKzNMHh9p7GUY3hL5XZ9S4x20CwaItsXFV
RKujsFVVBd8Kuq/jyOCBTRCscuHI4LW/wYeZYHFEZFSTK2liAqspgw== RKujsFVVBd8Kuq/jyOCBTRCscuHI4LW/wYeZYHFEZFSTK2liAqspgw==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
lastmodified: "2024-12-03T05:59:51Z" lastmodified: "2024-09-13T12:02:54Z"
mac: ENC[AES256_GCM,data:0dLbfkm7fJvH5Mmct0/qHulg2AtDCeeeOgWMXfeGRUaX3GlLDiLga0zW4uNPDuahVecdh6ofvYfBOxFaGUdBCHk9vq5GzrwrzBNhqObWQ3AqVuq5rjqSxEKoFM4Eb5qoqaOefFzT/9qC94NDETTsHhjiEeIgd4fgSr2dazNiFPE=,iv:Ggw0FHzkrhKh5Uzo3seHGwwHsWW/tTAgAl0iIq9PVk4=,tag:rJvUI5/wsLJ01XyKmkRghw==,type:str] mac: ENC[AES256_GCM,data:c5p+B2mPCDyS/Q4QH4MkzCww6jFDhP8RfHqrKLf4e/8XuNEGfNmPKaeliZG26j1YQWRvFHiGQX3AMnQ3Q+fSRUQCVi5KV+KW7fADNIB3TiTT5hAFuynhiWWQSmIrWP0GGek3GDGi7OJ1PrFbxWP9bwaf+zBegiaUcWoTorJg7No=,iv:6MohNgPpq80eTUlf3RvPKsxdx69V0jl+/hrMxAPpPQE=,tag:BtWp1FChP2hdclbGl5W+vQ==,type:str]
pgp: [] pgp: []
unencrypted_suffix: _unencrypted unencrypted_suffix: _unencrypted
version: 3.9.1 version: 3.9.0

View file

@ -3,6 +3,5 @@
./ocis.nix ./ocis.nix
./restic.nix ./restic.nix
./media-download.nix ./media-download.nix
./immich.nix
]; ];
} }

View file

@ -1,63 +0,0 @@
{
config,
...
}:
let
user = config.systemd.services.immich-server.serviceConfig.User;
jsonSettings = {
oauth = {
enabled = true;
issuerUrl = "https://auth.xinyang.life/oauth2/openid/immich/";
clientId = "immich";
clientSecret = config.sops.placeholder."immich/oauth_client_secret";
scope = "openid email profile";
signingAlgorithm = "ES256";
storageLabelClaim = "email";
buttonText = "Login with Kanidm";
autoLaunch = true;
mobileOverrideEnabled = true;
mobileRedirectUri = "https://immich.xinyang.life:8000/api/oauth/mobile-redirect/";
};
passwordLogin = {
enabled = false;
};
image = {
extractEmbedded = true;
};
newVersionCheck = {
enabled = false;
};
};
in
{
config = {
sops.secrets."immich/oauth_client_secret" = { };
sops.templates."immich/config.json" = {
owner = user; # Read when running
content = builtins.toJSON jsonSettings;
};
systemd.services.immich-server = {
serviceConfig = {
Environment = "IMMICH_CONFIG_FILE=${config.sops.templates."immich/config.json".path}";
};
};
services.immich = {
enable = true;
mediaLocation = "/mnt/XinPhotos/immich";
host = "127.0.0.1";
port = 3001;
openFirewall = true;
machine-learning.enable = true;
environment = {
IMMICH_MACHINE_LEARNING_ENABLED = "true";
};
database.enable = true;
};
# https://github.com/NixOS/nixpkgs/pull/324127/files#r1723763510
services.immich.redis.host = "/run/redis-immich/redis.sock";
};
}

View file

@ -13,13 +13,6 @@
openFirewall = false; openFirewall = false;
}; };
nixpkgs.config.permittedInsecurePackages = [
"aspnetcore-runtime-6.0.36"
"aspnetcore-runtime-wrapped-6.0.36"
"dotnet-sdk-6.0.428"
"dotnet-sdk-wrapped-6.0.428"
];
services.sonarr = { services.sonarr = {
enable = true; enable = true;
}; };

View file

@ -35,8 +35,6 @@ in
services.restic.backups = builtins.listToAttrs [ services.restic.backups = builtins.listToAttrs [
(mkPrune "xin" "calcite") (mkPrune "xin" "calcite")
(mkPrune "xin" "massicot") (mkPrune "xin" "massicot")
(mkPrune "xin" "biotite")
(mkPrune "xin" "thorite")
]; ];
networking.firewall.allowedTCPPorts = [ 8443 ]; networking.firewall.allowedTCPPorts = [ 8443 ];

View file

@ -91,10 +91,6 @@ in
${pkgs.comma}/bin/comma $argv ${pkgs.comma}/bin/comma $argv
end end
set -gx LS_COLORS (${lib.getExe pkgs.vivid} generate catppuccin-mocha) set -gx LS_COLORS (${lib.getExe pkgs.vivid} generate catppuccin-mocha)
alias ctlsp="systemctl stop"
alias ctlst="systemctl start"
alias ctlrt="systemctl restart"
alias ctls="systemctl status"
'' ''
else else
""; "";

View file

@ -25,9 +25,8 @@ in
}; };
}; };
}; };
config = mkIf cfg.enable { config = {
home.packages = [ pkgs.git-absorb ]; programs.git = mkIf cfg.enable {
programs.git = {
enable = true; enable = true;
delta.enable = true; delta.enable = true;
userName = "Xinyang Li"; userName = "Xinyang Li";
@ -43,10 +42,6 @@ in
signByDefault = true; signByDefault = true;
key = cfg.signing.keyFile; key = cfg.signing.keyFile;
}; };
extraConfig.absorb = {
oneFixupPerCommit = true;
maxStack = 20;
};
extraConfig.user = mkIf cfg.signing.enable { signingkey = cfg.signing.keyFile; }; extraConfig.user = mkIf cfg.signing.enable { signingkey = cfg.signing.keyFile; };
extraConfig.gpg = mkIf cfg.signing.enable { format = "ssh"; }; extraConfig.gpg = mkIf cfg.signing.enable { format = "ssh"; };
}; };

View file

@ -9,6 +9,8 @@ let
inherit (lib) inherit (lib)
mkIf mkIf
mkEnableOption mkEnableOption
mkOption
types
; ;
cfg = config.commonSettings.auth; cfg = config.commonSettings.auth;
@ -19,43 +21,25 @@ in
}; };
config = mkIf cfg.enable { config = mkIf cfg.enable {
services.kanidm = { custom.kanidm-client = {
enableClient = true; enable = true;
clientSettings = { uri = "https://auth.xinyang.life";
uri = "https://auth.xinyang.life"; asSSHAuth = {
}; enable = true;
enablePam = true; allowedGroups = [ "linux_users" ];
unixSettings = {
pam_allowed_login_groups = [ "linux_users" ];
default_shell = "/bin/sh";
}; };
sudoers = [ "xin@auth.xinyang.life" ];
}; };
services.openssh = { services.openssh = {
enable = true;
authorizedKeysCommand = "/etc/ssh/auth %u";
authorizedKeysCommandUser = "kanidm-ssh-runner";
settings = { settings = {
PasswordAuthentication = false; PasswordAuthentication = false;
KbdInteractiveAuthentication = false; KbdInteractiveAuthentication = false;
PermitRootLogin = lib.mkForce "no"; PermitRootLogin = "no";
GSSAPIAuthentication = "no";
KerberosAuthentication = "no";
}; };
}; };
environment.etc."ssh/auth" = {
mode = "0555";
text = ''
#!${pkgs.stdenv.shell}
${pkgs.kanidm}/bin/kanidm_ssh_authorizedkeys $1
'';
};
users.groups.wheel.members = [ "xin@auth.xinyang.life" ];
users.groups.kanidm-ssh-runner = { };
users.users.kanidm-ssh-runner = {
isSystemUser = true;
group = "kanidm-ssh-runner";
};
services.fail2ban.enable = true; services.fail2ban.enable = true;
security.sudo = { security.sudo = {

View file

@ -1,6 +1,5 @@
{ {
config, config,
pkgs,
lib, lib,
... ...
}: }:
@ -22,117 +21,106 @@ let
config.security.acme.certs.${config.deployment.targetHost}.directory + "/cert.pem"; config.security.acme.certs.${config.deployment.targetHost}.directory + "/cert.pem";
}; };
mkSingConfig = users: { mkSingConfig =
log = { { uuid, password, ... }:
level = "warn"; {
}; log = {
inbounds = level = "warn";
[ };
{ inbounds =
tag = "sg0";
type = "trojan";
listen = "::";
listen_port = cfg.trojan.port;
tcp_multi_path = true;
tcp_fast_open = true;
users = map (user: {
name = user.name;
password = {
_secret = user.passwordFile;
};
}) users;
tls = singTls;
}
]
++ lib.forEach (lib.range 6311 6314) (port: {
tag = "sg" + toString (port - 6310);
type = "tuic";
listen = "::";
listen_port = port;
congestion_control = "bbr";
users = map (user: {
name = user.name;
uuid = {
_secret = user.uuidFile;
};
password = {
_secret = user.passwordFile;
};
}) users;
tls = singTls;
});
outbounds =
# warp outbound goes first to make it default outbound
(lib.optionals (cfg.warp.onTuic or cfg.warp.onTrojan) [
{
type = "wireguard";
tag = "wg-out";
private_key = {
_secret = config.sops.secrets.wg_private_key.path;
};
local_address = [
"172.16.0.2/32"
{ _secret = config.sops.secrets.wg_ipv6_local_addr.path; }
];
peers = [
{
public_key = "bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=";
allowed_ips = [
"0.0.0.0/0"
"::/0"
];
server = "162.159.192.1";
server_port = 500;
}
];
}
])
++ [
{
type = "direct";
tag = "direct";
}
];
route = {
rules =
[ [
{ {
inbound = "sg4"; tag = "sg0";
outbound = "direct"; type = "trojan";
listen = "::";
listen_port = cfg.trojan.port;
tcp_multi_path = true;
tcp_fast_open = true;
users = [
{
name = "proxy";
password = {
_secret = password;
};
}
];
tls = singTls;
} }
] ]
++ (lib.optionals (!cfg.warp.onTuic) ( ++ lib.forEach (lib.range 6311 6314) (port: {
lib.forEach (lib.range 1 3) (i: { tag = "sg" + toString (port - 6310);
inbound = "sg${toString i}"; type = "tuic";
outbound = "direct"; listen = "::";
}) listen_port = port;
)) congestion_control = "bbr";
++ (lib.optionals (!cfg.warp.onTrojan) [ users = [
{
name = "proxy";
uuid = {
_secret = uuid;
};
password = {
_secret = password;
};
}
];
tls = singTls;
});
outbounds =
# warp outbound goes first to make it default outbound
(lib.optionals (cfg.warp.onTuic or cfg.warp.onTrojan) [
{ {
inbound = "sg0"; type = "wireguard";
outbound = "direct"; tag = "wg-out";
private_key = {
_secret = config.sops.secrets.wg_private_key.path;
};
local_address = [
"172.16.0.2/32"
{ _secret = config.sops.secrets.wg_ipv6_local_addr.path; }
];
peers = [
{
public_key = "bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=";
allowed_ips = [
"0.0.0.0/0"
"::/0"
];
server = "162.159.192.1";
server_port = 500;
}
];
} }
]); ])
}; ++ [
experimental = {
v2ray_api = { {
listen = "127.0.0.1:15175"; type = "direct";
stats = { tag = "direct";
users = map (u: u.name) users; }
enabled = true; ];
inbounds = map (p: "sg" + toString p) (lib.range 0 4); route = {
}; rules =
[
{
inbound = "sg4";
outbound = "direct";
}
]
++ (lib.optionals (!cfg.warp.onTuic) (
lib.forEach (lib.range 1 3) (i: {
inbound = "sg${toString i}";
outbound = "direct";
})
))
++ (lib.optionals (!cfg.warp.onTrojan) [
{
inbound = "sg0";
outbound = "direct";
}
]);
}; };
}; };
};
sing-box = pkgs.sing-box.overrideAttrs (
finalAttrs: previousAttrs: {
tags = previousAttrs.tags ++ [
"with_v2ray_api"
];
}
);
in in
{ {
options.commonSettings.proxyServer = { options.commonSettings.proxyServer = {
@ -149,62 +137,40 @@ in
onTrojan = mkEnableOption "forward to warp in trojan"; onTrojan = mkEnableOption "forward to warp in trojan";
onTuic = mkEnableOption "forward to warp in first two port of tuic"; onTuic = mkEnableOption "forward to warp in first two port of tuic";
}; };
users = mkOption {
type = lib.types.listOf lib.types.str;
};
}; };
config = mkIf cfg.enable ( config = mkIf cfg.enable {
{ boot.kernel.sysctl = {
boot.kernel.sysctl = { "net.core.default_qdisc" = "fq";
"net.core.default_qdisc" = "fq"; "net.ipv4.tcp_congestion_control" = "bbr";
"net.ipv4.tcp_congestion_control" = "bbr"; };
networking.firewall.trustedInterfaces = [ "tun0" ];
security.acme = {
acceptTerms = true;
certs.${config.deployment.targetHost} = {
email = "me@namely.icu";
# Avoid port conflict
listenHTTP = if config.services.caddy.enable then ":30310" else ":80";
}; };
};
services.caddy.virtualHosts."http://${config.deployment.targetHost}:80".extraConfig = ''
reverse_proxy 127.0.0.1:30310
'';
networking.firewall.trustedInterfaces = [ "tun0" ]; networking.firewall.allowedTCPPorts = [
80
cfg.trojan.port
];
networking.firewall.allowedUDPPorts = [ ] ++ (lib.range 6311 6314);
security.acme = { services.sing-box = {
acceptTerms = true; enable = true;
certs.${config.deployment.targetHost} = { settings = mkSingConfig {
email = "me@namely.icu"; uuid = config.sops.secrets."sing-box/uuid".path;
# Avoid port conflict password = config.sops.secrets."sing-box/password".path;
listenHTTP = if config.services.caddy.enable then ":30310" else ":80";
};
}; };
services.caddy.virtualHosts."http://${config.deployment.targetHost}:80".extraConfig = '' };
reverse_proxy 127.0.0.1:30310 };
'';
networking.firewall.allowedTCPPorts = [
80
cfg.trojan.port
];
networking.firewall.allowedUDPPorts = [ ] ++ (lib.range 6311 6314);
services.sing-box = {
enable = true;
package = sing-box;
settings = (
mkSingConfig (
map (n: {
name = n;
uuidFile = config.sops.secrets."sing-box/users/${n}/uuid".path;
passwordFile = config.sops.secrets."sing-box/users/${n}/password".path;
}) cfg.users
)
);
};
}
// {
sops.secrets = (
builtins.foldl' (a: b: a // b) { } (
map (u: {
"sing-box/users/${u}/uuid" = { };
"sing-box/users/${u}/password" = { };
}) cfg.users
)
);
}
);
} }

View file

@ -7,6 +7,15 @@
./common-settings/mainland.nix ./common-settings/mainland.nix
./disk-partitions ./disk-partitions
./restic.nix ./restic.nix
./vaultwarden.nix
./monitor ./monitor
./hedgedoc.nix
./sing-box.nix
./kanidm-client.nix
./ssh-tpm-agent.nix # FIXME: Waiting for upstream merge
./forgejo-actions-runner.nix
./oidc-agent.nix
./miniflux.nix
./immich.nix
]; ];
} }

View file

@ -0,0 +1,78 @@
{
config,
pkgs,
lib,
...
}:
with lib;
let
cfg = config.custom.hedgedoc;
in
{
options = {
custom.hedgedoc = {
enable = mkEnableOption "HedgeDoc Markdown Editor";
domain = mkOption {
type = types.str;
default = "docs.example.com";
description = "Domain name of the HedgeDoc server";
};
caddy = mkOption {
type = types.bool;
default = true;
description = "Enable Caddy as reverse proxy";
};
mediaPath = mkOption {
type = types.path;
default = /var/lib/hedgedoc/uploads;
description = "Directory for storing medias";
};
oidc = {
enable = mkEnableOption "OIDC support for HedgeDoc";
baseURL = mkOption { type = types.str; };
authorizationURL = mkOption { type = types.str; };
tokenURL = mkOption { type = types.str; };
userProfileURL = mkOption { type = types.str; };
};
environmentFile = mkOption { type = types.path; };
};
};
config = mkIf cfg.enable {
services.hedgedoc = {
enable = true;
environmentFile = cfg.environmentFile;
settings = {
domain = cfg.domain;
protocolUseSSL = cfg.caddy;
uploadsPath = cfg.mediaPath;
path = "/run/hedgedoc/hedgedoc.sock";
email = false;
allowEmailRegister = false;
oauth2 = mkIf cfg.oidc.enable {
baseURL = cfg.oidc.baseURL;
authorizationURL = cfg.oidc.authorizationURL;
tokenURL = cfg.oidc.tokenURL;
userProfileURL = cfg.oidc.userProfileURL;
userProfileEmailAttr = "email";
userProfileUsernameAttr = "name";
userProfileDisplayNameAttr = "preferred_name";
scope = "openid email profile";
clientID = "$HEDGEDOC_CLIENT_ID";
clientSecret = "$HEDGEDOC_CLIENT_SECRET";
};
allowAnonymous = false;
defaultPermission = "private";
};
};
services.caddy = mkIf cfg.caddy {
enable = true;
virtualHosts."https://${cfg.domain}".extraConfig = ''
reverse_proxy unix/${config.services.hedgedoc.settings.path}
'';
};
users.users.caddy.extraGroups = mkIf cfg.caddy [ "hedgedoc" ];
};
}

60
modules/nixos/immich.nix Normal file
View file

@ -0,0 +1,60 @@
{
config,
lib,
pkgs,
utils,
...
}:
let
cfg = config.custom.immich;
upstreamCfg = config.services.immich;
settingsFormat = pkgs.formats.json { };
user = config.systemd.services.immich-server.serviceConfig.User;
group = config.systemd.services.immich-server.serviceConfig.Group;
in
{
options = {
custom.immich.jsonSettings = lib.mkOption {
type = lib.types.submodule {
freeformType = settingsFormat.type;
};
default = { };
};
};
config = {
/*
LoadCredential happens before preStart. We need to ensure the
configuration file exist, otherwise LoadCredential will fail.
*/
systemd.tmpfiles.settings = lib.mkIf upstreamCfg.enable {
"10-etc-immich" = {
"/etc/immich" = {
d = {
inherit user group;
mode = "0700";
};
};
"/etc/immich/config.json" = {
"f+" = {
inherit user group;
mode = "0600";
};
};
};
};
systemd.services.immich-server = {
preStart = ''
umask 0077
${utils.genJqSecretsReplacementSnippet cfg.jsonSettings "/etc/immich/config.json"}
'';
serviceConfig = {
LoadCredential = "config:/etc/immich/config.json";
Environment = "IMMICH_CONFIG_FILE=%d/config";
};
};
# https://github.com/NixOS/nixpkgs/pull/324127/files#r1723763510
services.immich.redis.host = "/run/redis-immich/redis.sock";
};
}

134
modules/nixos/inbounds.nix Normal file
View file

@ -0,0 +1,134 @@
{ config, lib, ... }:
let
cfg = config.custom.sing-box-server;
secretFileType = lib.types.submodule { _secret = lib.types.path; };
singTls = {
enabled = true;
server_name = config.deployment.targetHost;
key_path = config.security.acme.certs.${config.deployment.targetHost}.directory + "/key.pem";
certificate_path =
config.security.acme.certs.${config.deployment.targetHost}.directory + "/cert.pem";
};
in
{
options = {
enable = lib.mkEnableOption "sing-box proxy server";
users = lib.types.listOf lib.types.submodule {
name = lib.mkOption {
type = lib.types.str;
default = "proxy";
};
password = lib.mkOption { type = secretFileType; };
uuid = lib.mkOption { type = secretFileType; };
};
wgOut = {
privKeyFile = lib.mkOption { type = lib.types.path; };
pubkey = lib.mkOption {
type = lib.types.str;
default = "bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=";
};
};
inbounds = {
trojan = {
enable = lib.mkOption {
type = lib.types.bool;
default = true;
};
};
tuic = {
enable = lib.mkOption {
type = lib.types.bool;
default = true;
};
ports = lib.mkOption {
type = lib.types.listOf lib.types.int;
default = lib.range 6311 6313;
};
directPorts = lib.mkOption {
type = lib.types.listOf lib.types.int;
default = [ 6314 ];
};
};
};
};
config = lib.mkIf cfg.enable {
services.sing-box = {
enable = true;
settings = {
dns = {
servers = [
{
address = "1.1.1.1";
detour = "wg-out";
}
];
};
inbounds =
[
# TODO: Trojan and tuic enable
{
tag = "trojan-in";
type = "trojan";
listen = "::";
listen_port = 8080;
users = map (u: removeAttrs u [ "uuid" ]) cfg.users;
tls = singTls;
}
]
++ lib.forEach (cfg.tuic.ports ++ cfg.tuic.directPorts) (port: {
tag = "tuic-in" + toString port;
type = "tuic";
listen = "::";
listen_port = port;
congestion_control = "bbr";
users = cfg.users;
tls = singTls;
});
outbounds = [
{
type = "wireguard";
tag = "wg-out";
private_key = cfg.wgOut.privKeyFile;
local_address = [
"172.16.0.2/32"
"2606:4700:110:82ed:a443:3c62:6cbc:b59b/128"
];
peers = [
{
public_key = cfg.wgOut.pubkey;
allowed_ips = [
"0.0.0.0/0"
"::/0"
];
server = "162.159.192.1";
server_port = 500;
}
];
}
{
type = "direct";
tag = "direct-out";
}
{
type = "dns";
tag = "dns-out";
}
];
route = {
rules =
[
{
outbound = "dns-out";
protocol = "dns";
}
]
++ lib.forEach cfg.tuic.directPorts (port: {
inbound = "tuic-in" + toString port;
outbound = "direct-out";
});
};
};
};
};
}

View file

@ -59,6 +59,8 @@ in
PasswordAuthentication = false; PasswordAuthentication = false;
KbdInteractiveAuthentication = false; KbdInteractiveAuthentication = false;
PermitRootLogin = lib.mkForce "no"; PermitRootLogin = lib.mkForce "no";
GSSAPIAuthentication = "no";
KerberosAuthentication = "no";
}; };
}; };

165
modules/nixos/miniflux.nix Normal file
View file

@ -0,0 +1,165 @@
{
config,
pkgs,
lib,
...
}:
let
inherit (lib)
mkEnableOption
mkPackageOption
mkOption
types
literalExpression
mkIf
mkDefault
;
cfg = config.custom.miniflux;
defaultAddress = "localhost:8080";
pgbin = "${config.services.postgresql.package}/bin";
preStart = pkgs.writeScript "miniflux-pre-start" ''
#!${pkgs.runtimeShell}
${pgbin}/psql "miniflux" -c "CREATE EXTENSION IF NOT EXISTS hstore"
'';
in
{
options = {
custom.miniflux = {
enable = mkEnableOption "miniflux";
package = mkPackageOption pkgs "miniflux" { };
oauth2SecretFile = mkOption { type = types.path; };
environment = mkOption {
type =
with types;
attrsOf (oneOf [
int
str
]);
};
createDatabaseLocally = mkOption {
type = types.bool;
default = true;
description = ''
Whether a PostgreSQL database should be automatically created and
configured on the local host. If set to `false`, you need provision a
database yourself and make sure to create the hstore extension in it.
'';
};
};
};
config = lib.mkIf cfg.enable {
services.miniflux.enable = false;
custom.miniflux.environment = {
LISTEN_ADDR = mkDefault defaultAddress;
RUN_MIGRATIONS = mkDefault 1;
DATABASE_URL = lib.mkIf cfg.createDatabaseLocally "user=miniflux host=/run/postgresql dbname=miniflux";
OAUTH2_CLIENT_SECRET_FILE = "%d/oauth2_secret";
WATCHDOG = mkDefault 1;
};
services.postgresql = lib.mkIf cfg.createDatabaseLocally {
enable = true;
ensureUsers = [
{
name = "miniflux";
ensureDBOwnership = true;
}
];
ensureDatabases = [ "miniflux" ];
};
systemd.services.miniflux-dbsetup = lib.mkIf cfg.createDatabaseLocally {
description = "Miniflux database setup";
requires = [ "postgresql.service" ];
after = [
"network.target"
"postgresql.service"
];
serviceConfig = {
Type = "oneshot";
User = config.services.postgresql.superUser;
ExecStart = preStart;
};
};
systemd.services.miniflux = {
description = "Miniflux service";
wantedBy = [ "multi-user.target" ];
requires = lib.optional cfg.createDatabaseLocally "miniflux-dbsetup.service";
after =
[ "network.target" ]
++ lib.optionals cfg.createDatabaseLocally [
"postgresql.service"
"miniflux-dbsetup.service"
];
serviceConfig = {
Type = "notify";
ExecStart = lib.getExe cfg.package;
User = "miniflux";
DynamicUser = true;
LoadCredential = [ "oauth2_secret:${cfg.oauth2SecretFile}" ];
RuntimeDirectory = "miniflux";
RuntimeDirectoryMode = "0750";
WatchdogSec = 60;
WatchdogSignal = "SIGKILL";
Restart = "always";
RestartSec = 5;
# Hardening
CapabilityBoundingSet = [ "" ];
DeviceAllow = [ "" ];
LockPersonality = true;
MemoryDenyWriteExecute = true;
PrivateDevices = true;
PrivateUsers = true;
ProcSubset = "pid";
ProtectClock = true;
ProtectControlGroups = true;
ProtectHome = true;
ProtectHostname = true;
ProtectKernelLogs = true;
ProtectKernelModules = true;
ProtectKernelTunables = true;
ProtectProc = "invisible";
RestrictAddressFamilies = [
"AF_INET"
"AF_INET6"
"AF_UNIX"
];
RestrictNamespaces = true;
RestrictRealtime = true;
RestrictSUIDSGID = true;
SystemCallArchitectures = "native";
SystemCallFilter = [
"@system-service"
"~@privileged"
];
UMask = "0077";
};
environment = lib.mapAttrs (_: toString) cfg.environment;
};
environment.systemPackages = [ cfg.package ];
security.apparmor.policies."bin.miniflux".profile = ''
include <tunables/global>
${cfg.package}/bin/miniflux {
include <abstractions/base>
include <abstractions/nameservice>
include <abstractions/ssl_certs>
include "${pkgs.apparmorRulesFromClosure { name = "miniflux"; } cfg.package}"
r ${cfg.package}/bin/miniflux,
r @{sys}/kernel/mm/transparent_hugepage/hpage_pmd_size,
rw /run/miniflux/**,
}
'';
};
}

View file

@ -11,7 +11,6 @@ let
mkMerge mkMerge
types types
; ;
inherit (config.my-lib.settings) ntfyUrl;
cfg = config.custom.prometheus; cfg = config.custom.prometheus;
mkRulesOption = mkOption { mkRulesOption = mkOption {
@ -57,13 +56,6 @@ in
default = "${config.networking.hostName}.coho-tet.ts.net"; default = "${config.networking.hostName}.coho-tet.ts.net";
}; };
}; };
v2ray = {
enable = mkEnableOption "blackbox exporter";
listenAddress = mkOption {
type = types.str;
default = "${config.networking.hostName}.coho-tet.ts.net";
};
};
}; };
}; };
}; };
@ -89,9 +81,19 @@ in
]; ];
} }
(mkIf cfg.enable { (mkIf cfg.enable {
services.caddy.virtualHosts."${config.networking.hostName}.coho-tet.ts.net".extraConfig = ''
reverse_proxy 127.0.0.1:${toString config.services.prometheus.port} services.tailscale = {
''; enable = true;
permitCertUid = config.services.caddy.user;
openFirewall = true;
};
services.caddy = {
enable = true;
virtualHosts."${config.networking.hostName}.coho-tet.ts.net".extraConfig = ''
reverse_proxy 127.0.0.1:${toString config.services.prometheus.port}
'';
};
services.prometheus = mkIf cfg.enable { services.prometheus = mkIf cfg.enable {
enable = true; enable = true;
port = 9091; port = 9091;
@ -119,11 +121,12 @@ in
name = "ntfy"; name = "ntfy";
webhook_configs = [ webhook_configs = [
{ {
url = "${ntfyUrl}/prometheus-alerts?tpl=yes&m=${lib.escapeURL '' url = "https://ntfy.xinyang.life/prometheus-alerts?tpl=yes&m=${lib.escapeURL ''
{{range .alerts}}[{{ if eq .status "resolved" }} RESOLVED{{ else }}{{ if eq .status "firing" }}🔥 FIRING{{end}}{{end}}]{{range $k,$v := .labels}} Alert {{.status}}
{{range .alerts}}-----{{range $k,$v := .labels}}
{{$k}}={{$v}}{{end}} {{$k}}={{$v}}{{end}}
{{end}}
{{end}}''}"; ''}";
send_resolved = true; send_resolved = true;
} }
]; ];

View file

@ -5,8 +5,7 @@
... ...
}: }:
let let
inherit (lib) mkIf concatStringsSep; inherit (lib) mkIf;
inherit (config.my-lib.settings) prometheusCollectors;
cfg = config.custom.prometheus.exporters; cfg = config.custom.prometheus.exporters;
in in
{ {
@ -47,13 +46,6 @@ in
); );
}; };
services.prometheus.exporters.v2ray = mkIf cfg.v2ray.enable {
enable = true;
listenAddress = cfg.v2ray.listenAddress;
port = 9516;
v2rayEndpoint = config.services.sing-box.settings.experimental.v2ray_api.listen;
};
# gotosocial # gotosocial
sops.templates."gotosocial_metrics.env" = { sops.templates."gotosocial_metrics.env" = {
content = '' content = ''
@ -79,7 +71,7 @@ in
services.restic.server.prometheus = true; services.restic.server.prometheus = true;
# miniflux # miniflux
sops.templates."miniflux_metrics_env" = { sops.templates."miniflux_metrics_env" = {
content = '' content = ''
METRICS_COLLECTOR=1 METRICS_COLLECTOR=1
@ -103,28 +95,8 @@ in
metrics metrics
} }
admin unix//var/run/caddy/admin.sock { admin ${config.networking.hostName}.coho-tet.ts.net:2019 {
origins 127.0.0.1 ${config.networking.hostName}.coho-tet.ts.net:2019
} }
''; '';
systemd.services.caddy.serviceConfig = {
RuntimeDirectory = "caddy";
RuntimeDirectoryMode = "0700";
};
services.tailscale = {
permitCertUid = config.services.caddy.user;
openFirewall = true;
};
services.caddy = {
virtualHosts."https://${config.networking.hostName}.coho-tet.ts.net:2019".extraConfig = ''
handle /metrics {
reverse_proxy unix//var/run/caddy/admin.sock
}
respond 403
'';
};
}; };
} }

View file

@ -1,6 +1,5 @@
{ config, lib, ... }: { config, lib, ... }:
let let
inherit (config.my-lib.settings) grafanaUrl idpUrl;
cfg = config.custom.monitoring.grafana; cfg = config.custom.monitoring.grafana;
in in
{ {
@ -14,17 +13,17 @@ in
server = { server = {
http_addr = "127.0.0.1"; http_addr = "127.0.0.1";
http_port = 3003; http_port = 3003;
root_url = grafanaUrl; root_url = "https://grafana.xinyang.life";
domain = lib.removePrefix "https://" grafanaUrl; domain = "grafana.xinyang.life";
}; };
"auth.generic_oauth" = { "auth.generic_oauth" = {
enabled = true; enabled = true;
name = "Kanidm"; name = "Kanidm";
client_id = "grafana"; client_id = "grafana";
scopes = "openid,profile,email,groups"; scopes = "openid,profile,email,groups";
auth_url = "${idpUrl}/ui/oauth2"; auth_url = "https://auth.xinyang.life/ui/oauth2";
token_url = "${idpUrl}/oauth2/token"; token_url = "https://auth.xinyang.life/oauth2/token";
api_url = "${idpUrl}/oauth2/openid/grafana/userinfo"; api_url = "https://auth.xinyang.life/oauth2/openid/grafana/userinfo";
use_pkce = true; use_pkce = true;
use_refresh_token = true; use_refresh_token = true;
allow_sign_up = true; allow_sign_up = true;

View file

@ -1,159 +1,68 @@
{ {
pkgs,
config, config,
lib, lib,
... ...
}: }:
let let
inherit (lib) inherit (lib)
mkOption
mkEnableOption mkEnableOption
mkIf mkIf
mkMerge mkMerge
types
literalExpression
;
inherit (config.my-lib.settings)
alertmanagerPort
; ;
cfg = config.custom.monitoring; cfg = config.custom.monitoring;
lokiPort = 3100; port-loki = 3100;
in in
{ {
options = { options = {
custom.monitoring = { custom.monitoring = {
loki = { loki.enable = mkEnableOption "loki";
enable = mkEnableOption "loki";
rules = mkOption {
type = types.attrsOf (
types.submodule {
options = {
expr = mkOption {
type = types.str;
description = ''
Loki alert expression.
'';
example = ''count_over_time({job=~"secure"} |="sshd[" |~": Failed|: Invalid|: Connection closed by authenticating user" | __error__="" [15m]) > 15'';
default = null;
};
description = mkOption {
type = types.str;
description = ''
Loki alert message.
'';
example = "Prometheus encountered value {{ $value }} with {{ $labels }}";
default = null;
};
labels = mkOption {
type = types.nullOr (types.attrsOf types.str);
description = ''
Additional alert labels.
'';
example = literalExpression ''
{ severity = "page" };
'';
default = { };
};
time = mkOption {
type = types.str;
description = ''
Time until the alert is fired.
'';
example = "5m";
default = "2m";
};
};
}
);
description = ''
Defines the loki rules.
'';
default = { };
};
};
promtail.enable = mkEnableOption "promtail"; promtail.enable = mkEnableOption "promtail";
}; };
}; };
config = mkMerge [ config = mkMerge [
( (mkIf cfg.loki.enable {
let services.loki = {
rulerConfig = { enable = true;
groups = [ configuration = {
auth_enabled = false;
server.http_listen_address = "${config.networking.hostName}.coho-tet.ts.net";
server.http_listen_port = port-loki;
common = {
ring = {
instance_addr = "${config.networking.hostName}.coho-tet.ts.net";
kvstore.store = "inmemory";
};
replication_factor = 1;
path_prefix = "/var/lib/loki";
};
schema_config.configs = [
{ {
name = "alerting-rules"; from = "2024-12-01";
rules = lib.mapAttrsToList (name: opts: { store = "boltdb-shipper";
alert = name; object_store = "filesystem";
inherit (opts) expr labels; schema = "v13";
for = opts.time; index = {
annotations.description = opts.description; prefix = "index_";
}) cfg.loki.rules; period = "24h";
};
} }
]; ];
};
rulerFile = pkgs.writeText "ruler.yml" (builtins.toJSON rulerConfig);
in
mkIf cfg.loki.enable {
services.loki = {
enable = true;
configuration = {
auth_enabled = false;
server.http_listen_address = "${config.networking.hostName}.coho-tet.ts.net";
server.http_listen_port = lokiPort;
common = { storage_config = {
ring = { filesystem.directory = "/var/lib/loki/chunks";
instance_addr = "${config.networking.hostName}.coho-tet.ts.net"; };
kvstore.store = "inmemory";
};
replication_factor = 1;
path_prefix = "/var/lib/loki";
};
schema_config.configs = [ limits_config = {
{ reject_old_samples = true;
from = "2024-12-01"; reject_old_samples_max_age = "168h";
store = "boltdb-shipper"; allow_structured_metadata = false;
object_store = "filesystem";
schema = "v13";
index = {
prefix = "index_";
period = "24h";
};
}
];
storage_config = {
filesystem.directory = "/var/lib/loki/chunks";
};
limits_config = {
reject_old_samples = true;
reject_old_samples_max_age = "168h";
allow_structured_metadata = false;
};
ruler = {
storage = {
type = "local";
local.directory = "${config.services.loki.dataDir}/rules";
};
rule_path = "${config.services.loki.dataDir}/rules-temp";
enable_api = true;
alertmanager_url = "http://127.0.0.1:${toString alertmanagerPort}";
};
}; };
}; };
systemd.tmpfiles.rules = [ };
"d /var/lib/loki 0700 loki loki - -" })
"d /var/lib/loki/rules-temp 0700 loki loki - -"
"d /var/lib/loki/rules 0700 loki loki - -"
"d /var/lib/loki/rules/fake 0700 loki loki - -"
"L /var/lib/loki/rules/fake/ruler.yml - - - - ${rulerFile}"
];
systemd.services.loki.restartTriggers = [ rulerFile ];
}
)
(mkIf cfg.promtail.enable { (mkIf cfg.promtail.enable {
services.promtail = { services.promtail = {
enable = true; enable = true;
@ -169,7 +78,7 @@ in
clients = [ clients = [
{ {
url = "http://thorite.coho-tet.ts.net:${toString lokiPort}/loki/api/v1/push"; url = "http://thorite.coho-tet.ts.net:${toString port-loki}/loki/api/v1/push";
} }
]; ];
@ -241,42 +150,17 @@ in
]; ];
} }
# { # {
# job_name = "caddy"; # job_name = "caddy-access";
# static_configs = [ # file_sd_configs = {
# { # files = [
# targets = [ "localhost" ]; # "/var/log/caddy/*.log"
# labels = { # ];
# job = "caddy"; # refresh_interval = "5m";
# __path__ = "/var/log/caddy/*log"; # };
# agent = "caddy-promtail";
# };
# }
# ];
# pipeline_stages = [
# {
# json = {
# expressions = {
# duration = "duration";
# status = "status";
# };
# };
# }
# {
# labels = {
# duration = null;
# status = null;
# };
# }
# ];
# } # }
]; ];
}; };
}; };
services.caddy.logFormat = ''
format json
level INFO
'';
}) })
]; ];
} }

View file

@ -39,7 +39,7 @@ let
echo "Creating snapshot for ${rootDir}" echo "Creating snapshot for ${rootDir}"
subvolumes=$(${pkgs.btrfs-progs}/bin/btrfs subvolume list -o "${rootDir}" | ${awk} '{print $NF}') subvolumes=$(${pkgs.btrfs-progs}/bin/btrfs subvolume list -o "${rootDir}" | ${awk} '{print $NF}')
mkdir -p "${backupDir}" mkdir -p "${backupDir}"
${pkgs.btrfs-progs}/bin/btrfs subvolume snapshot -r "${rootDir}" "${backupDir}/rootDirectory" ${pkgs.btrfs-progs}/bin/btrfs subvolume snapshot -r "${rootDir}" "${backupDir}/rootfs"
for subvol in $subvolumes; do for subvol in $subvolumes; do
${continueIfInExclude} ${continueIfInExclude}
[[ /"$subvol" == "${backupDir}"* ]] && continue [[ /"$subvol" == "${backupDir}"* ]] && continue

View file

@ -0,0 +1,87 @@
{
config,
pkgs,
lib,
utils,
...
}:
let
cfg = config.custom.sing-box;
settingsFormat = pkgs.formats.json { };
in
{
options = {
custom.sing-box = {
enable = lib.mkEnableOption "sing-box";
package = lib.mkPackageOption pkgs "sing-box" { };
stateDir = lib.mkOption {
type = lib.types.path;
default = "/var/lib/sing-box";
};
configFile = {
urlFile = lib.mkOption { type = lib.types.path; };
name = lib.mkOption {
type = lib.types.str;
default = "config.json";
};
hash = lib.mkOption {
type = lib.types.str;
example = "9a304bcb87d4c3f1e50f6281f25dd78635255ebde06cd4d2555729ecda43aed4";
};
};
overrideSettings = lib.mkOption {
type = lib.types.submodule {
freeformType = settingsFormat.type;
options = {
route = {
geoip.path = lib.mkOption {
type = lib.types.path;
default = "${pkgs.sing-geoip}/share/sing-box/geoip.db";
defaultText = lib.literalExpression "\${pkgs.sing-geoip}/share/sing-box/geoip.db";
description = lib.mdDoc ''
The path to the sing-geoip database.
'';
};
geosite.path = lib.mkOption {
type = lib.types.path;
default = "${pkgs.sing-geosite}/share/sing-box/geosite.db";
defaultText = lib.literalExpression "\${pkgs.sing-geosite}/share/sing-box/geosite.db";
description = lib.mdDoc ''
The path to the sing-geosite database.
'';
};
};
};
};
default = { };
};
};
};
config = lib.mkIf cfg.enable {
networking.firewall.trustedInterfaces = [ "tun0" ];
systemd.packages = [ cfg.package ];
systemd.services.sing-box =
let
configFile = cfg.stateDir + "/${cfg.configFile.name}";
in
{
preStart = ''
umask 0077
mkdir -p /etc/sing-box
if ! [ -e ${configFile} ]; then
${pkgs.curl}/bin/curl "$(${pkgs.coreutils}/bin/cat ${cfg.configFile.urlFile})" > '${configFile}'
test "${cfg.configFile.hash}" $(${pkgs.coreutils}/bin/sha256sum '${configFile}' | ${pkgs.coreutils}/bin/cut -d ' ' -f 1)
fi
${utils.genJqSecretsReplacementSnippet cfg.overrideSettings "/etc/sing-box/config.json"}
${cfg.package}/bin/sing-box merge -c '${configFile}' -c /etc/sing-box/config.json /etc/sing-box/config.json
'';
wantedBy = [ "multi-user.target" ];
};
};
}

View file

@ -1,10 +1,3 @@
# nix-tree # nix-tree
Demonstrate disk usage by nix-store path. Demonstrate disk usage by nix-store path.
## TODO
- [x] change caddy admin to unix socket
- [ ] admin config persist = false
- [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)

View file

@ -1,11 +1,3 @@
{ {
mkSystemdDebug =
{ lib, pkgs }:
{
ExecStart = lib.mkForce "${pkgs.tmux}/bin/tmux -S /tmp/tmux.socket new-session -s my-session -d";
ExecStop = lib.mkForce "${pkgs.tmux}/bin/tmux -S /tmp/tmux.socket kill-session -t my-session";
Type = "forking";
};
} }
// (import ./prometheus.nix) // (import ./prometheus.nix)
// (import ./settings.nix)

View file

@ -28,51 +28,17 @@ in
) )
); );
mkV2rayScrapes = targets: [ mkCaddyScrapes = mkFunction (
{ {
job_name = "v2ray-exporter"; address,
scheme = "http"; port ? 2019,
static_configs = map ( ...
{ }:
address,
port ? 9516,
}:
{
targets = [ "${address}${mkPort port}" ];
}
) targets;
}
{ {
job_name = "singbox_stat"; job_name = "caddy_${address}";
scheme = "http"; static_configs = [ { targets = [ "${address}${mkPort port}" ]; } ];
metrics_path = "/scrape";
static_configs = map (
{
address,
port ? 9516,
}:
{
targets = [ "${address}${mkPort port}" ];
}
) targets;
} }
]; );
mkCaddyScrapes = targets: [
{
job_name = "caddy";
scheme = "https";
static_configs = map (
{
address,
port ? 2019,
}:
{
targets = [ "${address}${mkPort port}" ];
}
) targets;
}
];
mkCaddyRules = mkFunction ( mkCaddyRules = mkFunction (
{ {
@ -97,20 +63,17 @@ in
} }
); );
mkNodeScrapes = targets: [ mkNodeScrapes = mkFunction (
{ {
job_name = "node_exporter"; address,
static_configs = map ( port ? 9100,
{ ...
address, }:
port ? 9100, {
}: job_name = "node_${address}";
{ static_configs = [ { targets = [ "${address}${mkPort port}" ]; } ];
targets = [ "${address}${mkPort port}" ];
}
) targets;
} }
]; );
mkNodeRules = mkFunction ( mkNodeRules = mkFunction (
{ {
@ -146,9 +109,21 @@ in
}; };
} }
{ {
alert = "NetworkTrafficExceedLimit"; alert = "HighTransmitTraffic";
expr = ''sum by(instance) (increase(node_network_transmit_bytes_total{device!="lo", device!~"tailscale.*", device!~"wg.*", device!~"br.*"}[30d])) > 322122547200''; expr = "rate(node_network_transmit_bytes_total{device!=\"lo\"}[5m]) > 100000000";
for = "1m"; for = "1m";
labels = {
severity = "warning";
};
annotations = {
summary = "High network transmit traffic on {{ $labels.instance }} ({{ $labels.device }})";
description = "The network interface {{ $labels.device }} on {{ $labels.instance }} is transmitting data at a rate exceeding 100 MB/s for the last 1 minute.";
};
}
{
alert = "NetworkTrafficExceedLimit";
expr = ''increase(node_network_transmit_bytes_total{device!="lo",device!~"tailscale.*",device!~"wg.*",device!~"br.*"}[30d]) > 322122547200'';
for = "0m";
labels = { labels = {
severity = "critical"; severity = "critical";
}; };
@ -156,66 +131,6 @@ in
summary = "Outbound network traffic exceed 300GB for last 30 day"; summary = "Outbound network traffic exceed 300GB for last 30 day";
}; };
} }
{
alert = "HighDiskUsage";
expr = ''(1 - node_filesystem_free_bytes{fstype!~"vfat|ramfs"} / node_filesystem_size_bytes) * 100 > 85'';
for = "5m";
labels = {
severity = "warning";
};
annotations = {
summary = "High disk usage on {{ $labels.instance }}";
};
}
{
alert = "DiskWillFull";
expr = ''predict_linear(node_filesystem_free_bytes{fstype!~"vfat|ramfs"}[1h], 12 * 3600) < (node_filesystem_size_bytes * 0.05)'';
for = "3m";
labels = {
severity = "critical";
};
annotations = {
summary = "Disk usage will exceed 95% in 12 hours on {{ $labels.instance }}";
description = "Disk {{ $labels.mountpoint }} is predicted to exceed 92% usage within 12 hours at current growth rate";
};
}
{
alert = "HighSwapUsage";
expr = ''(1 - (node_memory_SwapFree_bytes / node_memory_SwapTotal_bytes)) * 100 > 80'';
for = "5m";
labels = {
severity = "warning";
};
annotations = {
summary = "High swap usage on {{ $labels.instance }}";
description = "Swap usage is above 80% for 5 minutes\n Current value: {{ $value }}%";
};
}
{
alert = "OOMKillDetected";
expr = ''increase(node_vmstat_oom_kill[5m]) > 0'';
for = "1m";
labels = {
severity = "critical";
};
annotations = {
summary = "OOM kill detected on {{ $labels.instance }}";
description = "Out of memory killer was triggered in the last 5 minutes";
};
}
{
alert = "HighMemoryUsage";
expr = ''(1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) * 100 > 90'';
for = "5m";
labels = {
severity = "warning";
};
annotations = {
summary = "High memory usage on {{ $labels.instance }}";
description = "Memory usage is above 90% for 5 minutes\n Current value: {{ $value }}%";
};
}
]; ];
} }
); );
@ -237,9 +152,6 @@ in
static_configs = [ static_configs = [
{ {
targets = targetAddresses; targets = targetAddresses;
labels = {
from = hostAddress;
};
} }
]; ];
relabel_configs = [ relabel_configs = [
@ -267,17 +179,6 @@ in
{ {
inherit name; inherit name;
rules = [ rules = [
{
alert = "ProbeError";
expr = "probe_success != 1";
for = "3m";
labels = {
severity = "critical";
};
annotations = {
summary = "Probing {{ $labels.instance }} from {{ $labels.from }} failed";
};
}
{ {
alert = "HighProbeLatency"; alert = "HighProbeLatency";
expr = "probe_duration_seconds > 0.5"; expr = "probe_duration_seconds > 0.5";
@ -286,25 +187,23 @@ in
severity = "warning"; severity = "warning";
}; };
annotations = { annotations = {
summary = "High request latency from {{ $labels.from }} to {{ $labels.instance }}"; summary = "High request latency on {{ $labels.instance }}";
description = "Request latency is above 0.5 seconds for the last 2 minutes."; description = "Request latency is above 0.5 seconds for the last 3 minutes.";
}; };
} }
{ {
alert = "VeryHighProbeLatency"; alert = "VeryHighProbeLatency";
expr = "probe_duration_seconds > 2"; expr = "probe_duration_seconds > 1";
for = "3m"; for = "3m";
labels = { labels = {
severity = "critical"; severity = "critical";
}; };
annotations = { annotations = {
summary = "Very high request latency from {{ $labels.from }} to {{ $labels.instance }}"; summary = "High request latency on {{ $labels.instance }}";
description = "Request latency is above 2 seconds for the last 2 minutes."; description = "Request latency is above 0.5 seconds for the last 3 minutes.";
}; };
} }
]; ];
} }
); );
# mkResticScrapes = mkFunction () ;
} }

View file

@ -1,20 +0,0 @@
{
settings = {
alertmanagerPort = 9093;
idpUrl = "https://auth.xinyang.life";
gotosocialUrl = "https://gts.xiny.li";
minifluxUrl = "https://rss.xiny.li";
hedgedocDomain = "docs.xiny.li";
forgejoDomain = "git.xiny.li";
forgejoGitDomain = "git.xiny.li";
vaultwardenUrl = "https://vaultwarden.xiny.li";
ntfyUrl = "https://ntfy.xiny.li";
grafanaUrl = "https://grafana.xiny.li";
synapseUrl = "https://xiny.li";
synapseDelegateUrl = "https://synapse.xiny.li";
prometheusCollectors = [
"thorite.coho-tet.ts.net"
];
};
}

View file

@ -0,0 +1,56 @@
{
lib,
stdenv,
fetchFromGitHub,
curl,
webkitgtk,
libmicrohttpd,
libsecret,
qrencode,
libsodium,
pkg-config,
help2man,
}:
stdenv.mkDerivation rec {
pname = "oidc-agent";
version = "5.1.0";
src = fetchFromGitHub {
owner = "indigo-dc";
repo = "oidc-agent";
rev = "v${version}";
sha256 = "sha256-cOK/rZ/jnyALLuhDM3+qvwwe4Fjkv8diQBkw7NfVo0c=";
};
buildInputs = [
pkg-config
help2man
];
nativeBuildInputs = [
curl
webkitgtk
libmicrohttpd
libsecret
qrencode
libsodium
];
enableParallelBuilding = true;
installPhase = ''
make -j $NIX_BUILD_CORES PREFIX=$out BIN_PATH=$out LIB_PATH=$out/lib \
install_bin install_lib install_conf
'';
postFixup = ''
# Override with patched binary to be used by help2man
cp -r $out/bin/* bin
make install_man PREFIX=$out
'';
meta = with lib; {
description = "oidc-agent for managing OpenID Connect tokens on the command line";
homepage = "https://github.com/indigo-dc/oidc-agent";
maintainers = [ ];
license = licenses.mit;
};
}