feat: stalwart mail-server
This commit is contained in:
parent
85feeb7b3f
commit
a565033341
16 changed files with 1192 additions and 442 deletions
|
|
@ -8,6 +8,7 @@ creation_rules:
|
||||||
key_groups:
|
key_groups:
|
||||||
- age:
|
- age:
|
||||||
- *dn_server
|
- *dn_server
|
||||||
|
- *dn_pre7780
|
||||||
- path_regex: system/dev/dn-pre7780/secret.yaml
|
- path_regex: system/dev/dn-pre7780/secret.yaml
|
||||||
key_groups:
|
key_groups:
|
||||||
- age:
|
- age:
|
||||||
|
|
|
||||||
113
flake.lock
generated
113
flake.lock
generated
|
|
@ -491,6 +491,24 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"flake-parts_4": {
|
"flake-parts_4": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs-lib": "nixpkgs-lib_2"
|
||||||
|
},
|
||||||
|
"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-parts_5": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"nixpkgs-lib": [
|
"nixpkgs-lib": [
|
||||||
"nvf",
|
"nvf",
|
||||||
|
|
@ -511,7 +529,7 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"flake-parts_5": {
|
"flake-parts_6": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"nixpkgs-lib": [
|
"nixpkgs-lib": [
|
||||||
"stylix",
|
"stylix",
|
||||||
|
|
@ -532,6 +550,21 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"flake-root": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1723604017,
|
||||||
|
"narHash": "sha256-rBtQ8gg+Dn4Sx/s+pvjdq3CB2wQNzx9XGFq/JVGCB6k=",
|
||||||
|
"owner": "srid",
|
||||||
|
"repo": "flake-root",
|
||||||
|
"rev": "b759a56851e10cb13f6b8e5698af7b59c44be26e",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "srid",
|
||||||
|
"repo": "flake-root",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
"flake-schemas": {
|
"flake-schemas": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1721999734,
|
"lastModified": 1721999734,
|
||||||
|
|
@ -1405,6 +1438,22 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"marks-nvim": {
|
||||||
|
"flake": false,
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1747179163,
|
||||||
|
"narHash": "sha256-ho2b2Ulh+GTqY0QvW7zjFOSlF5g/kaxWyOjKWhTFq7c=",
|
||||||
|
"owner": "chentoast",
|
||||||
|
"repo": "marks.nvim",
|
||||||
|
"rev": "f353e8c08c50f39e99a9ed474172df7eddd89b72",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "chentoast",
|
||||||
|
"repo": "marks.nvim",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
"microvm": {
|
"microvm": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"flake-utils": "flake-utils_4",
|
"flake-utils": "flake-utils_4",
|
||||||
|
|
@ -1563,6 +1612,29 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"nixd": {
|
||||||
|
"inputs": {
|
||||||
|
"flake-parts": "flake-parts_4",
|
||||||
|
"flake-root": "flake-root",
|
||||||
|
"nixpkgs": [
|
||||||
|
"nixpkgs"
|
||||||
|
],
|
||||||
|
"treefmt-nix": "treefmt-nix_2"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1756563652,
|
||||||
|
"narHash": "sha256-0MvTa6l071JAbePgP3qTkNXr1CbeGDmqyDyvVHxetqg=",
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "nixd",
|
||||||
|
"rev": "15a3376f65de9e7984429b975777f3569430b8a6",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "nixd",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1755027561,
|
"lastModified": 1755027561,
|
||||||
|
|
@ -1594,6 +1666,18 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"nixpkgs-lib_2": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1733096140,
|
||||||
|
"narHash": "sha256-1qRH7uAUsyQI7R1Uwl4T+XvdNv778H0Nb5njNrqvylY=",
|
||||||
|
"type": "tarball",
|
||||||
|
"url": "https://github.com/NixOS/nixpkgs/archive/5487e69da40cbd611ab2cadee0b4637225f7cfae.tar.gz"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"type": "tarball",
|
||||||
|
"url": "https://github.com/NixOS/nixpkgs/archive/5487e69da40cbd611ab2cadee0b4637225f7cfae.tar.gz"
|
||||||
|
}
|
||||||
|
},
|
||||||
"nixpkgs-stable": {
|
"nixpkgs-stable": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1730741070,
|
"lastModified": 1730741070,
|
||||||
|
|
@ -1795,7 +1879,7 @@
|
||||||
"nvf": {
|
"nvf": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"flake-compat": "flake-compat_8",
|
"flake-compat": "flake-compat_8",
|
||||||
"flake-parts": "flake-parts_4",
|
"flake-parts": "flake-parts_5",
|
||||||
"mnw": "mnw",
|
"mnw": "mnw",
|
||||||
"nixpkgs": [
|
"nixpkgs": [
|
||||||
"nixpkgs"
|
"nixpkgs"
|
||||||
|
|
@ -1903,11 +1987,13 @@
|
||||||
"hyprlock": "hyprlock",
|
"hyprlock": "hyprlock",
|
||||||
"hyprtasking": "hyprtasking",
|
"hyprtasking": "hyprtasking",
|
||||||
"lanzaboote": "lanzaboote",
|
"lanzaboote": "lanzaboote",
|
||||||
|
"marks-nvim": "marks-nvim",
|
||||||
"microvm": "microvm",
|
"microvm": "microvm",
|
||||||
"neovim-nightly-overlay": "neovim-nightly-overlay",
|
"neovim-nightly-overlay": "neovim-nightly-overlay",
|
||||||
"nix-index-database": "nix-index-database",
|
"nix-index-database": "nix-index-database",
|
||||||
"nix-minecraft": "nix-minecraft",
|
"nix-minecraft": "nix-minecraft",
|
||||||
"nix-tmodloader": "nix-tmodloader",
|
"nix-tmodloader": "nix-tmodloader",
|
||||||
|
"nixd": "nixd",
|
||||||
"nixpkgs": "nixpkgs_7",
|
"nixpkgs": "nixpkgs_7",
|
||||||
"nvf": "nvf",
|
"nvf": "nvf",
|
||||||
"sops-nix": "sops-nix",
|
"sops-nix": "sops-nix",
|
||||||
|
|
@ -2042,7 +2128,7 @@
|
||||||
"base16-helix": "base16-helix",
|
"base16-helix": "base16-helix",
|
||||||
"base16-vim": "base16-vim",
|
"base16-vim": "base16-vim",
|
||||||
"firefox-gnome-theme": "firefox-gnome-theme",
|
"firefox-gnome-theme": "firefox-gnome-theme",
|
||||||
"flake-parts": "flake-parts_5",
|
"flake-parts": "flake-parts_6",
|
||||||
"gnome-shell": "gnome-shell",
|
"gnome-shell": "gnome-shell",
|
||||||
"nixpkgs": [
|
"nixpkgs": [
|
||||||
"nixpkgs"
|
"nixpkgs"
|
||||||
|
|
@ -2371,6 +2457,27 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"treefmt-nix_2": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": [
|
||||||
|
"nixd",
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1734704479,
|
||||||
|
"narHash": "sha256-MMi74+WckoyEWBRcg/oaGRvXC9BVVxDZNRMpL+72wBI=",
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "treefmt-nix",
|
||||||
|
"rev": "65712f5af67234dad91a5a4baee986a8b62dbf8f",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "treefmt-nix",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
"xdph": {
|
"xdph": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"hyprland-protocols": [
|
"hyprland-protocols": [
|
||||||
|
|
|
||||||
603
flake.nix
603
flake.nix
|
|
@ -117,307 +117,317 @@
|
||||||
url = "github:NotAShelf/nvf";
|
url = "github:NotAShelf/nvf";
|
||||||
inputs.nixpkgs.follows = "nixpkgs";
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
nixd = {
|
||||||
|
url = "github:nix-community/nixd";
|
||||||
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
};
|
||||||
|
|
||||||
|
marks-nvim = {
|
||||||
|
url = "github:chentoast/marks.nvim";
|
||||||
|
flake = false;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
outputs = {
|
outputs =
|
||||||
self,
|
{
|
||||||
nixpkgs,
|
self,
|
||||||
nix-index-database,
|
nixpkgs,
|
||||||
lanzaboote,
|
nix-index-database,
|
||||||
home-manager,
|
lanzaboote,
|
||||||
...
|
home-manager,
|
||||||
} @ inputs: let
|
...
|
||||||
system = "x86_64-linux";
|
}@inputs:
|
||||||
nix-version = "25.05";
|
let
|
||||||
|
system = "x86_64-linux";
|
||||||
|
nix-version = "25.05";
|
||||||
|
|
||||||
pkgs = import nixpkgs {
|
pkgs = import nixpkgs {
|
||||||
inherit system;
|
inherit system;
|
||||||
};
|
|
||||||
|
|
||||||
inherit (pkgs) lib;
|
|
||||||
|
|
||||||
helper = import ./helper {inherit pkgs lib;};
|
|
||||||
|
|
||||||
# Declare COMMON modules here
|
|
||||||
common-settings = {
|
|
||||||
modules = [
|
|
||||||
home-manager.nixosModules.default
|
|
||||||
nix-index-database.nixosModules.nix-index
|
|
||||||
inputs.sops-nix.nixosModules.sops
|
|
||||||
inputs.chaotic.nixosModules.default
|
|
||||||
inputs.actual-budget-api.nixosModules.default
|
|
||||||
inputs.stylix.nixosModules.stylix
|
|
||||||
];
|
|
||||||
args = {
|
|
||||||
inherit
|
|
||||||
helper
|
|
||||||
inputs
|
|
||||||
system
|
|
||||||
nix-version
|
|
||||||
self
|
|
||||||
;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
# Declaring All Devices
|
|
||||||
devices = {
|
|
||||||
# Home Computer
|
|
||||||
dn-pre7780 = {
|
|
||||||
hostname = "dn-pre7780";
|
|
||||||
domain = "net.dn";
|
|
||||||
username = "danny";
|
|
||||||
extra-modules = [
|
|
||||||
lanzaboote.nixosModules.lanzaboote
|
|
||||||
./system/dev/dn-pre7780
|
|
||||||
|
|
||||||
# VM
|
|
||||||
inputs.microvm.nixosModules.host
|
|
||||||
{
|
|
||||||
networking.useNetworkd = true;
|
|
||||||
systemd.network.enable = true;
|
|
||||||
systemd.network.networks."10-lan" = {
|
|
||||||
matchConfig.Name = [
|
|
||||||
"enp0s31f6"
|
|
||||||
"vm-*"
|
|
||||||
];
|
|
||||||
networkConfig = {
|
|
||||||
Bridge = "br0";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
systemd.network.netdevs."br0" = {
|
|
||||||
netdevConfig = {
|
|
||||||
Name = "br0";
|
|
||||||
Kind = "bridge";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
systemd.network.networks."10-lan-bridge" = {
|
|
||||||
matchConfig.Name = "br0";
|
|
||||||
networkConfig = {
|
|
||||||
Address = ["192.168.0.5/24"];
|
|
||||||
Gateway = "192.168.0.1";
|
|
||||||
DNS = ["192.168.0.1"];
|
|
||||||
};
|
|
||||||
|
|
||||||
linkConfig.RequiredForOnline = "routable";
|
|
||||||
};
|
|
||||||
|
|
||||||
microvm.vms = {
|
|
||||||
vm-1 = {
|
|
||||||
flake = self;
|
|
||||||
updateFlake = "git+file:///etc/nixos";
|
|
||||||
autostart = false;
|
|
||||||
};
|
|
||||||
vm-2 = {
|
|
||||||
flake = self;
|
|
||||||
updateFlake = "git+file:///etc/nixos";
|
|
||||||
autostart = false;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
];
|
|
||||||
overlays = [];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
# Laptop
|
inherit (pkgs) lib;
|
||||||
dn-lap = {
|
|
||||||
hostname = "dn-lap";
|
helper = import ./helper { inherit pkgs lib; };
|
||||||
username = "danny";
|
|
||||||
domain = "net.dn";
|
# Declare COMMON modules here
|
||||||
extra-modules = [
|
common-settings = {
|
||||||
lanzaboote.nixosModules.lanzaboote
|
modules = [
|
||||||
./system/dev/dn-lap
|
home-manager.nixosModules.default
|
||||||
];
|
nix-index-database.nixosModules.nix-index
|
||||||
overlays = [
|
inputs.sops-nix.nixosModules.sops
|
||||||
|
inputs.chaotic.nixosModules.default
|
||||||
|
inputs.actual-budget-api.nixosModules.default
|
||||||
|
inputs.stylix.nixosModules.stylix
|
||||||
];
|
];
|
||||||
|
args = {
|
||||||
|
inherit
|
||||||
|
helper
|
||||||
|
inputs
|
||||||
|
system
|
||||||
|
nix-version
|
||||||
|
self
|
||||||
|
;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
# Server
|
# Declaring All Devices
|
||||||
dn-server = {
|
devices = {
|
||||||
hostname = "dn-server";
|
# Home Computer
|
||||||
username = "danny";
|
dn-pre7780 = {
|
||||||
domain = "net.dn";
|
hostname = "dn-pre7780";
|
||||||
extra-modules = [
|
domain = "net.dn";
|
||||||
inputs.nix-minecraft.nixosModules.minecraft-servers
|
username = "danny";
|
||||||
inputs.nix-tmodloader.nixosModules.tmodloader
|
extra-modules = [
|
||||||
./system/dev/dn-server
|
lanzaboote.nixosModules.lanzaboote
|
||||||
./pkgs/options/dovecot.nix
|
./system/dev/dn-pre7780
|
||||||
];
|
|
||||||
overlays = [
|
# VM
|
||||||
inputs.nix-minecraft.overlay
|
inputs.microvm.nixosModules.host
|
||||||
inputs.nix-tmodloader.overlay
|
{
|
||||||
(import ./pkgs/overlays/dovecot.nix)
|
networking.useNetworkd = true;
|
||||||
];
|
systemd.network.enable = true;
|
||||||
|
systemd.network.networks."10-lan" = {
|
||||||
|
matchConfig.Name = [
|
||||||
|
"enp0s31f6"
|
||||||
|
"vm-*"
|
||||||
|
];
|
||||||
|
networkConfig = {
|
||||||
|
Bridge = "br0";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.network.netdevs."br0" = {
|
||||||
|
netdevConfig = {
|
||||||
|
Name = "br0";
|
||||||
|
Kind = "bridge";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.network.networks."10-lan-bridge" = {
|
||||||
|
matchConfig.Name = "br0";
|
||||||
|
networkConfig = {
|
||||||
|
Address = [ "192.168.0.5/24" ];
|
||||||
|
Gateway = "192.168.0.1";
|
||||||
|
DNS = [ "192.168.0.1" ];
|
||||||
|
};
|
||||||
|
|
||||||
|
linkConfig.RequiredForOnline = "routable";
|
||||||
|
};
|
||||||
|
|
||||||
|
microvm.vms = {
|
||||||
|
vm-1 = {
|
||||||
|
flake = self;
|
||||||
|
updateFlake = "git+file:///etc/nixos";
|
||||||
|
autostart = false;
|
||||||
|
};
|
||||||
|
vm-2 = {
|
||||||
|
flake = self;
|
||||||
|
updateFlake = "git+file:///etc/nixos";
|
||||||
|
autostart = false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
];
|
||||||
|
overlays = [ ];
|
||||||
|
};
|
||||||
|
|
||||||
|
# Laptop
|
||||||
|
dn-lap = {
|
||||||
|
hostname = "dn-lap";
|
||||||
|
username = "danny";
|
||||||
|
domain = "net.dn";
|
||||||
|
extra-modules = [
|
||||||
|
lanzaboote.nixosModules.lanzaboote
|
||||||
|
./system/dev/dn-lap
|
||||||
|
];
|
||||||
|
overlays = [
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
# Server
|
||||||
|
dn-server = {
|
||||||
|
hostname = "dn-server";
|
||||||
|
username = "danny";
|
||||||
|
domain = "net.dn";
|
||||||
|
extra-modules = [
|
||||||
|
inputs.nix-minecraft.nixosModules.minecraft-servers
|
||||||
|
inputs.nix-tmodloader.nixosModules.tmodloader
|
||||||
|
./system/dev/dn-server
|
||||||
|
./pkgs/options/dovecot.nix
|
||||||
|
];
|
||||||
|
overlays = [
|
||||||
|
inputs.nix-minecraft.overlay
|
||||||
|
inputs.nix-tmodloader.overlay
|
||||||
|
(import ./pkgs/overlays/dovecot.nix)
|
||||||
|
];
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
in
|
||||||
in {
|
{
|
||||||
nixosConfigurations =
|
nixosConfigurations =
|
||||||
(builtins.mapAttrs (
|
(builtins.mapAttrs (
|
||||||
dev: conf: let
|
dev: conf:
|
||||||
domain =
|
let
|
||||||
if conf.domain != null
|
domain = if conf.domain != null then conf.domain else "local";
|
||||||
then conf.domain
|
|
||||||
else "local";
|
|
||||||
inherit (conf) username hostname;
|
inherit (conf) username hostname;
|
||||||
in
|
in
|
||||||
nixpkgs.lib.nixosSystem {
|
nixpkgs.lib.nixosSystem {
|
||||||
modules =
|
modules = [
|
||||||
[
|
{
|
||||||
{
|
system.stateVersion = nix-version;
|
||||||
system.stateVersion = nix-version;
|
home-manager = {
|
||||||
home-manager = {
|
backupFileExtension = "backup-hm";
|
||||||
backupFileExtension = "backup-hm";
|
useUserPackages = true;
|
||||||
useUserPackages = true;
|
useGlobalPkgs = true;
|
||||||
useGlobalPkgs = true;
|
extraSpecialArgs = {
|
||||||
extraSpecialArgs = {
|
inherit
|
||||||
inherit
|
helper
|
||||||
helper
|
inputs
|
||||||
inputs
|
system
|
||||||
system
|
nix-version
|
||||||
nix-version
|
devices
|
||||||
devices
|
username
|
||||||
username
|
;
|
||||||
;
|
};
|
||||||
};
|
users."${username}" = lib.mkIf (!((conf ? isVM) && (conf.isVM))) {
|
||||||
users."${username}" = lib.mkIf (!((conf ? isVM) && (conf.isVM))) {
|
imports = [
|
||||||
imports = [
|
inputs.hyprland.homeManagerModules.default
|
||||||
inputs.hyprland.homeManagerModules.default
|
inputs.caelestia-shell.homeManagerModules.default
|
||||||
inputs.caelestia-shell.homeManagerModules.default
|
inputs.zen-browser.homeManagerModules.${system}.default
|
||||||
inputs.zen-browser.homeManagerModules.${system}.default
|
inputs.nvf.homeManagerModules.default
|
||||||
inputs.nvf.homeManagerModules.default
|
{
|
||||||
{
|
home = {
|
||||||
home = {
|
homeDirectory = "/home/${username}";
|
||||||
homeDirectory = "/home/${username}";
|
stateVersion = nix-version;
|
||||||
stateVersion = nix-version;
|
};
|
||||||
};
|
# Let Home Manager install and manage itself.
|
||||||
# Let Home Manager install and manage itself.
|
programs.home-manager.enable = true;
|
||||||
programs.home-manager.enable = true;
|
}
|
||||||
}
|
];
|
||||||
];
|
};
|
||||||
};
|
};
|
||||||
};
|
networking = {
|
||||||
networking = {
|
inherit domain;
|
||||||
inherit domain;
|
hostName = hostname;
|
||||||
hostName = hostname;
|
};
|
||||||
};
|
nixpkgs.hostPlatform = system;
|
||||||
nixpkgs.hostPlatform = system;
|
nixpkgs.config.allowUnfree = true;
|
||||||
nixpkgs.config.allowUnfree = true;
|
nixpkgs.overlays = (import ./pkgs/overlays) ++ conf.overlays;
|
||||||
nixpkgs.overlays = (import ./pkgs/overlays) ++ conf.overlays;
|
}
|
||||||
}
|
]
|
||||||
]
|
++ common-settings.modules
|
||||||
++ common-settings.modules
|
++ conf.extra-modules;
|
||||||
++ conf.extra-modules;
|
specialArgs = {
|
||||||
specialArgs =
|
inherit username;
|
||||||
{
|
|
||||||
inherit username;
|
|
||||||
}
|
|
||||||
// common-settings.args;
|
|
||||||
}
|
}
|
||||||
)
|
// common-settings.args;
|
||||||
devices)
|
}
|
||||||
//
|
) devices)
|
||||||
# VM For k8s
|
//
|
||||||
(
|
# VM For k8s
|
||||||
let
|
(
|
||||||
vmList = let
|
let
|
||||||
kubeMasterIP = "192.168.0.6";
|
vmList =
|
||||||
kubeMasterHostname = "api.kube";
|
let
|
||||||
kubeMasterAPIServerPort = 6443;
|
kubeMasterIP = "192.168.0.6";
|
||||||
kubeApi = "https://${kubeMasterHostname}:${toString kubeMasterAPIServerPort}";
|
kubeMasterHostname = "api.kube";
|
||||||
in {
|
kubeMasterAPIServerPort = 6443;
|
||||||
# master
|
kubeApi = "https://${kubeMasterHostname}:${toString kubeMasterAPIServerPort}";
|
||||||
vm-1 = {
|
in
|
||||||
ip = "192.168.0.6";
|
{
|
||||||
mac = "02:00:00:00:00:01";
|
# master
|
||||||
extraConfig = {
|
vm-1 = {
|
||||||
networking.extraHosts = "${kubeMasterIP} ${kubeMasterHostname}";
|
ip = "192.168.0.6";
|
||||||
environment.systemPackages = with pkgs; [
|
mac = "02:00:00:00:00:01";
|
||||||
kompose
|
extraConfig = {
|
||||||
kubectl
|
networking.extraHosts = "${kubeMasterIP} ${kubeMasterHostname}";
|
||||||
kubernetes
|
environment.systemPackages = with pkgs; [
|
||||||
];
|
kompose
|
||||||
|
kubectl
|
||||||
|
kubernetes
|
||||||
|
];
|
||||||
|
|
||||||
services.kubernetes = {
|
services.kubernetes = {
|
||||||
roles = [
|
roles = [
|
||||||
"master"
|
"master"
|
||||||
"node"
|
"node"
|
||||||
];
|
];
|
||||||
|
|
||||||
masterAddress = kubeMasterHostname;
|
masterAddress = kubeMasterHostname;
|
||||||
apiserverAddress = kubeApi;
|
apiserverAddress = kubeApi;
|
||||||
easyCerts = true;
|
easyCerts = true;
|
||||||
apiserver = {
|
apiserver = {
|
||||||
securePort = kubeMasterAPIServerPort;
|
securePort = kubeMasterAPIServerPort;
|
||||||
advertiseAddress = kubeMasterIP;
|
advertiseAddress = kubeMasterIP;
|
||||||
|
};
|
||||||
|
|
||||||
|
addons.dns.enable = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.services.link-kube-config = {
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "oneshot";
|
||||||
|
ExecStart = "${pkgs.writeShellScript "link-kube-config.sh" ''
|
||||||
|
target="/etc/kubernetes/cluster-admin.kubeconfig"
|
||||||
|
if [ -e "$target" ]; then
|
||||||
|
[ ! -d "/root/.kube" ] && mkdir -p "/root/.kube"
|
||||||
|
ln -sf $target /root/.kube/config
|
||||||
|
fi
|
||||||
|
''}";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
# Node
|
||||||
|
vm-2 = {
|
||||||
|
ip = "192.168.0.7";
|
||||||
|
mac = "02:00:00:00:00:02";
|
||||||
|
extraConfig = {
|
||||||
|
networking.extraHosts = "${kubeMasterIP} ${kubeMasterHostname}";
|
||||||
|
|
||||||
addons.dns.enable = true;
|
environment.systemPackages = with pkgs; [
|
||||||
};
|
kompose
|
||||||
|
kubectl
|
||||||
|
kubernetes
|
||||||
|
];
|
||||||
|
|
||||||
systemd.services.link-kube-config = {
|
services.kubernetes = {
|
||||||
wantedBy = ["multi-user.target"];
|
roles = [ "node" ];
|
||||||
serviceConfig = {
|
masterAddress = kubeMasterHostname;
|
||||||
Type = "oneshot";
|
easyCerts = true;
|
||||||
ExecStart = "${pkgs.writeShellScript "link-kube-config.sh" ''
|
|
||||||
target="/etc/kubernetes/cluster-admin.kubeconfig"
|
kubelet.kubeconfig.server = kubeApi;
|
||||||
if [ -e "$target" ]; then
|
apiserverAddress = kubeApi;
|
||||||
[ ! -d "/root/.kube" ] && mkdir -p "/root/.kube"
|
addons.dns.enable = true;
|
||||||
ln -sf $target /root/.kube/config
|
};
|
||||||
fi
|
};
|
||||||
''}";
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
|
||||||
};
|
|
||||||
# Node
|
|
||||||
vm-2 = {
|
|
||||||
ip = "192.168.0.7";
|
|
||||||
mac = "02:00:00:00:00:02";
|
|
||||||
extraConfig = {
|
|
||||||
networking.extraHosts = "${kubeMasterIP} ${kubeMasterHostname}";
|
|
||||||
|
|
||||||
environment.systemPackages = with pkgs; [
|
mkMicrovm = name: value: {
|
||||||
kompose
|
hypervisor = "qemu";
|
||||||
kubectl
|
vcpu = 4;
|
||||||
kubernetes
|
mem = 8192;
|
||||||
|
interfaces = [
|
||||||
|
{
|
||||||
|
type = "tap";
|
||||||
|
id = "${name}";
|
||||||
|
mac = value.mac;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
shares = [
|
||||||
|
{
|
||||||
|
tag = "ro-store";
|
||||||
|
source = "/nix/store";
|
||||||
|
mountPoint = "/nix/.ro-store";
|
||||||
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
services.kubernetes = {
|
|
||||||
roles = ["node"];
|
|
||||||
masterAddress = kubeMasterHostname;
|
|
||||||
easyCerts = true;
|
|
||||||
|
|
||||||
kubelet.kubeconfig.server = kubeApi;
|
|
||||||
apiserverAddress = kubeApi;
|
|
||||||
addons.dns.enable = true;
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
};
|
in
|
||||||
};
|
lib.mapAttrs' (
|
||||||
|
name: value:
|
||||||
mkMicrovm = name: value: {
|
|
||||||
hypervisor = "qemu";
|
|
||||||
vcpu = 4;
|
|
||||||
mem = 8192;
|
|
||||||
interfaces = [
|
|
||||||
{
|
|
||||||
type = "tap";
|
|
||||||
id = "${name}";
|
|
||||||
mac = value.mac;
|
|
||||||
}
|
|
||||||
];
|
|
||||||
shares = [
|
|
||||||
{
|
|
||||||
tag = "ro-store";
|
|
||||||
source = "/nix/store";
|
|
||||||
mountPoint = "/nix/.ro-store";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
in
|
|
||||||
lib.mapAttrs' (
|
|
||||||
name: value:
|
|
||||||
lib.nameValuePair name (
|
lib.nameValuePair name (
|
||||||
nixpkgs.lib.nixosSystem {
|
nixpkgs.lib.nixosSystem {
|
||||||
inherit system;
|
inherit system;
|
||||||
|
|
@ -448,15 +458,15 @@
|
||||||
systemd.network.networks."20-lan" = {
|
systemd.network.networks."20-lan" = {
|
||||||
matchConfig.Type = "ether";
|
matchConfig.Type = "ether";
|
||||||
networkConfig = {
|
networkConfig = {
|
||||||
Address = ["${value.ip}/24"];
|
Address = [ "${value.ip}/24" ];
|
||||||
Gateway = "192.168.0.1";
|
Gateway = "192.168.0.1";
|
||||||
DNS = ["192.168.0.1"];
|
DNS = [ "192.168.0.1" ];
|
||||||
DHCP = "no";
|
DHCP = "no";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
systemd.services.br-netfilter = {
|
systemd.services.br-netfilter = {
|
||||||
wantedBy = ["multi-user.target"];
|
wantedBy = [ "multi-user.target" ];
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
ExecStart = "/run/current-system/sw/bin/modprobe br_netfilter";
|
ExecStart = "/run/current-system/sw/bin/modprobe br_netfilter";
|
||||||
};
|
};
|
||||||
|
|
@ -479,23 +489,22 @@
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
) vmList
|
||||||
)
|
)
|
||||||
vmList
|
// {
|
||||||
)
|
vps = nixpkgs.lib.nixosSystem {
|
||||||
// {
|
inherit system;
|
||||||
vps = nixpkgs.lib.nixosSystem {
|
specialArgs = common-settings.args;
|
||||||
inherit system;
|
modules = [
|
||||||
specialArgs = common-settings.args;
|
inputs.disko.nixosModules.disko
|
||||||
modules = [
|
./system/dev/generic
|
||||||
inputs.disko.nixosModules.disko
|
];
|
||||||
./system/dev/generic
|
};
|
||||||
];
|
|
||||||
};
|
};
|
||||||
};
|
|
||||||
|
|
||||||
packages."${system}" = {
|
packages."${system}" = {
|
||||||
vm-1 = self.nixosConfigurations.vm-1.config.microvm.declaredRunner;
|
vm-1 = self.nixosConfigurations.vm-1.config.microvm.declaredRunner;
|
||||||
vm-2 = self.nixosConfigurations.vm-2.config.microvm.declaredRunner;
|
vm-2 = self.nixosConfigurations.vm-2.config.microvm.declaredRunner;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,11 @@
|
||||||
pkgs,
|
pkgs,
|
||||||
lib,
|
lib,
|
||||||
osConfig,
|
osConfig,
|
||||||
|
inputs,
|
||||||
|
system,
|
||||||
...
|
...
|
||||||
}: let
|
}:
|
||||||
|
let
|
||||||
inherit (lib.generators) mkLuaInline;
|
inherit (lib.generators) mkLuaInline;
|
||||||
|
|
||||||
suda-nvim = pkgs.vimUtils.buildVimPlugin {
|
suda-nvim = pkgs.vimUtils.buildVimPlugin {
|
||||||
|
|
@ -15,7 +18,13 @@
|
||||||
hash = "sha256-46sy3rAdOCULVt1RkIoGdweoV3MqQaB33Et9MrxI6Lk=";
|
hash = "sha256-46sy3rAdOCULVt1RkIoGdweoV3MqQaB33Et9MrxI6Lk=";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
in {
|
|
||||||
|
marks-nvim = pkgs.vimUtils.buildVimPlugin {
|
||||||
|
name = "marks-nvim";
|
||||||
|
src = inputs.marks-nvim;
|
||||||
|
};
|
||||||
|
in
|
||||||
|
{
|
||||||
programs.nvf = {
|
programs.nvf = {
|
||||||
enable = true;
|
enable = true;
|
||||||
settings = {
|
settings = {
|
||||||
|
|
@ -69,6 +78,12 @@ in {
|
||||||
suda = {
|
suda = {
|
||||||
package = suda-nvim;
|
package = suda-nvim;
|
||||||
};
|
};
|
||||||
|
marks = {
|
||||||
|
package = marks-nvim;
|
||||||
|
setup = ''
|
||||||
|
require("marks").setup {}
|
||||||
|
'';
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
keymaps = [
|
keymaps = [
|
||||||
|
|
@ -76,16 +91,16 @@ in {
|
||||||
# Explorer
|
# Explorer
|
||||||
{
|
{
|
||||||
key = "<leader>e";
|
key = "<leader>e";
|
||||||
mode = ["n"];
|
mode = [ "n" ];
|
||||||
action = ":Neotree toggle<CR>";
|
action = ":Neotree toggle<CR>";
|
||||||
silent = true;
|
silent = true;
|
||||||
desc = "Toggle file explorer";
|
desc = "Toggle file explorer";
|
||||||
}
|
}
|
||||||
# Fzf lua
|
# === Fzf lua === #
|
||||||
{
|
{
|
||||||
key = "<Leader><Space>";
|
key = "<Leader><Space>";
|
||||||
silent = true;
|
silent = true;
|
||||||
mode = ["n"];
|
mode = [ "n" ];
|
||||||
action = ":FzfLua files<CR>";
|
action = ":FzfLua files<CR>";
|
||||||
nowait = true;
|
nowait = true;
|
||||||
unique = true;
|
unique = true;
|
||||||
|
|
@ -93,7 +108,7 @@ in {
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
key = "<Leader>/";
|
key = "<Leader>/";
|
||||||
mode = ["n"];
|
mode = [ "n" ];
|
||||||
action = ":FzfLua live_grep<CR>";
|
action = ":FzfLua live_grep<CR>";
|
||||||
nowait = true;
|
nowait = true;
|
||||||
unique = true;
|
unique = true;
|
||||||
|
|
@ -103,7 +118,7 @@ in {
|
||||||
{
|
{
|
||||||
key = "<Leader>ss";
|
key = "<Leader>ss";
|
||||||
silent = true;
|
silent = true;
|
||||||
mode = ["n"];
|
mode = [ "n" ];
|
||||||
action = ":FzfLua lsp_document_symbols<CR>";
|
action = ":FzfLua lsp_document_symbols<CR>";
|
||||||
nowait = true;
|
nowait = true;
|
||||||
unique = true;
|
unique = true;
|
||||||
|
|
@ -113,23 +128,37 @@ in {
|
||||||
{
|
{
|
||||||
key = "<Leader>sS";
|
key = "<Leader>sS";
|
||||||
silent = true;
|
silent = true;
|
||||||
mode = ["n"];
|
mode = [ "n" ];
|
||||||
action = ":FzfLua lsp_workspace_symbols<CR>";
|
action = ":FzfLua lsp_workspace_symbols<CR>";
|
||||||
unique = true;
|
unique = true;
|
||||||
nowait = true;
|
nowait = true;
|
||||||
desc = "Find symbols (workspace)";
|
desc = "Find symbols (workspace)";
|
||||||
}
|
}
|
||||||
|
# Registers
|
||||||
|
{
|
||||||
|
key = ''""'';
|
||||||
|
mode = [ "n" ];
|
||||||
|
action = ":FzfLua registers<CR>";
|
||||||
|
desc = "Registers";
|
||||||
|
}
|
||||||
|
# Marks
|
||||||
|
{
|
||||||
|
key = "''";
|
||||||
|
mode = [ "n" ];
|
||||||
|
action = ":FzfLua marks<CR>";
|
||||||
|
desc = "Marks";
|
||||||
|
}
|
||||||
|
|
||||||
# === Buffer === #
|
# === Buffer === #
|
||||||
{
|
{
|
||||||
key = "<Leader>bo";
|
key = "<Leader>bo";
|
||||||
mode = ["n"];
|
mode = [ "n" ];
|
||||||
action = ":BufferLineCloseOther<CR>";
|
action = ":BufferLineCloseOther<CR>";
|
||||||
desc = "Close other buffer";
|
desc = "Close other buffer";
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
key = "<Leader>bS";
|
key = "<Leader>bS";
|
||||||
mode = ["n"];
|
mode = [ "n" ];
|
||||||
action = ":SudaWrite<CR>";
|
action = ":SudaWrite<CR>";
|
||||||
desc = "Save file as root";
|
desc = "Save file as root";
|
||||||
}
|
}
|
||||||
|
|
@ -148,48 +177,48 @@ in {
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
key = "<S-Tab>";
|
key = "<S-Tab>";
|
||||||
mode = ["i"];
|
mode = [ "i" ];
|
||||||
action = "<C-d>";
|
action = "<C-d>";
|
||||||
desc = "Shift left";
|
desc = "Shift left";
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
key = "gd";
|
key = "gd";
|
||||||
mode = ["n"];
|
mode = [ "n" ];
|
||||||
action = ":FzfLua lsp_definitions<CR>";
|
action = ":FzfLua lsp_definitions<CR>";
|
||||||
nowait = true;
|
nowait = true;
|
||||||
desc = "Go to definition";
|
desc = "Go to definition";
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
key = "gD";
|
key = "gD";
|
||||||
mode = ["n"];
|
mode = [ "n" ];
|
||||||
action = ":FzfLua lsp_declarations<CR>";
|
action = ":FzfLua lsp_declarations<CR>";
|
||||||
nowait = true;
|
nowait = true;
|
||||||
desc = "Go to declaration";
|
desc = "Go to declaration";
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
key = "gi";
|
key = "gi";
|
||||||
mode = ["n"];
|
mode = [ "n" ];
|
||||||
action = ":FzfLua lsp_implementations<CR>";
|
action = ":FzfLua lsp_implementations<CR>";
|
||||||
nowait = true;
|
nowait = true;
|
||||||
desc = "Go to implementation";
|
desc = "Go to implementation";
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
key = "gr";
|
key = "gr";
|
||||||
mode = ["n"];
|
mode = [ "n" ];
|
||||||
action = ":FzfLua lsp_references<CR>";
|
action = ":FzfLua lsp_references<CR>";
|
||||||
nowait = true;
|
nowait = true;
|
||||||
desc = "List references";
|
desc = "List references";
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
key = "<Leader>n";
|
key = "<Leader>n";
|
||||||
mode = ["n"];
|
mode = [ "n" ];
|
||||||
action = ":NoiceAll<CR>";
|
action = ":NoiceAll<CR>";
|
||||||
nowait = true;
|
nowait = true;
|
||||||
desc = "Notifications";
|
desc = "Notifications";
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
key = "<ESC><ESC>";
|
key = "<ESC><ESC>";
|
||||||
mode = ["n"];
|
mode = [ "n" ];
|
||||||
action = ":noh<CR>";
|
action = ":noh<CR>";
|
||||||
desc = "Clear highlight";
|
desc = "Clear highlight";
|
||||||
}
|
}
|
||||||
|
|
@ -197,14 +226,14 @@ in {
|
||||||
# === Tab === #
|
# === Tab === #
|
||||||
{
|
{
|
||||||
key = ">";
|
key = ">";
|
||||||
mode = ["v"];
|
mode = [ "v" ];
|
||||||
action = ">gv";
|
action = ">gv";
|
||||||
silent = true;
|
silent = true;
|
||||||
desc = "Shift right";
|
desc = "Shift right";
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
key = "<";
|
key = "<";
|
||||||
mode = ["v"];
|
mode = [ "v" ];
|
||||||
action = "<gv";
|
action = "<gv";
|
||||||
silent = true;
|
silent = true;
|
||||||
desc = "Shift left";
|
desc = "Shift left";
|
||||||
|
|
@ -213,22 +242,22 @@ in {
|
||||||
# === Terminal === #
|
# === Terminal === #
|
||||||
{
|
{
|
||||||
key = "<C-/>";
|
key = "<C-/>";
|
||||||
mode = ["t"];
|
mode = [ "t" ];
|
||||||
action = "<C-\\><C-n>:ToggleTerm<CR>";
|
action = "<C-\\><C-n>:ToggleTerm<CR>";
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
key = "<C-_>";
|
key = "<C-_>";
|
||||||
mode = ["t"];
|
mode = [ "t" ];
|
||||||
action = "<C-\\><C-n>:ToggleTerm<CR>";
|
action = "<C-\\><C-n>:ToggleTerm<CR>";
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
key = "<C-_>";
|
key = "<C-_>";
|
||||||
mode = ["n"];
|
mode = [ "n" ];
|
||||||
action = ":ToggleTerm<CR>";
|
action = ":ToggleTerm<CR>";
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
key = "<ESC><ESC>";
|
key = "<ESC><ESC>";
|
||||||
mode = ["t"];
|
mode = [ "t" ];
|
||||||
action = "<C-\\><C-n>";
|
action = "<C-\\><C-n>";
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
|
|
@ -270,7 +299,7 @@ in {
|
||||||
# New Term
|
# New Term
|
||||||
{
|
{
|
||||||
key = "<Leader>tn";
|
key = "<Leader>tn";
|
||||||
mode = ["n"];
|
mode = [ "n" ];
|
||||||
action = ":TermNew<CR>";
|
action = ":TermNew<CR>";
|
||||||
nowait = true;
|
nowait = true;
|
||||||
desc = "Spawn new terminal";
|
desc = "Spawn new terminal";
|
||||||
|
|
@ -278,7 +307,7 @@ in {
|
||||||
# Select Term
|
# Select Term
|
||||||
{
|
{
|
||||||
key = "<Leader>tt";
|
key = "<Leader>tt";
|
||||||
mode = ["n"];
|
mode = [ "n" ];
|
||||||
action = ":TermSelect<CR>";
|
action = ":TermSelect<CR>";
|
||||||
nowait = true;
|
nowait = true;
|
||||||
desc = "Select terminal";
|
desc = "Select terminal";
|
||||||
|
|
@ -286,7 +315,7 @@ in {
|
||||||
# Send current selection to Term
|
# Send current selection to Term
|
||||||
{
|
{
|
||||||
key = "<Leader>ts";
|
key = "<Leader>ts";
|
||||||
mode = ["v"];
|
mode = [ "v" ];
|
||||||
action = ":ToggleTermSendVisualSelection<CR>";
|
action = ":ToggleTermSendVisualSelection<CR>";
|
||||||
nowait = true;
|
nowait = true;
|
||||||
desc = "Send current selection to terminal";
|
desc = "Send current selection to terminal";
|
||||||
|
|
@ -295,7 +324,7 @@ in {
|
||||||
# === Fold (nvim-ufo) === #
|
# === Fold (nvim-ufo) === #
|
||||||
{
|
{
|
||||||
key = "zR";
|
key = "zR";
|
||||||
mode = ["n"];
|
mode = [ "n" ];
|
||||||
action = ''
|
action = ''
|
||||||
require("ufo").openAllFolds
|
require("ufo").openAllFolds
|
||||||
'';
|
'';
|
||||||
|
|
@ -303,7 +332,7 @@ in {
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
key = "zM";
|
key = "zM";
|
||||||
mode = ["n"];
|
mode = [ "n" ];
|
||||||
action = ''
|
action = ''
|
||||||
require("ufo").closeAllFolds
|
require("ufo").closeAllFolds
|
||||||
'';
|
'';
|
||||||
|
|
@ -313,29 +342,29 @@ in {
|
||||||
|
|
||||||
autocmds = [
|
autocmds = [
|
||||||
{
|
{
|
||||||
event = ["TextYankPost"];
|
event = [ "TextYankPost" ];
|
||||||
callback =
|
callback =
|
||||||
mkLuaInline
|
mkLuaInline
|
||||||
# lua
|
# lua
|
||||||
''
|
''
|
||||||
function()
|
function()
|
||||||
vim.highlight.on_yank({ higroup = "IncSearch", timeout = 150 })
|
vim.highlight.on_yank({ higroup = "IncSearch", timeout = 150 })
|
||||||
end
|
end
|
||||||
'';
|
'';
|
||||||
desc = "Highlight yanked";
|
desc = "Highlight yanked";
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
event = ["BufWritePost"];
|
event = [ "BufWritePost" ];
|
||||||
callback =
|
callback =
|
||||||
mkLuaInline
|
mkLuaInline
|
||||||
# lua
|
# lua
|
||||||
''
|
''
|
||||||
function(args)
|
function(args)
|
||||||
local bufname = vim.api.nvim_buf_get_name(args.buf)
|
local bufname = vim.api.nvim_buf_get_name(args.buf)
|
||||||
local info = string.format("Saved %s", vim.fn.fnamemodify(bufname, ":t"))
|
local info = string.format("Saved %s", vim.fn.fnamemodify(bufname, ":t"))
|
||||||
require("fidget").notify(info, vim.log.levels.INFO)
|
require("fidget").notify(info, vim.log.levels.INFO)
|
||||||
end
|
end
|
||||||
'';
|
'';
|
||||||
desc = "Fidget notify file saved";
|
desc = "Fidget notify file saved";
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
@ -391,12 +420,12 @@ in {
|
||||||
};
|
};
|
||||||
virtual_text.format =
|
virtual_text.format =
|
||||||
mkLuaInline
|
mkLuaInline
|
||||||
# lua
|
# lua
|
||||||
''
|
''
|
||||||
function(diagnostic)
|
function(diagnostic)
|
||||||
return string.format("%s (%s)", diagnostic.message, diagnostic.source)
|
return string.format("%s (%s)", diagnostic.message, diagnostic.source)
|
||||||
end
|
end
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -427,17 +456,21 @@ in {
|
||||||
};
|
};
|
||||||
nix = {
|
nix = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
extraDiagnostics.enable = false;
|
||||||
format.type = "nixfmt";
|
format.type = "nixfmt";
|
||||||
lsp = {
|
lsp = {
|
||||||
server = "nixd";
|
server = "nil";
|
||||||
options = {
|
options = {
|
||||||
nixos.expr =
|
nix.flake.autoArchive = true;
|
||||||
# nix
|
|
||||||
''(builtins.getFlake (builtins.toString ./.)).nixosConfigurations.${osConfig.networking.hostName}.options'';
|
|
||||||
home_manager.expr =
|
|
||||||
# nix
|
|
||||||
''(builtins.getFlake (builtins.toString ./.)).nixosConfigurations.${osConfig.networking.hostName}.options.home-manager.users.type.getSubOptions []'';
|
|
||||||
};
|
};
|
||||||
|
# options = {
|
||||||
|
# nixos.expr =
|
||||||
|
# # nix
|
||||||
|
# ''(builtins.getFlake (builtins.toString ./.)).nixosConfigurations.${osConfig.networking.hostName}.options'';
|
||||||
|
# home_manager.expr =
|
||||||
|
# # nix
|
||||||
|
# ''(builtins.getFlake (builtins.toString ./.)).nixosConfigurations.${osConfig.networking.hostName}.options.home-manager.users.type.getSubOptions []'';
|
||||||
|
# };
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
sql.enable = true;
|
sql.enable = true;
|
||||||
|
|
@ -450,7 +483,12 @@ in {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
python.enable = true;
|
python.enable = true;
|
||||||
markdown.enable = true;
|
markdown = {
|
||||||
|
enable = true;
|
||||||
|
extensions = {
|
||||||
|
render-markdown-nvim.enable = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
html.enable = true;
|
html.enable = true;
|
||||||
lua.enable = true;
|
lua.enable = true;
|
||||||
};
|
};
|
||||||
|
|
@ -667,7 +705,7 @@ in {
|
||||||
|
|
||||||
snippets.luasnip = {
|
snippets.luasnip = {
|
||||||
enable = true;
|
enable = true;
|
||||||
providers = ["blink-cmp"];
|
providers = [ "blink-cmp" ];
|
||||||
setupOpts.enable_autosnippets = true;
|
setupOpts.enable_autosnippets = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -716,7 +754,85 @@ in {
|
||||||
whichKey.enable = true;
|
whichKey.enable = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
fzf-lua.enable = true;
|
fzf-lua = {
|
||||||
|
enable = true;
|
||||||
|
setupOpts = {
|
||||||
|
previewers = {
|
||||||
|
builtin = {
|
||||||
|
extensions = {
|
||||||
|
"jpg" = {
|
||||||
|
"kitty" = "";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
snacks_image = {
|
||||||
|
enabled = false;
|
||||||
|
render_inline = false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
winopts = {
|
||||||
|
preview = {
|
||||||
|
hidden = "hidden";
|
||||||
|
};
|
||||||
|
border = "rounded";
|
||||||
|
};
|
||||||
|
fzf_opts = {
|
||||||
|
"--no-header" = "";
|
||||||
|
"--no-scrollbar" = "";
|
||||||
|
};
|
||||||
|
files = {
|
||||||
|
formatter = "path.filename_first";
|
||||||
|
prompt = ":";
|
||||||
|
no_header = true;
|
||||||
|
cwd_header = false;
|
||||||
|
cwd_prompt = false;
|
||||||
|
winopts = {
|
||||||
|
title = " files 📑 ";
|
||||||
|
title_pos = "center";
|
||||||
|
title_flags = false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
buffers = {
|
||||||
|
formatter = "path.filename_first";
|
||||||
|
prompt = ":";
|
||||||
|
no_header = true;
|
||||||
|
fzf_opts = {
|
||||||
|
"--delimiter" = " ";
|
||||||
|
"--with-nth" = "-1..";
|
||||||
|
};
|
||||||
|
winopts = {
|
||||||
|
title = " buffers 📝 ";
|
||||||
|
title_pos = "center";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
lsp = {
|
||||||
|
symbols = {
|
||||||
|
cwd_only = true;
|
||||||
|
no_header = true;
|
||||||
|
prompt = ":";
|
||||||
|
winopts = {
|
||||||
|
title = " symbols ✨ ";
|
||||||
|
title_pos = "center";
|
||||||
|
height = 0.6;
|
||||||
|
preview = {
|
||||||
|
hidden = "nohidden";
|
||||||
|
horizontal = "down:40%";
|
||||||
|
wrap = "wrap";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
registers = {
|
||||||
|
prompt = "registers:";
|
||||||
|
filter = "%a";
|
||||||
|
winopts = {
|
||||||
|
title = " registers 🏷️ ";
|
||||||
|
title_pos = "center";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
dashboard = {
|
dashboard = {
|
||||||
alpha.enable = true;
|
alpha.enable = true;
|
||||||
|
|
@ -745,7 +861,12 @@ in {
|
||||||
};
|
};
|
||||||
|
|
||||||
images = {
|
images = {
|
||||||
img-clip.enable = true;
|
image-nvim = {
|
||||||
|
enable = true;
|
||||||
|
setupOpts = {
|
||||||
|
backend = "kitty";
|
||||||
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -762,12 +883,12 @@ in {
|
||||||
};
|
};
|
||||||
setupOpts.winbar.name_formatter =
|
setupOpts.winbar.name_formatter =
|
||||||
mkLuaInline
|
mkLuaInline
|
||||||
# lua
|
# lua
|
||||||
''
|
''
|
||||||
function(term)
|
function(term)
|
||||||
return " " .. term.id
|
return " " .. term.id
|
||||||
end
|
end
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -782,7 +903,7 @@ in {
|
||||||
event = "notify";
|
event = "notify";
|
||||||
kind = "info";
|
kind = "info";
|
||||||
any = [
|
any = [
|
||||||
{find = "hidden";}
|
{ find = "hidden"; }
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -800,7 +921,7 @@ in {
|
||||||
filter = {
|
filter = {
|
||||||
event = "msg_show";
|
event = "msg_show";
|
||||||
any = [
|
any = [
|
||||||
{find = "written";}
|
{ find = "written"; }
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -814,45 +935,45 @@ in {
|
||||||
setupOpts = {
|
setupOpts = {
|
||||||
fold_virt_text_handler =
|
fold_virt_text_handler =
|
||||||
mkLuaInline
|
mkLuaInline
|
||||||
# lua
|
# lua
|
||||||
''
|
''
|
||||||
function(virtText, lnum, endLnum, width, truncate)
|
function(virtText, lnum, endLnum, width, truncate)
|
||||||
local newVirtText = {}
|
local newVirtText = {}
|
||||||
local suffix = (' %d '):format(endLnum - lnum)
|
local suffix = (' %d '):format(endLnum - lnum)
|
||||||
local sufWidth = vim.fn.strdisplaywidth(suffix)
|
local sufWidth = vim.fn.strdisplaywidth(suffix)
|
||||||
local targetWidth = width - sufWidth
|
local targetWidth = width - sufWidth
|
||||||
local curWidth = 0
|
local curWidth = 0
|
||||||
for _, chunk in ipairs(virtText) do
|
for _, chunk in ipairs(virtText) do
|
||||||
local chunkText = chunk[1]
|
local chunkText = chunk[1]
|
||||||
local chunkWidth = vim.fn.strdisplaywidth(chunkText)
|
local chunkWidth = vim.fn.strdisplaywidth(chunkText)
|
||||||
if targetWidth > curWidth + chunkWidth then
|
if targetWidth > curWidth + chunkWidth then
|
||||||
table.insert(newVirtText, chunk)
|
table.insert(newVirtText, chunk)
|
||||||
else
|
else
|
||||||
chunkText = truncate(chunkText, targetWidth - curWidth)
|
chunkText = truncate(chunkText, targetWidth - curWidth)
|
||||||
local hlGroup = chunk[2]
|
local hlGroup = chunk[2]
|
||||||
table.insert(newVirtText, {chunkText, hlGroup})
|
table.insert(newVirtText, {chunkText, hlGroup})
|
||||||
chunkWidth = vim.fn.strdisplaywidth(chunkText)
|
chunkWidth = vim.fn.strdisplaywidth(chunkText)
|
||||||
-- str width returned from truncate() may less than 2nd argument, need padding
|
-- str width returned from truncate() may less than 2nd argument, need padding
|
||||||
if curWidth + chunkWidth < targetWidth then
|
if curWidth + chunkWidth < targetWidth then
|
||||||
suffix = suffix .. (' '):rep(targetWidth - curWidth - chunkWidth)
|
suffix = suffix .. (' '):rep(targetWidth - curWidth - chunkWidth)
|
||||||
end
|
end
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
curWidth = curWidth + chunkWidth
|
curWidth = curWidth + chunkWidth
|
||||||
end
|
end
|
||||||
table.insert(newVirtText, {suffix, 'MoreMsg'})
|
table.insert(newVirtText, {suffix, 'MoreMsg'})
|
||||||
return newVirtText
|
return newVirtText
|
||||||
end
|
end
|
||||||
'';
|
'';
|
||||||
|
|
||||||
provider_selector =
|
provider_selector =
|
||||||
mkLuaInline
|
mkLuaInline
|
||||||
# lua
|
# lua
|
||||||
''
|
''
|
||||||
function(bufnr, filetype, buftype)
|
function(bufnr, filetype, buftype)
|
||||||
return {'treesitter', 'indent'}
|
return {'treesitter', 'indent'}
|
||||||
end
|
end
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
borders = {
|
borders = {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
[
|
[
|
||||||
(import ./vesktop.nix)
|
(import ./vesktop.nix)
|
||||||
(import ./powerdns-admin.nix)
|
(import ./powerdns-admin.nix)
|
||||||
|
(import ./stalwart-mail)
|
||||||
]
|
]
|
||||||
|
|
|
||||||
7
pkgs/overlays/stalwart-mail/default.nix
Normal file
7
pkgs/overlays/stalwart-mail/default.nix
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
final: prev: {
|
||||||
|
stalwart-mail = prev.stalwart-mail.overrideAttrs (oldAttrs: {
|
||||||
|
patches = [
|
||||||
|
./enable_root_ca.patch
|
||||||
|
];
|
||||||
|
});
|
||||||
|
}
|
||||||
291
pkgs/overlays/stalwart-mail/enable_root_ca.patch
Normal file
291
pkgs/overlays/stalwart-mail/enable_root_ca.patch
Normal file
|
|
@ -0,0 +1,291 @@
|
||||||
|
diff --git a/crates/common/src/config/server/tls.rs b/crates/common/src/config/server/tls.rs
|
||||||
|
index 603cf889..58e38c84 100644
|
||||||
|
--- a/crates/common/src/config/server/tls.rs
|
||||||
|
+++ b/crates/common/src/config/server/tls.rs
|
||||||
|
@@ -5,7 +5,7 @@
|
||||||
|
*/
|
||||||
|
|
||||||
|
use std::{
|
||||||
|
- io::Cursor,
|
||||||
|
+ io::{Cursor, Read},
|
||||||
|
net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr},
|
||||||
|
sync::Arc,
|
||||||
|
time::Duration,
|
||||||
|
@@ -35,7 +35,8 @@ use x509_parser::{
|
||||||
|
|
||||||
|
use crate::listener::{
|
||||||
|
acme::{
|
||||||
|
- AcmeProvider, ChallengeSettings, EabSettings, directory::LETS_ENCRYPT_PRODUCTION_DIRECTORY,
|
||||||
|
+ AcmeProvider, ChallengeSettings, EabSettings,
|
||||||
|
+ directory::{CABundle, LETS_ENCRYPT_PRODUCTION_DIRECTORY},
|
||||||
|
},
|
||||||
|
tls::AcmeProviders,
|
||||||
|
};
|
||||||
|
@@ -66,6 +67,31 @@ impl AcmeProviders {
|
||||||
|
.property_or_default(("acme", acme_id, "renew-before"), "30d")
|
||||||
|
.unwrap_or_else(|| Duration::from_secs(30 * 24 * 60 * 60));
|
||||||
|
|
||||||
|
+ let ca_bundle: CABundle = config
|
||||||
|
+ .value(("acme", acme_id, "ca_bundle"))
|
||||||
|
+ .map(|s| s.to_string())
|
||||||
|
+ .and_then(|path| {
|
||||||
|
+ let buf = std::fs::read(&path)
|
||||||
|
+ .map_err(|err| {
|
||||||
|
+ config.new_parse_error(
|
||||||
|
+ format!("acme.{acme_id}.ca_bundle"),
|
||||||
|
+ err.to_string(),
|
||||||
|
+ );
|
||||||
|
+ })
|
||||||
|
+ .ok()?;
|
||||||
|
+
|
||||||
|
+ reqwest::Certificate::from_pem_bundle(&buf)
|
||||||
|
+ .map_err(|err| {
|
||||||
|
+ config.new_parse_error(
|
||||||
|
+ format!("acme.{acme_id}.ca_bundle"),
|
||||||
|
+ err.to_string(),
|
||||||
|
+ );
|
||||||
|
+
|
||||||
|
+ err
|
||||||
|
+ })
|
||||||
|
+ .ok()
|
||||||
|
+ });
|
||||||
|
+
|
||||||
|
if directory.is_empty() {
|
||||||
|
config.new_parse_error(format!("acme.{acme_id}.directory"), "Missing property");
|
||||||
|
continue;
|
||||||
|
@@ -167,6 +193,7 @@ impl AcmeProviders {
|
||||||
|
contact,
|
||||||
|
challenge,
|
||||||
|
eab,
|
||||||
|
+ ca_bundle,
|
||||||
|
renew_before,
|
||||||
|
default,
|
||||||
|
) {
|
||||||
|
@@ -304,7 +331,7 @@ fn build_dns_updater(config: &mut Config, acme_id: &str) -> Option<DnsUpdater> {
|
||||||
|
.map_err(|err| {
|
||||||
|
config.new_build_error(
|
||||||
|
("acme", acme_id, "provider"),
|
||||||
|
- format!("Failed to create Desec DNS updater: {err}"),
|
||||||
|
+ format!("Failed to create OVH DNS updater: {err}"),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.ok(),
|
||||||
|
diff --git a/crates/common/src/listener/acme/directory.rs b/crates/common/src/listener/acme/directory.rs
|
||||||
|
index 21640cd6..bbefd7aa 100644
|
||||||
|
--- a/crates/common/src/listener/acme/directory.rs
|
||||||
|
+++ b/crates/common/src/listener/acme/directory.rs
|
||||||
|
@@ -20,6 +20,8 @@ use store::write::Archiver;
|
||||||
|
use trc::AddContext;
|
||||||
|
use trc::event::conv::AssertSuccess;
|
||||||
|
|
||||||
|
+pub type CABundle = Option<Vec<reqwest::Certificate>>;
|
||||||
|
+
|
||||||
|
pub const LETS_ENCRYPT_STAGING_DIRECTORY: &str =
|
||||||
|
"https://acme-staging-v02.api.letsencrypt.org/directory";
|
||||||
|
pub const LETS_ENCRYPT_PRODUCTION_DIRECTORY: &str =
|
||||||
|
@@ -31,6 +33,7 @@ pub struct Account {
|
||||||
|
pub key_pair: EcdsaKeyPair,
|
||||||
|
pub directory: Directory,
|
||||||
|
pub kid: String,
|
||||||
|
+ pub ca_bundle: CABundle,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, serde::Serialize)]
|
||||||
|
@@ -89,16 +92,23 @@ impl Account {
|
||||||
|
let body = sign(
|
||||||
|
&key_pair,
|
||||||
|
None,
|
||||||
|
- directory.nonce().await?,
|
||||||
|
+ directory.nonce(&provider.ca_bundle).await?,
|
||||||
|
&directory.new_account,
|
||||||
|
&payload,
|
||||||
|
)?;
|
||||||
|
- let response = https(&directory.new_account, Method::POST, Some(body)).await?;
|
||||||
|
+ let response = https(
|
||||||
|
+ &directory.new_account,
|
||||||
|
+ Method::POST,
|
||||||
|
+ Some(body),
|
||||||
|
+ &provider.ca_bundle,
|
||||||
|
+ )
|
||||||
|
+ .await?;
|
||||||
|
let kid = get_header(&response, "Location")?;
|
||||||
|
Ok(Account {
|
||||||
|
key_pair,
|
||||||
|
kid,
|
||||||
|
directory,
|
||||||
|
+ ca_bundle: provider.ca_bundle.clone(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -106,15 +116,16 @@ impl Account {
|
||||||
|
&self,
|
||||||
|
url: impl AsRef<str>,
|
||||||
|
payload: &str,
|
||||||
|
+ ca_bundle: &CABundle,
|
||||||
|
) -> trc::Result<(Option<String>, String)> {
|
||||||
|
let body = sign(
|
||||||
|
&self.key_pair,
|
||||||
|
Some(&self.kid),
|
||||||
|
- self.directory.nonce().await?,
|
||||||
|
+ self.directory.nonce(ca_bundle).await?,
|
||||||
|
url.as_ref(),
|
||||||
|
payload,
|
||||||
|
)?;
|
||||||
|
- let response = https(url.as_ref(), Method::POST, Some(body)).await?;
|
||||||
|
+ let response = https(url.as_ref(), Method::POST, Some(body), ca_bundle).await?;
|
||||||
|
let location = get_header(&response, "Location").ok();
|
||||||
|
let body = response
|
||||||
|
.text()
|
||||||
|
@@ -130,7 +141,9 @@ impl Account {
|
||||||
|
serde_json::to_string(&domains)
|
||||||
|
.map_err(|err| trc::EventType::Acme(trc::AcmeEvent::Error).from_json_error(err))?
|
||||||
|
);
|
||||||
|
- let response = self.request(&self.directory.new_order, &payload).await?;
|
||||||
|
+ let response = self
|
||||||
|
+ .request(&self.directory.new_order, &payload, &self.ca_bundle)
|
||||||
|
+ .await?;
|
||||||
|
let url = response.0.ok_or(
|
||||||
|
trc::EventType::Acme(trc::AcmeEvent::Error)
|
||||||
|
.caused_by(trc::location!())
|
||||||
|
@@ -143,30 +156,30 @@ impl Account {
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn auth(&self, url: impl AsRef<str>) -> trc::Result<Auth> {
|
||||||
|
- let response = self.request(url, "").await?;
|
||||||
|
+ let response = self.request(url, "", &self.ca_bundle).await?;
|
||||||
|
serde_json::from_str(&response.1)
|
||||||
|
.map_err(|err| trc::EventType::Acme(trc::AcmeEvent::Error).from_json_error(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn challenge(&self, url: impl AsRef<str>) -> trc::Result<()> {
|
||||||
|
- self.request(&url, "{}").await.map(|_| ())
|
||||||
|
+ self.request(&url, "{}", &self.ca_bundle).await.map(|_| ())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn order(&self, url: impl AsRef<str>) -> trc::Result<Order> {
|
||||||
|
- let response = self.request(&url, "").await?;
|
||||||
|
+ let response = self.request(&url, "", &self.ca_bundle).await?;
|
||||||
|
serde_json::from_str(&response.1)
|
||||||
|
.map_err(|err| trc::EventType::Acme(trc::AcmeEvent::Error).from_json_error(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn finalize(&self, url: impl AsRef<str>, csr: Vec<u8>) -> trc::Result<Order> {
|
||||||
|
let payload = format!("{{\"csr\":\"{}\"}}", URL_SAFE_NO_PAD.encode(csr));
|
||||||
|
- let response = self.request(&url, &payload).await?;
|
||||||
|
+ let response = self.request(&url, &payload, &self.ca_bundle).await?;
|
||||||
|
serde_json::from_str(&response.1)
|
||||||
|
.map_err(|err| trc::EventType::Acme(trc::AcmeEvent::Error).from_json_error(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn certificate(&self, url: impl AsRef<str>) -> trc::Result<String> {
|
||||||
|
- Ok(self.request(&url, "").await?.1)
|
||||||
|
+ Ok(self.request(&url, "", &self.ca_bundle).await?.1)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn http_proof(&self, challenge: &Challenge) -> trc::Result<Vec<u8>> {
|
||||||
|
@@ -218,9 +231,9 @@ pub struct Directory {
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Directory {
|
||||||
|
- pub async fn discover(url: impl AsRef<str>) -> trc::Result<Self> {
|
||||||
|
+ pub async fn discover(url: impl AsRef<str>, ca_bundle: &CABundle) -> trc::Result<Self> {
|
||||||
|
serde_json::from_str(
|
||||||
|
- &https(url, Method::GET, None)
|
||||||
|
+ &https(url, Method::GET, None, ca_bundle)
|
||||||
|
.await?
|
||||||
|
.text()
|
||||||
|
.await
|
||||||
|
@@ -228,9 +241,9 @@ impl Directory {
|
||||||
|
)
|
||||||
|
.map_err(|err| trc::EventType::Acme(trc::AcmeEvent::Error).from_json_error(err))
|
||||||
|
}
|
||||||
|
- pub async fn nonce(&self) -> trc::Result<String> {
|
||||||
|
+ pub async fn nonce(&self, ca_bundle: &CABundle) -> trc::Result<String> {
|
||||||
|
get_header(
|
||||||
|
- &https(&self.new_nonce.as_str(), Method::HEAD, None).await?,
|
||||||
|
+ &https(&self.new_nonce.as_str(), Method::HEAD, None, ca_bundle).await?,
|
||||||
|
"replay-nonce",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
@@ -316,6 +329,7 @@ async fn https(
|
||||||
|
url: impl AsRef<str>,
|
||||||
|
method: Method,
|
||||||
|
body: Option<String>,
|
||||||
|
+ ca_bundle: &CABundle,
|
||||||
|
) -> trc::Result<Response> {
|
||||||
|
let url = url.as_ref();
|
||||||
|
let mut builder = reqwest::Client::builder()
|
||||||
|
@@ -329,6 +343,15 @@ async fn https(
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ match ca_bundle {
|
||||||
|
+ Some(certs) => {
|
||||||
|
+ for cert in certs {
|
||||||
|
+ builder = builder.add_root_certificate(cert.clone());
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ None => {}
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
let mut request = builder
|
||||||
|
.build()
|
||||||
|
.map_err(|err| trc::EventType::Acme(trc::AcmeEvent::Error).from_http_error(err))?
|
||||||
|
diff --git a/crates/common/src/listener/acme/mod.rs b/crates/common/src/listener/acme/mod.rs
|
||||||
|
index a6d9b978..2674dd3a 100644
|
||||||
|
--- a/crates/common/src/listener/acme/mod.rs
|
||||||
|
+++ b/crates/common/src/listener/acme/mod.rs
|
||||||
|
@@ -16,7 +16,7 @@ use arc_swap::ArcSwap;
|
||||||
|
use dns_update::DnsUpdater;
|
||||||
|
use rustls::sign::CertifiedKey;
|
||||||
|
|
||||||
|
-use crate::Server;
|
||||||
|
+use crate::{Server, listener::acme::directory::CABundle};
|
||||||
|
|
||||||
|
use self::directory::{Account, ChallengeType};
|
||||||
|
|
||||||
|
@@ -27,6 +27,7 @@ pub struct AcmeProvider {
|
||||||
|
pub contact: Vec<String>,
|
||||||
|
pub challenge: ChallengeSettings,
|
||||||
|
pub eab: Option<EabSettings>,
|
||||||
|
+ pub ca_bundle: CABundle,
|
||||||
|
renew_before: chrono::Duration,
|
||||||
|
account_key: ArcSwap<Vec<u8>>,
|
||||||
|
default: bool,
|
||||||
|
@@ -64,6 +65,7 @@ impl AcmeProvider {
|
||||||
|
contact: Vec<String>,
|
||||||
|
challenge: ChallengeSettings,
|
||||||
|
eab: Option<EabSettings>,
|
||||||
|
+ ca_bundle: CABundle,
|
||||||
|
renew_before: Duration,
|
||||||
|
default: bool,
|
||||||
|
) -> trc::Result<Self> {
|
||||||
|
@@ -85,6 +87,7 @@ impl AcmeProvider {
|
||||||
|
account_key: Default::default(),
|
||||||
|
challenge,
|
||||||
|
eab,
|
||||||
|
+ ca_bundle,
|
||||||
|
default,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
@@ -153,6 +156,7 @@ impl Clone for AcmeProvider {
|
||||||
|
renew_before: self.renew_before,
|
||||||
|
account_key: ArcSwap::from_pointee(self.account_key.load().as_ref().clone()),
|
||||||
|
eab: self.eab.clone(),
|
||||||
|
+ ca_bundle: self.ca_bundle.clone(),
|
||||||
|
default: self.default,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
diff --git a/crates/common/src/listener/acme/order.rs b/crates/common/src/listener/acme/order.rs
|
||||||
|
index 6def86a4..8ba3b185 100644
|
||||||
|
--- a/crates/common/src/listener/acme/order.rs
|
||||||
|
+++ b/crates/common/src/listener/acme/order.rs
|
||||||
|
@@ -85,7 +85,7 @@ impl Server {
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn order(&self, provider: &AcmeProvider) -> trc::Result<Vec<u8>> {
|
||||||
|
- let directory = Directory::discover(&provider.directory_url).await?;
|
||||||
|
+ let directory = Directory::discover(&provider.directory_url, &provider.ca_bundle).await?;
|
||||||
|
let account = Account::create_with_keypair(directory, provider).await?;
|
||||||
|
|
||||||
|
let mut params = CertificateParams::new(provider.domains.clone());
|
||||||
|
|
@ -59,6 +59,33 @@ in
|
||||||
];
|
];
|
||||||
})
|
})
|
||||||
|
|
||||||
|
(import ../../modules/stalwart.nix {
|
||||||
|
enableNginx = true;
|
||||||
|
domain = "pre7780.dn";
|
||||||
|
adminPassFile = config.sops.secrets."stalwart/adminPassword".path;
|
||||||
|
dbPassFile = config.sops.secrets."stalwart/db".path;
|
||||||
|
acmeConf = {
|
||||||
|
directory = "https://ca.net.dn/acme/acme/directory";
|
||||||
|
ca_bundle = "${"" + ../../extra/ca.crt}";
|
||||||
|
challenge = "dns-01";
|
||||||
|
origin = "pre7780.dn";
|
||||||
|
contact = "admin@pre7780.dn";
|
||||||
|
domains = [
|
||||||
|
"pre7780.dn"
|
||||||
|
"mx1.pre7780.dn"
|
||||||
|
];
|
||||||
|
default = true;
|
||||||
|
provider = "rfc2136-tsig";
|
||||||
|
host = "10.0.0.1";
|
||||||
|
renew-before = "1d";
|
||||||
|
port = 5359;
|
||||||
|
cache = "${config.services.stalwart-mail.dataDir}/acme";
|
||||||
|
key = "stalwart";
|
||||||
|
tsig-algorithm = "hmac-sha512";
|
||||||
|
secret = "%{file:${config.sops.secrets."stalwart/tsig".path}}%";
|
||||||
|
};
|
||||||
|
})
|
||||||
|
|
||||||
../../modules/davinci-resolve.nix
|
../../modules/davinci-resolve.nix
|
||||||
../../modules/webcam.nix
|
../../modules/webcam.nix
|
||||||
../../modules/postgresql.nix
|
../../modules/postgresql.nix
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,20 @@
|
||||||
{ ... }:
|
{ config, ... }:
|
||||||
{
|
{
|
||||||
|
networking.firewall.allowedTCPPorts = [
|
||||||
|
443
|
||||||
|
80
|
||||||
|
];
|
||||||
|
|
||||||
security.acme = {
|
security.acme = {
|
||||||
acceptTerms = true;
|
acceptTerms = true;
|
||||||
defaults = {
|
defaults = {
|
||||||
validMinDays = 2;
|
validMinDays = 2;
|
||||||
server = "https://10.0.0.1:${toString 8443}/acme/acme/directory";
|
server = "https://ca.net.dn/acme/acme/directory";
|
||||||
renewInterval = "daily";
|
renewInterval = "daily";
|
||||||
email = "danny@net.dn";
|
email = "danny@net.dn";
|
||||||
webroot = "/var/lib/acme/acme-challenge";
|
dnsProvider = "pdns";
|
||||||
|
dnsPropagationCheck = false;
|
||||||
|
environmentFile = config.sops.secrets."acme/pdns".path;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,12 @@ openldap:
|
||||||
adminPassword: ENC[AES256_GCM,data:jEGuzgs5QTWfdyJenC3t3g==,iv:StfFOcvbDapnma6eAlpaGiBWnqiD3I/wfQsMBzufol0=,tag:892q7N4KrsSQoZYGy6CQrA==,type:str]
|
adminPassword: ENC[AES256_GCM,data:jEGuzgs5QTWfdyJenC3t3g==,iv:StfFOcvbDapnma6eAlpaGiBWnqiD3I/wfQsMBzufol0=,tag:892q7N4KrsSQoZYGy6CQrA==,type:str]
|
||||||
lam:
|
lam:
|
||||||
env: ENC[AES256_GCM,data:f1LlC/VvilH8o2Ra7MrSHsMEGlGw3LOV2O9JJf9f,iv:u7cXM8n3jJeLBfxXtA0QMyijBqTcC+yJeW/OO9JuZMI=,tag:QL5FkcCPI5Gxudi0NmCZWg==,type:str]
|
env: ENC[AES256_GCM,data:f1LlC/VvilH8o2Ra7MrSHsMEGlGw3LOV2O9JJf9f,iv:u7cXM8n3jJeLBfxXtA0QMyijBqTcC+yJeW/OO9JuZMI=,tag:QL5FkcCPI5Gxudi0NmCZWg==,type:str]
|
||||||
|
stalwart:
|
||||||
|
adminPassword: ENC[AES256_GCM,data:6tUL7b2s3gLtF4Ors9CgYQ==,iv:9UQowgXKr9HR/poELP6SZijp3c2HVTHzEfwf1tZI/3w=,tag:KIOiYEwLsZLH31E2Xb478A==,type:str]
|
||||||
|
tsig: ENC[AES256_GCM,data:wxsM/dbkW2fNf86b6TsLRNAce19h7mBEuSzFT84aIlaVZA/S29g1U4/CAwD4b+h/XfBgpZQCJf/9yT3yo6dbGAIAk5UgjV2cNY9pO1/uF1T6xoKDgfRZxA==,iv:9BvP8vQkTTEaNgYUPfQcfEMcWqDyD045EPBr7NyHmO4=,tag:coBBAe62kpe/L0S6V8NhXg==,type:str]
|
||||||
|
db: ENC[AES256_GCM,data:ZRZ2ZzUotYMe2GfkMS7o7dz0aGg=,iv:ys6ogueueESp0y6A+hUG9zTnqmCVobuIzyqA4WVtewo=,tag:p74G+8XhMcpgDnIfh1aXTg==,type:str]
|
||||||
|
acme:
|
||||||
|
pdns: ENC[AES256_GCM,data:+InGSnaGIFVtDRlVltzWbZfquzodHUQrPeMRBnVNB9mrajlKr5dFK6DD8dXAvN7UjZFBfrgZefOPkmLR2ncLXGOV2Kl7jorVw50Y0f0iKl7mqwHaZKaQdk7cpGDkCrt/LvfbP9x7gVrs6pQpsU+c/P5rbBLRyejchh/WtiyzgowYIJxYohggeG09+l7YI3FR6U5wiymIRISpNBGEhwG0q17qdAhdtc49qP/K,iv:JcSlxAwHwU528S7iSpAnSbUZw7iO+LMjR3qGwRHp+Zk=,tag:twf2WOQb/yZ3GtN/hlikMA==,type:str]
|
||||||
sops:
|
sops:
|
||||||
age:
|
age:
|
||||||
- recipient: age1uvsvf5ljaezh5wze32p685kfentyle0l2mvysc67yvgct2h4850qqph9lv
|
- recipient: age1uvsvf5ljaezh5wze32p685kfentyle0l2mvysc67yvgct2h4850qqph9lv
|
||||||
|
|
@ -19,7 +25,7 @@ sops:
|
||||||
MEdmWkFwNXZoR1ZVRnQ0aWlkYzZwSmsK0EFecUIdqlDKX08oRCoDQQ3QCX1wzb8w
|
MEdmWkFwNXZoR1ZVRnQ0aWlkYzZwSmsK0EFecUIdqlDKX08oRCoDQQ3QCX1wzb8w
|
||||||
lghDJhWlfuKr+X24GoE4UK04aJVLqVMRRI4BJW+LQXeHS+dWKu3mQA==
|
lghDJhWlfuKr+X24GoE4UK04aJVLqVMRRI4BJW+LQXeHS+dWKu3mQA==
|
||||||
-----END AGE ENCRYPTED FILE-----
|
-----END AGE ENCRYPTED FILE-----
|
||||||
lastmodified: "2025-06-15T08:18:50Z"
|
lastmodified: "2025-09-16T04:39:12Z"
|
||||||
mac: ENC[AES256_GCM,data:sq+/fpOeNO5wn9S1kFqzRy6xCOVkSBcAkral7MTn4UxRebBDa78KF76Nsba0+o5bzwCchoGl/TC6vySIzGq8FUYwd1tQ9nH5DlqYBVVRgRlKLRyhxXf14BTyYgzHzFuRWdFyY8i4j0flZtlDHk4dVQrE4OhHvhLQ2Zvet5HQ20I=,iv:qoPZ+8tAHJxcR53M2PNwukYgdguSRrAVB+FtKYbf+aM=,tag:FYaPzh6o0ZI27Ul5jEhgVg==,type:str]
|
mac: ENC[AES256_GCM,data:yRVAJz73AqlBm6fxeTehfSqlTLyRYIsPjC/5igpnGC8URUiK66SUtHJSE3196AaPV+CWJrxrXfNWoCmZsP85Rr5V9nw31ZF1boaAc0YzRQBxVmBBlAK7+9Z5KADShAetYNwk9qtCrXd6S8mCwmZjNJaN/Rthy3hchxzAB0/79R4=,iv:QeNUZfmnCx4QF/0wjU/JJRu6umNFC/weW2BJx+7OaPo=,tag:KsityLnPYhugFL4c6wrs6Q==,type:str]
|
||||||
unencrypted_suffix: _unencrypted
|
unencrypted_suffix: _unencrypted
|
||||||
version: 3.10.2
|
version: 3.10.2
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,36 @@
|
||||||
group = config.services.dovecot2.group;
|
group = config.services.dovecot2.group;
|
||||||
mode = "0660";
|
mode = "0660";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
"stalwart/adminPassword" =
|
||||||
|
let
|
||||||
|
inherit (config.users.users.stalwart-mail) name group;
|
||||||
|
in
|
||||||
|
lib.mkIf config.services.stalwart-mail.enable {
|
||||||
|
inherit group;
|
||||||
|
owner = name;
|
||||||
|
};
|
||||||
|
"stalwart/tsig" =
|
||||||
|
let
|
||||||
|
inherit (config.users.users.stalwart-mail) name group;
|
||||||
|
in
|
||||||
|
lib.mkIf config.services.stalwart-mail.enable {
|
||||||
|
inherit group;
|
||||||
|
owner = name;
|
||||||
|
};
|
||||||
|
"stalwart/db" =
|
||||||
|
let
|
||||||
|
inherit (config.users.users.stalwart-mail) name group;
|
||||||
|
in
|
||||||
|
lib.mkIf config.services.stalwart-mail.enable {
|
||||||
|
inherit group;
|
||||||
|
owner = name;
|
||||||
|
};
|
||||||
|
"acme/pdns" = {
|
||||||
|
mode = "0660";
|
||||||
|
owner = "acme";
|
||||||
|
group = "acme";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,14 @@
|
||||||
|
|
||||||
locations."/".proxyPass = "http://10.0.0.130:8001/phone.html";
|
locations."/".proxyPass = "http://10.0.0.130:8001/phone.html";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
"ca.net.dn" = {
|
||||||
|
enableACME = true;
|
||||||
|
forceSSL = true;
|
||||||
|
locations."/" = {
|
||||||
|
proxyPass = "https://10.0.0.1:8443/";
|
||||||
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,11 +33,20 @@ sops:
|
||||||
- recipient: age1z6f643a6vqm7cqh6fna5dhmxfkgwxgqy8kg9s0vf9uxhaswtngtspmqsjw
|
- recipient: age1z6f643a6vqm7cqh6fna5dhmxfkgwxgqy8kg9s0vf9uxhaswtngtspmqsjw
|
||||||
enc: |
|
enc: |
|
||||||
-----BEGIN AGE ENCRYPTED FILE-----
|
-----BEGIN AGE ENCRYPTED FILE-----
|
||||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBuKzJObXlPVUJzUkEyZXlV
|
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBuYWpiZ0h3VURrcW0rV0Vj
|
||||||
Q0tEbzBPTy9kUXIwVmJkckUyWklUMzhCcTE0Ckh3bXIwRkpESTJYeTBPMGhQYk9y
|
SFJwMlRUMHUyS1FGTEo3cHZJc1Z6a3FWbmtRCkdoZXhwOGJQNlV2dU8wRFRMUHVv
|
||||||
L2NQTWFuMWVqYzJHZGhTaHpDRE5CRGMKLS0tIEsybHdPMk9JeEM2cXFwdlpOeXRj
|
QzhxU3RiVHl5UVpUNk10S2VRVy95OHMKLS0tIE9zbUNUU3ZINU1JNGtmd2trS2tI
|
||||||
Qm0wbmNGZDZwZlNTOVl0WVh5RXNxK2cK1Fwbgl5kKAFyrIIhBP+X4ZKFS4Xl39QY
|
d3YxREtHcTBJYU1sNU9vMGZTUGh6NXMKtGKMnnamCAeftkQ0+Ygb/yg1NdyKDz1W
|
||||||
11qkglNgro/JBFJ/W7Hj5wtEd8QToiJM1RW0lQaI25sneQ2v6L5pDA==
|
UjYvW2PYKzkx8IWmIgzdAI3fWDOiE7tmBTMlX9C3/2PKR6dCc/a+SQ==
|
||||||
|
-----END AGE ENCRYPTED FILE-----
|
||||||
|
- recipient: age1uvsvf5ljaezh5wze32p685kfentyle0l2mvysc67yvgct2h4850qqph9lv
|
||||||
|
enc: |
|
||||||
|
-----BEGIN AGE ENCRYPTED FILE-----
|
||||||
|
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBxc3pna3R3aG85bmt2WERa
|
||||||
|
aG9TaDBKTlNMTUVwaFlIdkV0UmFJQStYSHdvCmNuYWJpN2M3QjRkV2s0MHJ4TzZP
|
||||||
|
ZkhKc0xPUFBrblVFR1U4SUdjYzQ2cm8KLS0tIDVuNW9tRGoxanVKOUJYa2QwNFNz
|
||||||
|
OTRiU0cxeXp5K1FjaWRGTnBHcnpUYmcKVVlueEj/DELe9Xi9iaBddpPPRmoUmD48
|
||||||
|
wyjtlvKzS20zishE/D7GkHZ2ZdNsLD3AOnYZ6r6ATAndssC2YT/SXA==
|
||||||
-----END AGE ENCRYPTED FILE-----
|
-----END AGE ENCRYPTED FILE-----
|
||||||
lastmodified: "2025-08-29T07:40:00Z"
|
lastmodified: "2025-08-29T07:40:00Z"
|
||||||
mac: ENC[AES256_GCM,data:QeQ5NOrcq3uNmt+MiVF+Jr3JWWBNGPw5A8pSdd1WR426WWqHTRP7NHAaVbS3st9VSmoYY5NI6JKeizuAq/NCvzOZL3Idy9mP+3HD9VZwn1GNSEGfhn+KZT02AY0JHq29KxcZlAYiWZOL4p+blG2aWfGm9+zy1GHoEXoo3OVhaEg=,iv:8uIoOE0ZJZYGZoQaskCXQKr7vl6wjsmJ4iudhvtgqtY=,tag:fRLGalP92dDyF8q+zT97BQ==,type:str]
|
mac: ENC[AES256_GCM,data:QeQ5NOrcq3uNmt+MiVF+Jr3JWWBNGPw5A8pSdd1WR426WWqHTRP7NHAaVbS3st9VSmoYY5NI6JKeizuAq/NCvzOZL3Idy9mP+3HD9VZwn1GNSEGfhn+KZT02AY0JHq29KxcZlAYiWZOL4p+blG2aWfGm9+zy1GHoEXoo3OVhaEg=,iv:8uIoOE0ZJZYGZoQaskCXQKr7vl6wjsmJ4iudhvtgqtY=,tag:fRLGalP92dDyF8q+zT97BQ==,type:str]
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@
|
||||||
username,
|
username,
|
||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
|
|
||||||
let
|
let
|
||||||
inherit username;
|
inherit username;
|
||||||
|
|
||||||
|
|
@ -13,10 +12,10 @@ let
|
||||||
sshPortsString = builtins.concatStringsSep ", " (builtins.map (p: builtins.toString p) sshPorts);
|
sshPortsString = builtins.concatStringsSep ", " (builtins.map (p: builtins.toString p) sshPorts);
|
||||||
|
|
||||||
personal = {
|
personal = {
|
||||||
|
inherit (config.networking) domain;
|
||||||
ip = "10.0.0.1/24";
|
ip = "10.0.0.1/24";
|
||||||
interface = "wg0";
|
interface = "wg0";
|
||||||
port = 51820;
|
port = 51820;
|
||||||
domain = config.networking.domain;
|
|
||||||
range = "10.0.0.0/24";
|
range = "10.0.0.0/24";
|
||||||
full = "10.0.0.1/25";
|
full = "10.0.0.1/25";
|
||||||
restrict = "10.0.0.128/25";
|
restrict = "10.0.0.128/25";
|
||||||
|
|
@ -160,11 +159,13 @@ in
|
||||||
kube.port
|
kube.port
|
||||||
25565
|
25565
|
||||||
kube.masterAPIServerPort
|
kube.masterAPIServerPort
|
||||||
|
5359
|
||||||
];
|
];
|
||||||
allowedTCPPorts = sshPorts ++ [
|
allowedTCPPorts = sshPorts ++ [
|
||||||
53
|
53
|
||||||
25565
|
25565
|
||||||
kube.masterAPIServerPort
|
kube.masterAPIServerPort
|
||||||
|
5359
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -237,8 +238,7 @@ in
|
||||||
listenPort = personal.port;
|
listenPort = personal.port;
|
||||||
privateKeyFile = config.sops.secrets."wireguard/privateKey".path;
|
privateKeyFile = config.sops.secrets."wireguard/privateKey".path;
|
||||||
peers = builtins.map (r: {
|
peers = builtins.map (r: {
|
||||||
publicKey = r.publicKey;
|
inherit (r) publicKey allowedIPs;
|
||||||
allowedIPs = r.allowedIPs;
|
|
||||||
}) (fullRoute ++ meshRoute);
|
}) (fullRoute ++ meshRoute);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -254,31 +254,31 @@ in
|
||||||
extraHosts = "${kube.masterIP} ${kube.masterHostname}";
|
extraHosts = "${kube.masterIP} ${kube.masterHostname}";
|
||||||
};
|
};
|
||||||
|
|
||||||
services.postgresql = {
|
|
||||||
enable = lib.mkDefault true;
|
|
||||||
authentication = ''
|
|
||||||
host powerdnsadmin powerdnsadmin 127.0.0.1/32 trust
|
|
||||||
'';
|
|
||||||
ensureUsers = [
|
|
||||||
{
|
|
||||||
name = "powerdnsadmin";
|
|
||||||
ensureDBOwnership = true;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "pdns";
|
|
||||||
ensureDBOwnership = true;
|
|
||||||
}
|
|
||||||
];
|
|
||||||
ensureDatabases = [
|
|
||||||
"powerdnsadmin"
|
|
||||||
"pdns"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
services = {
|
services = {
|
||||||
dbus.enable = true;
|
dbus.enable = true;
|
||||||
blueman.enable = true;
|
blueman.enable = true;
|
||||||
|
|
||||||
|
postgresql = {
|
||||||
|
enable = lib.mkDefault true;
|
||||||
|
authentication = ''
|
||||||
|
host powerdnsadmin powerdnsadmin 127.0.0.1/32 trust
|
||||||
|
'';
|
||||||
|
ensureUsers = [
|
||||||
|
{
|
||||||
|
name = "powerdnsadmin";
|
||||||
|
ensureDBOwnership = true;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name = "pdns";
|
||||||
|
ensureDBOwnership = true;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
ensureDatabases = [
|
||||||
|
"powerdnsadmin"
|
||||||
|
"pdns"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
openssh = {
|
openssh = {
|
||||||
enable = true;
|
enable = true;
|
||||||
ports = sshPorts;
|
ports = sshPorts;
|
||||||
|
|
@ -293,6 +293,7 @@ in
|
||||||
enable = true;
|
enable = true;
|
||||||
extraConfig = ''
|
extraConfig = ''
|
||||||
launch=gpgsql
|
launch=gpgsql
|
||||||
|
loglevel=6
|
||||||
webserver-password=$WEB_PASSWORD
|
webserver-password=$WEB_PASSWORD
|
||||||
api=yes
|
api=yes
|
||||||
api-key=$WEB_PASSWORD
|
api-key=$WEB_PASSWORD
|
||||||
|
|
@ -302,6 +303,8 @@ in
|
||||||
webserver=yes
|
webserver=yes
|
||||||
webserver-port=8081
|
webserver-port=8081
|
||||||
local-port=5359
|
local-port=5359
|
||||||
|
dnsupdate=yes
|
||||||
|
allow-dnsupdate-from=10.0.0.0/24
|
||||||
'';
|
'';
|
||||||
secretFile = config.sops.secrets.powerdns.path;
|
secretFile = config.sops.secrets.powerdns.path;
|
||||||
};
|
};
|
||||||
|
|
@ -310,6 +313,7 @@ in
|
||||||
enable = true;
|
enable = true;
|
||||||
forwardZones = {
|
forwardZones = {
|
||||||
"${config.networking.domain}." = "127.0.0.1:5359";
|
"${config.networking.domain}." = "127.0.0.1:5359";
|
||||||
|
"pre7780.dn." = "127.0.0.1:5359";
|
||||||
};
|
};
|
||||||
forwardZonesRecurse = {
|
forwardZonesRecurse = {
|
||||||
"." = "8.8.8.8";
|
"." = "8.8.8.8";
|
||||||
|
|
@ -380,11 +384,16 @@ in
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
systemd.services.raspamd-trainer = {
|
||||||
|
after = [ "pdns-recursor.service" ];
|
||||||
|
};
|
||||||
|
|
||||||
services.nginx.virtualHosts = {
|
services.nginx.virtualHosts = {
|
||||||
"powerdns.${config.networking.domain}" = {
|
"powerdns.${config.networking.domain}" = {
|
||||||
enableACME = true;
|
enableACME = true;
|
||||||
forceSSL = true;
|
forceSSL = true;
|
||||||
locations."/".proxyPass = "http://localhost:8000";
|
locations."/api".proxyPass = "http://127.0.0.1:8081";
|
||||||
|
locations."/".proxyPass = "http://127.0.0.1:8000";
|
||||||
};
|
};
|
||||||
|
|
||||||
"uptime.${config.networking.domain}" = {
|
"uptime.${config.networking.domain}" = {
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,6 @@ in
|
||||||
postRun = ''
|
postRun = ''
|
||||||
systemctl restart postfix.service
|
systemctl restart postfix.service
|
||||||
systemctl restart dovecot.service
|
systemctl restart dovecot.service
|
||||||
systemctl restart rspamd-trainer.service
|
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
"${cfg.domain}" = {
|
"${cfg.domain}" = {
|
||||||
|
|
|
||||||
118
system/modules/stalwart.nix
Normal file
118
system/modules/stalwart.nix
Normal file
|
|
@ -0,0 +1,118 @@
|
||||||
|
{
|
||||||
|
adminPassFile,
|
||||||
|
dbPassFile,
|
||||||
|
domain ? null,
|
||||||
|
acmeConf ? null,
|
||||||
|
enableNginx ? true,
|
||||||
|
}:
|
||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
inherit (lib) mkIf;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
services.postgresql = {
|
||||||
|
enable = true;
|
||||||
|
ensureDatabases = [
|
||||||
|
"stalwart"
|
||||||
|
];
|
||||||
|
ensureUsers = [
|
||||||
|
{
|
||||||
|
name = "stalwart";
|
||||||
|
ensureDBOwnership = true;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
services.stalwart-mail = {
|
||||||
|
enable = true;
|
||||||
|
openFirewall = true;
|
||||||
|
settings = {
|
||||||
|
server = {
|
||||||
|
hostname = if (domain != null) then "mx1.${domain}" else config.networking.fqdn;
|
||||||
|
auto-ban.scan.rate = "1000/1d";
|
||||||
|
tls = {
|
||||||
|
enable = true;
|
||||||
|
implicit = true;
|
||||||
|
};
|
||||||
|
listener = {
|
||||||
|
smtp = {
|
||||||
|
protocol = "smtp";
|
||||||
|
bind = "[::]:25";
|
||||||
|
};
|
||||||
|
submissions = {
|
||||||
|
protocol = "smtp";
|
||||||
|
bind = "[::]:465";
|
||||||
|
tls.implicit = true;
|
||||||
|
};
|
||||||
|
imaps = {
|
||||||
|
protocol = "imap";
|
||||||
|
bind = "[::]:993";
|
||||||
|
tls.implicit = true;
|
||||||
|
};
|
||||||
|
management = {
|
||||||
|
protocol = "http";
|
||||||
|
bind = [ "127.0.0.1:8080" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
lookup.default = {
|
||||||
|
hostname = "mx1.${domain}";
|
||||||
|
domain = "${domain}";
|
||||||
|
};
|
||||||
|
acme."step-ca" = mkIf (acmeConf != null) acmeConf;
|
||||||
|
session.auth = {
|
||||||
|
mechanisms = "[plain]";
|
||||||
|
directory = "'in-memory'";
|
||||||
|
require = true;
|
||||||
|
allow-plain-text = true;
|
||||||
|
};
|
||||||
|
storage.data = "db";
|
||||||
|
store."db" = {
|
||||||
|
type = "postgresql";
|
||||||
|
host = "localhost";
|
||||||
|
port = 5432;
|
||||||
|
database = "stalwart";
|
||||||
|
user = "stalwart";
|
||||||
|
password = "%{file:${dbPassFile}}%";
|
||||||
|
};
|
||||||
|
directory = {
|
||||||
|
"imap".lookup.domains = [ domain ];
|
||||||
|
"in-memory" = {
|
||||||
|
type = "memory";
|
||||||
|
principals = [
|
||||||
|
{
|
||||||
|
name = "admin";
|
||||||
|
class = "admin";
|
||||||
|
secret = "%{file:${adminPassFile}}%";
|
||||||
|
email = [ "admin@${domain}" ];
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
authentication.fallback-admin = {
|
||||||
|
user = "admin";
|
||||||
|
secret = "%{file:${adminPassFile}}%";
|
||||||
|
};
|
||||||
|
tracer."stdout" = {
|
||||||
|
enable = true;
|
||||||
|
type = "console";
|
||||||
|
level = "debug";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
services.nginx = mkIf enableNginx {
|
||||||
|
enable = true;
|
||||||
|
virtualHosts = {
|
||||||
|
"mail.${domain}" = {
|
||||||
|
locations."/".proxyPass = "http://127.0.0.1:8080";
|
||||||
|
enableACME = true;
|
||||||
|
forceSSL = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue