nix-flakes/hosts/server/kazusa/services/mailserver.nix
imnyang 70284509f3
Some checks failed
CI / check (push) Has been cancelled
CI / ida (push) Has been cancelled
CI / cpt (push) Has been cancelled
CI / build-nixos (ena) (push) Has been cancelled
CI / build-nixos (hako) (push) Has been cancelled
CI / build-nixos (kazusa) (push) Has been cancelled
CI / build-nixos (mizuki) (push) Has been cancelled
Initial commit
2026-07-03 16:53:49 +09:00

201 lines
5.1 KiB
Nix

{
config,
pkgs,
lib,
...
}:
let
mailSecret = key: {
sopsFile = ../secrets/mailserver.yaml;
inherit key;
owner = "nginx";
group = "nginx";
mode = "0440";
restartUnits = [
"phpfpm-roundcube.service"
"dovecot.service"
];
};
clientIdSecret = config.sops.secrets."mailserver/oauth/client-id".path;
clientSecret = config.sops.secrets."mailserver/oauth/client-secret".path;
in
{
sops.secrets."mailserver/oauth/client-id" = mailSecret "mailserver/oauth/client-id";
sops.secrets."mailserver/oauth/client-secret" = mailSecret "mailserver/oauth/client-secret";
imports = [
(builtins.fetchTarball {
url = "https://gitlab.com/simple-nixos-mailserver/nixos-mailserver/-/archive/51726d7b7fd94aa69829fd42749a803914cbf3b7/nixos-mailserver-51726d7b7fd94aa69829fd42749a803914cbf3b7.tar.gz";
sha256 = "0449ssnpwbgfv0cyddzb8s6g641gy5xh1hd3shg32x8pv0a5qy3a";
})
];
security.acme.acceptTerms = false;
services.roundcube = {
enable = true;
hostName = "mail.mizuki.guru";
package = pkgs.roundcube.withPlugins (
plugins: with plugins; [
persistent_login
]
);
plugins = [
"persistent_login"
"managesieve"
];
dicts = with pkgs.aspellDicts; [
en
];
maxAttachmentSize = config.mailserver.messageSizeLimit / 1024 / 1024;
extraConfig = ''
$_SERVER['HTTPS'] = 'on';
$_SERVER['SERVER_PORT'] = 443;
$_SERVER['HTTP_X_FORWARDED_PORT'] = 443;
$_SERVER['HTTP_X_FORWARDED_PROTO'] = 'https';
$_SERVER['HTTP_HOST'] = 'mail.mizuki.guru';
$config['proxy_ips'] = '127.0.0.1';
$config['imap_host'] = "ssl://${config.mailserver.fqdn}";
$config['smtp_host'] = "ssl://${config.mailserver.fqdn}";
$config['smtp_user'] = "%u";
$config['smtp_pass'] = "%p";
$config['managesieve_host'] = "tls://${config.mailserver.fqdn}";
$config['managesieve_port'] = 4190;
$config['managesieve_usetls'] = true;
$config['oauth_provider'] = 'generic';
$config['oauth_provider_name'] = 'authentik';
$config['oauth_client_id'] =
trim(file_get_contents('${clientIdSecret}'));
$config['oauth_client_secret'] =
trim(file_get_contents('${clientSecret}'));
$config['oauth_auth_uri'] =
'https://auth.mizuki.guru/application/o/authorize/';
$config['oauth_token_uri'] =
'https://auth.mizuki.guru/application/o/token/';
$config['oauth_identity_uri'] =
'https://auth.mizuki.guru/application/o/userinfo/';
$config['oauth_scope'] =
"email openid dovecotprofile offline_access";
$config['oauth_auth_parameters'] = [];
$config['oauth_identity_fields'] = ['email'];
'';
};
services.nginx.virtualHosts.${config.services.roundcube.hostName} = {
forceSSL = false;
enableACME = false;
listen = [
{
addr = "127.0.0.1";
port = 5656;
}
];
extraConfig = ''
set_real_ip_from 127.0.0.1;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
'';
};
services.caddy = {
enable = true;
virtualHosts."mail.mizuki.guru" = {
extraConfig = ''
reverse_proxy localhost:5656
'';
};
};
services.dovecot2.settings = {
auth_mechanisms = lib.mkForce [
"plain"
"login"
"xoauth2"
"oauthbearer"
];
oauth2_tokeninfo_url = "https://auth.mizuki.guru/application/o/userinfo/?access_token=";
# 주의:
# 여기는 아직 secret '값'이 아니라 secret '경로'가 들어감.
# Dovecot이 URL 안에서 file_get_contents 같은 처리를 안 하므로
# 이 방식은 제대로 동작하지 않을 가능성이 큼.
oauth2_introspection_url = "https://auth.mizuki.guru/application/o/introspect/";
oauth2_introspection_mode = "post";
oauth2_force_introspection = "yes";
oauth2_active_attribute = "active";
oauth2_active_value = "true";
oauth2_username_attribute = "email";
};
users.users.dovecot = {
isSystemUser = true;
group = "dovecot";
extraGroups = [ "caddy" ];
};
users.groups.dovecot = { };
users.users.postfix.extraGroups = [ "caddy" ];
mailserver = {
enable = true;
stateVersion = 4;
fqdn = "mail.mizuki.guru";
domains = [ "mizuki.guru" ];
x509 = {
certificateFile = "/var/lib/caddy/.local/share/caddy/certificates/acme-v02.api.letsencrypt.org-directory/mail.mizuki.guru/mail.mizuki.guru.crt";
privateKeyFile = "/var/lib/caddy/.local/share/caddy/certificates/acme-v02.api.letsencrypt.org-directory/mail.mizuki.guru/mail.mizuki.guru.key";
};
ldap = {
enable = true;
uris = [ "ldap://10.11.8.102" ];
bind = {
dn = "cn=mailserver,ou=users,dc=ldap,dc=goauthentik,dc=io";
passwordFile = "/var/lib/secrets/authentik-ldap-bind-pw";
};
base = "ou=users,dc=ldap,dc=goauthentik,dc=io";
scope = "sub";
attributes = {
uuid = "uid";
username = "mail";
mail = "mail";
};
dovecot = {
passFilter = "mail=%{user}\n bind = yes";
};
};
accounts = { };
};
}