• Operand
  • no leg, a'sea.

gram:build

> ./nixos/gram/relay.nix

Lenses
(coming soon!)


{ ipv4, ipv6, domain }:
{ options, config, pkgs, lib, ... }:
let alps_channel = 2002;
in {
  imports = [ (builtins.fetchTarball {
    url = "https://gitlab.com/simple-nixos-mailserver/nixos-mailserver/-/archive/nixos-24.05/nixos-mailserver-nixos-23.05.tar.gz";
    # sha256 = "0000000000000000000000000000000000000000000000000000";
  }) ];

  networking.firewall.allowedTCPPorts = [
    80 443
    alps_channel
    25 53 68 143 465 546 587 993
  ];

  mailserver = {
    enable = true;
    fqdn = domain;
    domains = [ domain ];

    # A list of all login accounts. To create the password hashes, use
    # nix-shell -p mkpasswd --run 'mkpasswd -sm bcrypt'
    loginAccounts = let
      code = pkgs.writeText "checkcheck"
      "$2b$05$E9TTgGjLapKSJ9OtElMX6.VveGF4zdU0AxA.wIhx7JXpo8tLSRqWi";
    in {
      "mail@assembled.app" = { hashedPasswordFile = code; };
      "mail@operand.online" = { hashedPasswordFile = code; };
      "mail@opendemocracy.group" = { hashedPasswordFile = code; };
      "calliope@operand.online" = { hashedPasswordFile = code; };
      "calliope@assembled.app" = { hashedPasswordFile = code; };
      "commercial@assembled.app" = { hashedPasswordFile = code; };
      "bill@assembled.app" = { hashedPasswordFile = code; };
      "code@assembled.app" = { hashedPasswordFile = code; };
      "g@assembled.app" = { hashedPasswordFile = code; };
      "domains@assembled.app" = { hashedPasswordFile = code; };
      "calliope@opendemocracy.group" = { hashedPasswordFile = code; };
    };
    certificateScheme = "acme";
  };

  # security.acme.defaults.server = "https://acme-staging-v02.api.letsencrypt.org/directory";

  security.acme = {
    acceptTerms = true;
    defaults.email = "calli.youngblood@gmail.com";
    certs.${domain}.listenHTTP = ":2001";
  };

    # acme certificates
  services.caddy = {
    virtualHosts."http://${domain}:80".extraConfig = ''
    reverse_proxy 127.0.0.1:2001
    log {
      output file /var/lib/caddy/acme.log {
        roll_size     200MiB
        roll_local_time
        roll_keep     1440
        roll_keep_for 1440d
      }
    }
    '';

  services.maddy = {
    enable = false;
    primaryDomain = "assembled.app";
    ensureAccounts = [
      "mail@assembled.app"
      "calliope@assembled.app"
      "commercial@assembled.app"
      "bill@assembled.app"
      "code@assembled.app"
      "g@assembled.app"
      "domains@assembled.app"

      "mail@opendemocracy.group"
      "calliope@opendemocracy.group"

      "mail@operand.online"
      "calliope@operand.online"
      "inbound@operand.online"
    ];
    ensureCredentials = {
      "user1@example.org".passwordFile = "${pkgs.writeText "postmaster" "test"}";
      "postmaster@example.org".passwordFile = "${pkgs.writeText "postmaster" "test"}";
    };
    tls = {
      loader = "acme";
      extraConfig = ''
        email inbound@operand.online
        agreed # LetsEncrypt ToS
        host ${config.services.maddy.primaryDomain}
        challenge dns-01
        dns namedotcom {
          username "c_lliope"
          api_token "12ea305c66790b742f6d536d1dc7105b7163cbc1"
        }
      '';
    };
    config = builtins.replaceStrings [
      "imap tcp://0.0.0.0:143"
      "submission tcp://0.0.0.0:587"
    ] [
      "imap tls://0.0.0.0:993 tcp://0.0.0.0:143"
      "submission tls://0.0.0.0:465 tcp://0.0.0.0:587"
    ] options.services.maddy.config.default;

  };

  services.caddy.enable = true;
  # alps webmail
  services.caddy.virtualHosts.${domain}.extraConfig = ''
    reverse_proxy 127.0.0.1:${toString alps_channel}
    log {
      output file /var/lib/caddy/${domain}.log {
        roll_size     200MiB
        roll_local_time
        roll_keep     1440
        roll_keep_for 1440d
      }
    }
  '';
  service.caddy.virtualHosts."mta-sts.assembled.app".extraConfig = ''
    encode gzip
    file_server
    root * ${
      pkgs.runCommand "testdir" {} ''
        mkdir -p "$out/.well-known"
        echo "
          version: STSv1
          mode: enforce
          max_age: 604800
          mx: mx1.assembled.app
        " > "$out/.well-known/mta-sts.txt"
      ''
    }
  '';

  services.alps = {
    enable = true;
    # theme
    smtps.port = 465;
    smtps.host = "assembled.app";
    port = alps_channel;
    imaps.port = 993;
    imaps.host = "assembled.app";
    bindIP = "0.0.0.0";
  };
}