diff --git a/.sops.yaml b/.sops.yaml index 77c8518..55d6eb3 100644 --- a/.sops.yaml +++ b/.sops.yaml @@ -5,7 +5,13 @@ keys: - &wodan age15m0pdv8mkt4aue8wjay9k4endyymtka5je3gc2t63dgamfzh9vts7774hh creation_rules: - - path_regex: hosts/common/secrets.yam?l$ + - path_regex: hosts/common/global/secrets.yam?l$ + key_groups: + - age: + - *wodan + pgp: + - *lander + - path_regex: home/lander/global/secrets.yam?l$ key_groups: - age: - *wodan diff --git a/flake.nix b/flake.nix index 4b39b16..05cff27 100644 --- a/flake.nix +++ b/flake.nix @@ -35,8 +35,8 @@ wodan = nixpkgs.lib.nixosSystem { specialArgs = { inherit inputs outputs; }; modules = [ - ./hosts/wodan - ]; + ./hosts/wodan + ]; }; }; }; diff --git a/home/lander/features/workstation/default.nix b/home/lander/features/workstation/default.nix index e8d8deb..deb3556 100644 --- a/home/lander/features/workstation/default.nix +++ b/home/lander/features/workstation/default.nix @@ -3,5 +3,6 @@ { imports = [ ./alacritty.nix + ./mail.nix ]; } diff --git a/home/lander/features/workstation/mail.nix b/home/lander/features/workstation/mail.nix new file mode 100644 index 0000000..a2b03c4 --- /dev/null +++ b/home/lander/features/workstation/mail.nix @@ -0,0 +1,97 @@ +# adapted from github:Misterio77/nix-config + +{ pkgs, lib, config, ... }: + +let + mbsync = "$(config.programs.mbsync.package}/bin/mbsync"; + + common = rec { + realName = "Lander Van den Bulcke"; + gpg = { + key = "4BE1 2570 1558 0BAB 9F4B 9D5F CA5B 1C34 E649 BF92"; + signByDefault = true; + }; + signature = { + showSignature = "append"; + text = '' + ${realName} + + PGP: ${gpg.key} + ''; + }; + }; +in { + accounts.email = { + maildirBasePath = "Mail"; + accounts = { + inuits = rec { + primary = true; + address = "landervdb@inuits.eu"; + passwordCommand = "cat ${config.sops.secrets.inuits-mail-pass.path}"; + + imap.host = "zimbra88.inuits.eu"; + mbsync = { + enable = true; + create = "maildir"; + expunge = "both"; + }; + folders = { + inbox = "Inbox"; + drafts = "Drafts"; + sent = "Sent"; + trash = "Trash"; + }; + neomutt = { + enable = true; + extraMailboxes = [ + "Archive" + "Drafts" + "Junk" + "Sent" + "Trash" + ]; + }; + + msmtp.enable = true; + smtp.host = "zimbra88.inuits.eu"; + userName = "landervdb"; + } // common; + }; + }; + + programs.mbsync.enable = true; + programs.msmtp.enable = true; + + systemd.user.services.mbsynce = { + Unit = { + Description = "mbsync synchronization"; + }; + Service = { + Type = "oneshot"; + ExecStart = "${mbsync} -a"; + }; + }; + systemd.user.timers.mbsync = { + Unit = { + Description = "Automatic mbsync synchronization"; + }; + Timer = { + OnBootSec = "30"; + OnUnitActiveSec = "5m"; + }; + Install = { + WantedBy = [ "timers.target" ]; + }; + }; + + # run `createMaildir` after `linkGeneration` + home.activation = let + mbsyncAccounts = lib.filter (a: a.mbsync.enable) (lib.attrValues config.accounts.email.accounts); + in lib.mkIf (mbsyncAccounts != [ ]) { + createMaildir = lib.mkForce (lib.hm.dag.entryAfter [ "linkGeneration" ] '' + run mkdir -m700 -p $VERBOSE_ARG ${ + lib.concatMapStringsSep " " (a: a.maildir.absPath) mbsyncAccounts + } + ''); + }; +} diff --git a/home/lander/global/default.nix b/home/lander/global/default.nix index 18943e3..7988af7 100644 --- a/home/lander/global/default.nix +++ b/home/lander/global/default.nix @@ -12,6 +12,9 @@ in imports = [ inputs.catppuccin.homeManagerModules.catppuccin + ./neomutt.nix + ./secrets.nix + ./sops.nix ../features/cli ]; @@ -32,6 +35,10 @@ in home-manager.enable = true; }; + home.packages = with pkgs; [ + sops + ]; + # https://nixos.wiki/wiki/FAQ/When_do_I_update_stateVersion home.stateVersion = "23.05"; } diff --git a/home/lander/global/neomutt.nix b/home/lander/global/neomutt.nix new file mode 100644 index 0000000..899b8c0 --- /dev/null +++ b/home/lander/global/neomutt.nix @@ -0,0 +1,256 @@ +{ + config, + pkgs, + lib, + ... +}: { + xdg = { + desktopEntries = { + neomutt = { + name = "Neomutt"; + genericName = "Email Client"; + comment = "Read and send emails"; + exec = "neomutt %U"; + icon = "mutt"; + terminal = true; + categories = [ + "Network" + "Email" + "ConsoleOnly" + ]; + type = "Application"; + mimeType = ["x-scheme-handler/mailto"]; + }; + }; + mimeApps.defaultApplications = { + "x-scheme-handler/mailto" = "neomutt.desktop"; + }; + }; + + programs.neomutt = { + enable = true; + vimKeys = true; + checkStatsInterval = 60; + sidebar = { + enable = true; + width = 30; + }; + settings = { + mark_old = "no"; + text_flowed = "yes"; + reverse_name = "yes"; + query_command = ''"khard email --parsable '%s'"''; + }; + binds = [ + { + action = "sidebar-toggle-visible"; + key = "\\\\"; + map = [ + "index" + "pager" + ]; + } + { + action = "group-reply"; + key = "L"; + map = [ + "index" + "pager" + ]; + } + { + action = "toggle-new"; + key = "B"; + map = ["index"]; + } + ]; + macros = let + browserpipe = "cat /dev/stdin > /tmp/muttmail.html && xdg-open /tmp/muttmail.html"; + in [ + { + action = ""; + key = "J"; + map = [ + "index" + "pager" + ]; + } + { + action = ""; + key = "K"; + map = [ + "index" + "pager" + ]; + } + { + action = "+Archive"; + key = "A"; + map = [ + "index" + "pager" + ]; + } + { + action = "${browserpipe}"; + key = "V"; + map = ["attach"]; + } + { + action = "${pkgs.urlscan}/bin/urlscan"; + key = "F"; + map = ["pager"]; + } + { + action = "html${browserpipe}"; + key = "V"; + map = [ + "index" + "pager" + ]; + } + ]; + extraConfig = let + # Collect all addresses and aliases + addresses = lib.flatten ( + lib.mapAttrsToList (_: v: [v.address] ++ v.aliases) config.accounts.email.accounts + ); + in + '' + alternates "${lib.concatStringsSep "|" addresses}" + '' + + '' + # From: https://github.com/altercation/mutt-colors-solarized/blob/master/mutt-colors-solarized-dark-16.muttrc + + # basic colors --------------------------------------------------------- + color normal brightyellow default + color error red default + color tilde black default + color message cyan default + color markers red white + color attachment white default + color search brightmagenta default + color status brightyellow black + color indicator brightblack yellow + color tree cyan default # arrow in threads + + # basic monocolor screen + mono bold bold + mono underline underline + mono indicator reverse + mono error bold + + # index ---------------------------------------------------------------- + + color index red default "~A" # all messages + color index blue default "~N" # new messages + color index brightred default "~E" # expired messages + color index blue default "~N" # new messages + color index blue default "~O" # old messages + color index brightmagenta default "~Q" # messages that have been replied to + color index brightgreen default "~R" # read messages + color index blue default "~U" # unread messages + color index blue default "~U~$" # unread, unreferenced messages + color index cyan default "~v" # messages part of a collapsed thread + color index magenta default "~P" # messages from me + color index cyan default "~p!~F" # messages to me + color index cyan default "~N~p!~F" # new messages to me + color index cyan default "~U~p!~F" # unread messages to me + color index brightgreen default "~R~p!~F" # messages to me + color index red default "~F" # flagged messages + color index red default "~F~p" # flagged messages to me + color index red default "~N~F" # new flagged messages + color index red default "~N~F~p" # new flagged messages to me + color index red default "~U~F~p" # new flagged messages to me + color index brightcyan default "~v~(!~N)" # collapsed thread with no unread + color index yellow default "~v~(~N)" # collapsed thread with some unread + color index green default "~N~v~(~N)" # collapsed thread with unread parent + color index red black "~v~(~F)!~N" # collapsed thread with flagged, no unread + color index yellow black "~v~(~F~N)" # collapsed thread with some unread & flagged + color index green black "~N~v~(~F~N)" # collapsed thread with unread parent & flagged + color index green black "~N~v~(~F)" # collapsed thread with unread parent, no unread inside, but some flagged + color index cyan black "~v~(~p)" # collapsed thread with unread parent, no unread inside, some to me directly + color index yellow red "~v~(~D)" # thread with deleted (doesn't differentiate between all or partial) + color index yellow default "~(~N)" # messages in threads with some unread + color index green default "~S" # superseded messages + color index black red "~D" # deleted messages + color index black red "~N~D" # deleted messages + color index red default "~T" # tagged messages + + # message headers ------------------------------------------------------ + + color hdrdefault brightgreen default + color header brightyellow default "^(From)" + color header blue default "^(Subject)" + + # body ----------------------------------------------------------------- + + color quoted blue default + color quoted1 cyan default + color quoted2 yellow default + color quoted3 red default + color quoted4 brightred default + + color signature brightgreen default + color bold black default + color underline black default + color normal default default + color body brightcyan default "[;:][-o][)/(|]" # emoticons + color body brightcyan default "[;:][)(|]" # emoticons + color body brightcyan default "[*]?((N)?ACK|CU|LOL|SCNR|BRB|BTW|CWYL|\ + |FWIW|vbg|GD&R|HTH|HTHBE|IMHO|IMNSHO|\ + |IRL|RTFM|ROTFL|ROFL|YMMV)[*]?" + color body brightcyan default "[ ][*][^*]*[*][ ]?" # more emoticon? + color body brightcyan default "[ ]?[*][^*]*[*][ ]" # more emoticon? + + ## pgp + + color body red default "(BAD signature)" + color body cyan default "(Good signature)" + color body brightblack default "^gpg: Good signature .*" + color body brightyellow default "^gpg: " + color body brightyellow red "^gpg: BAD signature from.*" + mono body bold "^gpg: Good signature" + mono body bold "^gpg: BAD signature from.*" + + # yes, an insance URL regex + color body red default "([a-z][a-z0-9+-]*://(((([a-z0-9_.!~*'();:&=+$,-]|%[0-9a-f][0-9a-f])*@)?((([a-z0-9]([a-z0-9-]*[a-z0-9])?)\\.)*([a-z]([a-z0-9-]*[a-z0-9])?)\\.?|[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+)(:[0-9]+)?)|([a-z0-9_.!~*'()$,;:@&=+-]|%[0-9a-f][0-9a-f])+)(/([a-z0-9_.!~*'():@&=+$,-]|%[0-9a-f][0-9a-f])*(;([a-z0-9_.!~*'():@&=+$,-]|%[0-9a-f][0-9a-f])*)*(/([a-z0-9_.!~*'():@&=+$,-]|%[0-9a-f][0-9a-f])*(;([a-z0-9_.!~*'():@&=+$,-]|%[0-9a-f][0-9a-f])*)*)*)?(\\?([a-z0-9_.!~*'();/?:@&=+$,-]|%[0-9a-f][0-9a-f])*)?(#([a-z0-9_.!~*'();/?:@&=+$,-]|%[0-9a-f][0-9a-f])*)?|(www|ftp)\\.(([a-z0-9]([a-z0-9-]*[a-z0-9])?)\\.)*([a-z]([a-z0-9-]*[a-z0-9])?)\\.?(:[0-9]+)?(/([-a-z0-9_.!~*'():@&=+$,]|%[0-9a-f][0-9a-f])*(;([-a-z0-9_.!~*'():@&=+$,]|%[0-9a-f][0-9a-f])*)*(/([-a-z0-9_.!~*'():@&=+$,]|%[0-9a-f][0-9a-f])*(;([-a-z0-9_.!~*'():@&=+$,]|%[0-9a-f][0-9a-f])*)*)*)?(\\?([-a-z0-9_.!~*'();/?:@&=+$,]|%[0-9a-f][0-9a-f])*)?(#([-a-z0-9_.!~*'();/?:@&=+$,]|%[0-9a-f][0-9a-f])*)?)[^].,:;!)? \t\r\n<>\"]" + # and a heavy handed email regex + color body magenta default "((@(([0-9a-z-]+\\.)*[0-9a-z-]+\\.?|#[0-9]+|\\[[0-9]?[0-9]?[0-9]\\.[0-9]?[0-9]?[0-9]\\.[0-9]?[0-9]?[0-9]\\.[0-9]?[0-9]?[0-9]\\]),)*@(([0-9a-z-]+\\.)*[0-9a-z-]+\\.?|#[0-9]+|\\[[0-9]?[0-9]?[0-9]\\.[0-9]?[0-9]?[0-9]\\.[0-9]?[0-9]?[0-9]\\.[0-9]?[0-9]?[0-9]\\]):)?[0-9a-z_.+%$-]+@(([0-9a-z-]+\\.)*[0-9a-z-]+\\.?|#[0-9]+|\\[[0-2]?[0-9]?[0-9]\\.[0-2]?[0-9]?[0-9]\\.[0-2]?[0-9]?[0-9]\\.[0-2]?[0-9]?[0-9]\\])" + + # Various smilies and the like + color body brightwhite default "<[Gg]>" # + color body brightwhite default "<[Bb][Gg]>" # + color body yellow default " [;:]-*[})>{(<|]" # :-) etc... + # *bold* + color body blue default "(^|[[:space:][:punct:]])\\*[^*]+\\*([[:space:][:punct:]]|$)" + mono body bold "(^|[[:space:][:punct:]])\\*[^*]+\\*([[:space:][:punct:]]|$)" + # _underline_ + color body blue default "(^|[[:space:][:punct:]])_[^_]+_([[:space:][:punct:]]|$)" + mono body underline "(^|[[:space:][:punct:]])_[^_]+_([[:space:][:punct:]]|$)" + # /italic/ (Sometimes gets directory names) + color body blue default "(^|[[:space:][:punct:]])/[^/]+/([[:space:][:punct:]]|$)" + mono body underline "(^|[[:space:][:punct:]])/[^/]+/([[:space:][:punct:]]|$)" + + # Border lines. + color body blue default "( *[-+=#*~_]){6,}" + + # From https://github.com/jessfraz/dockerfiles/blob/master/mutt/.mutt/mutt-patch-highlighting.muttrc + color body cyan default ^(Signed-off-by).* + color body cyan default ^(Docker-DCO-1.1-Signed-off-by).* + color body brightwhite default ^(Cc) + color body yellow default "^diff \-.*" + color body brightwhite default "^index [a-f0-9].*" + color body brightblue default "^---$" + color body white default "^\-\-\- .*" + color body white default "^[\+]{3} .*" + color body green default "^[\+][^\+]+.*" + color body red default "^\-[^\-]+.*" + color body brightblue default "^@@ .*" + color body green default "LGTM" + color body brightmagenta default "-- Commit Summary --" + color body brightmagenta default "-- File Changes --" + color body brightmagenta default "-- Patch Links --" + ''; + }; +} diff --git a/home/lander/global/secrets.nix b/home/lander/global/secrets.nix new file mode 100644 index 0000000..d019522 --- /dev/null +++ b/home/lander/global/secrets.nix @@ -0,0 +1,7 @@ +{ ... }: + +{ + sops.secrets.inuits-mail-pass = { + sopsFile = ./secrets.yaml; + }; +} diff --git a/home/lander/global/secrets.yaml b/home/lander/global/secrets.yaml new file mode 100644 index 0000000..8e312aa --- /dev/null +++ b/home/lander/global/secrets.yaml @@ -0,0 +1,32 @@ +inuits-mail-pass: ENC[AES256_GCM,data:0MqpjT2mmKs9UiY=,iv:yFo08gU4jfocr8yOQKQPBl49lOeE1QZrdsdjjOxp0dE=,tag:o2mOPnNJM0EXvkRep5w92w==,type:str] +sops: + kms: [] + gcp_kms: [] + azure_kv: [] + hc_vault: [] + age: + - recipient: age15m0pdv8mkt4aue8wjay9k4endyymtka5je3gc2t63dgamfzh9vts7774hh + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBnNjFaMmY0cE5QSWZyUmRh + VnB1cWJub1lZcWZhQjdJMlJCM0tjV1Eya1RVCjlHODZGQVF6R3N4WDd2dlk5WGRU + YlB5eEFDMFcyU1pvM2ZOZjB6dW5uaFkKLS0tIGRvaU1kS2RZc3E0YVUyNy9CSTA0 + Zm84S0dCNmtUeVJwd3JsZFZTZ0NJUjAKS4z1n4Tns76En2Hj+bzxKK9O/8xKvMIW + 7frvaBMIIXN2hZkaGbDladav4Z4h858Pr9QG9pSTvIDlVYnapWYyiw== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2024-09-05T06:11:39Z" + mac: ENC[AES256_GCM,data:SVdNtwrN7MEtXMdWKLQXR9BRlRaYvOBRDLmoDZMkX3t3dlUMR5m5m/btpal1+nPkYjUk58q0hSGA94BREdDTpMYHmvr0V+tWnKsmE8j7r51plN1Dp/4sfgtZBgaqHD2IRDGLI4pW9GCg2fXIxB+BGC6GNU/ZAVbhB4bmzNfFqOY=,iv:ElCt+fJFSjsykoiIS9XO9ViaBJ02Oi169YnUeHiATPk=,tag:vR/KXyuRMnWtW9uXIHNwUw==,type:str] + pgp: + - created_at: "2024-09-05T06:11:29Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hF4DARdpY4woM6wSAQdAGSK2AVRQnRUm4xQfA3XsO+PMCN9Gss9+jJOKD+npryYw + DcwFC5udj+M+XPa3Ggk5WK+vC5hkvUrvwsPqILqzJSv7aiSRqmDyoxTVcsVsIXEP + 0l4BXgG9tcQMTu5SjVkeVi5YrS+4GPjmSGXUm83BcJ27CHHv9coGu7wb53KotC2N + xBNBWLrhn37jXovF2EFAMI/CBXU6svqDKYoFHXZpW06LLw/F7EgKd2zHReRVHuwj + =ETqP + -----END PGP MESSAGE----- + fp: 4BE1257015580BAB9F4B9D5FCA5B1C34E649BF92 + unencrypted_suffix: _unencrypted + version: 3.8.1 diff --git a/home/lander/global/sops.nix b/home/lander/global/sops.nix new file mode 100644 index 0000000..49464d6 --- /dev/null +++ b/home/lander/global/sops.nix @@ -0,0 +1,17 @@ +{ inputs, config, ... }: + +{ + imports = [ + inputs.sops-nix.homeManagerModules.sops + ]; + + sops = { + gnupg = { + home = "~/.gnupg"; + sshKeyPaths = []; + }; + + defaultSymlinkPath = "/run/user/1000/secrets"; + defaultSecretsMountPoint = "/run/user/1000/secrets.d"; + }; +} diff --git a/hosts/common/global/default.nix b/hosts/common/global/default.nix index 0830df8..058af55 100644 --- a/hosts/common/global/default.nix +++ b/hosts/common/global/default.nix @@ -13,6 +13,7 @@ ./locale.nix ./nh.nix ./openssh.nix + ./secrets.nix ./sops.nix ]; diff --git a/hosts/common/global/secrets.nix b/hosts/common/global/secrets.nix new file mode 100644 index 0000000..9f06134 --- /dev/null +++ b/hosts/common/global/secrets.nix @@ -0,0 +1,9 @@ +{ ... }: + +{ + sops.secrets.inuits-mail-pass = { + owner = "lander"; + group = "lander"; + sopsFile = ./secrets.yaml; + }; +} diff --git a/hosts/common/global/secrets.yaml b/hosts/common/global/secrets.yaml new file mode 100644 index 0000000..edd1931 --- /dev/null +++ b/hosts/common/global/secrets.yaml @@ -0,0 +1,32 @@ +inuits-mail-pass: ENC[AES256_GCM,data:FgZZfDIPcJc4Vn4=,iv:e5yq7bi6peOrf7eehi0860eEY9dFYFjuVOmGOyxSAKY=,tag:V/hY/9zW5Z7NqhW2fzdt2A==,type:str] +sops: + kms: [] + gcp_kms: [] + azure_kv: [] + hc_vault: [] + age: + - recipient: age15m0pdv8mkt4aue8wjay9k4endyymtka5je3gc2t63dgamfzh9vts7774hh + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA3amZHakdya085QjRCVWN5 + OWM0OWh2OVBpYmxYTWVXdXkyck9iVFVJd2dVCk1zU2x0eFNPRmpUcUFTMWpBaHQz + a0ZzTEF0TUlkTmpXV1VEN1JaTHQyY3cKLS0tIEttMmE4UGlIU05oNFR3RnZiNkNU + Q3UyUzRBZW9YNjlVdDF4akRjcEd5K2MK2c3KfLBgnorRQGvW0AcnJmZTc0rJ9BKi + fFuBpIU5GWyd4BvNMF30ChEfJr/CQ3Zh3YEowquVajtBlUGt32nePw== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2024-08-29T14:26:20Z" + mac: ENC[AES256_GCM,data:4yvj8696SpXsEucOShKjMKIiFcq7L0B6KpH6CFw3aIFslMKa1Wa8aQp64F9pF9grWi9LcXG6btL/iOhPvDXeW1VRwtckzuzhFnI+PMuxJmYVNZHvDkUNBpshCI3BvRzEixpqtwXq36AXtrPoHC39ieQy8EIxpJjMksCODyZyBms=,iv:JcbMRmJwEoRgSx1n9Gb6RzMzZvb/3UiEyk3lBvhYF8I=,tag:BKPx2ZTRkNWRNljkrVyoCA==,type:str] + pgp: + - created_at: "2024-08-29T13:58:05Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hF4DARdpY4woM6wSAQdAwnsdN5NJNjxX8y4uZsQ7KCSSSjsUpN7uCuo634KQPyMw + uVb6m7wa3SfMy6ex6QZqvVDr8hIbFhmB7SwQ0EpcnK+axnMn8ni1fsfRY007+H0e + 0lwBZRErE5y+N+9P16FNnEJfnO2KxtrOIYgIPAeds1mFF6OmbUe5bnWBtl/U74nP + XfuG9segRf/1Alma43FlflacJ5koaxwItj8MSVwsG0YX//78O++h5Wy8JnC1QQ== + =wZyC + -----END PGP MESSAGE----- + fp: 4BE1257015580BAB9F4B9D5FCA5B1C34E649BF92 + unencrypted_suffix: _unencrypted + version: 3.8.1