mailserver: init
This commit is contained in:
parent
a7c73695db
commit
ef19e76b97
6 changed files with 1398 additions and 12 deletions
|
|
@ -174,6 +174,7 @@ Also, the stack fits together nicely thanks to [contracts](#contracts).
|
|||
- Nextcloud
|
||||
- Audiobookshelf
|
||||
- Deluge + *arr stack
|
||||
- Simple NixOS Mailserver
|
||||
- Firefly-iii
|
||||
- Forgejo
|
||||
- Grocy
|
||||
|
|
|
|||
|
|
@ -2720,6 +2720,9 @@
|
|||
"services-category-documents": [
|
||||
"services.html#services-category-documents"
|
||||
],
|
||||
"services-category-emails": [
|
||||
"services.html#services-category-emails"
|
||||
],
|
||||
"services-category-finance": [
|
||||
"services.html#services-category-finance"
|
||||
],
|
||||
|
|
@ -3944,6 +3947,294 @@
|
|||
"services-karakeep-usage": [
|
||||
"services-karakeep.html#services-karakeep-usage"
|
||||
],
|
||||
"services-mailserver": [
|
||||
"services-mailserver.html#services-mailserver"
|
||||
],
|
||||
"services-mailserver-certs": [
|
||||
"services-mailserver.html#services-mailserver-certs"
|
||||
],
|
||||
"services-mailserver-debug": [
|
||||
"services-mailserver.html#services-mailserver-debug"
|
||||
],
|
||||
"services-mailserver-debug-auth": [
|
||||
"services-mailserver.html#services-mailserver-debug-auth"
|
||||
],
|
||||
"services-mailserver-debug-folder-mapping": [
|
||||
"services-mailserver.html#services-mailserver-debug-folder-mapping"
|
||||
],
|
||||
"services-mailserver-debug-folders": [
|
||||
"services-mailserver.html#services-mailserver-debug-folders"
|
||||
],
|
||||
"services-mailserver-debug-local-folders": [
|
||||
"services-mailserver.html#services-mailserver-debug-local-folders"
|
||||
],
|
||||
"services-mailserver-debug-ports": [
|
||||
"services-mailserver.html#services-mailserver-debug-ports"
|
||||
],
|
||||
"services-mailserver-debug-systemd": [
|
||||
"services-mailserver.html#services-mailserver-debug-systemd"
|
||||
],
|
||||
"services-mailserver-declarative-ldap": [
|
||||
"services-mailserver.html#services-mailserver-declarative-ldap"
|
||||
],
|
||||
"services-mailserver-impermanence": [
|
||||
"services-mailserver.html#services-mailserver-impermanence"
|
||||
],
|
||||
"services-mailserver-mobile": [
|
||||
"services-mailserver.html#services-mailserver-mobile"
|
||||
],
|
||||
"services-mailserver-options": [
|
||||
"services-mailserver.html#services-mailserver-options"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.adminPassword": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.adminPassword"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.adminPassword.request": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.adminPassword.request"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.adminPassword.request.group": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.adminPassword.request.group"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.adminPassword.request.mode": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.adminPassword.request.mode"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.adminPassword.request.owner": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.adminPassword.request.owner"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.adminPassword.request.restartUnits": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.adminPassword.request.restartUnits"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.adminPassword.result": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.adminPassword.result"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.adminPassword.result.path": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.adminPassword.result.path"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.adminUsername": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.adminUsername"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.backup": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.backup"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.backup.request": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.backup.request"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.backup.request.excludePatterns": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.backup.request.excludePatterns"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.backup.request.hooks": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.backup.request.hooks"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.backup.request.hooks.afterBackup": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.backup.request.hooks.afterBackup"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.backup.request.hooks.beforeBackup": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.backup.request.hooks.beforeBackup"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.backup.request.sourceDirectories": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.backup.request.sourceDirectories"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.backup.request.user": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.backup.request.user"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.backup.result": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.backup.result"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.backup.result.backupService": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.backup.result.backupService"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.backup.result.restoreScript": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.backup.result.restoreScript"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.domain": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.domain"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.enable": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.enable"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.imapSync": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.imapSync"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.imapSync.accounts": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.imapSync.accounts"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.imapSync.accounts._name_.host": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.imapSync.accounts._name_.host"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.imapSync.accounts._name_.mapSpecialDrafts": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.imapSync.accounts._name_.mapSpecialDrafts"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.imapSync.accounts._name_.mapSpecialJunk": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.imapSync.accounts._name_.mapSpecialJunk"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.imapSync.accounts._name_.mapSpecialSent": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.imapSync.accounts._name_.mapSpecialSent"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.imapSync.accounts._name_.mapSpecialTrash": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.imapSync.accounts._name_.mapSpecialTrash"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.imapSync.accounts._name_.password": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.imapSync.accounts._name_.password"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.imapSync.accounts._name_.password.request": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.imapSync.accounts._name_.password.request"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.imapSync.accounts._name_.password.request.group": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.imapSync.accounts._name_.password.request.group"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.imapSync.accounts._name_.password.request.mode": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.imapSync.accounts._name_.password.request.mode"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.imapSync.accounts._name_.password.request.owner": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.imapSync.accounts._name_.password.request.owner"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.imapSync.accounts._name_.password.request.restartUnits": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.imapSync.accounts._name_.password.request.restartUnits"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.imapSync.accounts._name_.password.result": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.imapSync.accounts._name_.password.result"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.imapSync.accounts._name_.password.result.path": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.imapSync.accounts._name_.password.result.path"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.imapSync.accounts._name_.port": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.imapSync.accounts._name_.port"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.imapSync.accounts._name_.sslType": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.imapSync.accounts._name_.sslType"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.imapSync.accounts._name_.timeout": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.imapSync.accounts._name_.timeout"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.imapSync.accounts._name_.username": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.imapSync.accounts._name_.username"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.imapSync.debug": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.imapSync.debug"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.imapSync.syncTimer": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.imapSync.syncTimer"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.impermanence": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.impermanence"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.ldap": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.ldap"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.ldap.account": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.ldap.account"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.ldap.adminName": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.ldap.adminName"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.ldap.adminPassword": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.ldap.adminPassword"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.ldap.adminPassword.request": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.ldap.adminPassword.request"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.ldap.adminPassword.request.group": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.ldap.adminPassword.request.group"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.ldap.adminPassword.request.mode": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.ldap.adminPassword.request.mode"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.ldap.adminPassword.request.owner": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.ldap.adminPassword.request.owner"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.ldap.adminPassword.request.restartUnits": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.ldap.adminPassword.request.restartUnits"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.ldap.adminPassword.result": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.ldap.adminPassword.result"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.ldap.adminPassword.result.path": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.ldap.adminPassword.result.path"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.ldap.dcdomain": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.ldap.dcdomain"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.ldap.enable": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.ldap.enable"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.ldap.host": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.ldap.host"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.ldap.port": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.ldap.port"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.ldap.userGroup": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.ldap.userGroup"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.smtpRelay": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.smtpRelay"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.smtpRelay.host": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.smtpRelay.host"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.smtpRelay.password": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.smtpRelay.password"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.smtpRelay.password.request": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.smtpRelay.password.request"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.smtpRelay.password.request.group": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.smtpRelay.password.request.group"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.smtpRelay.password.request.mode": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.smtpRelay.password.request.mode"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.smtpRelay.password.request.owner": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.smtpRelay.password.request.owner"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.smtpRelay.password.request.restartUnits": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.smtpRelay.password.request.restartUnits"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.smtpRelay.password.result": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.smtpRelay.password.result"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.smtpRelay.password.result.path": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.smtpRelay.password.result.path"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.smtpRelay.port": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.smtpRelay.port"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.smtpRelay.username": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.smtpRelay.username"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.ssl": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.ssl"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.ssl.paths": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.ssl.paths"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.ssl.paths.cert": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.ssl.paths.cert"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.ssl.paths.key": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.ssl.paths.key"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.ssl.systemdService": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.ssl.systemdService"
|
||||
],
|
||||
"services-mailserver-options-shb.mailserver.subdomain": [
|
||||
"services-mailserver.html#services-mailserver-options-shb.mailserver.subdomain"
|
||||
],
|
||||
"services-mailserver-usage": [
|
||||
"services-mailserver.html#services-mailserver-usage"
|
||||
],
|
||||
"services-mailserver-usage-backup": [
|
||||
"services-mailserver.html#services-mailserver-usage-backup"
|
||||
],
|
||||
"services-mailserver-usage-disk-layout": [
|
||||
"services-mailserver.html#services-mailserver-usage-disk-layout"
|
||||
],
|
||||
"services-mailserver-usage-ldap": [
|
||||
"services-mailserver.html#services-mailserver-usage-ldap"
|
||||
],
|
||||
"services-mailserver-usage-secrets": [
|
||||
"services-mailserver.html#services-mailserver-usage-secrets"
|
||||
],
|
||||
"services-monitoring-features": [
|
||||
"blocks-monitoring.html#services-monitoring-features"
|
||||
],
|
||||
|
|
|
|||
|
|
@ -13,18 +13,19 @@ Not all services are yet documented. You can find all available services [in the
|
|||
The following table summarizes for each documented service what features it provides. More
|
||||
information is provided in the respective manual sections.
|
||||
|
||||
| Service | Backup | Reverse Proxy | SSO | LDAP | Monitoring | Profiling |
|
||||
|----------------------|--------|---------------|-----|-------|------------|-----------|
|
||||
| [*Arr][] | Y (1) | Y | Y | Y (4) | Y (2) | N |
|
||||
| [Firefly-iii][] | Y (1) | Y | Y | Y | Y (2) | N |
|
||||
| [Forgejo][] | Y (1) | Y | Y | Y | Y (2) | N |
|
||||
| [Home-Assistant][] | Y (1) | Y | N | Y | Y (2) | N |
|
||||
| [Jellyfin][] | Y (1) | Y | Y | Y | Y (2) | N |
|
||||
| [Karakeep][] | Y (1) | Y | Y | Y | Y (2) | N |
|
||||
| [Nextcloud Server][] | Y (1) | Y | Y | Y | Y (2) | P (3) |
|
||||
| [Open WebUI][] | Y (1) | Y | Y | Y | Y (2) | N |
|
||||
| [Pinchflat][] | Y | Y | Y | Y (4) | Y (5) | N |
|
||||
| [Vaultwarden][] | Y (1) | Y | Y | Y | Y (2) | N |
|
||||
| Service | Backup | Reverse Proxy | SSO | LDAP | Monitoring | Profiling |
|
||||
|-----------------------------|--------|---------------|-----|-------|------------|-----------|
|
||||
| [*Arr][] | Y (1) | Y | Y | Y (4) | Y (2) | N |
|
||||
| [Firefly-iii][] | Y (1) | Y | Y | Y | Y (2) | N |
|
||||
| [Forgejo][] | Y (1) | Y | Y | Y | Y (2) | N |
|
||||
| [Home-Assistant][] | Y (1) | Y | N | Y | Y (2) | N |
|
||||
| [Jellyfin][] | Y (1) | Y | Y | Y | Y (2) | N |
|
||||
| [Karakeep][] | Y (1) | Y | Y | Y | Y (2) | N |
|
||||
| [Nextcloud Server][] | Y (1) | Y | Y | Y | Y (2) | P (3) |
|
||||
| [Open WebUI][] | Y (1) | Y | Y | Y | Y (2) | N |
|
||||
| [Pinchflat][] | Y | Y | Y | Y (4) | Y (5) | N |
|
||||
| [Simple NixOS Mailserver][] | Y | Y | N | Y | Y | N |
|
||||
| [Vaultwarden][] | Y (1) | Y | Y | Y | Y (2) | N |
|
||||
|
||||
Legend: **N**: no but WIP; **P**: partial; **Y**: yes
|
||||
|
||||
|
|
@ -44,6 +45,7 @@ Legend: **N**: no but WIP; **P**: partial; **Y**: yes
|
|||
[Nextcloud Server]: services-nextcloud.html
|
||||
[Open WebUI]: services-open-webui.html
|
||||
[Pinchflat]: services-pinchflat.html
|
||||
[Simple NixOS Mailserver]: services-mailserver.html
|
||||
[Vaultwarden]: services-vaultwarden.html
|
||||
|
||||
## Documents {#services-category-documents}
|
||||
|
|
@ -52,6 +54,12 @@ Legend: **N**: no but WIP; **P**: partial; **Y**: yes
|
|||
modules/services/nextcloud-server/docs/default.md
|
||||
```
|
||||
|
||||
## Emails {#services-category-emails}
|
||||
|
||||
```{=include=} chapters html:into-file=//services-mailserver.html
|
||||
modules/services/mailserver/docs/default.md
|
||||
```
|
||||
|
||||
## Passwords {#services-category-passwords}
|
||||
|
||||
```{=include=} chapters html:into-file=//services-vaultwarden.html
|
||||
|
|
|
|||
|
|
@ -112,6 +112,7 @@
|
|||
"services/home-assistant" = ./modules/services/home-assistant.nix;
|
||||
"services/jellyfin" = ./modules/services/jellyfin.nix;
|
||||
"services/karakeep" = ./modules/services/karakeep.nix;
|
||||
"services/mailserver" = ./modules/services/mailserver.nix;
|
||||
"services/nextcloud-server" = {
|
||||
module = ./modules/services/nextcloud-server.nix;
|
||||
optionRoot = [
|
||||
|
|
@ -398,6 +399,7 @@
|
|||
self.nixosModules.home-assistant
|
||||
self.nixosModules.jellyfin
|
||||
self.nixosModules.karakeep
|
||||
self.nixosModules.mailserver
|
||||
self.nixosModules.nextcloud-server
|
||||
self.nixosModules.open-webui
|
||||
self.nixosModules.pinchflat
|
||||
|
|
@ -435,6 +437,7 @@
|
|||
nixosModules.home-assistant = modules/services/home-assistant.nix;
|
||||
nixosModules.jellyfin = modules/services/jellyfin.nix;
|
||||
nixosModules.karakeep = modules/services/karakeep.nix;
|
||||
nixosModules.mailserver = modules/services/mailserver.nix;
|
||||
nixosModules.nextcloud-server = modules/services/nextcloud-server.nix;
|
||||
nixosModules.open-webui = modules/services/open-webui.nix;
|
||||
nixosModules.paperless = modules/services/paperless.nix;
|
||||
|
|
|
|||
703
modules/services/mailserver.nix
Normal file
703
modules/services/mailserver.nix
Normal file
|
|
@ -0,0 +1,703 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
shb,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
let
|
||||
cfg = config.shb.mailserver;
|
||||
in
|
||||
{
|
||||
imports = [
|
||||
(
|
||||
builtins.fetchGit {
|
||||
url = "https://gitlab.com/simple-nixos-mailserver/nixos-mailserver.git";
|
||||
ref = "master";
|
||||
rev = "5965fae920b6b97f39f94bdb6195631e274c93a5";
|
||||
}
|
||||
+ "/default.nix"
|
||||
)
|
||||
../blocks/lldap.nix
|
||||
];
|
||||
|
||||
options.shb.mailserver = {
|
||||
enable = lib.mkEnableOption "SHB's nixos-mailserver module";
|
||||
|
||||
subdomain = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "Subdomain under which imap and smtp functions will be served.";
|
||||
default = "imap";
|
||||
};
|
||||
|
||||
domain = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "domain under which imap and smtp functions will be served.";
|
||||
example = "mydomain.com";
|
||||
};
|
||||
|
||||
ssl = lib.mkOption {
|
||||
description = "Path to SSL files";
|
||||
type = lib.types.nullOr shb.contracts.ssl.certs;
|
||||
default = null;
|
||||
};
|
||||
|
||||
adminUsername = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = null;
|
||||
description = ''
|
||||
Admin username.
|
||||
|
||||
postmaster will be made an alias of this user.
|
||||
'';
|
||||
example = "admin";
|
||||
};
|
||||
|
||||
adminPassword = lib.mkOption {
|
||||
description = "Admin user password.";
|
||||
default = null;
|
||||
type = lib.types.nullOr (
|
||||
lib.types.submodule {
|
||||
options = shb.contracts.secret.mkRequester {
|
||||
mode = "0400";
|
||||
owner = config.services.postfix.user;
|
||||
ownerText = "services.postfix.user";
|
||||
restartUnits = [ "dovecot.service" ];
|
||||
};
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
imapSync = lib.mkOption {
|
||||
description = ''
|
||||
Synchronize one or more email providers through IMAP
|
||||
to your dovecot2 instance.
|
||||
|
||||
This allows you to backup that email provider
|
||||
and centralize your accounts in this dovecot2 instance.
|
||||
'';
|
||||
default = null;
|
||||
type = lib.types.nullOr (
|
||||
lib.types.submodule {
|
||||
options = {
|
||||
syncTimer = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "5m";
|
||||
description = ''
|
||||
Systemd timer for when imap sync job should happen.
|
||||
|
||||
This timer is not scheduling the job at regular intervals.
|
||||
After a job finishes, the given amount of time is waited then the next job is started.
|
||||
|
||||
The default is set deliberatily slow to not spam you when setting up your mailserver.
|
||||
When everything works, you will want to reduce it to 10s or something like that.
|
||||
'';
|
||||
example = "10s";
|
||||
};
|
||||
|
||||
debug = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = "Enable verbose mbsync logging.";
|
||||
};
|
||||
|
||||
accounts = lib.mkOption {
|
||||
description = ''
|
||||
Accounts to sync emails from using IMAP.
|
||||
|
||||
Emails will be stored under `''${config.mailserver.mailDirectory}/''${name}/''${username}`
|
||||
'';
|
||||
type = lib.types.attrsOf (
|
||||
lib.types.submodule {
|
||||
options = {
|
||||
host = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "Hostname of the email's provider IMAP server.";
|
||||
example = "imap.fastmail.com";
|
||||
};
|
||||
|
||||
port = lib.mkOption {
|
||||
type = lib.types.port;
|
||||
description = "Port of the email's provider IMAP server.";
|
||||
default = 993;
|
||||
};
|
||||
|
||||
username = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "Username used to login to the email's provider IMAP server.";
|
||||
example = "userA@fastmail.com";
|
||||
};
|
||||
|
||||
password = lib.mkOption {
|
||||
description = ''
|
||||
Password used to login to the email's provider IMAP server.
|
||||
|
||||
The password could be an "app password" like for [Fastmail](https://www.fastmail.help/hc/en-us/articles/360058752854-App-passwords)
|
||||
'';
|
||||
type = lib.types.submodule {
|
||||
options = shb.contracts.secret.mkRequester {
|
||||
mode = "0400";
|
||||
owner = config.mailserver.vmailUserName;
|
||||
restartUnits = [ "mbsync.service" ];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
sslType = lib.mkOption {
|
||||
description = "Connection security method.";
|
||||
type = lib.types.enum [
|
||||
"IMAPS"
|
||||
"STARTTLS"
|
||||
];
|
||||
default = "IMAPS";
|
||||
};
|
||||
|
||||
timeout = lib.mkOption {
|
||||
description = "Connect and data timeout.";
|
||||
type = lib.types.int;
|
||||
default = 120;
|
||||
};
|
||||
|
||||
mapSpecialDrafts = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "Drafts";
|
||||
description = ''
|
||||
Drafts special folder name on far side.
|
||||
|
||||
You only need to change this if mbsync logs the following error:
|
||||
|
||||
Error: ... far side box Drafts cannot be opened
|
||||
'';
|
||||
};
|
||||
mapSpecialSent = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "Sent";
|
||||
description = ''
|
||||
Sent special folder name on far side.
|
||||
|
||||
You only need to change this if mbsync logs the following error:
|
||||
|
||||
Error: ... far side box Sent cannot be opened
|
||||
'';
|
||||
};
|
||||
mapSpecialTrash = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "Trash";
|
||||
description = ''
|
||||
Trash special folder name on far side.
|
||||
|
||||
You only need to change this if mbsync logs the following error:
|
||||
|
||||
Error: ... far side box Trash cannot be opened
|
||||
'';
|
||||
};
|
||||
mapSpecialJunk = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "Junk";
|
||||
description = ''
|
||||
Junk special folder name on far side.
|
||||
|
||||
You only need to change this if mbsync logs the following error:
|
||||
|
||||
Error: ... far side box Junk cannot be opened
|
||||
'';
|
||||
example = "Spam";
|
||||
};
|
||||
};
|
||||
}
|
||||
);
|
||||
};
|
||||
};
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
smtpRelay = lib.mkOption {
|
||||
description = ''
|
||||
Proxy outgoing emails through an email provider.
|
||||
|
||||
In short, this can help you avoid having your outgoing emails marked as spam.
|
||||
See the manual for a lengthier explanation.
|
||||
'';
|
||||
default = null;
|
||||
type = lib.types.nullOr (
|
||||
lib.types.submodule {
|
||||
options = {
|
||||
host = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "Hostname of the email's provider SMTP server.";
|
||||
example = "smtp.fastmail.com";
|
||||
};
|
||||
|
||||
port = lib.mkOption {
|
||||
type = lib.types.port;
|
||||
description = "Port of the email's provider SMTP server.";
|
||||
default = 587;
|
||||
};
|
||||
|
||||
username = lib.mkOption {
|
||||
description = "Username used to login to the email's provider SMTP server.";
|
||||
type = lib.types.str;
|
||||
};
|
||||
|
||||
password = lib.mkOption {
|
||||
description = ''
|
||||
Password used to login to the email's provider IMAP server.
|
||||
|
||||
The password could be an "app password" like for [Fastmail](https://www.fastmail.help/hc/en-us/articles/360058752854-App-passwords)
|
||||
'';
|
||||
type = lib.types.submodule {
|
||||
options = shb.contracts.secret.mkRequester {
|
||||
mode = "0400";
|
||||
owner = config.services.postfix.user;
|
||||
ownerText = "services.postfix.user";
|
||||
restartUnits = [ "postfix.service" ];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
ldap = lib.mkOption {
|
||||
description = ''
|
||||
LDAP Integration.
|
||||
|
||||
Enabling this app will create a new LDAP configuration or update one that exists with
|
||||
the given host.
|
||||
'';
|
||||
default = { };
|
||||
type = lib.types.nullOr (
|
||||
lib.types.submodule {
|
||||
options = {
|
||||
enable = lib.mkEnableOption "LDAP app.";
|
||||
|
||||
host = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = ''
|
||||
Host serving the LDAP server.
|
||||
'';
|
||||
default = "127.0.0.1";
|
||||
};
|
||||
|
||||
port = lib.mkOption {
|
||||
type = lib.types.port;
|
||||
description = ''
|
||||
Port of the service serving the LDAP server.
|
||||
'';
|
||||
default = 389;
|
||||
};
|
||||
|
||||
dcdomain = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "dc domain for ldap.";
|
||||
example = "dc=mydomain,dc=com";
|
||||
};
|
||||
|
||||
account = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = ''
|
||||
Select one account from those defined in `shb.mailserver.imapSync.accounts`
|
||||
to login with.
|
||||
|
||||
Using LDAP, you can only connect to one account.
|
||||
This limitation could maybe be lifted, feel free to post an issue if you need this.
|
||||
'';
|
||||
};
|
||||
|
||||
adminName = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "Admin user of the LDAP server.";
|
||||
default = "admin";
|
||||
};
|
||||
|
||||
adminPassword = lib.mkOption {
|
||||
description = "LDAP server admin password.";
|
||||
type = lib.types.submodule {
|
||||
options = shb.contracts.secret.mkRequester {
|
||||
mode = "0400";
|
||||
owner = "nextcloud";
|
||||
restartUnits = [ "dovecot.service" ];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
userGroup = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "Group users must belong to to be able to use mails.";
|
||||
default = "mail_user";
|
||||
};
|
||||
};
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
backup = lib.mkOption {
|
||||
description = ''
|
||||
Backup emails.
|
||||
'';
|
||||
default = { };
|
||||
type = lib.types.submodule {
|
||||
options = shb.contracts.backup.mkRequester {
|
||||
user = config.mailserver.vmailUserName;
|
||||
sourceDirectories = builtins.filter (x: x != null) [
|
||||
config.mailserver.indexDir
|
||||
config.mailserver.mailDirectory
|
||||
config.mailserver.sieveDirectory
|
||||
config.mailserver.dkimKeyDirectory
|
||||
];
|
||||
sourceDirectoriesText = ''
|
||||
[
|
||||
config.mailserver.indexDir
|
||||
config.mailserver.mailDirectory
|
||||
config.mailserver.sieveDirectory
|
||||
config.mailserver.dkimKeyDirectory
|
||||
]
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
impermanence = lib.mkOption {
|
||||
description = ''
|
||||
Path to save when using impermanence setup.
|
||||
'';
|
||||
type = lib.types.attrsOf lib.types.str;
|
||||
default = {
|
||||
index = config.mailserver.indexDir;
|
||||
mail = config.mailserver.mailDirectory;
|
||||
sieve = config.mailserver.sieveDirectory;
|
||||
dkim = config.mailserver.dkimKeyDirectory;
|
||||
};
|
||||
defaultText = lib.literalExpression ''
|
||||
{
|
||||
index = config.mailserver.indexDir;
|
||||
mail = config.mailserver.mailDirectory;
|
||||
sieve = config.mailserver.sieveDirectory;
|
||||
dkim = config.mailserver.dkimKeyDirectory;
|
||||
}
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkMerge [
|
||||
(lib.mkIf cfg.enable {
|
||||
mailserver = {
|
||||
enable = true;
|
||||
stateVersion = 3;
|
||||
fqdn = "${cfg.subdomain}.${cfg.domain}";
|
||||
domains = [ cfg.domain ];
|
||||
|
||||
localDnsResolver = false;
|
||||
|
||||
certificateScheme = "acme-nginx";
|
||||
enableImapSsl = true;
|
||||
enableSubmissionSsl = true;
|
||||
|
||||
# Using / is needed for iOS mail.
|
||||
# Both following options are used to organize subfolders in subdirectories.
|
||||
hierarchySeparator = "/";
|
||||
useFsLayout = true;
|
||||
};
|
||||
|
||||
services.postfix.config = {
|
||||
smtpd_tls_security_level = lib.mkForce "encrypt";
|
||||
};
|
||||
|
||||
# Is probably needed for iOS mail.
|
||||
services.dovecot2.extraConfig = ''
|
||||
ssl_min_protocol = TLSv1.2
|
||||
ssl_cipher_list = HIGH:!aNULL:!MD5
|
||||
'';
|
||||
|
||||
services.nginx = {
|
||||
enable = true;
|
||||
|
||||
virtualHosts."${cfg.domain}" =
|
||||
let
|
||||
announce = pkgs.writeTextDir "config-v1.1.xml" ''
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<clientConfig version="1.1">
|
||||
<emailProvider id="${cfg.domain}">
|
||||
<domain>${cfg.domain}</domain>
|
||||
<displayName>${cfg.domain} Mailserver</displayName>
|
||||
|
||||
<!-- Incoming IMAP server -->
|
||||
<incomingServer type="imap">
|
||||
<hostname>${cfg.subdomain}.${cfg.domain}</hostname>
|
||||
<port>993</port>
|
||||
<socketType>SSL</socketType>
|
||||
<authentication>password-cleartext</authentication>
|
||||
<username>%EMAILADDRESS%</username>
|
||||
</incomingServer>
|
||||
|
||||
<!-- Outgoing SMTP server -->
|
||||
<outgoingServer type="smtp">
|
||||
<hostname>${cfg.subdomain}.${cfg.domain}</hostname>
|
||||
<port>465</port>
|
||||
<socketType>STARTTLS</socketType>
|
||||
<authentication>password-cleartext</authentication>
|
||||
<username>%EMAILADDRESS%</username>
|
||||
</outgoingServer>
|
||||
|
||||
</emailProvider>
|
||||
</clientConfig>
|
||||
'';
|
||||
in
|
||||
{
|
||||
forceSSL = true; # Redirect HTTP → HTTPS
|
||||
root = "/var/www"; # Dummy root
|
||||
locations."/.well-known/autoconfig/mail/" = {
|
||||
alias = "${announce}/";
|
||||
extraConfig = ''
|
||||
default_type application/xml;
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
})
|
||||
(lib.mkIf (cfg.enable && cfg.adminUsername != null) {
|
||||
assertions = [
|
||||
{
|
||||
assertion = cfg.adminPassword != null;
|
||||
message = "`shb.mailserver.adminPassword` must be not null if `shb.mailserver.adminUsername` is not null.";
|
||||
}
|
||||
];
|
||||
|
||||
mailserver = {
|
||||
# To create the password hashes, use:
|
||||
# nix run nixpkgs#mkpasswd -- --run 'mkpasswd -s'
|
||||
loginAccounts = {
|
||||
"${cfg.adminUsername}@${cfg.domain}" = {
|
||||
hashedPasswordFile = cfg.adminPassword.result.path;
|
||||
aliases = [ "postmaster@${cfg.domain}" ];
|
||||
};
|
||||
};
|
||||
};
|
||||
})
|
||||
(lib.mkIf (cfg.enable && cfg.ldap != null) {
|
||||
assertions = [
|
||||
{
|
||||
assertion = cfg.adminUsername == null;
|
||||
message = "`shb.mailserver.adminUsername` must be null `shb.mailserver.ldap` integration is set.";
|
||||
}
|
||||
];
|
||||
|
||||
shb.lldap.ensureGroups = {
|
||||
${cfg.ldap.userGroup} = { };
|
||||
};
|
||||
|
||||
mailserver = {
|
||||
ldap = {
|
||||
enable = true;
|
||||
uris = [
|
||||
"ldap://${cfg.ldap.host}:${toString cfg.ldap.port}"
|
||||
];
|
||||
searchBase = "ou=people,${cfg.ldap.dcdomain}";
|
||||
searchScope = "sub";
|
||||
bind = {
|
||||
dn = "uid=${cfg.ldap.adminName},ou=people,${cfg.ldap.dcdomain}";
|
||||
passwordFile = cfg.ldap.adminPassword.result.path;
|
||||
};
|
||||
# Note that nixos simple mailserver sets auth_bind=yes
|
||||
# which means authentication binds are used.
|
||||
# https://doc.dovecot.org/2.3/configuration_manual/authentication/ldap_bind/#authentication-ldap-bind
|
||||
dovecot =
|
||||
let
|
||||
filter = "(&(objectClass=inetOrgPerson)(mail=%{user})(memberOf=cn=${cfg.ldap.userGroup},ou=groups,${cfg.ldap.dcdomain}))";
|
||||
in
|
||||
{
|
||||
passAttrs = "user=user";
|
||||
passFilter = filter;
|
||||
userAttrs = lib.concatStringsSep "," [
|
||||
"=home=${config.mailserver.mailDirectory}/${cfg.ldap.account}/%u"
|
||||
# "mail=maildir:${config.mailserver.mailDirectory}/${cfg.ldap.account}/%u/mail"
|
||||
"uid=${config.mailserver.vmailUserName}"
|
||||
"gid=${config.mailserver.vmailGroupName}"
|
||||
];
|
||||
userFilter = filter;
|
||||
};
|
||||
postfix = {
|
||||
filter = "(&(objectClass=inetOrgPerson)(mail=%s)(memberOf=cn=${cfg.ldap.userGroup},ou=groups,${cfg.ldap.dcdomain}))";
|
||||
mailAttribute = "mail";
|
||||
uidAttribute = "mail";
|
||||
};
|
||||
};
|
||||
};
|
||||
})
|
||||
(lib.mkIf (cfg.enable && cfg.imapSync != null) {
|
||||
systemd.services.mbsync =
|
||||
let
|
||||
configFile =
|
||||
let
|
||||
mkAccount = name: acct: ''
|
||||
# ${name} account
|
||||
|
||||
IMAPAccount ${name}
|
||||
Host ${acct.host}
|
||||
Port ${toString acct.port}
|
||||
User ${acct.username}
|
||||
PassCmd "cat ${acct.password.result.path}"
|
||||
TLSType ${acct.sslType}
|
||||
AuthMechs LOGIN
|
||||
Timeout ${toString acct.timeout}
|
||||
|
||||
IMAPStore ${name}-remote
|
||||
Account ${name}
|
||||
|
||||
MaildirStore ${name}-local
|
||||
INBOX ${config.mailserver.mailDirectory}/${name}/${acct.username}/mail/
|
||||
# Maps subfolders on far side to actual subfolders on disk.
|
||||
# The other option is Maildir++ but then the mailserver.hierarchySeparator must be set to a dot '.'
|
||||
SubFolders Verbatim
|
||||
Path ${config.mailserver.mailDirectory}/${name}/${acct.username}/mail/
|
||||
|
||||
Channel ${name}-main
|
||||
Far :${name}-remote:
|
||||
Near :${name}-local:
|
||||
Patterns * !Drafts !Sent !Trash !Junk !${acct.mapSpecialDrafts} !${acct.mapSpecialSent} !${acct.mapSpecialTrash} !${acct.mapSpecialJunk}
|
||||
Create Both
|
||||
Expunge Both
|
||||
SyncState *
|
||||
Sync All
|
||||
CopyArrivalDate yes # Preserve date from incoming message.
|
||||
|
||||
Channel ${name}-drafts
|
||||
Far :${name}-remote:"${acct.mapSpecialDrafts}"
|
||||
Near :${name}-local:"Drafts"
|
||||
Create Both
|
||||
Expunge Both
|
||||
SyncState *
|
||||
Sync All
|
||||
CopyArrivalDate yes # Preserve date from incoming message.
|
||||
|
||||
Channel ${name}-sent
|
||||
Far :${name}-remote:"${acct.mapSpecialSent}"
|
||||
Near :${name}-local:"Sent"
|
||||
Create Both
|
||||
Expunge Both
|
||||
SyncState *
|
||||
Sync All
|
||||
CopyArrivalDate yes # Preserve date from incoming message.
|
||||
|
||||
Channel ${name}-trash
|
||||
Far :${name}-remote:"${acct.mapSpecialTrash}"
|
||||
Near :${name}-local:"Trash"
|
||||
Create Both
|
||||
Expunge Both
|
||||
SyncState *
|
||||
Sync All
|
||||
CopyArrivalDate yes # Preserve date from incoming message.
|
||||
|
||||
Channel ${name}-junk
|
||||
Far :${name}-remote:"${acct.mapSpecialJunk}"
|
||||
Near :${name}-local:"Junk"
|
||||
Create Both
|
||||
Expunge Both
|
||||
SyncState *
|
||||
Sync All
|
||||
CopyArrivalDate yes # Preserve date from incoming message.
|
||||
|
||||
Group ${name}
|
||||
Channel ${name}-main
|
||||
Channel ${name}-drafts
|
||||
Channel ${name}-sent
|
||||
Channel ${name}-trash
|
||||
Channel ${name}-junk
|
||||
|
||||
# END ${name} account
|
||||
'';
|
||||
|
||||
in
|
||||
pkgs.writeText "mbsync.conf" (
|
||||
lib.concatStringsSep "\n" (lib.mapAttrsToList mkAccount cfg.imapSync.accounts)
|
||||
);
|
||||
in
|
||||
{
|
||||
description = "Sync mailbox";
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
User = config.mailserver.vmailUserName;
|
||||
};
|
||||
script =
|
||||
let
|
||||
debug = if cfg.imapSync.debug then "-V" else "";
|
||||
in
|
||||
''
|
||||
${pkgs.isync}/bin/mbsync --all ${debug} --config ${configFile}
|
||||
'';
|
||||
};
|
||||
|
||||
systemd.tmpfiles.rules =
|
||||
let
|
||||
mkAccount =
|
||||
name: acct:
|
||||
# The equal sign makes sure parent directories have the corret user and group too.
|
||||
[
|
||||
"d '${config.mailserver.mailDirectory}/${name}' 0750 ${config.mailserver.vmailUserName} ${config.mailserver.vmailGroupName} - -"
|
||||
"d '${config.mailserver.mailDirectory}/${name}/${acct.username}' 0750 ${config.mailserver.vmailUserName} ${config.mailserver.vmailGroupName} - -"
|
||||
];
|
||||
in
|
||||
lib.flatten (lib.mapAttrsToList mkAccount cfg.imapSync.accounts);
|
||||
|
||||
systemd.timers.mbsync = {
|
||||
wantedBy = [ "timers.target" ];
|
||||
timerConfig = {
|
||||
OnBootSec = cfg.imapSync.syncTimer;
|
||||
OnUnitActiveSec = cfg.imapSync.syncTimer;
|
||||
};
|
||||
};
|
||||
})
|
||||
(lib.mkIf (cfg.enable && cfg.smtpRelay != null) (
|
||||
let
|
||||
url = "[${cfg.smtpRelay.host}]:${toString cfg.smtpRelay.port}";
|
||||
in
|
||||
{
|
||||
assertions = [
|
||||
{
|
||||
assertion = lib.hasAttr cfg.adminPassword != null;
|
||||
message = "`shb.mailserver.adminPassword` must be not null if `shb.mailserver.adminUsername` is not null.";
|
||||
}
|
||||
];
|
||||
|
||||
# Inspiration from https://www.brull.me/postfix/debian/fastmail/2016/08/16/fastmail-smtp.html
|
||||
services.postfix = {
|
||||
settings.main = {
|
||||
relayhost = [ url ];
|
||||
smtp_sasl_auth_enable = "yes";
|
||||
smtp_sasl_password_maps = "texthash:/run/secrets/postfix/postfix-smtp-relay-password";
|
||||
smtp_sasl_security_options = "noanonymous";
|
||||
smtp_use_tls = "yes";
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.postfix-pre = {
|
||||
script = shb.replaceSecrets {
|
||||
userConfig = {
|
||||
inherit url;
|
||||
inherit (cfg.smtpRelay) username;
|
||||
password.source = cfg.smtpRelay.password.result.path;
|
||||
};
|
||||
generator =
|
||||
name:
|
||||
{
|
||||
url,
|
||||
username,
|
||||
password,
|
||||
}:
|
||||
pkgs.writeText "postfix-smtp-relay-password" ''
|
||||
${url} ${username}:${password}
|
||||
'';
|
||||
resultPath = "/run/secrets/postfix/postfix-smtp-relay-password";
|
||||
user = config.services.postfix.user;
|
||||
};
|
||||
serviceConfig.Type = "oneshot";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
before = [ "postfix.service" ];
|
||||
requiredBy = [ "postfix.service" ];
|
||||
};
|
||||
}
|
||||
))
|
||||
];
|
||||
}
|
||||
380
modules/services/mailserver/docs/default.md
Normal file
380
modules/services/mailserver/docs/default.md
Normal file
|
|
@ -0,0 +1,380 @@
|
|||
# Mailserver Service {#services-mailserver}
|
||||
|
||||
Defined in [`/modules/services/mailserver.nix`](@REPO@/modules/services/mailserver.nix).
|
||||
|
||||
This NixOS module is a service that sets up
|
||||
the [NixOS Simple Mailserver](https://gitlab.com/simple-nixos-mailserver/nixos-mailserver) project.
|
||||
It integrates the upstream project
|
||||
with the SHB modules like the SSL module, the contract for secrets and the LLDAP module.
|
||||
|
||||
It also exposes an XML file which allows some email clients to auto configure themselves.
|
||||
|
||||
Setting up a self-hosted email server in this age
|
||||
can be quite time consuming because you need to maintain
|
||||
a good IP hygiene to avoid being marked as spam from the big players.
|
||||
To avoid needing to deal with this,
|
||||
this module provides the means
|
||||
to use an email provider (like Fastmail or ProtonMail) as a mere proxy.
|
||||
If you also setup the email provider using your own custom domain,
|
||||
this combination allows you to change email provider
|
||||
without needing to change your clients or notify your email correspondents
|
||||
and keep a backup of all your emails at the same time.
|
||||
The setup looks like so:
|
||||
|
||||
```
|
||||
Domain --[ DNS records ]-> Email Provider --[ mbsync ]-> SHB Server
|
||||
|
||||
Internet <---------------- Email Provider <-[ postfix ]-- SHB Server
|
||||
```
|
||||
|
||||
Configuring your domain name to point to your email provider is out of scope here.
|
||||
See the documentation for "custom domain" for you email provider,
|
||||
like for [Fastmail](https://www.fastmail.com/features/domains/)
|
||||
and [ProtonMail](https://proton.me/support/custom-domain)
|
||||
|
||||
To use an email provider as a proxy, use the
|
||||
[shb.mailserver.imapSync](#services-mailserver-options-shb.mailserver.imapSync)
|
||||
and [shb.mailserver.smtpRelay](#services-mailserver-options-shb.mailserver.smtpRelay),
|
||||
options.
|
||||
|
||||
## Usage {#services-mailserver-usage}
|
||||
|
||||
The following snippet assumes a few blocks have been setup already:
|
||||
|
||||
- the [secrets block](usage.html#usage-secrets) with SOPS,
|
||||
- the [`shb.ssl` block](blocks-ssl.html#usage),
|
||||
- the [`shb.lldap` block](blocks-lldap.html#blocks-lldap-global-setup).
|
||||
|
||||
```nix
|
||||
let
|
||||
domain = "example.com";
|
||||
username = "me@example.com";
|
||||
in
|
||||
{
|
||||
imports = [
|
||||
selfhostblocks.nixosModules.mailserver
|
||||
];
|
||||
|
||||
shb.mailserver = {
|
||||
enable = true;
|
||||
inherit domain;
|
||||
subdomain = "imap";
|
||||
ssl = config.shb.certs.certs.letsencrypt."domain";
|
||||
|
||||
imapSync = {
|
||||
syncTimer = "10s";
|
||||
accounts.fastmail = {
|
||||
host = "imap.fastmail.com";
|
||||
port = 993;
|
||||
inherit username;
|
||||
password.result = config.shb.sops.secret."mailserver/imap/fastmail/password".result;
|
||||
mapSpecialJunk = "Spam";
|
||||
};
|
||||
};
|
||||
|
||||
smtpRelay = {
|
||||
host = "smtp.fastmail.com";
|
||||
port = 587;
|
||||
inherit username;
|
||||
password.result = config.shb.sops.secret."mailserver/smtp/fastmail/password".result;
|
||||
};
|
||||
|
||||
ldap = {
|
||||
enable = true;
|
||||
host = "127.0.0.1";
|
||||
port = config.shb.lldap.ldapPort;
|
||||
dcdomain = config.shb.lldap.dcdomain;
|
||||
adminName = "admin";
|
||||
adminPassword.result = config.shb.sops.secret."mailserver/ldap_admin_password".result;
|
||||
account = "fastmail";
|
||||
};
|
||||
};
|
||||
|
||||
# Optionally add some mailboxes
|
||||
mailserver.mailboxes = {
|
||||
Drafts = {
|
||||
auto = "subscribe";
|
||||
specialUse = "Drafts";
|
||||
};
|
||||
Junk = {
|
||||
auto = "subscribe";
|
||||
specialUse = "Junk";
|
||||
};
|
||||
Sent = {
|
||||
auto = "subscribe";
|
||||
specialUse = "Sent";
|
||||
};
|
||||
Trash = {
|
||||
auto = "subscribe";
|
||||
specialUse = "Trash";
|
||||
};
|
||||
Archive = {
|
||||
auto = "subscribe";
|
||||
specialUse = "Archive";
|
||||
};
|
||||
};
|
||||
|
||||
shb.sops.secret."mailserver/smtp/fastmail/password".request =
|
||||
config.shb.mailserver.smtpRelay.password.request;
|
||||
|
||||
shb.sops.secret."mailserver/imap/fastmail/password".request =
|
||||
config.shb.mailserver.imapSync.accounts.fastmail.password.request;
|
||||
|
||||
shb.sops.secret."mailserver/ldap_admin_password" = {
|
||||
request = config.shb.mailserver.ldap.adminPassword.request;
|
||||
# This reuses the admin password set in the shb.lldap module.
|
||||
settings.key = "lldap/user_password";
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
### Secrets {#services-mailserver-usage-secrets}
|
||||
|
||||
Secrets can be randomly generated with `nix run nixpkgs#openssl -- rand -hex 64`.
|
||||
|
||||
### LDAP {#services-mailserver-usage-ldap}
|
||||
|
||||
The [user](#services-mailserver-options-shb.mailserver.ldap.userGroup)
|
||||
LDAP group is created automatically.
|
||||
|
||||
### Disk Layout {#services-mailserver-usage-disk-layout}
|
||||
|
||||
The disk layout has been purposely set to use slashes `/` for subfolders.
|
||||
By experience, this works better with iOS mail.
|
||||
|
||||
### Backup {#services-mailserver-usage-backup}
|
||||
|
||||
Backing up your emails using the [Restic block](blocks-restic.html) is done like so:
|
||||
|
||||
```nix
|
||||
shb.restic.instances."mailserver" = {
|
||||
request = config.shb.mailserver.backup;
|
||||
settings = {
|
||||
enable = true;
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
The name `"mailserver"` in the `instances` can be anything.
|
||||
The `config.shb.mailserver.backup` option provides what directories to backup.
|
||||
You can define any number of Restic instances to backup your emails multiple times.
|
||||
|
||||
You will then need to configure more options like the `repository`,
|
||||
as explained in the [restic](blocks-restic.html) documentation.
|
||||
|
||||
### Certificates {#services-mailserver-certs}
|
||||
|
||||
For Let's Encrypt certificates, add:
|
||||
|
||||
```nix
|
||||
let
|
||||
domain = "example.com";
|
||||
in
|
||||
{
|
||||
shb.certs.certs.letsencrypt.${domain}.extraDomains = [
|
||||
"${config.shb.mailserver.subdomain}.${config.shb.mailserver.domain}"
|
||||
];
|
||||
}
|
||||
```
|
||||
|
||||
### Impermanence {#services-mailserver-impermanence}
|
||||
|
||||
To save the data folder in an impermanence setup, add:
|
||||
|
||||
```nix
|
||||
{
|
||||
shb.zfs.datasets."safe/mailserver/index".path = config.shb.mailserver.impermanence.index;
|
||||
shb.zfs.datasets."safe/mailserver/mail".path = config.shb.mailserver.impermanence.mail;
|
||||
shb.zfs.datasets."safe/mailserver/sieve".path = config.shb.mailserver.impermanence.sieve;
|
||||
shb.zfs.datasets."safe/mailserver/dkim".path = config.shb.mailserver.impermanence.dkim;
|
||||
}
|
||||
```
|
||||
|
||||
### Declarative LDAP {#services-mailserver-declarative-ldap}
|
||||
|
||||
To add a user `USERNAME` to the user group, add:
|
||||
|
||||
```nix
|
||||
shb.lldap.ensureUsers.USERNAME.groups = [
|
||||
config.shb.mailserver.ldap.userGroup
|
||||
];
|
||||
```
|
||||
|
||||
## Debug {#services-mailserver-debug}
|
||||
|
||||
Debugging this will be certainly necessary.
|
||||
The first issue you will encounter will probably be with `mbsync`
|
||||
under the [shb.mailserver.imapSync](#services-mailserver-options-shb.mailserver.imapSync) option
|
||||
with the folder name mapping.
|
||||
|
||||
### Systemd Services {#services-mailserver-debug-systemd}
|
||||
|
||||
The 3 systemd services setup by this module are:
|
||||
|
||||
- `mbsync.service`
|
||||
- `dovecot.service`
|
||||
- `postfix.service`
|
||||
|
||||
### Folders {#services-mailserver-debug-folders}
|
||||
|
||||
The 4 folders where state is stored are:
|
||||
|
||||
- `config.mailserver.indexDir` = `/var/lib/dovecot/indices`
|
||||
- `config.mailserver.mailDirectory` = `/var/vmail`
|
||||
- `config.mailserver.sieveDirectory` = `/var/sieve`
|
||||
- `config.mailserver.dkimKeyDirectory` = `/var/dkim`
|
||||
|
||||
### Open Ports {#services-mailserver-debug-ports}
|
||||
|
||||
The ports opened by default in this module are:
|
||||
|
||||
- Submissions: 465
|
||||
- Imap: 993
|
||||
|
||||
You will need to forward those ports on your router
|
||||
if you want to access to your emails from the internet.
|
||||
|
||||
The complete list can be found in the [upstream repository](https://gitlab.com/simple-nixos-mailserver/nixos-mailserver/-/blob/5965fae920b6b97f39f94bdb6195631e274c93a5/mail-server/networking.nix).
|
||||
|
||||
### List Email Provider Folder Mapping {#services-mailserver-debug-folder-mapping}
|
||||
|
||||
Replace `$USER` and `$PASSWORD` by those used to connect to your email provider.
|
||||
Yes, you will need to enter verbatim `a LOGIN ...` and `b LIST "" "*"`.
|
||||
|
||||
```
|
||||
$ nix run nixpkgs#openssl -- s_client -connect imap.fastmail.com:993 -crlf -quiet
|
||||
a LOGIN $USER $password
|
||||
b LIST "" "*"
|
||||
```
|
||||
|
||||
Example output will be:
|
||||
|
||||
```
|
||||
* LIST (\HasNoChildren) "/" INBOX
|
||||
* LIST (\HasNoChildren \Drafts) "/" Drafts
|
||||
* LIST (\HasNoChildren \Sent) "/" Sent
|
||||
* LIST (\Noinferiors \HasNoChildren \Junk) "/" Spam
|
||||
|
||||
...
|
||||
```
|
||||
|
||||
Here you can see the special folder `\Junk` is actually named `Spam`.
|
||||
To handle this, set the `.mapSpecial*` options:
|
||||
|
||||
```
|
||||
{
|
||||
shb.mailserver.imapSync.accounts.<account> = {
|
||||
mapSpecialJunk = "Spam";
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
### List Local Folders {#services-mailserver-debug-local-folders}
|
||||
|
||||
Check the local folders to make sure the mapping is correct
|
||||
and all folders are correctly downloaded.
|
||||
For example, if the mapping above is wrong, you will see both a
|
||||
`Junk` and `Spam` folder while if it is correct,
|
||||
you will only see the `Junk` folder.
|
||||
|
||||
```
|
||||
$ sudo doveadm mailbox list -u $USER
|
||||
Junk
|
||||
Trash
|
||||
Drafts
|
||||
Sent
|
||||
INBOX
|
||||
MyCustomFolder
|
||||
```
|
||||
|
||||
The following command shows the number of messages in a folder:
|
||||
|
||||
```
|
||||
$ sudo doveadm mailbox status -u $USER messages INBOX
|
||||
INBOX messages=13591
|
||||
```
|
||||
|
||||
If any folder is not appearing or has 0 message but should have some,
|
||||
it could mean dovecot is not setup correctly and assumes an incorrect folder layout.
|
||||
If that is the case, check the user config with:
|
||||
|
||||
```
|
||||
$ sudo doveadm user $USER
|
||||
field value
|
||||
uid 5000
|
||||
gid 5000
|
||||
home /var/vmail/fastmail/$USER
|
||||
mail maildir:~/mail:LAYOUT=fs
|
||||
virtualMail
|
||||
```
|
||||
|
||||
### Test Auth {#services-mailserver-debug-auth}
|
||||
|
||||
To test authentication to your dovecot instance, run:
|
||||
|
||||
```
|
||||
$ nix run nixpkgs#openssl -- s_client -connect $SUBDOMAIN.$DOMAIN:993 -crlf -quiet
|
||||
. LOGIN $USER $PASSWORD
|
||||
```
|
||||
|
||||
You must here also enter the second line verbatim,
|
||||
replacing your user and password with the real one.
|
||||
|
||||
On success, you will see:
|
||||
|
||||
```
|
||||
. OK [CAPABILITY IMAP4rev1 ...] Logged in
|
||||
```
|
||||
|
||||
Otherwise, either if the password is wrong or,
|
||||
when using LDAP if the user is not part of the LDAP group, you will see:
|
||||
|
||||
```
|
||||
. NO [AUTHENTICATIONFAILED] Authentication failed.
|
||||
```
|
||||
|
||||
To test the postfix instance, run:
|
||||
|
||||
```
|
||||
$ swaks \
|
||||
--server $SUBDOMAIN.$DOMAIN \
|
||||
--port 465 \
|
||||
--tls-on-connect \
|
||||
--auth LOGIN \
|
||||
--auth-user $USER \
|
||||
--auth-password '$PASSWORD' \
|
||||
--from $USER \
|
||||
--to $USER
|
||||
```
|
||||
|
||||
Try once with a wrong password and once with a correct one.
|
||||
The former should log:
|
||||
|
||||
```
|
||||
<~* 535 5.7.8 Error: authentication failed: (reason unavailable)
|
||||
```
|
||||
|
||||
## Mobile Apps {#services-mailserver-mobile}
|
||||
|
||||
This module was tested with:
|
||||
- the iOS mail mobile app,
|
||||
- Thunderbird on NixOS.
|
||||
|
||||
The iOS mail app is pretty finicky.
|
||||
If downloading emails does not work,
|
||||
make sure the certificate used includes the whole chain:
|
||||
|
||||
```bash
|
||||
$ openssl s_client -connect $SUBDOMAIN.$DOMAIN:993 -showcerts
|
||||
```
|
||||
|
||||
Normally, the other options are setup correctly but if it fails for you,
|
||||
feel free to open an issue.
|
||||
|
||||
## Options Reference {#services-mailserver-options}
|
||||
|
||||
```{=include=} options
|
||||
id-prefix: services-mailserver-options-
|
||||
list-id: selfhostblocks-service-mailserver-options
|
||||
source: @OPTIONS_JSON@
|
||||
```
|
||||
Loading…
Reference in a new issue