Non working attempt at getting correct login information working
This commit is contained in:
parent
fbe957b046
commit
cd4c06686e
4 changed files with 189 additions and 24 deletions
|
@ -43,6 +43,7 @@ in
|
||||||
system.autoUpgrade = {
|
system.autoUpgrade = {
|
||||||
enable = true;
|
enable = true;
|
||||||
flake = upgradePath;
|
flake = upgradePath;
|
||||||
|
allowReboot = true;
|
||||||
};
|
};
|
||||||
systemd.services.nixos-upgrade-prepare-flake = {
|
systemd.services.nixos-upgrade-prepare-flake = {
|
||||||
wantedBy = [ "nixos-upgrade.service" ];
|
wantedBy = [ "nixos-upgrade.service" ];
|
||||||
|
|
|
@ -7,6 +7,17 @@
|
||||||
let
|
let
|
||||||
cfg = config.khscodes."mx.kaareskovgaard.net";
|
cfg = config.khscodes."mx.kaareskovgaard.net";
|
||||||
passDbFile = "/run/secret/dovecot/passwd";
|
passDbFile = "/run/secret/dovecot/passwd";
|
||||||
|
# This just replicates what simple-nixos-mailserver does, but using the proper usernames
|
||||||
|
userDbFile = pkgs.writeTextFile {
|
||||||
|
name = "userdb";
|
||||||
|
text = lib.concatStringsSep "\n" (
|
||||||
|
lib.mapAttrsToList (
|
||||||
|
name: value:
|
||||||
|
"${name}:::::::"
|
||||||
|
+ lib.optionalString (value.quota != null) "userdb_quota_rule=*:storage=${value.quota}"
|
||||||
|
) cfg.accounts
|
||||||
|
);
|
||||||
|
};
|
||||||
bogusPasswdFile = pkgs.writeTextFile {
|
bogusPasswdFile = pkgs.writeTextFile {
|
||||||
name = "bogus-passwd";
|
name = "bogus-passwd";
|
||||||
text = "$6$1234";
|
text = "$6$1234";
|
||||||
|
@ -128,7 +139,7 @@ let
|
||||||
|
|
||||||
systemAccounts = lib.attrsets.foldlAttrs (
|
systemAccounts = lib.attrsets.foldlAttrs (
|
||||||
acc: name: value:
|
acc: name: value:
|
||||||
if value.isLdapAccount then acc else acc ++ [ name ]
|
if value.isLdapAccount then acc else acc ++ [ (accountPrimaryEmail name value) ]
|
||||||
) [ ] cfg.accounts;
|
) [ ] cfg.accounts;
|
||||||
|
|
||||||
systemAccountsPassDbTemplateContents =
|
systemAccountsPassDbTemplateContents =
|
||||||
|
@ -142,16 +153,14 @@ let
|
||||||
# Just make sure the file is not empty
|
# Just make sure the file is not empty
|
||||||
+ "\n";
|
+ "\n";
|
||||||
|
|
||||||
# I would like to not use emails as usernames, but this is not something postfix is particularly happy with,
|
data = import ./accounts/mailbox_map.nix {
|
||||||
# as far as I can see. I *think* I can do this by randomly selecting an address, ie. the first, as the "primary"
|
inherit lib accountPrimaryEmail accountAlternativeEmails;
|
||||||
# address, and then map all other addresses to that one. Then create a virtual mailbox map that maps that back
|
accounts = cfg.accounts;
|
||||||
# to the username before delivering it to lmtp. All of this just worked when using ldap, but that meant
|
extraVirtualAliases = { };
|
||||||
# not using code configured accounts set up with opentofu as well, and would also make the email delivery
|
};
|
||||||
# take a hard dependency on ldap (and not just the login process).
|
|
||||||
|
|
||||||
# Create extra virtual aliases for all accounts (as they are not emails, that maps them to their primary email).
|
mappedFile = name: "hash:/var/lib/postfix/conf/${name}";
|
||||||
# Then we map those emails back into the account name in the mailbox maps.
|
mappedRegexFile = name: "pcre:/var/lib/postfix/conf/${name}";
|
||||||
extraVirtualAliases = lib.mapAttrs (name: account: accountPrimaryEmail name account) cfg.accounts;
|
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
options.khscodes."mx.kaareskovgaard.net".accounts = lib.mkOption {
|
options.khscodes."mx.kaareskovgaard.net".accounts = lib.mkOption {
|
||||||
|
@ -160,20 +169,34 @@ in
|
||||||
};
|
};
|
||||||
config = {
|
config = {
|
||||||
mailserver = {
|
mailserver = {
|
||||||
inherit extraVirtualAliases;
|
loginAccounts = lib.attrsets.mapAttrs' (name: value: {
|
||||||
loginAccounts = lib.attrsets.mapAttrs (name: value: {
|
name = accountPrimaryEmail name value;
|
||||||
inherit (value)
|
value = {
|
||||||
name
|
inherit (value)
|
||||||
aliasesRegexp
|
name
|
||||||
catchAll
|
aliasesRegexp
|
||||||
quota
|
catchAll
|
||||||
sieveScript
|
quota
|
||||||
sendOnly
|
sieveScript
|
||||||
sendOnlyRejectMessage
|
sendOnly
|
||||||
;
|
sendOnlyRejectMessage
|
||||||
aliases = accountAlternativeEmails name value;
|
;
|
||||||
hashedPasswordFile = bogusPasswdFile;
|
aliases = accountAlternativeEmails name value;
|
||||||
|
hashedPasswordFile = bogusPasswdFile;
|
||||||
|
};
|
||||||
}) cfg.accounts;
|
}) cfg.accounts;
|
||||||
|
extraVirtualAliases = data.mailserverExtraVirtualAliases;
|
||||||
|
};
|
||||||
|
services.postfix = {
|
||||||
|
mapFiles."valias_maps" = data.valiases_file;
|
||||||
|
mapFiles."regex_valias_maps" = data.regex_valiases_file;
|
||||||
|
mapFiles."vaccounts" = lib.mkForce data.vaccounts_file;
|
||||||
|
mapFiles."regex_vaccounts" = lib.mkForce data.regex_vaccounts_file;
|
||||||
|
config.virtual_mailbox_maps = lib.mkForce [
|
||||||
|
(mappedFile "valias_maps")
|
||||||
|
(mappedRegexFile "regex_valias_maps")
|
||||||
|
];
|
||||||
|
|
||||||
};
|
};
|
||||||
khscodes.infrastructure.vault-server-approle.policy = {
|
khscodes.infrastructure.vault-server-approle.policy = {
|
||||||
"mx.kaareskovgaard.net/data/users/*" = {
|
"mx.kaareskovgaard.net/data/users/*" = {
|
||||||
|
@ -235,6 +258,7 @@ in
|
||||||
# with our own.
|
# with our own.
|
||||||
preStart = lib.mkAfter ''
|
preStart = lib.mkAfter ''
|
||||||
cp ${passDbFile} /run/dovecot2/passwd
|
cp ${passDbFile} /run/dovecot2/passwd
|
||||||
|
cp ${userDbFile} /run/dovecot2/userdb
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
# This prevents local usernames without domain names to get rewritten.
|
# This prevents local usernames without domain names to get rewritten.
|
||||||
|
|
|
@ -0,0 +1,140 @@
|
||||||
|
{
|
||||||
|
lib,
|
||||||
|
accounts,
|
||||||
|
accountPrimaryEmail,
|
||||||
|
accountAlternativeEmails,
|
||||||
|
extraVirtualAliases ? { },
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
# I would like to not use emails as usernames, but this is not something postfix is particularly happy with,
|
||||||
|
# as far as I can see. I *think* I can do this by randomly selecting an address, ie. the first, as the "primary"
|
||||||
|
# address, and then map all other addresses to that one. Then create a virtual mailbox map that maps that back
|
||||||
|
# to the username before delivering it to lmtp. All of this just worked when using ldap, but that meant
|
||||||
|
# not using code configured accounts set up with opentofu as well, and would also make the email delivery
|
||||||
|
# take a hard dependency on ldap (and not just the login process).
|
||||||
|
|
||||||
|
# Most of these functions are almost the same as what is found inside nixos-simple-mailserver,
|
||||||
|
# just modified with this in mind.
|
||||||
|
|
||||||
|
# Merge several lookup tables. A lookup table is a attribute set where
|
||||||
|
# - the key is an address (user@example.com) or a domain (@example.com)
|
||||||
|
# - the value is a list of addresses
|
||||||
|
mergeLookupTables = tables: lib.zipAttrsWith (_: v: lib.flatten v) tables;
|
||||||
|
|
||||||
|
# lookupTableToString :: Map String [String] -> String
|
||||||
|
lookupTableToString =
|
||||||
|
attrs:
|
||||||
|
let
|
||||||
|
valueToString = value: lib.concatStringsSep ", " value;
|
||||||
|
in
|
||||||
|
lib.concatStringsSep "\n" (
|
||||||
|
lib.mapAttrsToList (name: value: "${name} ${valueToString value}") attrs
|
||||||
|
);
|
||||||
|
# attrsToLookupTable :: Map String (Either String [ String ]) -> Map String [String]
|
||||||
|
attrsToLookupTable =
|
||||||
|
aliases:
|
||||||
|
let
|
||||||
|
lookupTables = lib.mapAttrsToList (from: to: { "${from}" = to; }) aliases;
|
||||||
|
in
|
||||||
|
mergeLookupTables lookupTables;
|
||||||
|
|
||||||
|
# valiases_postfix :: Map String [String]
|
||||||
|
valiases_postfix = mergeLookupTables (
|
||||||
|
lib.flatten (
|
||||||
|
lib.mapAttrsToList (
|
||||||
|
name: value:
|
||||||
|
let
|
||||||
|
to = name;
|
||||||
|
in
|
||||||
|
map (from: { "${from}" = to; }) (
|
||||||
|
(accountAlternativeEmails name value) ++ lib.singleton (accountPrimaryEmail name value)
|
||||||
|
)
|
||||||
|
) accounts
|
||||||
|
)
|
||||||
|
);
|
||||||
|
# catchAllPostfix :: Map String [String]
|
||||||
|
catchAllPostfix = mergeLookupTables (
|
||||||
|
lib.flatten (
|
||||||
|
lib.mapAttrsToList (
|
||||||
|
name: value:
|
||||||
|
let
|
||||||
|
to = name;
|
||||||
|
in
|
||||||
|
map (from: { "@${from}" = to; }) value.catchAll
|
||||||
|
) accounts
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
# mailserverExtraVirtualAliases :: Map String (Map String)
|
||||||
|
mailserverExtraVirtualAliases = lib.attrsets.mapAttrs (
|
||||||
|
name: value:
|
||||||
|
let
|
||||||
|
value = if lib.lists.isList value then value else [ value ];
|
||||||
|
to = name;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
name = to;
|
||||||
|
value = lib.lists.map (
|
||||||
|
addr:
|
||||||
|
assert (lib.attrsets.hasAttr addr accounts);
|
||||||
|
accountPrimaryEmail name accounts."${addr}"
|
||||||
|
) value;
|
||||||
|
}
|
||||||
|
) extraVirtualAliases;
|
||||||
|
|
||||||
|
# extra_valiases_postfix :: Map String [String]
|
||||||
|
extra_valiases_postfix = attrsToLookupTable extraVirtualAliases;
|
||||||
|
|
||||||
|
# all_valiases_postfix :: Map String [String]
|
||||||
|
all_valiases_postfix = mergeLookupTables [
|
||||||
|
valiases_postfix
|
||||||
|
extra_valiases_postfix
|
||||||
|
];
|
||||||
|
|
||||||
|
# valiases_file :: Path
|
||||||
|
valiases_file =
|
||||||
|
let
|
||||||
|
content = lookupTableToString (mergeLookupTables [
|
||||||
|
all_valiases_postfix
|
||||||
|
catchAllPostfix
|
||||||
|
]);
|
||||||
|
in
|
||||||
|
builtins.toFile "valias" content;
|
||||||
|
|
||||||
|
regex_valiases_postfix = mergeLookupTables (
|
||||||
|
lib.flatten (
|
||||||
|
lib.mapAttrsToList (
|
||||||
|
name: value:
|
||||||
|
let
|
||||||
|
to = name;
|
||||||
|
in
|
||||||
|
map (from: { "${from}" = to; }) value.aliasesRegexp
|
||||||
|
) accounts
|
||||||
|
)
|
||||||
|
);
|
||||||
|
regex_valiases_file =
|
||||||
|
let
|
||||||
|
content = lookupTableToString regex_valiases_postfix;
|
||||||
|
in
|
||||||
|
builtins.toFile "regex_valias" content;
|
||||||
|
|
||||||
|
# vaccounts_file :: Path
|
||||||
|
# see
|
||||||
|
# https://blog.grimneko.de/2011/12/24/a-bunch-of-tips-for-improving-your-postfix-setup/
|
||||||
|
# for details on how this file looks. By using the same file as valiases,
|
||||||
|
# every alias is owned (uniquely) by its user.
|
||||||
|
# The user's own address is already in all_valiases_postfix.
|
||||||
|
vaccounts_file = builtins.toFile "vaccounts" (lookupTableToString all_valiases_postfix);
|
||||||
|
regex_vaccounts_file = builtins.toFile "regex_vaccounts" (
|
||||||
|
lookupTableToString regex_valiases_postfix
|
||||||
|
);
|
||||||
|
in
|
||||||
|
{
|
||||||
|
inherit
|
||||||
|
valiases_file
|
||||||
|
regex_valiases_file
|
||||||
|
vaccounts_file
|
||||||
|
regex_vaccounts_file
|
||||||
|
mailserverExtraVirtualAliases
|
||||||
|
;
|
||||||
|
}
|
|
@ -41,7 +41,7 @@ in
|
||||||
base = dc=login,dc=kaareskovgaard,dc=net
|
base = dc=login,dc=kaareskovgaard,dc=net
|
||||||
scope = subtree
|
scope = subtree
|
||||||
pass_attrs = uid=user
|
pass_attrs = uid=user
|
||||||
pass_filter = (&(class=account)(memberOf=mail_user)(uid=%u)
|
pass_filter = (&(class=account)(memberOf=mail_user)(uid=%u))
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
'';
|
'';
|
||||||
destination = secretFile;
|
destination = secretFile;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue