-
-
Notifications
You must be signed in to change notification settings - Fork 97
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add simple-nixos-mailserver to umbriel
- Loading branch information
Showing
11 changed files
with
346 additions
and
3 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
# NixOS mailserver | ||
|
||
This module will [eventually][issue 485] provide mail services for `nixos.org`. | ||
|
||
## Mailing lists | ||
|
||
To create a new mailing list, or change membership of a mailing list, see the | ||
instructions at the top of [`mailing-lists.nix`](./mailing-lists.nix). | ||
|
||
## Sending mail | ||
|
||
This module does not yet provide SMTP login. | ||
|
||
[issue 485]: https://github.com/NixOS/infra/issues/485 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
{ config, ... }: | ||
|
||
{ | ||
imports = [ ./mailing-lists.nix ]; | ||
|
||
mailserver = { | ||
enable = true; | ||
certificateScheme = "acme-nginx"; | ||
|
||
# Until we have login accounts, there's no reason to run either of these. | ||
enablePop3 = false; | ||
enableImap = false; | ||
|
||
fqdn = config.networking.fqdn; | ||
|
||
# TODO: change to `nixos.org` when ready | ||
domains = [ "mail-test.nixos.org" ]; | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
# This module provides the mailing list definitions for `@nixos.org`. | ||
# | ||
# Simply change the `lists` attribute set below to create new mailing lists or | ||
# edit membership of existing lists. | ||
# | ||
# If you wish to hide your email address, you can encrypt it with SOPS. Just | ||
# run `nix run .#encrypt-email-address` in the `non-critical-infra/` folder and | ||
# follow the instructions. | ||
|
||
{ config, lib, ... }: | ||
|
||
let | ||
# Mailing lists go here. | ||
# TODO: replace with the real `nixos.org` mailing lists. | ||
listsWithSecretFiles = { | ||
"[email protected]" = [ | ||
"[email protected]" | ||
../../secrets/jfly-email.umbriel | ||
"[email protected]" | ||
]; | ||
}; | ||
|
||
fileToSecretId = file: builtins.baseNameOf file; | ||
|
||
listsWithSecretPlaceholders = lib.mapAttrs' (name: members: { | ||
name = name; | ||
value = map ( | ||
member: | ||
if builtins.isString member then member else config.sops.placeholder.${fileToSecretId member} | ||
) members; | ||
}) listsWithSecretFiles; | ||
|
||
secretFiles = lib.pipe listsWithSecretFiles [ | ||
(lib.mapAttrsToList (_name: members: members)) | ||
lib.flatten | ||
(builtins.filter (member: !builtins.isString member)) | ||
]; | ||
in | ||
|
||
{ | ||
# Declare secrets for every secret email in the lists above. | ||
sops.secrets = builtins.listToAttrs ( | ||
map (file: { | ||
name = fileToSecretId file; | ||
value = { | ||
format = "binary"; | ||
sopsFile = file; | ||
}; | ||
}) secretFiles | ||
); | ||
|
||
sops.templates."postfix-virtual-mailing-lists".content = lib.concatStringsSep "\n" ( | ||
lib.mapAttrsToList ( | ||
name: members: "${name} ${lib.concatStringsSep ", " members}" | ||
) listsWithSecretPlaceholders | ||
); | ||
|
||
services.postfix.mapFiles.virtual-mailing-lists = | ||
config.sops.templates."postfix-virtual-mailing-lists".path; | ||
|
||
services.postfix.config.virtual_alias_maps = [ "hash:/etc/postfix/virtual-mailing-lists" ]; | ||
} |
20 changes: 20 additions & 0 deletions
20
non-critical-infra/packages/encrypt-email-address/default.nix
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
{ | ||
lib, | ||
python3, | ||
sops, | ||
}: | ||
|
||
python3.pkgs.buildPythonApplication { | ||
name = "encrypt-email-address"; | ||
src = ./.; | ||
|
||
format = "other"; | ||
|
||
propagatedBuildInputs = [ python3.pkgs.click ]; | ||
|
||
installPhase = '' | ||
mkdir -p $out/bin | ||
mv ./encrypt-email-address.py $out/bin/encrypt-email-address | ||
wrapProgram $out/bin/encrypt-email-address --prefix PATH : ${lib.makeBinPath [ sops ]} | ||
''; | ||
} |
86 changes: 86 additions & 0 deletions
86
non-critical-infra/packages/encrypt-email-address/encrypt-email-address.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
#!/usr/bin/env python3 | ||
|
||
import re | ||
import click | ||
import subprocess | ||
from pathlib import Path | ||
from textwrap import dedent | ||
|
||
|
||
@click.command( | ||
help=dedent("""\ | ||
Encrypt an email address (or email addresses) for inclusion in a mailing list. | ||
See `non-critical-infra/modules/mailserver/mailing-lists.nix` for | ||
documentation about how to use this. | ||
""") | ||
) | ||
@click.argument("id") | ||
@click.argument("email") | ||
@click.option("--force/--no-force", "-f/ ", default=False) | ||
def main(id: str, email: str, force: bool) -> None: | ||
# Feel free to make the regex less restrictive if you need to. | ||
id_re = re.compile("[A-Za-z0-9-]+") | ||
if not id_re.fullmatch(id): | ||
raise click.ClickException( | ||
f"Given ID: {id!r} is invalid. Must match regex: {id_re.pattern}" | ||
) | ||
|
||
# Make sure we aren't being given a text file that happens to have a newline at the end. | ||
clean_email = email.strip() | ||
if clean_email != email: | ||
click.secho("Removed whitespace surrounding given email address", fg="yellow") | ||
email = clean_email | ||
|
||
if Path.cwd().name != "non-critical-infra": | ||
raise click.ClickException( | ||
"You must run this command inside the `non-critical-infra/` folder." | ||
) | ||
|
||
secret_path = Path(f"secrets/{id}-email.umbriel") | ||
|
||
if secret_path.exists(): | ||
if not force: | ||
raise click.ClickException( | ||
f"Refusing to clobber existing {secret_path}. Use `--force` to override." | ||
) | ||
else: | ||
click.secho(f"Clobbering existing {secret_path}", fg="yellow") | ||
|
||
cp = subprocess.run( | ||
["sops", "--encrypt", "--filename-override", secret_path, "/dev/stdin"], | ||
text=True, | ||
check=True, | ||
stdout=subprocess.PIPE, | ||
input=email, | ||
) | ||
|
||
secret_path.write_text(cp.stdout) | ||
subprocess.run( | ||
["git", "add", "--intent-to-add", "--force", "--", secret_path], check=True | ||
) | ||
|
||
click.secho(f"Successfully generated {secret_path}", fg="green") | ||
|
||
mailing_list_nix = Path("modules/mailserver/mailing-lists.nix") | ||
assert mailing_list_nix.exists() | ||
|
||
click.secho() | ||
click.secho("Now add yourself to ", nl=False) | ||
click.secho(mailing_list_nix, fg="blue", nl=False) | ||
click.secho(". ") | ||
|
||
click.secho() | ||
click.secho("Lastly, add `", nl=False) | ||
click.secho( | ||
secret_path.relative_to(mailing_list_nix.parent, walk_up=True), | ||
fg="blue", | ||
nl=False, | ||
) | ||
click.secho("` to the relevant mailing list under '", nl=False) | ||
click.secho("# Mailing lists go here.", fg="blue", nl=False) | ||
click.secho("'.") | ||
|
||
|
||
if __name__ == "__main__": | ||
main() |
Oops, something went wrong.