Compare commits
7 commits
7fb530b64e
...
9cee7f22d7
Author | SHA1 | Date | |
---|---|---|---|
chayleaf | 9cee7f22d7 | ||
chayleaf | 762e02ef3f | ||
chayleaf | c415a21fae | ||
chayleaf | 105c3dd321 | ||
chayleaf | beb834e04c | ||
chayleaf | 2b61423e72 | ||
chayleaf | b41ca57cb3 |
67
flake.lock
67
flake.lock
|
@ -113,11 +113,11 @@
|
||||||
"nixpkgs-lib": "nixpkgs-lib"
|
"nixpkgs-lib": "nixpkgs-lib"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1712014858,
|
"lastModified": 1717285511,
|
||||||
"narHash": "sha256-sB4SWl2lX95bExY2gMFG5HIzvva5AVMJd4Igm+GpZNw=",
|
"narHash": "sha256-iKzJcpdXih14qYVcZ9QC9XuZYnPc6T8YImb6dX166kw=",
|
||||||
"owner": "hercules-ci",
|
"owner": "hercules-ci",
|
||||||
"repo": "flake-parts",
|
"repo": "flake-parts",
|
||||||
"rev": "9126214d0a59633752a136528f5f3b9aa8565b7d",
|
"rev": "2a55567fcf15b1b1c7ed712a2c6fadaec7412ea8",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
@ -205,11 +205,11 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1712452624,
|
"lastModified": 1717550333,
|
||||||
"narHash": "sha256-R35K+4krhK5B2fcV6W2HFe/uhXmP8YGTb35uZ+nDAxw=",
|
"narHash": "sha256-QebVpP3Z0zVBTSqExNQRg3FLOi2h0bPML6urBbUPzLY=",
|
||||||
"owner": "fufexan",
|
"owner": "fufexan",
|
||||||
"repo": "nix-gaming",
|
"repo": "nix-gaming",
|
||||||
"rev": "06314bbf8fedd83c7253442994a2f0c81d47988e",
|
"rev": "de70cdf224bd40928fe2af7fa558e1bdb7d8d619",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
@ -225,11 +225,11 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1712459390,
|
"lastModified": 1717297675,
|
||||||
"narHash": "sha256-e12bNDottaGoBgd0AdH/bQvk854xunlWAdZwr/oHO1c=",
|
"narHash": "sha256-43UmlS1Ifx17y93/Vc258U7bOlAAIZbu8dsGDHOIIr0=",
|
||||||
"owner": "nix-community",
|
"owner": "nix-community",
|
||||||
"repo": "nix-index-database",
|
"repo": "nix-index-database",
|
||||||
"rev": "4676d72d872459e1e3a248d049609f110c570e9a",
|
"rev": "972a52bee3991ae1f1899e6452e0d7c01ee566d9",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
@ -240,11 +240,11 @@
|
||||||
},
|
},
|
||||||
"nixos-hardware": {
|
"nixos-hardware": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1712760404,
|
"lastModified": 1717574423,
|
||||||
"narHash": "sha256-4zhaEW1nB+nGbCNMjOggWeY5nXs/H0Y71q0+h+jdxoU=",
|
"narHash": "sha256-cz3P5MZffAHwL2IQaNzsqUBsJS+u0J/AAwArHMAcCa0=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixos-hardware",
|
"repo": "nixos-hardware",
|
||||||
"rev": "e1c4bac14beb8c409d0534382cf967171706b9d9",
|
"rev": "d6c6cf6f5fead4057d8fb2d5f30aa8ac1727f177",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
@ -263,11 +263,11 @@
|
||||||
"utils": "utils"
|
"utils": "utils"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1710449465,
|
"lastModified": 1717515088,
|
||||||
"narHash": "sha256-2orO8nfplp6uQJBFqKkj1iyNMC6TysmwbWwbb4osTag=",
|
"narHash": "sha256-nWOLpPA7+k7V1OjXTuxdsVd5jeeI0b13Di57wvnqkic=",
|
||||||
"owner": "simple-nixos-mailserver",
|
"owner": "simple-nixos-mailserver",
|
||||||
"repo": "nixos-mailserver",
|
"repo": "nixos-mailserver",
|
||||||
"rev": "79c8cfcd5873a85559da6201b116fb38b490d030",
|
"rev": "0d51a32e4799d081f260eb4db37145f5f4ee7456",
|
||||||
"type": "gitlab"
|
"type": "gitlab"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
@ -298,35 +298,30 @@
|
||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1712769857,
|
"lastModified": 1717670534,
|
||||||
"narHash": "sha256-YUyh+yfB15+2gvvvTvWBQbAUrD1x391QF1PRZUSt87k=",
|
"narHash": "sha256-pzkVew3wK8RIa8tQMzU3kd8Cf+u9g1XDfNpBT+k5lyo=",
|
||||||
"owner": "chayleaf",
|
"owner": "chayleaf",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "058c6a3724a1cc5ef010ce6f2163d959666e8a86",
|
"rev": "b4313b98b86d588375cdad46f75279b7aa45bd41",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "chayleaf",
|
"owner": "chayleaf",
|
||||||
|
"ref": "ci",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nixpkgs-lib": {
|
"nixpkgs-lib": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"dir": "lib",
|
"lastModified": 1717284937,
|
||||||
"lastModified": 1711703276,
|
"narHash": "sha256-lIbdfCsf8LMFloheeE6N31+BMIeixqyQWbSr2vk79EQ=",
|
||||||
"narHash": "sha256-iMUFArF0WCatKK6RzfUJknjem0H9m4KgorO/p3Dopkk=",
|
"type": "tarball",
|
||||||
"owner": "NixOS",
|
"url": "https://github.com/NixOS/nixpkgs/archive/eb9ceca17df2ea50a250b6b27f7bf6ab0186f198.tar.gz"
|
||||||
"repo": "nixpkgs",
|
|
||||||
"rev": "d8fe5e6c92d0d190646fb9f1056741a229980089",
|
|
||||||
"type": "github"
|
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"dir": "lib",
|
"type": "tarball",
|
||||||
"owner": "NixOS",
|
"url": "https://github.com/NixOS/nixpkgs/archive/eb9ceca17df2ea50a250b6b27f7bf6ab0186f198.tar.gz"
|
||||||
"ref": "nixos-unstable",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"type": "github"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"notlua": {
|
"notlua": {
|
||||||
|
@ -371,11 +366,11 @@
|
||||||
},
|
},
|
||||||
"nur": {
|
"nur": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1712785619,
|
"lastModified": 1717590062,
|
||||||
"narHash": "sha256-1RCStMZUGqus3DAl7jivw7XM5jpbecfqWtA1r45Ts90=",
|
"narHash": "sha256-Xw9yQ3KttiV/t9ClwC2Eo6EX1IEEONw4jCe9s794zhg=",
|
||||||
"owner": "nix-community",
|
"owner": "nix-community",
|
||||||
"repo": "NUR",
|
"repo": "NUR",
|
||||||
"rev": "a0471f14e0499a66898fc1c7d5aff259a9fa58b9",
|
"rev": "a364b6de0f2bd5ed5614ee3827f2ad135c69c73d",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
@ -411,11 +406,11 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1712715149,
|
"lastModified": 1717553884,
|
||||||
"narHash": "sha256-uOx7GaLV+5hekAYtm/CBr627Pi7+d1Yh70hwKmVjYYo=",
|
"narHash": "sha256-+t3XaYEvlMo5BUJ/6C6RZcEfBTWFVUdMHpNoqUU+pSE=",
|
||||||
"owner": "oxalica",
|
"owner": "oxalica",
|
||||||
"repo": "rust-overlay",
|
"repo": "rust-overlay",
|
||||||
"rev": "9ef1eca23bee5fb8080863909af3802130b2ee57",
|
"rev": "8795c817dfab19243a33387a16c98d2df4075bb3",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
inputs = {
|
inputs = {
|
||||||
#nixpkgs.url = "github:NixOS/nixpkgs/3dc2b4f8166f744c3b3e9ff8224e7c5d74a5424f";
|
#nixpkgs.url = "github:NixOS/nixpkgs/3dc2b4f8166f744c3b3e9ff8224e7c5d74a5424f";
|
||||||
# nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
# nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||||
nixpkgs.url = "github:chayleaf/nixpkgs";
|
nixpkgs.url = "github:chayleaf/nixpkgs/ci";
|
||||||
nixos-hardware.url = "github:NixOS/nixos-hardware";
|
nixos-hardware.url = "github:NixOS/nixos-hardware";
|
||||||
nix-index-database = {
|
nix-index-database = {
|
||||||
url = "github:nix-community/nix-index-database";
|
url = "github:nix-community/nix-index-database";
|
||||||
|
|
|
@ -42,7 +42,7 @@
|
||||||
home.stateVersion = "22.11";
|
home.stateVersion = "22.11";
|
||||||
home.username = "user";
|
home.username = "user";
|
||||||
home.homeDirectory = "/home/user";
|
home.homeDirectory = "/home/user";
|
||||||
terminals = [ "kitty" ];
|
terminals = [ "alacritty" "foot" "kitty" ];
|
||||||
# xsession.windowManager.i3.enable = true;
|
# xsession.windowManager.i3.enable = true;
|
||||||
wayland.windowManager.sway.enable = true;
|
wayland.windowManager.sway.enable = true;
|
||||||
services.kdeconnect.enable = true;
|
services.kdeconnect.enable = true;
|
||||||
|
@ -58,13 +58,13 @@
|
||||||
anki-bin
|
anki-bin
|
||||||
(gimp.overrideAttrs (old: { doCheck = false; })) krita blender-hip
|
(gimp.overrideAttrs (old: { doCheck = false; })) krita blender-hip
|
||||||
kdenlive glaxnimate mediainfo
|
kdenlive glaxnimate mediainfo
|
||||||
ghidra (cutter.withPlugins (p: with p; [ sigdb rz-ghidra ]))
|
ghidra # (cutter.withPlugins (p: with p; [ sigdb rz-ghidra ]))
|
||||||
openrgb piper
|
openrgb piper
|
||||||
steam-run steam
|
steam-run steam
|
||||||
# faf-client
|
# faf-client
|
||||||
(osu-lazer-bin.override {
|
#(osu-lazer-bin.override {
|
||||||
command_prefix = "env SDL_VIDEODRIVER=wayland ${obs-studio-plugins.obs-vkcapture}/bin/obs-gamecapture";
|
#command_prefix = "env SDL_VIDEODRIVER=wayland ${obs-studio-plugins.obs-vkcapture}/bin/obs-gamecapture";
|
||||||
})
|
#})
|
||||||
taisei
|
taisei
|
||||||
techmino
|
techmino
|
||||||
(wrapOBS {
|
(wrapOBS {
|
||||||
|
|
|
@ -80,6 +80,7 @@
|
||||||
ripgrep
|
ripgrep
|
||||||
(python3.withPackages (p: with p; [
|
(python3.withPackages (p: with p; [
|
||||||
python-lsp-server
|
python-lsp-server
|
||||||
|
python-lsp-black
|
||||||
pylsp-mypy
|
pylsp-mypy
|
||||||
python-lsp-server.optional-dependencies.pyflakes
|
python-lsp-server.optional-dependencies.pyflakes
|
||||||
python-lsp-server.optional-dependencies.mccabe
|
python-lsp-server.optional-dependencies.mccabe
|
||||||
|
@ -433,6 +434,7 @@
|
||||||
pylsp = {
|
pylsp = {
|
||||||
settings = {
|
settings = {
|
||||||
pylsp.plugins.pylsp_mypy.enabled = true;
|
pylsp.plugins.pylsp_mypy.enabled = true;
|
||||||
|
pylsp.plugins.black.enabled = true;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
svelte = { };
|
svelte = { };
|
||||||
|
|
|
@ -22,24 +22,24 @@
|
||||||
"pinned": false,
|
"pinned": false,
|
||||||
"src": {
|
"src": {
|
||||||
"name": null,
|
"name": null,
|
||||||
"sha256": "sha256-wCIffeayOy3kEwmIKB7e+NrliuSpKXoVYC334fxVB3U=",
|
"sha256": "sha256-gHNrozbSBlTFY5VzRyhdiv3YkS+rXTekRJWSXlMalLY=",
|
||||||
"type": "url",
|
"type": "url",
|
||||||
"url": "https://github.com/GloriousEggroll/proton-ge-custom/releases/download/GE-Proton9-1/GE-Proton9-1.tar.gz"
|
"url": "https://github.com/GloriousEggroll/proton-ge-custom/releases/download/GE-Proton9-6/GE-Proton9-6.tar.gz"
|
||||||
},
|
},
|
||||||
"version": "GE-Proton9-1"
|
"version": "GE-Proton9-6"
|
||||||
},
|
},
|
||||||
"searxng": {
|
"searxng": {
|
||||||
"cargoLocks": null,
|
"cargoLocks": null,
|
||||||
"date": "2024-03-15",
|
"date": "2024-05-31",
|
||||||
"extract": null,
|
"extract": null,
|
||||||
"name": "searxng",
|
"name": "searxng",
|
||||||
"passthru": null,
|
"passthru": null,
|
||||||
"pinned": false,
|
"pinned": false,
|
||||||
"src": {
|
"src": {
|
||||||
"sha256": "sha256-BqVnp/lByAMr/LOCGkuXCYsomu9hRBGXK3DbBQX10TA=",
|
"sha256": "sha256-okE/Uxl7YqcM99kLJ4KAlMQi50x5m0bPfYp5bv62WEw=",
|
||||||
"type": "tarball",
|
"type": "tarball",
|
||||||
"url": "https://github.com/searxng/searxng/archive/e2af3e49702f6fb40e1614f826544dc3b03bca2f.tar.gz"
|
"url": "https://github.com/searxng/searxng/archive/18fb701be225560b3fb1011cc533f785823f26a4.tar.gz"
|
||||||
},
|
},
|
||||||
"version": "e2af3e49702f6fb40e1614f826544dc3b03bca2f"
|
"version": "18fb701be225560b3fb1011cc533f785823f26a4"
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -12,19 +12,19 @@
|
||||||
};
|
};
|
||||||
proton-ge = {
|
proton-ge = {
|
||||||
pname = "proton-ge";
|
pname = "proton-ge";
|
||||||
version = "GE-Proton9-1";
|
version = "GE-Proton9-6";
|
||||||
src = fetchurl {
|
src = fetchurl {
|
||||||
url = "https://github.com/GloriousEggroll/proton-ge-custom/releases/download/GE-Proton9-1/GE-Proton9-1.tar.gz";
|
url = "https://github.com/GloriousEggroll/proton-ge-custom/releases/download/GE-Proton9-6/GE-Proton9-6.tar.gz";
|
||||||
sha256 = "sha256-wCIffeayOy3kEwmIKB7e+NrliuSpKXoVYC334fxVB3U=";
|
sha256 = "sha256-gHNrozbSBlTFY5VzRyhdiv3YkS+rXTekRJWSXlMalLY=";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
searxng = {
|
searxng = {
|
||||||
pname = "searxng";
|
pname = "searxng";
|
||||||
version = "e2af3e49702f6fb40e1614f826544dc3b03bca2f";
|
version = "18fb701be225560b3fb1011cc533f785823f26a4";
|
||||||
src = fetchTarball {
|
src = fetchTarball {
|
||||||
url = "https://github.com/searxng/searxng/archive/e2af3e49702f6fb40e1614f826544dc3b03bca2f.tar.gz";
|
url = "https://github.com/searxng/searxng/archive/18fb701be225560b3fb1011cc533f785823f26a4.tar.gz";
|
||||||
sha256 = "sha256-BqVnp/lByAMr/LOCGkuXCYsomu9hRBGXK3DbBQX10TA=";
|
sha256 = "sha256-okE/Uxl7YqcM99kLJ4KAlMQi50x5m0bPfYp5bv62WEw=";
|
||||||
};
|
};
|
||||||
date = "2024-03-15";
|
date = "2024-05-31";
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,26 @@ in
|
||||||
stable = nixForNixPlugins;
|
stable = nixForNixPlugins;
|
||||||
unstable = nixForNixPlugins;
|
unstable = nixForNixPlugins;
|
||||||
};
|
};
|
||||||
|
matrix-appservice-discord = pkgs.matrix-appservice-discord.overrideAttrs (old: {
|
||||||
|
patches = (old.patches or []) ++ [
|
||||||
|
(pkgs.fetchpatch {
|
||||||
|
url = "https://github.com/matrix-org/matrix-appservice-discord/commit/eb989fa710e8db4ebc8f2ce36c6679ee6cbc1a44.patch";
|
||||||
|
hash = "sha256-GPeFDw3XujqXHJveHSsBHwHuG51vad50p55FX1Esq58=";
|
||||||
|
})
|
||||||
|
(pkgs.fetchpatch {
|
||||||
|
url = "https://github.com/matrix-org/matrix-appservice-discord/commit/a4cd5e3a6a2d544adac2a263e164671c8a9009d9.patch";
|
||||||
|
hash = "sha256-qQJ4V6/Ns2Msu8+X8JoEycuQ2Jc90TXulsuLLmPecGU=";
|
||||||
|
})
|
||||||
|
(pkgs.fetchpatch {
|
||||||
|
url = "https://github.com/matrix-org/matrix-appservice-discord/commit/fc850ba2473973e28858449ec4020380470d78b2.patch";
|
||||||
|
hash = "sha256-Lq0FWmR08wLsoq4APRTokZzb7U2po98pgyxH4UR/9/M=";
|
||||||
|
})
|
||||||
|
(pkgs.fetchpatch {
|
||||||
|
url = "https://github.com/matrix-org/matrix-appservice-discord/commit/7f3d41d86ebce057cfdc82ce3aaab64b533e8f0b.patch";
|
||||||
|
hash = "sha256-HmQ1KASZS+a78fe5yOCVXAnXLRmJUglzc6OxNJazOSk=";
|
||||||
|
})
|
||||||
|
];
|
||||||
|
});
|
||||||
# Various patches to change Nix version of existing packages so they don't error out because of nix-plugins in nix.conf
|
# Various patches to change Nix version of existing packages so they don't error out because of nix-plugins in nix.conf
|
||||||
/*nix-plugins = (pkgs.nix-plugins.override { nix = nixForNixPlugins; }).overrideAttrs (old: {
|
/*nix-plugins = (pkgs.nix-plugins.override { nix = nixForNixPlugins; }).overrideAttrs (old: {
|
||||||
version = "13.0.0";
|
version = "13.0.0";
|
||||||
|
@ -79,9 +99,11 @@ in
|
||||||
sha256 = "sha256-6vYbNmNJBCoU23nVculac24tHqH7F4AZVftIjL93WJU=";
|
sha256 = "sha256-6vYbNmNJBCoU23nVculac24tHqH7F4AZVftIjL93WJU=";
|
||||||
fetchSubmodules = true;
|
fetchSubmodules = true;
|
||||||
};
|
};
|
||||||
|
patches = [ ];
|
||||||
});
|
});
|
||||||
kvmfrOverlay = kvmfr: kvmfr.overrideAttrs (old: {
|
kvmfrOverlay = kvmfr: kvmfr.overrideAttrs (old: {
|
||||||
inherit (pkgs'.looking-glass-client) version src;
|
inherit (pkgs'.looking-glass-client) version src;
|
||||||
|
patches = [ ./looking-glass.patch ];
|
||||||
});
|
});
|
||||||
mobile-config-firefox = callPackage ./mobile-config-firefox { };
|
mobile-config-firefox = callPackage ./mobile-config-firefox { };
|
||||||
osu-wine = callPackage ./osu-wine { };
|
osu-wine = callPackage ./osu-wine { };
|
||||||
|
|
|
@ -2,10 +2,10 @@
|
||||||
{
|
{
|
||||||
"fastforwardteam" = buildFirefoxXpiAddon {
|
"fastforwardteam" = buildFirefoxXpiAddon {
|
||||||
pname = "fastforwardteam";
|
pname = "fastforwardteam";
|
||||||
version = "0.2334";
|
version = "0.2383";
|
||||||
addonId = "addon@fastforward.team";
|
addonId = "addon@fastforward.team";
|
||||||
url = "https://addons.mozilla.org/firefox/downloads/file/4177101/fastforwardteam-0.2334.xpi";
|
url = "https://addons.mozilla.org/firefox/downloads/file/4258067/fastforwardteam-0.2383.xpi";
|
||||||
sha256 = "d790219622469f08316b41c0d01abf2b584a37fa87b45666a74bd30cffb95ed0";
|
sha256 = "eec6328df3df1afe2cb6a331f6907669d804235551ea766d48655f8f831caf28";
|
||||||
meta = with lib;
|
meta = with lib;
|
||||||
{
|
{
|
||||||
homepage = "https://fastforward.team";
|
homepage = "https://fastforward.team";
|
||||||
|
@ -23,10 +23,10 @@
|
||||||
};
|
};
|
||||||
"rikaitan" = buildFirefoxXpiAddon {
|
"rikaitan" = buildFirefoxXpiAddon {
|
||||||
pname = "rikaitan";
|
pname = "rikaitan";
|
||||||
version = "24.3.7.1";
|
version = "24.5.21.0";
|
||||||
addonId = "tatsu@autistici.org";
|
addonId = "tatsu@autistici.org";
|
||||||
url = "https://addons.mozilla.org/firefox/downloads/file/4246908/rikaitan-24.3.7.1.xpi";
|
url = "https://addons.mozilla.org/firefox/downloads/file/4291845/rikaitan-24.5.21.0.xpi";
|
||||||
sha256 = "db849343b029b2f1b510cc66032157502e3fe9e6168072d27e8aad9867b6ec17";
|
sha256 = "a2a94d88af04023f14daaafda1f6ca7a7197f2ab92ada08ee2e9e4292d57a391";
|
||||||
meta = with lib;
|
meta = with lib;
|
||||||
{
|
{
|
||||||
homepage = "https://github.com/Ajatt-Tools/rikaitan";
|
homepage = "https://github.com/Ajatt-Tools/rikaitan";
|
||||||
|
|
16
pkgs/looking-glass.patch
Normal file
16
pkgs/looking-glass.patch
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
diff --git a/kvmfr.c b/kvmfr.c
|
||||||
|
index 121aae5b..2f4c9e1a 100644
|
||||||
|
--- a/kvmfr.c
|
||||||
|
+++ b/kvmfr.c
|
||||||
|
@@ -539,7 +539,11 @@ static int __init kvmfr_module_init(void)
|
||||||
|
if (kvmfr->major < 0)
|
||||||
|
goto out_free;
|
||||||
|
|
||||||
|
+#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 4, 0)
|
||||||
|
kvmfr->pClass = class_create(THIS_MODULE, KVMFR_DEV_NAME);
|
||||||
|
+#else
|
||||||
|
+ kvmfr->pClass = class_create(KVMFR_DEV_NAME);
|
||||||
|
+#endif
|
||||||
|
if (IS_ERR(kvmfr->pClass))
|
||||||
|
goto out_unreg;
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -49,7 +49,12 @@ let
|
||||||
# vpn table, assign an id but don't actually add a rule for it, so it is the default
|
# vpn table, assign an id but don't actually add a rule for it, so it is the default
|
||||||
vpn_table = 2;
|
vpn_table = 2;
|
||||||
|
|
||||||
vpn_mtu = config.networking.wireguard.interfaces.wg0.mtu;
|
vpn_iface =
|
||||||
|
if cfg.vpn.openvpn.enable && !cfg.vpn.wireguard.enable then "tun0"
|
||||||
|
else if cfg.vpn.wireguard.enable && !cfg.vpn.openvpn.enable then "wg0"
|
||||||
|
else throw "Exactly one of OpenVPN/Wireguard must be used";
|
||||||
|
|
||||||
|
vpn_mtu = config.networking.wireguard.interfaces.${vpn_iface}.mtu or 1320;
|
||||||
vpn_ipv4_mss = vpn_mtu - 40;
|
vpn_ipv4_mss = vpn_mtu - 40;
|
||||||
vpn_ipv6_mss = vpn_mtu - 60;
|
vpn_ipv6_mss = vpn_mtu - 60;
|
||||||
|
|
||||||
|
@ -411,7 +416,8 @@ in {
|
||||||
# ethernet wan
|
# ethernet wan
|
||||||
router.interfaces.wan = {
|
router.interfaces.wan = {
|
||||||
dependentServices = [
|
dependentServices = [
|
||||||
{ service = "wireguard-wg0"; inNetns = false; }
|
(lib.mkIf cfg.vpn.wireguard.enable { service = "wireguard-${vpn_iface}"; inNetns = false; })
|
||||||
|
(lib.mkIf cfg.vpn.openvpn.enable { service = "openvpn-client"; inNetns = false; })
|
||||||
{ service = "wireguard-wg1"; inNetns = false; }
|
{ service = "wireguard-wg1"; inNetns = false; }
|
||||||
];
|
];
|
||||||
systemdLink.linkConfig.MACAddressPolicy = "none";
|
systemdLink.linkConfig.MACAddressPolicy = "none";
|
||||||
|
@ -477,7 +483,7 @@ in {
|
||||||
{ ipv6 = true; extraArgs = [ "fwmark" wan_table "table" wan_table ]; }
|
{ ipv6 = true; extraArgs = [ "fwmark" wan_table "table" wan_table ]; }
|
||||||
# below is dnat config
|
# below is dnat config
|
||||||
] ++ builtins.concatLists (map (rule: let
|
] ++ builtins.concatLists (map (rule: let
|
||||||
table = if rule.inVpn then 0 else wan_table;
|
table = if rule.inVpn then vpn_table else wan_table;
|
||||||
forEachPort = func: port:
|
forEachPort = func: port:
|
||||||
if builtins.isInt port then [ (func port) ]
|
if builtins.isInt port then [ (func port) ]
|
||||||
else if port?set then builtins.concatLists (map (forEachPort func) port.set)
|
else if port?set then builtins.concatLists (map (forEachPort func) port.set)
|
||||||
|
@ -503,12 +509,12 @@ in {
|
||||||
selfIp4 = netAddresses.lan4;
|
selfIp4 = netAddresses.lan4;
|
||||||
selfIp6 = netAddresses.lan6;
|
selfIp6 = netAddresses.lan6;
|
||||||
lans = [ "br0" "wg1" ];
|
lans = [ "br0" "wg1" ];
|
||||||
wans = [ "wg0" "veth-wan-a" ];
|
wans = [ vpn_iface "veth-wan-a" ];
|
||||||
logPrefix = "lan ";
|
logPrefix = "lan ";
|
||||||
netdevIngressWanRules = with notnft.dsl; with payload; [
|
netdevIngressWanRules = with notnft.dsl; with payload; [
|
||||||
# check oif only from vpn
|
# check oif only from vpn
|
||||||
# dont check it from veth-wan-a because of dnat fuckery and because we already check packets coming from wan there
|
# dont check it from veth-wan-a because of dnat fuckery and because we already check packets coming from wan there
|
||||||
[(is.eq meta.iifname (set [ "wg0" "wg1" ])) (is.eq (fib (f: with f; [ saddr mark iif ]) (f: f.oif)) missing) (log "lan oif missing ") drop]
|
[(is.eq meta.iifname (set [ vpn_iface "wg1" ])) (is.eq (fib (f: with f; [ saddr mark iif ]) (f: f.oif)) missing) (log "lan oif missing ") drop]
|
||||||
];
|
];
|
||||||
inetDnatRules =
|
inetDnatRules =
|
||||||
builtins.concatLists (map
|
builtins.concatLists (map
|
||||||
|
@ -517,10 +523,10 @@ in {
|
||||||
rule4 = rule.target4; rule6 = rule.target6;
|
rule4 = rule.target4; rule6 = rule.target6;
|
||||||
in with notnft.dsl; with payload;
|
in with notnft.dsl; with payload;
|
||||||
lib.optional (rule4 != null)
|
lib.optional (rule4 != null)
|
||||||
[ (is.eq meta.iifname "wg0") (is.eq ip.protocol protocols) (is.eq th.dport rule.port)
|
[ (is.eq meta.iifname vpn_iface) (is.eq ip.protocol protocols) (is.eq th.dport rule.port)
|
||||||
(if rule4.port == null then dnat.ip rule4.address else dnat.ip rule4.address rule4.port) ]
|
(if rule4.port == null then dnat.ip rule4.address else dnat.ip rule4.address rule4.port) ]
|
||||||
++ lib.optional (rule6 != null)
|
++ lib.optional (rule6 != null)
|
||||||
[ (is.eq meta.iifname "wg0") (is.eq ip6.nexthdr protocols) (is.eq th.dport rule.port)
|
[ (is.eq meta.iifname vpn_iface) (is.eq ip6.nexthdr protocols) (is.eq th.dport rule.port)
|
||||||
(if rule6.port == null then dnat.ip6 rule6.address else dnat.ip6 rule6.address rule6.port) ]
|
(if rule6.port == null then dnat.ip6 rule6.address else dnat.ip6 rule6.address rule6.port) ]
|
||||||
)
|
)
|
||||||
(builtins.filter (x: x.inVpn && (x.tcp || x.udp)) cfg.dnatRules))
|
(builtins.filter (x: x.inVpn && (x.tcp || x.udp)) cfg.dnatRules))
|
||||||
|
@ -574,13 +580,14 @@ in {
|
||||||
[(is.eq ip6.daddr "@block6") (log "block6 ") drop]
|
[(is.eq ip6.daddr "@block6") (log "block6 ") drop]
|
||||||
[(is.eq ip.saddr "@block4") (log "block4/s ") drop]
|
[(is.eq ip.saddr "@block4") (log "block4/s ") drop]
|
||||||
[(is.eq ip6.saddr "@block6") (log "block6/s ") drop]
|
[(is.eq ip6.saddr "@block6") (log "block6/s ") drop]
|
||||||
|
[(mangle meta.mark wan_table)]
|
||||||
# default to vpn...
|
# default to vpn...
|
||||||
[(mangle meta.mark vpn_table)]
|
# [(mangle meta.mark vpn_table)]
|
||||||
# ...but unvpn traffic to/from force_unvpn4/force_unvpn6
|
# ...but unvpn traffic to/from force_unvpn4/force_unvpn6
|
||||||
[(is.eq ip.daddr "@force_unvpn4") (mangle meta.mark wan_table)]
|
# [(is.eq ip.daddr "@force_unvpn4") (mangle meta.mark wan_table)]
|
||||||
[(is.eq ip6.daddr "@force_unvpn6") (mangle meta.mark wan_table)]
|
# [(is.eq ip6.daddr "@force_unvpn6") (mangle meta.mark wan_table)]
|
||||||
[(is.eq ip.saddr "@force_unvpn4") (mangle meta.mark wan_table)]
|
# [(is.eq ip.saddr "@force_unvpn4") (mangle meta.mark wan_table)]
|
||||||
[(is.eq ip6.saddr "@force_unvpn6") (mangle meta.mark wan_table)]
|
# [(is.eq ip6.saddr "@force_unvpn6") (mangle meta.mark wan_table)]
|
||||||
# ...force vpn to/from force_vpn4/force_vpn6
|
# ...force vpn to/from force_vpn4/force_vpn6
|
||||||
# (disable this if it breaks some sites)
|
# (disable this if it breaks some sites)
|
||||||
[(is.eq ip.daddr "@force_vpn4") (mangle meta.mark vpn_table)]
|
[(is.eq ip.daddr "@force_vpn4") (mangle meta.mark vpn_table)]
|
||||||
|
@ -619,12 +626,12 @@ in {
|
||||||
lib.optionals (rule4 != null) [
|
lib.optionals (rule4 != null) [
|
||||||
[ (is.eq meta.iifname lanSet) (is.eq ip.protocol protocols) (is.eq ip.saddr rule4.address)
|
[ (is.eq meta.iifname lanSet) (is.eq ip.protocol protocols) (is.eq ip.saddr rule4.address)
|
||||||
(is.eq th.sport (if rule4.port != null then rule4.port else rule.port)) (mangle meta.mark vpn_table) ]
|
(is.eq th.sport (if rule4.port != null then rule4.port else rule.port)) (mangle meta.mark vpn_table) ]
|
||||||
[ (is.eq meta.iifname "wg0") (is.eq ip.protocol protocols) (is.eq ip.daddr rule4.address)
|
[ (is.eq meta.iifname vpn_iface) (is.eq ip.protocol protocols) (is.eq ip.daddr rule4.address)
|
||||||
(is.eq th.dport (if rule4.port != null then rule4.port else rule.port)) (mangle meta.mark vpn_table) ]
|
(is.eq th.dport (if rule4.port != null then rule4.port else rule.port)) (mangle meta.mark vpn_table) ]
|
||||||
] ++ lib.optionals (rule6 != null) [
|
] ++ lib.optionals (rule6 != null) [
|
||||||
[ (is.eq meta.iifname lanSet) (is.eq ip6.nexthdr protocols) (is.eq ip6.saddr rule6.address)
|
[ (is.eq meta.iifname lanSet) (is.eq ip6.nexthdr protocols) (is.eq ip6.saddr rule6.address)
|
||||||
(is.eq th.sport (if rule6.port != null then rule6.port else rule.port)) (mangle meta.mark vpn_table) ]
|
(is.eq th.sport (if rule6.port != null then rule6.port else rule.port)) (mangle meta.mark vpn_table) ]
|
||||||
[ (is.eq meta.iifname "wg0") (is.eq ip6.nexthdr protocols) (is.eq ip6.daddr rule6.address)
|
[ (is.eq meta.iifname vpn_iface) (is.eq ip6.nexthdr protocols) (is.eq ip6.daddr rule6.address)
|
||||||
(is.eq th.dport (if rule6.port != null then rule6.port else rule.port)) (mangle meta.mark vpn_table) ]
|
(is.eq th.dport (if rule6.port != null then rule6.port else rule.port)) (mangle meta.mark vpn_table) ]
|
||||||
])
|
])
|
||||||
(builtins.filter (x: x.inVpn && (x.tcp || x.udp) && dnatRuleMode x == "mark") cfg.dnatRules))
|
(builtins.filter (x: x.inVpn && (x.tcp || x.udp) && dnatRuleMode x == "mark") cfg.dnatRules))
|
||||||
|
@ -756,9 +763,43 @@ in {
|
||||||
|
|
||||||
# vpn socket is in wan namespace, meaning traffic gets sent through the wan namespace
|
# vpn socket is in wan namespace, meaning traffic gets sent through the wan namespace
|
||||||
# vpn interface is in default namespace, meaning it can be used in the default namespace
|
# vpn interface is in default namespace, meaning it can be used in the default namespace
|
||||||
networking.wireguard.interfaces.wg0 = cfg.wireguard // {
|
# networking.wireguard.interfaces.${vpn_iface} = cfg.vpn.wireguard.config // {
|
||||||
socketNamespace = "wan";
|
# socketNamespace = "wan";
|
||||||
interfaceNamespace = "init";
|
# interfaceNamespace = "init";
|
||||||
|
# };
|
||||||
|
|
||||||
|
systemd.services.vpn-tunnel = {
|
||||||
|
description = "VPN Tunnel";
|
||||||
|
wantedBy = [
|
||||||
|
"multi-user.target"
|
||||||
|
(lib.mkIf cfg.vpn.openvpn.enable "openvpn-client.service")
|
||||||
|
(lib.mkIf cfg.vpn.wireguard.enable "wireguard-${vpn_iface}.service")
|
||||||
|
];
|
||||||
|
after = [ "network.target" "netns-wan.service" ];
|
||||||
|
bindsTo = [ "netns-wan.service" ];
|
||||||
|
stopIfChanged = false;
|
||||||
|
path = [ config.programs.ssh.package ];
|
||||||
|
script = ''
|
||||||
|
while true; do
|
||||||
|
${config.programs.ssh.package}/bin/ssh \
|
||||||
|
-i /secrets/vpn/sshtunnel.key \
|
||||||
|
-L ${netAddresses.netnsWan4}:${toString cfg.vpn.tunnel.localPort}:127.0.0.1:${toString cfg.vpn.tunnel.remotePort} \
|
||||||
|
-p ${toString cfg.vpn.tunnel.port} \
|
||||||
|
-N -T -v \
|
||||||
|
sshtunnel@${cfg.vpn.tunnel.ip}
|
||||||
|
echo "Restarting..."
|
||||||
|
sleep 10
|
||||||
|
done
|
||||||
|
'';
|
||||||
|
serviceConfig = {
|
||||||
|
Restart = "always";
|
||||||
|
Type = "simple";
|
||||||
|
NetworkNamespacePath = "/var/run/netns/wan";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
services.openvpn.servers = lib.mkIf cfg.vpn.openvpn.enable {
|
||||||
|
client.config = cfg.vpn.openvpn.config;
|
||||||
};
|
};
|
||||||
|
|
||||||
# use main netns's address instead of 127.0.0.1
|
# use main netns's address instead of 127.0.0.1
|
||||||
|
@ -847,15 +888,18 @@ in {
|
||||||
wants = [ "nftables-default.service" "avahi-daemon.service" ];
|
wants = [ "nftables-default.service" "avahi-daemon.service" ];
|
||||||
# allow it to call nft
|
# allow it to call nft
|
||||||
serviceConfig.AmbientCapabilities = [ "CAP_NET_ADMIN" ];
|
serviceConfig.AmbientCapabilities = [ "CAP_NET_ADMIN" ];
|
||||||
|
serviceConfig.CapabilityBoundingSet = [ "CAP_NET_ADMIN" ];
|
||||||
};
|
};
|
||||||
systemd.services.update-rkn-blacklist = {
|
systemd.services.update-rkn-blacklist = {
|
||||||
# fetch vpn_ips.json and vpn_domains.json for unbound
|
# fetch vpn_ips.json and vpn_domains.json for unbound
|
||||||
script = ''
|
script = ''
|
||||||
BLACKLIST=$(${pkgs.coreutils}/bin/mktemp) || exit 1
|
BLACKLIST=$(${pkgs.coreutils}/bin/mktemp) || exit 1
|
||||||
${pkgs.curl}/bin/curl "https://reestr.rublacklist.net/api/v2/ips/json/" -o "$BLACKLIST" || exit 1
|
${pkgs.curl}/bin/curl "https://reestr.rublacklist.net/api/v3/ips/" -o "$BLACKLIST" || exit 1
|
||||||
${pkgs.jq}/bin/jq ".[0:0]" "$BLACKLIST" && chown unbound:unbound "$BLACKLIST" && mv "$BLACKLIST" /var/lib/unbound/vpn_ips.json
|
${pkgs.jq}/bin/jq ".[0:0]" "$BLACKLIST" && chown unbound:unbound "$BLACKLIST" && mv "$BLACKLIST" /var/lib/unbound/vpn_ips.json
|
||||||
${pkgs.curl}/bin/curl "https://reestr.rublacklist.net/api/v2/domains/json/" -o "$BLACKLIST" || exit 1
|
${pkgs.curl}/bin/curl "https://reestr.rublacklist.net/api/v3/domains/" -o "$BLACKLIST" || exit 1
|
||||||
${pkgs.jq}/bin/jq ".[0:0]" "$BLACKLIST" && chown unbound:unbound "$BLACKLIST" && mv "$BLACKLIST" /var/lib/unbound/vpn_domains.json
|
${pkgs.jq}/bin/jq ".[0:0]" "$BLACKLIST" && chown unbound:unbound "$BLACKLIST" && mv "$BLACKLIST" /var/lib/unbound/vpn_domains.json
|
||||||
|
${pkgs.curl}/bin/curl "https://reestr.rublacklist.net/api/v3/dpi/" -o "$BLACKLIST" || exit 1
|
||||||
|
${pkgs.jq}/bin/jq ".[0:0]" "$BLACKLIST" && chown unbound:unbound "$BLACKLIST" && mv "$BLACKLIST" /var/lib/unbound/vpn_dpi.json
|
||||||
'';
|
'';
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
Type = "oneshot";
|
Type = "oneshot";
|
||||||
|
@ -864,7 +908,6 @@ in {
|
||||||
systemd.timers.update-rkn-blacklist = {
|
systemd.timers.update-rkn-blacklist = {
|
||||||
wantedBy = [ "timers.target" ];
|
wantedBy = [ "timers.target" ];
|
||||||
partOf = [ "update-rkn-blacklist.service" ];
|
partOf = [ "update-rkn-blacklist.service" ];
|
||||||
# slightly unusual time to reduce server load
|
|
||||||
timerConfig.OnCalendar = [ "*-*-* 00:00:00" ]; # every day
|
timerConfig.OnCalendar = [ "*-*-* 00:00:00" ]; # every day
|
||||||
timerConfig.RandomizedDelaySec = 43200; # execute at random time in the first 12 hours
|
timerConfig.RandomizedDelaySec = 43200; # execute at random time in the first 12 hours
|
||||||
};
|
};
|
||||||
|
|
|
@ -5,6 +5,38 @@
|
||||||
|
|
||||||
{
|
{
|
||||||
options.router-settings = {
|
options.router-settings = {
|
||||||
|
vpn = {
|
||||||
|
tunnel = {
|
||||||
|
enable = lib.mkEnableOption "VPN tunnel";
|
||||||
|
localPort = lib.mkOption {
|
||||||
|
description = "local port";
|
||||||
|
type = lib.types.port;
|
||||||
|
};
|
||||||
|
remotePort = lib.mkOption {
|
||||||
|
description = "remote port";
|
||||||
|
type = lib.types.port;
|
||||||
|
};
|
||||||
|
ip = lib.mkOption {
|
||||||
|
description = "remote ip";
|
||||||
|
type = router-lib.types.ipv4;
|
||||||
|
};
|
||||||
|
port = lib.mkOption {
|
||||||
|
description = "SSH port";
|
||||||
|
type = lib.types.port;
|
||||||
|
default = 22;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
openvpn.enable = lib.mkEnableOption "OpenVPN";
|
||||||
|
openvpn.config = lib.mkOption {
|
||||||
|
description = "OpenVPN config";
|
||||||
|
type = lib.types.lines;
|
||||||
|
};
|
||||||
|
wireguard.enable = lib.mkEnableOption "Wireguard";
|
||||||
|
wireguard.config = lib.mkOption {
|
||||||
|
description = "wireguard config";
|
||||||
|
type = lib.types.attrs;
|
||||||
|
};
|
||||||
|
};
|
||||||
routerMac = lib.mkOption {
|
routerMac = lib.mkOption {
|
||||||
description = "router's mac address";
|
description = "router's mac address";
|
||||||
type = lib.types.str;
|
type = lib.types.str;
|
||||||
|
@ -82,10 +114,6 @@
|
||||||
description = "wlan passphrase";
|
description = "wlan passphrase";
|
||||||
type = lib.types.str;
|
type = lib.types.str;
|
||||||
};
|
};
|
||||||
wireguard = lib.mkOption {
|
|
||||||
description = "wireguard config";
|
|
||||||
type = lib.types.attrs;
|
|
||||||
};
|
|
||||||
dhcpReservations = lib.mkOption {
|
dhcpReservations = lib.mkOption {
|
||||||
description = "dhcp reservations (ipv4)";
|
description = "dhcp reservations (ipv4)";
|
||||||
default = [ ];
|
default = [ ];
|
||||||
|
|
|
@ -5,33 +5,19 @@
|
||||||
|
|
||||||
let
|
let
|
||||||
cfg = config.server;
|
cfg = config.server;
|
||||||
|
python = pkgs.python3.withPackages (p: with p; [ cryptography pyasn1 pyasn1-modules requests ]);
|
||||||
|
tool = pkgs.writeScript "certspotter.py" ''
|
||||||
|
#!${python}/bin/python3
|
||||||
|
${builtins.readFile ./certspotter.py}
|
||||||
|
'';
|
||||||
in {
|
in {
|
||||||
security.acme.certs = lib.flip builtins.mapAttrs (lib.filterAttrs (k: v: v.enableACME) config.services.nginx.virtualHosts) (k: v: {
|
security.acme.certs = lib.mkIf config.services.certspotter.enable (lib.flip builtins.mapAttrs (lib.filterAttrs (k: v: v.enableACME) config.services.nginx.virtualHosts) (k: v: {
|
||||||
postRun = let
|
postRun = ''
|
||||||
python = pkgs.python3.withPackages (p: with p; [ cryptography pyasn1 pyasn1-modules ]);
|
${tool} tbs full.pem > "/var/lib/certspotter/tbs-hashes/${k}"
|
||||||
tbs-hash = pkgs.writeScript "tbs-hash.py" ''
|
|
||||||
#!${python}/bin/python3
|
|
||||||
import hashlib
|
|
||||||
from pyasn1.codec.der.decoder import decode
|
|
||||||
from pyasn1.codec.der.encoder import encode
|
|
||||||
from pyasn1_modules import rfc5280
|
|
||||||
from cryptography import x509
|
|
||||||
|
|
||||||
with open('full.pem', 'rb') as f:
|
|
||||||
cert = x509.load_pem_x509_certificate(f.read())
|
|
||||||
tbs, _leftover = decode(cert.tbs_certificate_bytes, asn1Spec=rfc5280.TBSCertificate())
|
|
||||||
precert_exts = [v.dotted_string for k, v in x509.ExtensionOID.__dict__.items() if k.startswith('PRECERT_')]
|
|
||||||
exts = [ext for ext in tbs["extensions"] if str(ext["extnID"]) not in precert_exts]
|
|
||||||
tbs["extensions"].clear()
|
|
||||||
tbs["extensions"].extend(exts)
|
|
||||||
print(hashlib.sha256(encode(tbs)).hexdigest())
|
|
||||||
'';
|
|
||||||
in ''
|
|
||||||
${tbs-hash} > "/var/lib/certspotter/tbs-hashes/${k}"
|
|
||||||
'';
|
'';
|
||||||
});
|
}));
|
||||||
services.certspotter = {
|
services.certspotter = {
|
||||||
enable = true;
|
enable = false;
|
||||||
extraFlags = [ ];
|
extraFlags = [ ];
|
||||||
watchlist = [ ".${cfg.domainName}" ];
|
watchlist = [ ".${cfg.domainName}" ];
|
||||||
hooks = lib.toList (pkgs.writeShellScript "certspotter-hook" ''
|
hooks = lib.toList (pkgs.writeShellScript "certspotter-hook" ''
|
||||||
|
@ -41,4 +27,25 @@ in {
|
||||||
(echo "Subject: $SUMMARY" && echo && cat "$TEXT_FILENAME") | /run/wrappers/bin/sendmail -i webmaster-certspotter@${cfg.domainName}
|
(echo "Subject: $SUMMARY" && echo && cat "$TEXT_FILENAME") | /run/wrappers/bin/sendmail -i webmaster-certspotter@${cfg.domainName}
|
||||||
'');
|
'');
|
||||||
};
|
};
|
||||||
|
systemd.services.certspotter-lite = {
|
||||||
|
script = ''
|
||||||
|
exec ${tool} spot \
|
||||||
|
-c /var/lib/acme/certspotter-lite.txt \
|
||||||
|
-d ${cfg.domainName} \
|
||||||
|
-t webmaster-certspotter@${cfg.domainName} \
|
||||||
|
-s /run/wrappers/bin/sendmail \
|
||||||
|
/var/lib/acme/*/full.pem
|
||||||
|
'';
|
||||||
|
serviceConfig = {
|
||||||
|
User = "acme";
|
||||||
|
Group = "acme";
|
||||||
|
Type = "oneshot";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
systemd.timers.certspotter-lite = {
|
||||||
|
wantedBy = [ "timers.target" ];
|
||||||
|
partOf = [ "certspotter-lite.service" ];
|
||||||
|
timerConfig.OnCalendar = [ "*-*-* 00:00:00" ]; # every day
|
||||||
|
timerConfig.RandomizedDelaySec = 43200; # execute at random time in the first 12 hours
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
158
system/hosts/server/certspotter.py
Normal file
158
system/hosts/server/certspotter.py
Normal file
|
@ -0,0 +1,158 @@
|
||||||
|
import argparse
|
||||||
|
import hashlib
|
||||||
|
import requests
|
||||||
|
import subprocess
|
||||||
|
import traceback
|
||||||
|
from datetime import date
|
||||||
|
from pyasn1.codec.der.decoder import decode
|
||||||
|
from pyasn1.codec.der.encoder import encode
|
||||||
|
from pyasn1_modules import rfc5280
|
||||||
|
from cryptography import x509
|
||||||
|
|
||||||
|
|
||||||
|
def calc_tbs(pem: bytes) -> str:
|
||||||
|
cert = x509.load_pem_x509_certificate(pem)
|
||||||
|
tbs, _leftover = decode(
|
||||||
|
cert.tbs_certificate_bytes, asn1Spec=rfc5280.TBSCertificate()
|
||||||
|
)
|
||||||
|
precert_exts = [
|
||||||
|
v.dotted_string
|
||||||
|
for k, v in x509.ExtensionOID.__dict__.items()
|
||||||
|
if k.startswith("PRECERT_")
|
||||||
|
]
|
||||||
|
exts = [ext for ext in tbs["extensions"] if str(ext["extnID"]) not in precert_exts]
|
||||||
|
tbs["extensions"].clear()
|
||||||
|
tbs["extensions"].extend(exts)
|
||||||
|
return hashlib.sha256(encode(tbs)).hexdigest()
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
subparsers = parser.add_subparsers(required=True)
|
||||||
|
spot = subparsers.add_parser("spot")
|
||||||
|
spot.set_defaults(func=spotter)
|
||||||
|
spot.add_argument("--sendmail", "-s", type=str, required=True)
|
||||||
|
spot.add_argument("--from", "-f", type=str, required=False, default="Certificate Monitoring")
|
||||||
|
spot.add_argument("--to", "-t", type=str, required=False)
|
||||||
|
spot.add_argument("--domain", "-d", type=str, required=True)
|
||||||
|
spot.add_argument("--cache_file", "-c", type=str, required=True)
|
||||||
|
spot.add_argument("certs", type=str, nargs="*")
|
||||||
|
tbs = subparsers.add_parser("tbs")
|
||||||
|
tbs.set_defaults(func=print_tbs)
|
||||||
|
tbs.add_argument("path", type=str)
|
||||||
|
args = parser.parse_args()
|
||||||
|
args.func(args)
|
||||||
|
|
||||||
|
|
||||||
|
def print_tbs(args) -> None:
|
||||||
|
with open(args.path, "rb") as f:
|
||||||
|
print(calc_tbs(f.read()))
|
||||||
|
|
||||||
|
|
||||||
|
def send_mail(
|
||||||
|
sendmail: str, from_: str | None, to: str | None, subject: str, text: str
|
||||||
|
):
|
||||||
|
proc = subprocess.Popen(
|
||||||
|
[sendmail, "-i"] + (["-F", from_] if from_ else []) + (['--', to] if to else []),
|
||||||
|
stdin=subprocess.PIPE,
|
||||||
|
)
|
||||||
|
assert proc.stdin is not None
|
||||||
|
proc.stdin.write(f"Subject: {subject}\n\n".encode("utf-8"))
|
||||||
|
proc.stdin.write((text + "\n").encode("utf-8"))
|
||||||
|
proc.stdin.close()
|
||||||
|
proc.wait()
|
||||||
|
assert proc.returncode == 0
|
||||||
|
|
||||||
|
|
||||||
|
def spotter(args) -> None:
|
||||||
|
try:
|
||||||
|
spotter1(args)
|
||||||
|
except Exception:
|
||||||
|
subject = "Certificate monitoring failure"
|
||||||
|
text = traceback.format_exc()
|
||||||
|
send_mail(args.sendmail, args.__dict__["from"], args.to, subject, text)
|
||||||
|
|
||||||
|
|
||||||
|
def spotter1(args) -> None:
|
||||||
|
url = f"https://crt.sh/?CN={args.domain}&dir=^&sort=1&group=none"
|
||||||
|
|
||||||
|
try:
|
||||||
|
with open(args.cache_file, "rt") as f:
|
||||||
|
lastid = int(f.read())
|
||||||
|
except FileNotFoundError:
|
||||||
|
lastid = 0
|
||||||
|
|
||||||
|
body = requests.get(url).text
|
||||||
|
|
||||||
|
def parse_row(row: str, tag: str) -> list[str]:
|
||||||
|
ret = []
|
||||||
|
for col in row.split(f"</{tag}>")[:-1]:
|
||||||
|
if "</A>" in col:
|
||||||
|
col = col.split("</A>")[-2].split(">")[-1]
|
||||||
|
else:
|
||||||
|
col = col.split(">")[-1]
|
||||||
|
ret.append(col)
|
||||||
|
return ret
|
||||||
|
|
||||||
|
cols: list[str] = []
|
||||||
|
rows: list[dict[str, str]] = []
|
||||||
|
for s_row in body.split("<TR>")[2:]:
|
||||||
|
s_row = s_row.split("</TR>")[0]
|
||||||
|
if "<TH" in s_row:
|
||||||
|
cols = parse_row(s_row, "TH")
|
||||||
|
elif cols:
|
||||||
|
rows.append({k: v for k, v in zip(cols, parse_row(s_row, "TD"))})
|
||||||
|
|
||||||
|
today = date.today()
|
||||||
|
pem_urls = {}
|
||||||
|
issuers = {}
|
||||||
|
cns = {}
|
||||||
|
|
||||||
|
if not rows:
|
||||||
|
raise Exception("No rows found!")
|
||||||
|
|
||||||
|
for row in rows:
|
||||||
|
crtid = int(row["crt.sh ID"])
|
||||||
|
if crtid <= lastid:
|
||||||
|
continue
|
||||||
|
d = date.fromisoformat(row["Logged At"])
|
||||||
|
if (today - d).days > 30:
|
||||||
|
continue
|
||||||
|
pem_urls[crtid] = f"https://crt.sh/?d={crtid}"
|
||||||
|
issuers[crtid] = row.get("Issuer Name", "")
|
||||||
|
cns[crtid] = row.get("Matching Identities", "")
|
||||||
|
|
||||||
|
if not pem_urls:
|
||||||
|
return
|
||||||
|
|
||||||
|
valid_hashes: set[str] = set()
|
||||||
|
for path in args.certs:
|
||||||
|
with open(path, "rb") as f1:
|
||||||
|
valid_hashes.add(calc_tbs(f1.read()))
|
||||||
|
|
||||||
|
pems: dict[int, bytes] = {}
|
||||||
|
|
||||||
|
for id, pem_url in pem_urls.items():
|
||||||
|
lastid = max(id, lastid)
|
||||||
|
pems[id] = requests.get(pem_url).content
|
||||||
|
|
||||||
|
invalid_ids: set[int] = set()
|
||||||
|
|
||||||
|
for id, pem in pems.items():
|
||||||
|
if calc_tbs(pem) not in valid_hashes:
|
||||||
|
invalid_ids.add(id)
|
||||||
|
|
||||||
|
if invalid_ids:
|
||||||
|
subject = f"{len(invalid_ids)} invalid certs discovered!"
|
||||||
|
text = "\n".join(
|
||||||
|
f"https://crt.sh/?id={id} ({cns[id]}, {issuers[id]})"
|
||||||
|
for id in sorted(invalid_ids)
|
||||||
|
)
|
||||||
|
send_mail(args.sendmail, args.__dict__["from"], args.to, subject, text)
|
||||||
|
|
||||||
|
with open(args.cache_file, "wt") as f:
|
||||||
|
f.write(str(lastid))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
|
@ -107,14 +107,11 @@ in {
|
||||||
# make sure only hydra has access to this file
|
# make sure only hydra has access to this file
|
||||||
# so normal nix evals don't have access to builtins
|
# so normal nix evals don't have access to builtins
|
||||||
nix.settings.extra-builtins-file = "/secrets/nixos/extra-builtins.nix";
|
nix.settings.extra-builtins-file = "/secrets/nixos/extra-builtins.nix";
|
||||||
|
# required for hydra which uses restricted mode
|
||||||
nix.settings.allowed-uris = [
|
nix.settings.allowed-uris = [
|
||||||
# required for home-manager (no idea if it's required at this point)
|
"https://git.sr.ht/"
|
||||||
"https://git.sr.ht/~rycee/nmd/"
|
"https://api.github.com/repos/"
|
||||||
# ...for the rest of the home config
|
"https://github.com/"
|
||||||
"https://api.github.com/repos/FAForever/"
|
|
||||||
"https://github.com/nix-community/nix-index-database/releases/download/"
|
|
||||||
# required for server (I suppose since nvfetcher uses fetchTarball here...)
|
|
||||||
"https://github.com/searxng/searxng/"
|
|
||||||
# for nginx CF-Connecting-IP config generation
|
# for nginx CF-Connecting-IP config generation
|
||||||
"https://www.cloudflare.com/ips-v4"
|
"https://www.cloudflare.com/ips-v4"
|
||||||
"https://www.cloudflare.com/ips-v6"
|
"https://www.cloudflare.com/ips-v6"
|
||||||
|
@ -283,7 +280,7 @@ in {
|
||||||
job_name = "local_medium_freq";
|
job_name = "local_medium_freq";
|
||||||
scrape_interval = "15m";
|
scrape_interval = "15m";
|
||||||
static_configs = [ {
|
static_configs = [ {
|
||||||
targets = [ "127.0.0.1:9548" "127.0.0.1:9198" ];
|
targets = [ "127.0.0.1:9548" "127.0.0.1:9198" "127.0.0.1:9173" ];
|
||||||
labels.machine = "server";
|
labels.machine = "server";
|
||||||
} ];
|
} ];
|
||||||
}
|
}
|
||||||
|
@ -359,6 +356,12 @@ in {
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
# TODO: enable
|
||||||
|
services.matrix-appservice-discord.settings.metrics = {
|
||||||
|
enable = true;
|
||||||
|
host = "127.0.0.1";
|
||||||
|
port = 9173;
|
||||||
|
};
|
||||||
services.matrix-synapse.settings = {
|
services.matrix-synapse.settings = {
|
||||||
enable_metrics = true;
|
enable_metrics = true;
|
||||||
federation_metrics_domains = [ "matrix.org" ];
|
federation_metrics_domains = [ "matrix.org" ];
|
||||||
|
|
|
@ -36,7 +36,8 @@ in {
|
||||||
|
|
||||||
# a crude way to make some python packages available for synapse
|
# a crude way to make some python packages available for synapse
|
||||||
services.matrix-synapse.plugins = with pkgs.python3.pkgs; [ authlib ];
|
services.matrix-synapse.plugins = with pkgs.python3.pkgs; [ authlib ];
|
||||||
services.matrix-synapse.settings.password_config.enabled = false;
|
# i'm managing this manually in a stateful way
|
||||||
|
# services.matrix-synapse.settings.password_config.enabled = false;
|
||||||
systemd.services.matrix-synapse.after = [ "keycloak.service" ];
|
systemd.services.matrix-synapse.after = [ "keycloak.service" ];
|
||||||
|
|
||||||
# See also https://meta.akkoma.dev/t/390
|
# See also https://meta.akkoma.dev/t/390
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
{ config
|
{ config
|
||||||
, lib
|
, lib
|
||||||
|
, pkgs
|
||||||
, ... }:
|
, ... }:
|
||||||
|
|
||||||
let
|
let
|
||||||
|
@ -51,12 +52,32 @@ in {
|
||||||
homeserver = "http://${lib.quoteListenAddr matrixAddr}:${toString matrixPort}/";
|
homeserver = "http://${lib.quoteListenAddr matrixAddr}:${toString matrixPort}/";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
services.matrix-appservice-discord = {
|
||||||
|
enable = true;
|
||||||
|
environmentFile = "/secrets/discord-bridge-token";
|
||||||
|
settings = {
|
||||||
|
auth.usePrivilegedIntents = true;
|
||||||
|
database.filename = "";
|
||||||
|
bridge = {
|
||||||
|
domain = "matrix.${cfg.domainName}";
|
||||||
|
homeserverUrl = "https://matrix.${cfg.domainName}";
|
||||||
|
enableSelfServiceBridging = true;
|
||||||
|
disablePresence = true;
|
||||||
|
disablePortalBridging = true;
|
||||||
|
disableInviteNotifications = true;
|
||||||
|
disableJoinLeaveNotifications = true;
|
||||||
|
disableRoomTopicNotifications = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
services.matrix-synapse = {
|
services.matrix-synapse = {
|
||||||
enable = true;
|
enable = true;
|
||||||
extraConfigFiles = [ "/var/lib/matrix-synapse/config.yaml" ];
|
extraConfigFiles = [ "/var/lib/matrix-synapse/config.yaml" ];
|
||||||
settings = {
|
settings = {
|
||||||
app_service_config_files = [
|
app_service_config_files = [
|
||||||
"/var/lib/heisenbridge/registration.yml"
|
"/var/lib/heisenbridge/registration.yml"
|
||||||
|
"/var/lib/matrix-synapse/discord-registration.yaml"
|
||||||
];
|
];
|
||||||
allow_guest_access = true;
|
allow_guest_access = true;
|
||||||
url_preview_enabled = true;
|
url_preview_enabled = true;
|
||||||
|
|
|
@ -30,5 +30,6 @@ in {
|
||||||
];
|
];
|
||||||
services.maubot.pythonPackages = with pkgs.python3.pkgs; [
|
services.maubot.pythonPackages = with pkgs.python3.pkgs; [
|
||||||
levenshtein
|
levenshtein
|
||||||
|
pillow
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
12
update.sh
12
update.sh
|
@ -7,9 +7,9 @@ mozilla-addons-to-nix \
|
||||||
./pkgs/firefox-addons/addons.json \
|
./pkgs/firefox-addons/addons.json \
|
||||||
./pkgs/firefox-addons/generated.nix || echo "failed to update firefox addons"
|
./pkgs/firefox-addons/generated.nix || echo "failed to update firefox addons"
|
||||||
nix flake update
|
nix flake update
|
||||||
if [ -z ${SUDO_ASKPASS+x} ]; then
|
#if [ -z ${SUDO_ASKPASS+x} ]; then
|
||||||
sudo nixos-rebuild switch --flake . --option extra-builtins-file "$(pwd)/extra-builtins.nix"
|
# sudo nixos-rebuild switch --flake . --option extra-builtins-file "$(pwd)/extra-builtins.nix"
|
||||||
else
|
#else
|
||||||
sudo -A nixos-rebuild switch --flake . --option extra-builtins-file "$(pwd)/extra-builtins.nix"
|
# sudo -A nixos-rebuild switch --flake . --option extra-builtins-file "$(pwd)/extra-builtins.nix"
|
||||||
fi
|
#fi
|
||||||
home-manager switch --flake . --option extra-builtins-file "$(pwd)/extra-builtins.nix"
|
#home-manager switch --flake . --option extra-builtins-file "$(pwd)/extra-builtins.nix"
|
||||||
|
|
Loading…
Reference in a new issue