feat: add smolboye mailserver setup

* add mailserver module based on simple-nixos-mailserver
* add smolboye server running on Hetzner Cloud
* add support for grub, make systemd-boot an optional default

Signed-off-by: Chinmay D. Pai <chinmaydpai@gmail.com>
This commit is contained in:
Chinmay D. Pai 2024-10-09 17:54:43 +05:30
parent bc05090f5b
commit 98fbfc0590
Signed by: thunderbottom
GPG Key ID: 75507BE256F40CED
12 changed files with 365 additions and 7 deletions

View File

@ -9,6 +9,10 @@
password.file = ./secrets/machines/bicboye/password.age; password.file = ./secrets/machines/bicboye/password.age;
root-password.file = ./secrets/machines/bicboye/root-password.age; root-password.file = ./secrets/machines/bicboye/root-password.age;
}; };
smolboye = {
password.file = ./secrets/machines/smolboye/password.age;
root-password.file = ./secrets/machines/smolboye/root-password.age;
};
}; };
monitoring = { monitoring = {
grafana = { grafana = {
@ -23,6 +27,9 @@
gitea = { gitea = {
password.file = ./secrets/services/gitea/password.age; password.file = ./secrets/services/gitea/password.age;
}; };
mailserver = {
watashi.password.file = ./secrets/services/mailserver/watashi.age;
};
miniflux = { miniflux = {
password.file = ./secrets/services/miniflux/password.age; password.file = ./secrets/services/miniflux/password.age;
}; };

View File

@ -25,6 +25,22 @@
"type": "github" "type": "github"
} }
}, },
"blobs": {
"flake": false,
"locked": {
"lastModified": 1604995301,
"narHash": "sha256-wcLzgLec6SGJA8fx1OEN1yV/Py5b+U5iyYpksUY/yLw=",
"owner": "simple-nixos-mailserver",
"repo": "blobs",
"rev": "2cccdf1ca48316f2cfd1c9a0017e8de5a7156265",
"type": "gitlab"
},
"original": {
"owner": "simple-nixos-mailserver",
"repo": "blobs",
"type": "gitlab"
}
},
"cachix": { "cachix": {
"locked": { "locked": {
"lastModified": 1635350005, "lastModified": 1635350005,
@ -243,6 +259,22 @@
} }
}, },
"flake-compat_4": { "flake-compat_4": {
"flake": false,
"locked": {
"lastModified": 1696426674,
"narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"type": "github"
}
},
"flake-compat_5": {
"flake": false, "flake": false,
"locked": { "locked": {
"lastModified": 1650374568, "lastModified": 1650374568,
@ -677,6 +709,29 @@
"type": "github" "type": "github"
} }
}, },
"nixos-mailserver": {
"inputs": {
"blobs": "blobs",
"flake-compat": "flake-compat_4",
"nixpkgs": [
"nixpkgs"
],
"nixpkgs-24_05": "nixpkgs-24_05"
},
"locked": {
"lastModified": 1722877200,
"narHash": "sha256-qgKDNJXs+od+1UbRy62uk7dYal3h98I4WojfIqMoGcg=",
"owner": "simple-nixos-mailserver",
"repo": "nixos-mailserver",
"rev": "af7d3bf5daeba3fc28089b015c0dd43f06b176f2",
"type": "gitlab"
},
"original": {
"owner": "simple-nixos-mailserver",
"repo": "nixos-mailserver",
"type": "gitlab"
}
},
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1727802920, "lastModified": 1727802920,
@ -693,6 +748,21 @@
"type": "github" "type": "github"
} }
}, },
"nixpkgs-24_05": {
"locked": {
"lastModified": 1717144377,
"narHash": "sha256-F/TKWETwB5RaR8owkPPi+SPJh83AQsm6KrQAlJ8v/uA=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "805a384895c696f802a9bf5bf4720f37385df547",
"type": "github"
},
"original": {
"id": "nixpkgs",
"ref": "nixos-24.05",
"type": "indirect"
}
},
"nixpkgs-lib": { "nixpkgs-lib": {
"locked": { "locked": {
"lastModified": 1727571693, "lastModified": 1727571693,
@ -794,6 +864,7 @@
"maych-in": "maych-in", "maych-in": "maych-in",
"nil": "nil", "nil": "nil",
"nixos-hardware": "nixos-hardware", "nixos-hardware": "nixos-hardware",
"nixos-mailserver": "nixos-mailserver",
"nixpkgs": "nixpkgs_2", "nixpkgs": "nixpkgs_2",
"nur": "nur", "nur": "nur",
"snowfall-lib": "snowfall-lib", "snowfall-lib": "snowfall-lib",
@ -883,7 +954,7 @@
}, },
"snowfall-lib": { "snowfall-lib": {
"inputs": { "inputs": {
"flake-compat": "flake-compat_4", "flake-compat": "flake-compat_5",
"flake-utils-plus": "flake-utils-plus", "flake-utils-plus": "flake-utils-plus",
"nixpkgs": [ "nixpkgs": [
"nixpkgs" "nixpkgs"

View File

@ -22,7 +22,6 @@
chaotic.nixosModules.default chaotic.nixosModules.default
disko.nixosModules.disko disko.nixosModules.disko
srvos.nixosModules.common srvos.nixosModules.common
srvos.nixosModules.mixins-systemd-boot
inputs.lanzaboote.nixosModules.lanzaboote inputs.lanzaboote.nixosModules.lanzaboote
]; ];
@ -33,11 +32,19 @@
inherit userdata; inherit userdata;
}; };
# TODO: setup atticd # TODO: setup atticd
systems.hosts.bicboye.modules = [inputs.srvos.nixosModules.server]; systems.hosts.bicboye.modules = [
inputs.srvos.nixosModules.server
inputs.srvos.nixosModules.mixins-systemd-boot
];
systems.hosts.bicboye.specialArgs = { systems.hosts.bicboye.specialArgs = {
inherit userdata; inherit userdata;
}; };
systems.hosts.smolboye.modules = [inputs.srvos.nixosModules.server]; systems.hosts.smolboye.modules = [
inputs.nixos-hardware.nixosModules.common-cpu-intel
];
systems.hosts.smolboye.specialArgs = {
inherit userdata;
};
homes.modules = with inputs; [ homes.modules = with inputs; [
nur.hmModules.nur nur.hmModules.nur
@ -103,6 +110,9 @@
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
nixos-hardware.url = "github:nixos/nixos-hardware"; nixos-hardware.url = "github:nixos/nixos-hardware";
nixos-mailserver.url = "gitlab:simple-nixos-mailserver/nixos-mailserver";
nixos-mailserver.inputs.nixpkgs.follows = "nixpkgs";
nur.url = "github:nix-community/nur"; nur.url = "github:nix-community/nur";
snowfall-lib.url = "github:snowfallorg/lib"; snowfall-lib.url = "github:snowfallorg/lib";

View File

@ -0,0 +1,10 @@
_: {
snowfallorg.user.enable = true;
snowfallorg.user.name = "server";
snowflake.development.helix.enable = true;
snowflake.development.tmux.enable = true;
snowflake.shell.fish.enable = true;
home.stateVersion = "24.11";
}

View File

@ -62,7 +62,6 @@
grub = { grub = {
enable = config.snowflake.bootloader == "grub"; enable = config.snowflake.bootloader == "grub";
efiSupport = true; efiSupport = true;
efiInstallAsRemovable = true;
forceInstall = true; forceInstall = true;
}; };
}; };

View File

@ -0,0 +1,95 @@
{
config,
inputs,
lib,
...
}: {
imports = [inputs.nixos-mailserver.nixosModules.mailserver];
options.snowflake.services.mailserver = {
enable = lib.mkEnableOption "Enable mailserver service";
fqdn = lib.mkOption {
type = lib.types.str;
description = "FQDN for the mailserver";
};
domains = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [];
description = "Configuration domains to use for the mailserver";
};
loginAccounts = lib.mkOption {
description = "Login accounts for the domain. Every account is mapped to a unix user";
};
};
config = let
cfg = config.snowflake.services.mailserver;
in
lib.mkIf cfg.enable {
# Ref: https://gitlab.com/simple-nixos-mailserver/nixos-mailserver/-/issues/275
services.dovecot2.sieve.extensions = ["fileinto"];
mailserver = {
inherit (cfg) enable fqdn domains loginAccounts;
# Spin up a stripped-down nginx instance on
# port 80 to generate a certificate automatically.
certificateScheme = "acme-nginx";
# Enable a better way of storing emails.
useFsLayout = true;
mailboxes = {
Archive = {
auto = "subscribe";
specialUse = "Archive";
};
Drafts = {
auto = "subscribe";
specialUse = "Drafts";
};
Sent = {
auto = "subscribe";
specialUse = "Sent";
};
Junk = {
auto = "subscribe";
specialUse = "Junk";
};
Trash = {
auto = "subscribe";
specialUse = "Trash";
};
};
};
# Prefer using ipv4 and use correct ipv6 address
# to avoid rDNS issues
# NOTE: this needs to be changed on every new system.
# TODO: figure out how to handle this case better.
services.postfix.extraConfig = ''
smtp_bind_address6 = 2a01:4f8:1c1c:90b::
smtp_address_preference = ipv4
'';
services.fail2ban.jails = {
postfix = {
settings = {
enabled = true;
mode = "extra";
};
};
dovecot = {
settings = {
enabled = true;
filter = "dovecot[mode=aggressive]";
maxretry = 3;
};
};
};
};
}

Binary file not shown.

View File

@ -0,0 +1,7 @@
age-encryption.org/v1
-> ssh-ed25519 XInHQA BeG8hdmEGOcfCJGjZ8ps03XDV4DNPqMfXuFGIXitSVM
5lTE5CORKB107B8509PPiLCeYlwP1x80Jyh2CxI0BTg
-> ssh-ed25519 H9OGOA gqAqKcTLuE7gJ5lWvTUs/mnmTv4CyN9GWj6ce9YmSz0
AVKH1l8QEuBlCJS7dZ8cFxbeWF6qjjZWn9fg3uOF9WU
--- U0k1MgVffkdgn+pStscCnCNOFgtlCW8URf5wesIjO5w
žYzSº<53>¿úfêÍù““ã†ÂOP³Ù,N7°¯~” Šb<>=ùK èiâõ”~•ŠéBkÙO=½¸Ó<19>ï½}}AäNYmÇwíëS>uh\?Z<>%&õ¹ ÞX7a'H˜.+Ø<>6%{¥ôL ŒZýÆõñ¨&T ·ýAµ.¶÷™ã

View File

@ -24,12 +24,15 @@ in {
"machines/thonkpad/root-password.age".publicKeys = thunderbottom ++ thonkpad; "machines/thonkpad/root-password.age".publicKeys = thunderbottom ++ thonkpad;
"machines/bicboye/password.age".publicKeys = thunderbottom ++ bicboye; "machines/bicboye/password.age".publicKeys = thunderbottom ++ bicboye;
"machines/bicboye/root-password.age".publicKeys = thunderbottom ++ bicboye; "machines/bicboye/root-password.age".publicKeys = thunderbottom ++ bicboye;
"machines/smolboye/password.age".publicKeys = thunderbottom ++ smolboye;
"machines/smolboye/root-password.age".publicKeys = thunderbottom ++ smolboye;
"monitoring/grafana/password.age".publicKeys = thunderbottom ++ bicboye; "monitoring/grafana/password.age".publicKeys = thunderbottom ++ bicboye;
"services/backup/environment.age".publicKeys = thunderbottom ++ bicboye; "services/backups/environment.age".publicKeys = thunderbottom ++ bicboye;
"services/backup/password.age".publicKeys = thunderbottom ++ bicboye; "services/backups/password.age".publicKeys = thunderbottom ++ bicboye;
"services/gitea/password.age".publicKeys = thunderbottom ++ bicboye; "services/gitea/password.age".publicKeys = thunderbottom ++ bicboye;
"services/maddy/password.age".publicKeys = thunderbottom ++ bicboye; "services/maddy/password.age".publicKeys = thunderbottom ++ bicboye;
"services/maddy/user-watashi.age".publicKeys = thunderbottom ++ servers; "services/maddy/user-watashi.age".publicKeys = thunderbottom ++ servers;
"services/mailserver/watashi.age".publicKeys = thunderbottom ++ smolboye;
"services/miniflux/password.age".publicKeys = thunderbottom ++ bicboye; "services/miniflux/password.age".publicKeys = thunderbottom ++ bicboye;
"services/paperless/password.age".publicKeys = users ++ bicboye; "services/paperless/password.age".publicKeys = users ++ bicboye;
"services/unifi-unpoller/password.age".publicKeys = users ++ bicboye; "services/unifi-unpoller/password.age".publicKeys = users ++ bicboye;

View File

@ -0,0 +1,7 @@
<EFBFBD>
<EFBFBD>
<EFBFBD>
<EFBFBD>
<EFBFBD>
<EFBFBD>
<EFBFBD>

View File

@ -0,0 +1,92 @@
{
config,
lib,
userdata,
...
}: {
imports = [./disk-config.nix];
hardware.cpu.intel.updateMicrocode = true;
hardware.enableRedistributableFirmware = true;
networking = {
hostName = "smolboye";
nameservers = ["1.1.1.1"];
useDHCP = lib.mkDefault false;
interfaces.enp1s0 = {
useDHCP = lib.mkDefault true;
ipv6.addresses = [
{
address = "2a01:4f8:1c1c:90b::";
prefixLength = 64;
}
];
};
defaultGateway6 = {
address = "fe80::1";
interface = "enp1s0";
};
firewall.allowedTCPPorts = [80 443];
};
boot = {
initrd.availableKernelModules = ["xhci_pci" "ahci" "ehci_pci" "nvme" "usb_storage" "sd_mod"];
kernelModules = ["kvm-amd" "virtio_gpu"];
kernelParams = ["console=tty"];
loader.grub.device = "/dev/sda";
supportedFilesystems = ["btrfs"];
};
# Enable weekly btrfs auto-scrub.
services.btrfs.autoScrub = {
enable = true;
interval = "weekly";
fileSystems = ["/"];
};
security.acme.defaults.email = "chinmaydpai@gmail.com";
age.secrets = {
mailserver-watashi.file = userdata.secrets.services.mailserver.watashi.password.file;
};
snowflake = {
stateVersion = "24.11";
bootloader = "grub";
core.security.sysctl.enable = lib.mkForce false;
networking.firewall.enable = true;
networking.networkManager.enable = true;
networking.resolved.enable = true;
services = {
mailserver = {
enable = true;
fqdn = "mail.deku.moe";
domains = ["deku.moe"];
loginAccounts = {
"watashi@deku.moe" = {
hashedPasswordFile = config.age.secrets.mailserver-watashi.path;
aliases = ["@deku.moe"];
catchAll = ["deku.moe"];
};
};
};
};
user = {
enable = true;
username = "server";
description = "Smolboye Server";
userPasswordAgeModule = userdata.secrets.machines.smolboye.password;
rootPasswordAgeModule = userdata.secrets.machines.smolboye.root-password;
extraAuthorizedKeys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIG3PeMbehJBkmv8Ee7xJimTzXoSdmAnxhBatHSdS+saM"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOyY8ZkhwWiqJCiTqXvHnLpXQb1qWwSZAoqoSWJI1ogP"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJQWA+bAwpm9ca5IhC6q2BsxeQH4WAiKyaht48b7/xkN"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKJnFvU6nBXEuZF08zRLFfPpxYjV3o0UayX0zTPbDb7C"
];
};
};
}

View File

@ -0,0 +1,57 @@
{
disko.devices = {
disk = {
sda = {
type = "disk";
device = "/dev/sda";
content = {
type = "gpt";
partitions = {
boot = {
priority = 1;
name = "ESP";
start = "1M";
end = "128M";
type = "EF00";
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
};
};
root = {
size = "100%";
content = {
type = "btrfs";
extraArgs = ["-f"];
subvolumes = {
"/root" = {
mountpoint = "/";
mountOptions = ["compress=zstd" "noatime"];
};
"/home" = {
mountpoint = "/home";
mountOptions = ["compress=zstd" "noatime"];
};
"/nix" = {
mountpoint = "/nix";
mountOptions = ["compress=zstd" "noatime"];
};
"/swap" = {
mountpoint = "/.swapvol";
mountOptions = ["nodatacow" "noatime"];
swap.swapfile.size = "20M";
};
"/log" = {
mountpoint = "/var/log";
mountOptions = ["compress=zstd" "noatime"];
};
};
};
};
};
};
};
};
};
}