infrastructure

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

commit 47fdc6b188dbbc055c2dba7b9ea055458db9e85b
parent 0842b6f6a2644ec2a4a1c23c01c6323bf49141a2
Author: Silas Brack <silasbrack@gmail.com>
Date:   Sun, 31 May 2026 21:33:20 +0200

feat: implement mailserver & others

Diffstat:
Mflake.lock | 105+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mflake.nix | 6++++++
Mhosts/gaia/configuration.nix | 11++++++-----
Mhosts/gaia/home.nix | 68++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mhosts/gaia/init.el | 13+++++++++++++
Mhosts/helios.nix | 15+++++++++++++++
Amodules/mailserver.nix | 41+++++++++++++++++++++++++++++++++++++++++
Mmodules/wireguard-client.nix | 2+-
Msecrets.yaml | 5+++--
9 files changed, 258 insertions(+), 8 deletions(-)

diff --git a/flake.lock b/flake.lock @@ -1,5 +1,21 @@ { "nodes": { + "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" + } + }, "crane": { "locked": { "lastModified": 1776635034, @@ -15,6 +31,22 @@ "type": "github" } }, + "flake-compat": { + "flake": false, + "locked": { + "lastModified": 1767039857, + "narHash": "sha256-vNpUSpF5Nuw8xvDLj2KCwwksIbjua2LZCqhV1LNRDns=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "5edf11c44bc78a0d334f6334cdaf7d60d732daab", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, "flake-utils": { "inputs": { "systems": "systems" @@ -33,6 +65,54 @@ "type": "github" } }, + "git-hooks": { + "inputs": { + "flake-compat": [ + "nixos-mailserver", + "flake-compat" + ], + "gitignore": "gitignore", + "nixpkgs": [ + "nixos-mailserver", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1772893680, + "narHash": "sha256-JDqZMgxUTCq85ObSaFw0HhE+lvdOre1lx9iI6vYyOEs=", + "owner": "cachix", + "repo": "git-hooks.nix", + "rev": "8baab586afc9c9b57645a734c820e4ac0a604af9", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "git-hooks.nix", + "type": "github" + } + }, + "gitignore": { + "inputs": { + "nixpkgs": [ + "nixos-mailserver", + "git-hooks", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1709087332, + "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "gitignore.nix", + "type": "github" + } + }, "home-manager": { "inputs": { "nixpkgs": [ @@ -73,6 +153,30 @@ "url": "ssh://git@github.com/silasbrack/mkv" } }, + "nixos-mailserver": { + "inputs": { + "blobs": "blobs", + "flake-compat": "flake-compat", + "git-hooks": "git-hooks", + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1773912645, + "narHash": "sha256-QHzRqq6gh+t3F/QU9DkP7X63dDDcuIQmaDz12p7ANTg=", + "owner": "simple-nixos-mailserver", + "repo": "nixos-mailserver", + "rev": "25e6dbb8fca3b6e779c5a46fd03bd760b2165bb5", + "type": "gitlab" + }, + "original": { + "owner": "simple-nixos-mailserver", + "ref": "nixos-25.11", + "repo": "nixos-mailserver", + "type": "gitlab" + } + }, "nixpkgs": { "locked": { "lastModified": 1772773019, @@ -157,6 +261,7 @@ "inputs": { "home-manager": "home-manager", "mkv": "mkv", + "nixos-mailserver": "nixos-mailserver", "nixpkgs": "nixpkgs_2", "nixpkgs-unstable": "nixpkgs-unstable", "simple-web-app": "simple-web-app", diff --git a/flake.nix b/flake.nix @@ -9,6 +9,10 @@ url = "git+ssh://forgejo@git.fnarglebeast.com/silas/website.git"; flake = false; }; + nixos-mailserver = { + url = "gitlab:simple-nixos-mailserver/nixos-mailserver/nixos-25.11"; + inputs.nixpkgs.follows = "nixpkgs"; + }; home-manager = { url = "github:nix-community/home-manager/release-25.11"; inputs.nixpkgs.follows = "nixpkgs"; @@ -22,6 +26,7 @@ simple-web-app, mkv, website, + nixos-mailserver, home-manager, ... }: @@ -42,6 +47,7 @@ inherit system; modules = [ sops-nix.nixosModules.sops + nixos-mailserver.nixosModules.mailserver ( inputs@{ pkgs, diff --git a/hosts/gaia/configuration.nix b/hosts/gaia/configuration.nix @@ -146,7 +146,7 @@ nixpkgs.config.allowUnfreePredicate = pkg: builtins.elem (lib.getName pkg) [ - # "claude-code" + "claude-code" "spotify" ]; users.users.silas = { @@ -167,7 +167,7 @@ # anki # blender # btop-rocm - # claude-code + claude-code # discord # duckdb # rocmPackages.clr @@ -208,7 +208,7 @@ # gnumake # hadolint # inkscape - # isync + isync jq keepassxc # kitty @@ -218,11 +218,11 @@ # localsend # mosh mpv - # msmtp + msmtp # ncdu # nil # nixfmt-rfc-style - # notmuch + notmuch # obs-studio # obsidian # pandoc @@ -476,6 +476,7 @@ extensions = ps: with ps; [ pgvector ]; ensureDatabases = [ "paperless" + "daily_tracker_dev" ]; ensureUsers = [ { diff --git a/hosts/gaia/home.nix b/hosts/gaia/home.nix @@ -23,6 +23,7 @@ ep.magit ep.expand-region ep.hyperbole + ep.notmuch (ep.treesit-grammars.with-grammars (g: [ g.tree-sitter-python g.tree-sitter-rust @@ -30,5 +31,72 @@ ])) ]; }; + + programs.mbsync = { + enable = true; + extraConfig = '' + IMAPAccount silasbrack + Host mail.silasbrack.com + User silas@silasbrack.com + PassCmd "cat ~/.mail-password" + SSLType IMAPS + + IMAPStore silasbrack-remote + Account silasbrack + + MaildirStore silasbrack-local + Path ~/Mail/silasbrack/ + Inbox ~/Mail/silasbrack/INBOX + SubFolders Verbatim + + Channel silasbrack + Far :silasbrack-remote: + Near :silasbrack-local: + Patterns * + Create Both + Expunge Both + SyncState * + ''; + }; + + programs.msmtp = { + enable = true; + extraConfig = '' + defaults + tls on + + account silasbrack + host mail.silasbrack.com + port 465 + tls_starttls off + auth on + user silas@silasbrack.com + from silas@silasbrack.com + passwordeval "cat ~/.mail-password" + + account default : silasbrack + ''; + }; + + accounts.email.maildirBasePath = "Mail"; + accounts.email.accounts.silasbrack = { + primary = true; + address = "silas@silasbrack.com"; + realName = "Silas Brack"; + notmuch.enable = true; + }; + + programs.notmuch = { + enable = true; + new.tags = [ "new" ]; + search.excludeTags = [ "deleted" "spam" ]; + hooks.postNew = '' + notmuch tag +inbox -new -- tag:new AND folder:silasbrack/INBOX + notmuch tag +sent -new -- tag:new AND folder:silasbrack/Sent + notmuch tag +trash -new -- tag:new AND folder:silasbrack/Trash + notmuch tag +spam -new -- tag:new AND folder:silasbrack/Junk + notmuch tag -new -- tag:new + ''; + }; }; } diff --git a/hosts/gaia/init.el b/hosts/gaia/init.el @@ -34,3 +34,16 @@ ;; expand-region (require 'expand-region) (global-set-key (kbd "C-=") 'er/expand-region) + +;; notmuch +(require 'notmuch) +(setq mail-user-agent 'notmuch-user-agent) +(setq notmuch-fcc-dirs "silasbrack/Sent") +(setq notmuch-search-oldest-first nil) +(setq message-send-mail-function 'message-send-mail-with-sendmail) +(setq sendmail-program "msmtp") +(setq message-sendmail-extra-arguments '("--read-envelope-from")) +(setq message-sendmail-f-is-evil t) +(setq user-mail-address "silas@silasbrack.com") +(setq user-full-name "Silas Brack") +(global-set-key (kbd "C-c m") 'notmuch) diff --git a/hosts/helios.nix b/hosts/helios.nix @@ -15,6 +15,7 @@ ../modules/forgejo.nix ../modules/mkv.nix ../modules/simple-web-app.nix + ../modules/mailserver.nix ]; # Generic @@ -123,6 +124,20 @@ traildepotPath = "${simple-web-app}/traildepot"; }; + # Mail server + services.local.mailserver = { + enable = true; + fqdn = "mail.silasbrack.com"; + domains = [ "silasbrack.com" ]; + accounts = { + "silas@silasbrack.com" = { + hashedPasswordFile = config.sops.secrets.mail_silas_password_hash.path; + aliases = [ "postmaster@silasbrack.com" ]; + }; + }; + }; + sops.secrets.mail_silas_password_hash = { }; + # Users users.users = { root.openssh.authorizedKeys.keys = [ diff --git a/modules/mailserver.nix b/modules/mailserver.nix @@ -0,0 +1,41 @@ +{ + config, + lib, + ... +}: + +let + cfg = config.services.local.mailserver; +in +{ + options.services.local.mailserver = { + enable = lib.mkEnableOption "Mail server"; + + fqdn = lib.mkOption { + type = lib.types.str; + description = "Fully qualified domain name of the mail server"; + }; + + domains = lib.mkOption { + type = lib.types.listOf lib.types.str; + description = "Domains to receive mail for"; + }; + + accounts = lib.mkOption { + type = lib.types.attrs; + default = { }; + description = "Mail accounts configuration"; + }; + }; + + config = lib.mkIf cfg.enable { + mailserver = { + enable = true; + stateVersion = 5; + fqdn = cfg.fqdn; + domains = cfg.domains; + certificateScheme = "acme-nginx"; + loginAccounts = cfg.accounts; + }; + }; +} diff --git a/modules/wireguard-client.nix b/modules/wireguard-client.nix @@ -16,7 +16,7 @@ let 10.100.0.4 gaia 10.100.0.5 ipad 10.100.0.6 macbook - 10.100.0.7 helios + 10.100.0.7 helios mail.silasbrack.com 10.100.0.8 xps ''; in diff --git a/secrets.yaml b/secrets.yaml @@ -7,6 +7,7 @@ gaia_wireguard_private_key: ENC[AES256_GCM,data:pWIY9Hf4/diJsREVZQR1D9noV1vdQrWg gaia_forgejo_runner_token: ENC[AES256_GCM,data:0XA6nSeBW4uh/cx/95xw0Ood/a68qD4Z/8d77rj4WEnHQPNDRKzBBKQZFqjk7ME=,iv:CcWsra/iSYH+edNixzxw6WNYHZUJO1SDXwJrho6i1DE=,tag:3tximHNd2TnTZLAPOghpMg==,type:str] gaia_gitea_runner_ssh_key: ENC[AES256_GCM,data:CZZMptDd9s7WQsx9vnHv7tF1CJ9cKd+lnwuv75+a1p4OWxANObfIFtJOTDDHNL1+fk4/48/OOtODrgZlfeLxVPmmiPsvnSPOA1POhi6q97bpOWk/YWgViIWaf4UsLWDBq3/tngcJCa5JebrKuY+T7MaJn1Lw+C8h+91WiIWYSzOSMmZIoMDo5Y85cPqesFKxgmSlgTYbv5mJnFQ6pvhqTLHRpIPW5PNgRjeXsjJrblvs/edYtLyAVm6H0IYMiMa24+272f90l/2Vc16PXk6RCCFIIJ9HuGYGRBFMAD0bYPDo/ESTMn2u1MATGVCPKCLMjTxFglowfavZpb7xLk7EvZoWPQXx/+KcTV3+iVabOv0kI8OLZFGUPCs4B1MiIeCfSLEr4nop2SNm3C7pGFuKJ0EFGbnhdfBqBqVKZVkXJNGY023BHC3eXx57VatisHQAwLbs2qgSWvOetTAhw8E12QylFtq6mXWG3lZuhJxoiZ6QMI9Yjc/Fvxt4NBOjFtbF0iDRd0g0FSv+geQ7BNid,iv:ufcXcVm2NQRTmG7mYDPwCihm4SYkQ9llpoKtP73Z9Ik=,tag:g4RNNXCBZL0EluwGTYC7fA==,type:str] gaia_forgejo_access_token: ENC[AES256_GCM,data:KpAnvpevOWgbNrEr+QynldkDqonVD90MuVDrBwG7mBClZxHfcps6aw==,iv:22zJ3/BBu5/aFMjgwhQ3lJH+lzOT53bozdAdrzMUGRI=,tag:Vic8ZfT43b0CfphZ/hP1DQ==,type:str] +mail_silas_password_hash: ENC[AES256_GCM,data:E3NCQ5/eRfpbaOVpK0Ovk/vE+h1q5/z7rZrSelQy2Qc++a6nMYA/q7/YmfFT2R68JwOJMaeNMnOKjn1A,iv:sGgRC5SRRiziBd5TVO273uouyFhRqvB0e04xDhifSfM=,tag:U1QxtlVbDUw+nhFm+ZnxOA==,type:str] sops: age: - recipient: age1s29qgfupgx7mqn9dk2rndp6xh63f5qan8vqa77ve603wd5m9a9rqkpq7re @@ -45,7 +46,7 @@ sops: ZGptR25vdWhEKzFxbE5qS051ZFF4RkEK1hGCQVE1E92nFSwSeYRRhxn2p3wBfhpS TZMRsiXtUdlgnoa+IJcFKsbwaZspYnKCA93IEfOXy6TadcoNiFzypw== -----END AGE ENCRYPTED FILE----- - lastmodified: "2026-05-10T13:36:39Z" - mac: ENC[AES256_GCM,data:4mM0xVE2VBP428DVAJJ5GkaE19QsIvj+pVc9UI9U90dnjUT6VkZlVxLdYgnbE1yuVhzGIksrwFEQYvr1hporQUWaL2cdF/CYPf8OHyM3xnpNa+U3xF0sb3TGz0YyF1QDBvpTF+avsSQNb+NAs4M0eEE9MWOuGmkROAHKnoK/2z0=,iv:6JH7nV2SYii1ojmMp6KMtzi0dkB6a9xWlfItZOQ9jS8=,tag:yaFwI4KJX+P7tPQ2udSvUw==,type:str] + lastmodified: "2026-05-31T11:49:47Z" + mac: ENC[AES256_GCM,data:6X9/faApExW9xtorxSAODyVQwSCtDTel0iTtc7ZaeRgiRqQmpPTw8bZ4Zln51lWqUO3EOSRH6ge2btNrtQbPmZoBAmh0dntDvB6LsvJn3NVDeq5vM3vV1dMDyjiXBMqxT99tYkTSK08j10QcCLRRkHIoj4wHIabg7INPCpNadnA=,iv:18yZmCDZzRf96i7L72ogvwCJ6rHvGhzvA0Pq07Jhy08=,tag:j8xTjdG7tndylumNkNVFGA==,type:str] unencrypted_suffix: _unencrypted version: 3.12.1